* uint16 epoch; // DTLS only
* uint48 sequence_number; // DTLS only
* uint16 length;
+ *
+ * Return 0 if header looks sane (and, for DTLS, the record is expected)
+ * MBEDTLS_ERR_SSL_INVALID_RECORD if the header looks bad,
+ * MBEDTLS_ERR_SSL_UNEXPECTED_RECORD (DTLS only) if sane but unexpected.
+ *
+ * With DTLS, mbedtls_ssl_read_record() will:
+ * 1. proceed with the record if this function returns 0
+ * 2. drop only the current record if this function returns UNEXPECTED_RECORD
+ * 3. return CLIENT_RECONNECT if this function return that value
+ * 4. drop the whole datagram if this function returns anything else.
+ * Point 2 is needed when the peer is resending, and we have already received
+ * the first record from a datagram but are still waiting for the others.
*/
static int ssl_parse_record_header( mbedtls_ssl_context *ssl )
{
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
}
+ /* Check version */
+ if( major_ver != ssl->major_ver )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "major version mismatch" ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+
+ if( minor_ver > ssl->conf->max_minor_ver )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "minor version mismatch" ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+
+ /* Check length against the size of our buffer */
+ if( ssl->in_msglen > MBEDTLS_SSL_BUFFER_LEN
+ - (size_t)( ssl->in_msg - ssl->in_buf ) )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+
+ /* Check length against bounds of the current transform and version */
+ if( ssl->transform_in == NULL )
+ {
+ if( ssl->in_msglen < 1 ||
+ ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+ }
+ else
+ {
+ if( ssl->in_msglen < ssl->transform_in->minlen )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+
+#if defined(MBEDTLS_SSL_PROTO_SSL3)
+ if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 &&
+ ssl->in_msglen > ssl->transform_in->minlen + MBEDTLS_SSL_MAX_CONTENT_LEN )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+#endif
+#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
+ defined(MBEDTLS_SSL_PROTO_TLS1_2)
+ /*
+ * TLS encrypted messages can have up to 256 bytes of padding
+ */
+ if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 &&
+ ssl->in_msglen > ssl->transform_in->minlen +
+ MBEDTLS_SSL_MAX_CONTENT_LEN + 256 )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+#endif
+ }
+
+ /*
+ * DTLS-related tests done last, because most of them may result in
+ * silently dropping the record (but not the whole datagram), and we only
+ * want to consider that after ensuring that the "basic" fields (type,
+ * version, length) are sane.
+ */
#if defined(MBEDTLS_SSL_PROTO_DTLS)
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
{
+ unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1];
+
/* Drop unexpected ChangeCipherSpec messages */
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC &&
ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC &&
ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ChangeCipherSpec" ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
}
/* Drop unexpected ApplicationData records,
)
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ApplicationData" ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
}
- }
-#endif
-
- /* Check version */
- if( major_ver != ssl->major_ver )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "major version mismatch" ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
-
- if( minor_ver > ssl->conf->max_minor_ver )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "minor version mismatch" ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
-
- /* Check epoch (and sequence number) with DTLS */
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
- {
- unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1];
+ /* Check epoch (and sequence number) with DTLS */
if( rec_epoch != ssl->in_epoch )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "record from another epoch: "
}
else
#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
}
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
mbedtls_ssl_dtls_replay_check( ssl ) != 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record" ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
}
#endif
}
#endif /* MBEDTLS_SSL_PROTO_DTLS */
- /* Check length against the size of our buffer */
- if( ssl->in_msglen > MBEDTLS_SSL_BUFFER_LEN
- - (size_t)( ssl->in_msg - ssl->in_buf ) )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
-
- /* Check length against bounds of the current transform and version */
- if( ssl->transform_in == NULL )
- {
- if( ssl->in_msglen < 1 ||
- ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
- }
- else
- {
- if( ssl->in_msglen < ssl->transform_in->minlen )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
-
-#if defined(MBEDTLS_SSL_PROTO_SSL3)
- if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 &&
- ssl->in_msglen > ssl->transform_in->minlen + MBEDTLS_SSL_MAX_CONTENT_LEN )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
-#endif
-#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
- defined(MBEDTLS_SSL_PROTO_TLS1_2)
- /*
- * TLS encrypted messages can have up to 256 bytes of padding
- */
- if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 &&
- ssl->in_msglen > ssl->transform_in->minlen +
- MBEDTLS_SSL_MAX_CONTENT_LEN + 256 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
-#endif
- }
-
return( 0 );
}
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
ret != MBEDTLS_ERR_SSL_CLIENT_RECONNECT )
{
- /* Ignore bad record and get next one; drop the whole datagram
- * since current header cannot be trusted to find the next record
- * in current datagram */
- ssl->next_record_offset = 0;
- ssl->in_left = 0;
+ if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD )
+ {
+ /* Skip unexpected record (but not whole datagram) */
+ ssl->next_record_offset = ssl->in_msglen
+ + mbedtls_ssl_hdr_len( ssl );
+
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding unexpected record "
+ "(header)" ) );
+ }
+ else
+ {
+ /* Skip invalid record and the rest of the datagram */
+ ssl->next_record_offset = 0;
+ ssl->in_left = 0;
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record (header)" ) );
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record "
+ "(header)" ) );
+ }
+
+ /* Get next record */
goto read_record_header;
}
#endif
memset( conf, 0, sizeof( mbedtls_ssl_config ) );
}
+#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED)
+static int ssl_preset_default_hashes[] = {
+#if defined(MBEDTLS_SHA512_C)
+ MBEDTLS_MD_SHA512,
+ MBEDTLS_MD_SHA384,
+#endif
+#if defined(MBEDTLS_SHA256_C)
+ MBEDTLS_MD_SHA256,
+ MBEDTLS_MD_SHA224,
+#endif
+#if defined(MBEDTLS_SHA1_C)
+ MBEDTLS_MD_SHA1,
+#endif
+ MBEDTLS_MD_NONE
+};
+#endif
+
static int ssl_preset_suiteb_ciphersuites[] = {
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
#endif
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED)
- conf->sig_hashes = mbedtls_md_list();
+ conf->sig_hashes = ssl_preset_default_hashes;
#endif
#if defined(MBEDTLS_ECP_C)