Remove CRT digest from SSL session if !RENEGO + !KEEP_PEER_CERT
If `MBEDTLS_SSL_KEEP_PEER_CERTIFICATE` is not set, `mbedtls_ssl_session`
contains the digest of the peer's certificate for the sole purpose of
detecting a CRT change on renegotiation. Hence, it is not needed if
renegotiation is disabled.
This commit removes the `peer_cert_digest` fields (and friends) from
`mbedtls_ssl_session` if
`!MBEDTLS_SSL_KEEP_PEER_CERTIFICATE + !MBEDTLS_SSL_RENEGOTIATION`,
which is a sensible configuration for constrained devices.
Apart from straightforward replacements of
`if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)`
by
`if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) && \
defined(MBEDTLS_SSL_RENEGOTIATION)`,
there's one notable change: On the server-side, the CertificateVerify
parsing function is a no-op if the client hasn't sent a certificate.
So far, this was determined by either looking at the peer CRT or the
peer CRT digest in the SSL session structure (depending on the setting
of `MBEDTLS_SSL_KEEP_PEER_CERTIFICATE`), which now no longer works if
`MBEDTLS_SSL_KEEP_PEER_CERTIFICATE` is unset. Instead, this function
now checks whether the temporary copy of the peer's public key within
the handshake structure is initialized or not (which is also a
beneficial simplification in its own right, because the pubkey is
all the function needs anyway).
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index 06fe3ee..a8821f3 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -4161,7 +4161,7 @@
mbedtls_md_type_t md_alg;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
ssl->handshake->ciphersuite_info;
- mbedtls_pk_context * peer_pk;
+ mbedtls_pk_context *peer_pk = NULL;
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) );
@@ -4172,21 +4172,30 @@
return( 0 );
}
-#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
- if( ssl->session_negotiate->peer_cert == NULL )
+ /* Skip if we haven't received a certificate from the client.
+ * If MBEDTLS_SSL_KEEP_PEER_CERTIFICATE is set, this can be
+ * inferred from the setting of mbedtls_ssl_session::peer_cert.
+ * If MBEDTLS_SSL_KEEP_PEER_CERTIFICATE is not set, it can
+ * be inferred from whether we've held back the peer CRT's
+ * public key in mbedtls_ssl_handshake_params::peer_pubkey. */
+#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+ /* Because the peer CRT pubkey is embedded into the handshake
+ * params currently, and there's no 'is_init' functions for PK
+ * contexts, we need to break the abstraction and peek into
+ * the PK context to see if it has been initialized. */
+ if( ssl->handshake->peer_pubkey.pk_info != NULL )
+ peer_pk = &ssl->handshake->peer_pubkey;
+#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+ if( ssl->session_negotiate->peer_cert != NULL )
+ peer_pk = &ssl->session_negotiate->peer_cert->pk;
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+
+ if( peer_pk == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) );
ssl->state++;
return( 0 );
}
-#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
- if( ssl->session_negotiate->peer_cert_digest == NULL )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) );
- ssl->state++;
- return( 0 );
- }
-#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
/* Read the message without adding it to the checksum */
ret = mbedtls_ssl_read_record( ssl, 0 /* no checksum update */ );
@@ -4208,17 +4217,6 @@
i = mbedtls_ssl_hs_hdr_len( ssl );
-#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
- peer_pk = &ssl->handshake->peer_pubkey;
-#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
- if( ssl->session_negotiate->peer_cert == NULL )
- {
- /* Should never happen */
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
- peer_pk = &ssl->session_negotiate->peer_cert->pk;
-#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-
/*
* struct {
* SignatureAndHashAlgorithm algorithm; -- TLS 1.2 only