From cf291d63ddb251dd1cfa32451439c2dd99685bea Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Wed, 6 Feb 2019 16:19:04 +0000 Subject: [PATCH] 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. --- library/ssl_tls.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index d752aeb1a..c739fe776 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -6698,6 +6698,24 @@ crt_verify: 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;