Make a copy of peer's raw public key after verifying its CRT chain
This commit modifies `mbedtls_ssl_parse_certificate()` to store a
copy of the peer's public key after parsing and verifying the peer's
CRT chain.
So far, this leads to heavy memory duplication: We have the CRT chain
in the I/O buffer, then parse (and, thereby, copy) it to a
`mbedtls_x509_crt` structure, and then make another copy of the
peer's public key, plus the overhead from the MPI and ECP structures.
This inefficiency will soon go away to a significant extend, because:
- Another PR adds functionality to parse CRTs without taking
ownership of the input buffers. Applying this here will allow
parsing and verifying the peer's chain without making an additional
raw copy. The overhead reduces to the size of `mbedtls_x509_crt`,
the public key, and the DN structures referenced in the CRT.
- Once copyless parsing is in place and the removal of the peer CRT
is fully implemented, we can extract the public key bounds from
the parsed certificate and then free the entire chain before
parsing the public key again. This means that we never store
the parsed public key twice at the same time.
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 290dbe0..0afdd61 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -6284,6 +6284,24 @@
MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN;
#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+ /* Make a copy of the peer's raw public key. */
+ mbedtls_pk_init( &ssl->handshake->peer_pubkey );
+ {
+ unsigned char *p, *end;
+ p = chain->pk_raw.p;
+ end = p + chain->pk_raw.len;
+ ret = mbedtls_pk_parse_subpubkey( &p, end,
+ &ssl->handshake->peer_pubkey );
+ if( ret != 0 )
+ {
+ /* We should have parsed the public key before. */
+ ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+ goto exit;
+ }
+ }
+#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+
ssl->session_negotiate->peer_cert = chain;
chain = NULL;