Push the difference in chain semantics to the edge.
OpenSSL includes a leaf certificate in a certificate chain when it's a
client, but doesn't when it's a server. This is also reflected in the
serialisation of sessions.
This change makes the internal semantics consistent: the leaf is always
included in the chain in memory, and never duplicated when serialised.
To maintain the same API, SSL_get_peer_cert_chain will construct a copy
of the chain without the leaf if needed.
Since the serialised format of a client session has changed, an
|is_server| boolean is added to the ASN.1 that defaults to true. Thus
any old client sessions will be parsed as server sessions and (silently)
discarded by a client.
Change-Id: Ibcf72bc8a130cedb423bc0fd3417868e0af3ca3e
Reviewed-on: https://boringssl-review.googlesource.com/12704
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: Adam Langley <agl@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/ssl/handshake_client.c b/ssl/handshake_client.c
index bae5365..59fefc4 100644
--- a/ssl/handshake_client.c
+++ b/ssl/handshake_client.c
@@ -756,7 +756,8 @@
* version, drop it. */
if (ssl->session != NULL) {
uint16_t session_version;
- if (!ssl->method->version_from_wire(&session_version,
+ if (ssl->session->is_server ||
+ !ssl->method->version_from_wire(&session_version,
ssl->session->ssl_version) ||
(session_version < TLS1_3_VERSION &&
ssl->session->session_id_length == 0) ||
@@ -1059,10 +1060,10 @@
goto err;
}
- /* NOTE: Unlike the server half, the client's copy of |x509_chain| includes
- * the leaf. */
sk_X509_pop_free(ssl->s3->new_session->x509_chain, X509_free);
ssl->s3->new_session->x509_chain = chain;
+ sk_X509_pop_free(ssl->s3->new_session->x509_chain_without_leaf, X509_free);
+ ssl->s3->new_session->x509_chain_without_leaf = NULL;
X509_free(ssl->s3->new_session->x509_peer);
X509_up_ref(leaf);