Switch the keylog BIO to a callback.
The keylog BIO is internally synchronized by the SSL_CTX lock, but an
application may wish to log keys from multiple SSL_CTXs. This is in
preparation for switching Chromium to use a separate SSL_CTX per profile
to more naturally split up the session caches.
It will also be useful for routing up SSLKEYLOGFILE in WebRTC. There,
each log line must be converted to an IPC up from the renderer
processes.
This will require changes in Chromium when we roll BoringSSL.
BUG=458365,webrtc:4417
Change-Id: I2945bdb4def0a9c36e751eab3d5b06c330d66b54
Reviewed-on: https://boringssl-review.googlesource.com/6514
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index c78a91a..aaebf32 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -343,7 +343,6 @@
OPENSSL_free(ctx->ocsp_response);
OPENSSL_free(ctx->signed_cert_timestamp_list);
EVP_PKEY_free(ctx->tlsext_channel_id_private);
- BIO_free(ctx->keylog_bio);
OPENSSL_free(ctx);
}
@@ -2252,9 +2251,9 @@
ssl->msg_callback_arg = arg;
}
-void SSL_CTX_set_keylog_bio(SSL_CTX *ctx, BIO *keylog_bio) {
- BIO_free(ctx->keylog_bio);
- ctx->keylog_bio = keylog_bio;
+void SSL_CTX_set_keylog_callback(SSL_CTX *ctx,
+ void (*cb)(const SSL *ssl, const char *line)) {
+ ctx->keylog_callback = cb;
}
static int cbb_add_hex(CBB *cbb, const uint8_t *in, size_t in_len) {
@@ -2274,18 +2273,12 @@
return 1;
}
-int ssl_ctx_log_rsa_client_key_exchange(SSL_CTX *ctx,
- const uint8_t *encrypted_premaster,
- size_t encrypted_premaster_len,
- const uint8_t *premaster,
- size_t premaster_len) {
- BIO *bio = ctx->keylog_bio;
- CBB cbb;
- uint8_t *out;
- size_t out_len;
- int ret;
-
- if (bio == NULL) {
+int ssl_log_rsa_client_key_exchange(const SSL *ssl,
+ const uint8_t *encrypted_premaster,
+ size_t encrypted_premaster_len,
+ const uint8_t *premaster,
+ size_t premaster_len) {
+ if (ssl->ctx->keylog_callback == NULL) {
return 1;
}
@@ -2294,7 +2287,9 @@
return 0;
}
- CBB_zero(&cbb);
+ CBB cbb;
+ uint8_t *out;
+ size_t out_len;
if (!CBB_init(&cbb, 4 + 16 + 1 + premaster_len * 2 + 1) ||
!CBB_add_bytes(&cbb, (const uint8_t *)"RSA ", 4) ||
/* Only the first 8 bytes of the encrypted premaster secret are
@@ -2302,30 +2297,21 @@
!cbb_add_hex(&cbb, encrypted_premaster, 8) ||
!CBB_add_bytes(&cbb, (const uint8_t *)" ", 1) ||
!cbb_add_hex(&cbb, premaster, premaster_len) ||
- !CBB_add_bytes(&cbb, (const uint8_t *)"\n", 1) ||
+ !CBB_add_u8(&cbb, 0 /* NUL */) ||
!CBB_finish(&cbb, &out, &out_len)) {
CBB_cleanup(&cbb);
return 0;
}
- CRYPTO_MUTEX_lock_write(&ctx->lock);
- ret = BIO_write(bio, out, out_len) >= 0 && BIO_flush(bio);
- CRYPTO_MUTEX_unlock(&ctx->lock);
-
+ ssl->ctx->keylog_callback(ssl, (const char *)out);
OPENSSL_free(out);
- return ret;
+ return 1;
}
-int ssl_ctx_log_master_secret(SSL_CTX *ctx, const uint8_t *client_random,
- size_t client_random_len, const uint8_t *master,
- size_t master_len) {
- BIO *bio = ctx->keylog_bio;
- CBB cbb;
- uint8_t *out;
- size_t out_len;
- int ret;
-
- if (bio == NULL) {
+int ssl_log_master_secret(const SSL *ssl, const uint8_t *client_random,
+ size_t client_random_len, const uint8_t *master,
+ size_t master_len) {
+ if (ssl->ctx->keylog_callback == NULL) {
return 1;
}
@@ -2334,24 +2320,23 @@
return 0;
}
- CBB_zero(&cbb);
+ CBB cbb;
+ uint8_t *out;
+ size_t out_len;
if (!CBB_init(&cbb, 14 + 64 + 1 + master_len * 2 + 1) ||
!CBB_add_bytes(&cbb, (const uint8_t *)"CLIENT_RANDOM ", 14) ||
!cbb_add_hex(&cbb, client_random, 32) ||
!CBB_add_bytes(&cbb, (const uint8_t *)" ", 1) ||
!cbb_add_hex(&cbb, master, master_len) ||
- !CBB_add_bytes(&cbb, (const uint8_t *)"\n", 1) ||
+ !CBB_add_u8(&cbb, 0 /* NUL */) ||
!CBB_finish(&cbb, &out, &out_len)) {
CBB_cleanup(&cbb);
return 0;
}
- CRYPTO_MUTEX_lock_write(&ctx->lock);
- ret = BIO_write(bio, out, out_len) >= 0 && BIO_flush(bio);
- CRYPTO_MUTEX_unlock(&ctx->lock);
-
+ ssl->ctx->keylog_callback(ssl, (const char *)out);
OPENSSL_free(out);
- return ret;
+ return 1;
}
int SSL_is_init_finished(const SSL *ssl) {