Add SSL_can_release_private_key. Callers using private key callbacks may retain non-trivial state with a private key. In many cases, the private key is no longer necessary immediately after the first round-trip (e.g. non-HRR TLS 1.3 connections). Add a function that callers can query to drop the state a hair earlier. This is tested in two ways. First, the asserts in front of using the key, combined with existing tests, ensure we don't start reporting it too early. Second, I've added tests in ssl_test.cc to assert we report it as early as we expect to. In doing so, the number of parameters on ConnectClientAndServer() started getting tedious, so I've split that into a CreateClientAndServer() and CompleteHandshakes(). Callers that need to configure weird things or drive the handshake manually can call CreateClientAndServer() (which takes care of the BIO pair business) and continue from there. Bug: b/183734559 Change-Id: I05e1edb6d269c8468ba7cde7dc90e0856694a0ca Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/47344 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/ssl_lib.cc b/ssl/ssl_lib.cc index 260d3cd7..43510f1 100644 --- a/ssl/ssl_lib.cc +++ b/ssl/ssl_lib.cc
@@ -463,7 +463,8 @@ return false; } - if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) { + if (ssl->s3->have_version && + ssl_protocol_version(ssl) >= TLS1_3_VERSION) { return false; } @@ -1788,6 +1789,9 @@ return 0; } + // We should not have told the caller to release the private key. + assert(!SSL_can_release_private_key(ssl)); + // Renegotiation is only supported at quiescent points in the application // protocol, namely in HTTPS, just before reading the HTTP response. // Require the record-layer be idle and avoid complexities of sending a @@ -2840,6 +2844,17 @@ ctx->current_time_cb = cb; } +int SSL_can_release_private_key(const SSL *ssl) { + if (ssl_can_renegotiate(ssl)) { + // If the connection can renegotiate (client only), the private key may be + // used in a future handshake. + return 0; + } + + // Otherwise, this is determined by the current handshake. + return !ssl->s3->hs || ssl->s3->hs->can_release_private_key; +} + int SSL_is_init_finished(const SSL *ssl) { return !SSL_in_init(ssl); }