Implement record checking API
This commit implements the record checking API
mbedtls_ssl_check_record()
on top of the restructured incoming record stack.
Specifically, it makes use of the fact that the core processing routines
ssl_parse_record_header()
mbedtls_ssl_decrypt_buf()
now operate on instances of the SSL record structure mbedtls_record
instead of the previous mbedtls_ssl_context::in_xxx fields.
@@ -113,14 +113,67 @@ static void ssl_update_out_pointers( mbedtls_ssl_context *ssl,
static void ssl_update_in_pointers( mbedtls_ssl_context *ssl );
#if defined(MBEDTLS_SSL_RECORD_CHECKING)
+static int ssl_parse_record_header( mbedtls_ssl_context const *ssl,
+ unsigned char *buf,
+ size_t len,
+ mbedtls_record *rec );
+
int mbedtls_ssl_check_record( mbedtls_ssl_context const *ssl,
unsigned char *buf,
size_t buflen )
{
- ((void) ssl);
- ((void) buf);
- ((void) buflen);
- return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE );
+ int ret = 0;
+ mbedtls_record rec;
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "=> mbedtls_ssl_check_record" ) );
+ MBEDTLS_SSL_DEBUG_BUF( 3, "record buffer", buf, buflen );
+
+ /* We don't support record checking in TLS because
+ * (a) there doesn't seem to be a usecase for it, and
+ * (b) In SSLv3 and TLS 1.0, CBC record decryption has state
+ * and we'd need to backup the transform here.
+ */
+ if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM )
+ {
+ ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+ goto exit;
+ }
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ else
+ {
+ ret = ssl_parse_record_header( ssl, buf, buflen, &rec );
+ if( ret != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 3, "ssl_parse_record_header", ret );
+ goto exit;
+ }
+
+ if( ssl->transform_in != NULL )
+ {
+ ret = mbedtls_ssl_decrypt_buf( ssl, ssl->transform_in, &rec );
+ if( ret != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 3, "mbedtls_ssl_decrypt_buf", ret );
+ goto exit;
+ }
+ }
+ }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+exit:
+ /* On success, we have decrypted the buffer in-place, so make
+ * sure we don't leak any plaintext data. */
+ mbedtls_platform_zeroize( buf, buflen );
+
+ /* For the purpose of this API, treat messages with unexpected CID
+ * as well as such from future epochs as unexpected. */
+ if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID ||
+ ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE )
+ {
+ ret = MBEDTLS_ERR_SSL_UNEXPECTED_RECORD;
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "<= mbedtls_ssl_check_record" ) );
+ return( ret );
}
#endif /* MBEDTLS_SSL_RECORD_CHECKING */
@@ -4993,7 +5046,8 @@ static int ssl_parse_record_header( mbedtls_ssl_context const *ssl,
{
if( ssl_check_record_type( rec->type ) )
{
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type" ) );
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type %u",
+ (unsigned) rec->type ) );
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
}
}
