Merge remote-tracking branch 'origin/pr/612' into baremetal
diff --git a/.gitignore b/.gitignore
index 789f57e..11d91ee 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,6 +22,9 @@
# generated by scripts/memory.sh
massif-*
+# scripts/baremetal.sh --ram build artefacts:
+*.su
+
# MSVC build artifacts:
*.exe
*.pdb
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index eef01f6..1119438 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -1319,7 +1319,6 @@
* (the end is marked by in_len). */
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
unsigned char *in_len; /*!< two-bytes message length field */
- unsigned char *in_iv; /*!< ivlen-byte IV */
unsigned char *in_msg; /*!< message contents (in_iv+ivlen) */
unsigned char *in_offt; /*!< read offset in application data */
diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h
index 6f77730..192bc7a 100644
--- a/include/mbedtls/ssl_internal.h
+++ b/include/mbedtls/ssl_internal.h
@@ -789,18 +789,29 @@
typedef struct
{
- uint8_t ctr[8]; /* Record sequence number */
- uint8_t type; /* Record type */
- uint8_t ver[2]; /* SSL/TLS version */
+ uint8_t ctr[8]; /* In TLS: The implicit record sequence number.
+ * In DTLS: The 2-byte epoch followed by
+ * the 6-byte sequence number.
+ * This is stored as a raw big endian byte array
+ * as opposed to a uint64_t because we rarely
+ * need to perform arithmetic on this, but do
+ * need it as a Byte array for the purpose of
+ * MAC computations. */
+ uint8_t type; /* The record content type. */
+ uint8_t ver[2]; /* SSL/TLS version as present on the wire.
+ * Convert to internal presentation of versions
+ * using mbedtls_ssl_read_version() and
+ * mbedtls_ssl_write_version().
+ * Keep wire-format for MAC computations. */
- unsigned char *buf; /* Memory buffer enclosing the record content */
- size_t buf_len; /* Buffer length */
- size_t data_offset; /* Offset of record content */
- size_t data_len; /* Length of record content */
+ unsigned char *buf; /* Memory buffer enclosing the record content */
+ size_t buf_len; /* Buffer length */
+ size_t data_offset; /* Offset of record content */
+ size_t data_len; /* Length of record content */
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
- uint8_t cid_len; /* Length of the CID (0 if not present) */
- unsigned char cid[ MBEDTLS_SSL_CID_LEN_MAX ]; /* The CID */
+ uint8_t cid_len; /* Length of the CID (0 if not present) */
+ unsigned char cid[ MBEDTLS_SSL_CID_LEN_MAX ]; /* The CID */
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
} mbedtls_record;
@@ -1062,7 +1073,22 @@
static inline size_t mbedtls_ssl_in_hdr_len( const mbedtls_ssl_context *ssl )
{
- return( (size_t) ( ssl->in_iv - ssl->in_hdr ) );
+#if !defined(MBEDTLS_SSL_PROTO__BOTH)
+ ((void) ssl);
+#endif
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( MBEDTLS_SSL_TRANSPORT_IS_DTLS( ssl->conf->transport ) )
+ {
+ return( 13 );
+ }
+ MBEDTLS_SSL_TRANSPORT_ELSE
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+#if defined(MBEDTLS_SSL_PROTO_TLS)
+ {
+ return( 5 );
+ }
+#endif /* MBEDTLS_SSL_PROTO_TLS */
}
static inline size_t mbedtls_ssl_out_hdr_len( const mbedtls_ssl_context *ssl )
@@ -1095,7 +1121,7 @@
/* Visible for testing purposes only */
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
-int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context *ssl );
+int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context const *ssl );
void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl );
#endif
@@ -1212,7 +1238,7 @@
mbedtls_record *rec,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
-int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context *ssl,
+int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl,
mbedtls_ssl_transform *transform,
mbedtls_record *rec );
diff --git a/library/Makefile b/library/Makefile
index 45ed148..50faed9 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -200,7 +200,7 @@
clean:
ifndef WINDOWS
- rm -f *.o libmbed*
+ rm -f *.o *.su libmbed*
else
- del /Q /F *.o libmbed*
+ del /Q /F *.o *.su libmbed*
endif
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index bcc1052..5a6441f 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -1098,10 +1098,15 @@
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
}
+#if !defined(MBEDTLS_SSL_CONF_FIXED_MAJOR_VER)
ssl->major_ver = MBEDTLS_SSL_MAJOR_VERSION_3;
+#endif
+
+#if !defined(MBEDTLS_SSL_CONF_FIXED_MINOR_VER)
ssl->minor_ver =
( buf[4] <= mbedtls_ssl_conf_get_max_minor_ver( ssl->conf ) )
? buf[4] : mbedtls_ssl_conf_get_max_minor_ver( ssl->conf );
+#endif
if( mbedtls_ssl_get_minor_ver( ssl ) < mbedtls_ssl_conf_get_min_minor_ver( ssl->conf ) )
{
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 95a5e9c..d5fdbba 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -123,14 +123,69 @@
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 defined(MBEDTLS_SSL_PROTO_TLS)
+ if( MBEDTLS_SSL_TRANSPORT_IS_TLS( ssl->conf->transport ) )
+ {
+ ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+ goto exit;
+ }
+ MBEDTLS_SSL_TRANSPORT_ELSE
+#endif /* MBEDTLS_SSL_PROTO_TLS */
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ {
+ 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 */
@@ -258,7 +313,8 @@
static int ssl_load_buffered_message( mbedtls_ssl_context *ssl );
static int ssl_load_buffered_record( mbedtls_ssl_context *ssl );
static int ssl_buffer_message( mbedtls_ssl_context *ssl );
-static int ssl_buffer_future_record( mbedtls_ssl_context *ssl );
+static int ssl_buffer_future_record( mbedtls_ssl_context *ssl,
+ mbedtls_record const *rec );
static int ssl_next_record_is_in_datagram( mbedtls_ssl_context *ssl );
static size_t ssl_get_current_mtu( const mbedtls_ssl_context *ssl );
@@ -2348,7 +2404,7 @@
return( 0 );
}
-int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context *ssl,
+int mbedtls_ssl_decrypt_buf( mbedtls_ssl_context const *ssl,
mbedtls_ssl_transform *transform,
mbedtls_record *rec )
{
@@ -2368,11 +2424,6 @@
#endif
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> decrypt buf" ) );
- if( transform == NULL )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "no transform provided to decrypt_buf" ) );
- return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
- }
if( rec == NULL ||
rec->buf == NULL ||
rec->buf_len < rec->data_offset ||
@@ -2429,8 +2480,12 @@
size_t explicit_iv_len = transform->ivlen - transform->fixed_ivlen;
/*
- * Compute and update sizes
+ * Prepare IV from explicit and implicit data.
*/
+
+ /* Check that there's enough space for the explicit IV
+ * (at the beginning of the record) and the MAC (at the
+ * end of the record). */
if( rec->data_len < explicit_iv_len + transform->taglen )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) < explicit_iv_len (%d) "
@@ -2439,17 +2494,20 @@
return( MBEDTLS_ERR_SSL_INVALID_MAC );
}
- /*
- * Prepare IV
- */
+#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C)
if( transform->ivlen == 12 && transform->fixed_ivlen == 4 )
{
- /* GCM and CCM: fixed || explicit (transmitted) */
- memcpy( iv, transform->iv_dec, transform->fixed_ivlen );
- memcpy( iv + transform->fixed_ivlen, data, 8 );
+ /* GCM and CCM: fixed || explicit */
+ /* Fixed */
+ memcpy( iv, transform->iv_dec, transform->fixed_ivlen );
+ /* Explicit */
+ memcpy( iv + transform->fixed_ivlen, data, 8 );
}
- else if( transform->ivlen == 12 && transform->fixed_ivlen == 12 )
+ else
+#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */
+#if defined(MBEDTLS_CHACHAPOLY_C)
+ if( transform->ivlen == 12 && transform->fixed_ivlen == 12 )
{
/* ChachaPoly: fixed XOR sequence number */
unsigned char i;
@@ -2460,12 +2518,15 @@
iv[i+4] ^= rec->ctr[i];
}
else
+#endif /* MBEDTLS_CHACHAPOLY_C */
{
/* Reminder if we ever add an AEAD mode with a different size */
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
+ /* Group changes to data, data_len, and add_data, because
+ * add_data depends on data_len. */
data += explicit_iv_len;
rec->data_offset += explicit_iv_len;
rec->data_len -= explicit_iv_len + transform->taglen;
@@ -2474,14 +2535,16 @@
MBEDTLS_SSL_DEBUG_BUF( 4, "additional data used for AEAD",
add_data, add_data_len );
- memcpy( transform->iv_dec + transform->fixed_ivlen,
- data - explicit_iv_len, explicit_iv_len );
+ /* Because of the check above, we know that there are
+ * explicit_iv_len Bytes preceeding data, and taglen
+ * bytes following data + data_len. This justifies
+ * the debug message and the invocation of
+ * mbedtls_cipher_auth_decrypt() below. */
MBEDTLS_SSL_DEBUG_BUF( 4, "IV used", iv, transform->ivlen );
MBEDTLS_SSL_DEBUG_BUF( 4, "TAG used", data + rec->data_len,
transform->taglen );
-
/*
* Decrypt and authenticate
*/
@@ -2502,6 +2565,7 @@
}
auth_done++;
+ /* Double-check that AEAD decryption doesn't change content length. */
if( olen != rec->data_len )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
@@ -2569,11 +2633,20 @@
MBEDTLS_SSL_DEBUG_MSG( 3, ( "using encrypt then mac" ) );
- /* Safe due to the check data_len >= minlen + maclen + 1 above. */
+ /* Update data_len in tandem with add_data.
+ *
+ * The subtraction is safe because of the previous check
+ * data_len >= minlen + maclen + 1.
+ *
+ * Afterwards, we know that data + data_len is followed by at
+ * least maclen Bytes, which justifies the call to
+ * mbedtls_ssl_safer_memcmp() below.
+ *
+ * Further, we still know that data_len > minlen */
rec->data_len -= transform->maclen;
-
ssl_extract_add_data_from_record( add_data, &add_data_len, rec );
+ /* Calculate expected MAC. */
MBEDTLS_SSL_DEBUG_BUF( 4, "MAC'd meta-data", add_data,
add_data_len );
mbedtls_md_hmac_update( &transform->md_ctx_dec, add_data,
@@ -2588,6 +2661,7 @@
MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect,
transform->maclen );
+ /* Compare expected MAC with MAC at the end of the record. */
if( mbedtls_ssl_safer_memcmp( data + rec->data_len, mac_expect,
transform->maclen ) != 0 )
{
@@ -2601,6 +2675,10 @@
/*
* Check length sanity
*/
+
+ /* We know from above that data_len > minlen >= 0,
+ * so the following check in particular implies that
+ * data_len >= minlen + ivlen ( = minlen or 2 * minlen ). */
if( rec->data_len % transform->ivlen != 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "msglen (%d) %% ivlen (%d) != 0",
@@ -2615,9 +2693,7 @@
if( mbedtls_ssl_transform_get_minor_ver( transform ) >=
MBEDTLS_SSL_MINOR_VERSION_2 )
{
- /* This is safe because data_len >= minlen + maclen + 1 initially,
- * and at this point we have at most subtracted maclen (note that
- * minlen == transform->ivlen here). */
+ /* Safe because data_len >= minlen + ivlen = 2 * ivlen. */
memcpy( transform->iv_dec, data, transform->ivlen );
data += transform->ivlen;
@@ -2626,6 +2702,8 @@
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */
+ /* We still have data_len % ivlen == 0 and data_len >= ivlen here. */
+
if( ( ret = mbedtls_cipher_crypt( &transform->cipher_ctx_dec,
transform->iv_dec, transform->ivlen,
data, rec->data_len, data, &olen ) ) != 0 )
@@ -2634,6 +2712,7 @@
return( ret );
}
+ /* Double-check that length hasn't changed during decryption. */
if( rec->data_len != olen )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
@@ -2645,7 +2724,10 @@
MBEDTLS_SSL_MINOR_VERSION_2 )
{
/*
- * Save IV in SSL3 and TLS1
+ * Save IV in SSL3 and TLS1, where CBC decryption of consecutive
+ * records is equivalent to CBC decryption of the concatenation
+ * of the records; in other words, IVs are maintained across
+ * record decryptions.
*/
memcpy( transform->iv_dec, transform->cipher_ctx_dec.iv,
transform->ivlen );
@@ -2654,7 +2736,8 @@
/* Safe since data_len >= minlen + maclen + 1, so after having
* subtracted at most minlen and maclen up to this point,
- * data_len > 0. */
+ * data_len > 0 (because of data_len % ivlen == 0, it's actually
+ * >= ivlen ). */
padlen = data[rec->data_len - 1];
if( auth_done == 1 )
@@ -2784,7 +2867,6 @@
* hence data_len >= maclen in any case.
*/
rec->data_len -= transform->maclen;
-
ssl_extract_add_data_from_record( add_data, &add_data_len, rec );
#if defined(MBEDTLS_SSL_PROTO_SSL3)
@@ -2839,7 +2921,7 @@
* in_msglen over all padlen values.
*
* They're independent of padlen, since we previously did
- * in_msglen -= padlen.
+ * data_len -= padlen.
*
* Note that max_len + maclen is never more than the buffer
* length, as we previously did in_msglen -= maclen too.
@@ -4406,7 +4488,7 @@
/*
* Return 0 if sequence number is acceptable, -1 otherwise
*/
-int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context *ssl )
+int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context const *ssl )
{
uint64_t rec_seqnum = ssl_load_six_bytes( ssl->in_ctr + 2 );
uint64_t bit;
@@ -4496,9 +4578,6 @@
size_t sid_len, cookie_len;
unsigned char *p;
- if( f_cookie_write == NULL || f_cookie_check == NULL )
- return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
-
/*
* Structure of ClientHello with record and handshake headers,
* and expected values. We don't need to check a lot, more checks will be
@@ -4624,6 +4703,14 @@
int ret;
size_t len;
+ if( ssl->conf->f_cookie_write == NULL ||
+ ssl->conf->f_cookie_check == NULL )
+ {
+ /* If we can't use cookies to verify reachability of the peer,
+ * drop the record. */
+ return( 0 );
+ }
+
ret = ssl_check_dtls_clihlo_cookie(
ssl->conf->f_cookie_write,
ssl->conf->f_cookie_check,
@@ -4640,8 +4727,7 @@
* If the error is permanent we'll catch it later,
* if it's not, then hopefully it'll work next time. */
(void) mbedtls_ssl_get_send( ssl )( ssl->p_bio, ssl->out_buf, len );
-
- return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED );
+ ret = 0;
}
if( ret == 0 )
@@ -4692,21 +4778,74 @@
* 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 )
+static int ssl_parse_record_header( mbedtls_ssl_context const *ssl,
+ unsigned char *buf,
+ size_t len,
+ mbedtls_record *rec )
{
int major_ver, minor_ver;
- int ret;
- /* Parse and validate record content type and version */
+ size_t const rec_hdr_type_offset = 0;
+ size_t const rec_hdr_type_len = 1;
- ssl->in_msgtype = ssl->in_hdr[0];
- mbedtls_ssl_read_version( &major_ver, &minor_ver, ssl->conf->transport, ssl->in_hdr + 1 );
+ size_t const rec_hdr_version_offset = rec_hdr_type_offset +
+ rec_hdr_type_len;
+ size_t const rec_hdr_version_len = 2;
- /* Check record type */
+ size_t const rec_hdr_ctr_len = 8;
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ uint32_t rec_epoch;
+ size_t const rec_hdr_ctr_offset = rec_hdr_version_offset +
+ rec_hdr_version_len;
+
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ size_t const rec_hdr_cid_offset = rec_hdr_ctr_offset +
+ rec_hdr_ctr_len;
+ size_t rec_hdr_cid_len = 0;
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+ size_t rec_hdr_len_offset; /* To be determined */
+ size_t const rec_hdr_len_len = 2;
+
+ /*
+ * Check minimum lengths for record header.
+ */
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( MBEDTLS_SSL_TRANSPORT_IS_DTLS( ssl->conf->transport ) )
+ {
+ rec_hdr_len_offset = rec_hdr_ctr_offset + rec_hdr_ctr_len;
+ }
+ MBEDTLS_SSL_TRANSPORT_ELSE
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+#if defined(MBEDTLS_SSL_PROTO_TLS)
+ {
+ rec_hdr_len_offset = rec_hdr_version_offset + rec_hdr_version_len;
+ }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+
+ if( len < rec_hdr_len_offset + rec_hdr_len_len )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "datagram of length %u too small to hold DTLS record header of length %u",
+ (unsigned) len,
+ (unsigned)( rec_hdr_len_len + rec_hdr_len_len ) ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+
+ /*
+ * Parse and validate record content type
+ */
+
+ rec->type = buf[ rec_hdr_type_offset ];
+
+ /* Check record content type */
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ rec->cid_len = 0;
+
if( MBEDTLS_SSL_TRANSPORT_IS_DTLS( ssl->conf->transport ) &&
- ssl->in_msgtype == MBEDTLS_SSL_MSG_CID &&
- mbedtls_ssl_conf_get_cid_len( ssl->conf ) != 0 )
+ mbedtls_ssl_conf_get_cid_len( ssl->conf ) != 0 &&
+ rec->type == MBEDTLS_SSL_MSG_CID )
{
/* Shift pointers to account for record header including CID
* struct {
@@ -4723,29 +4862,43 @@
/* So far, we only support static CID lengths
* fixed in the configuration. */
- ssl->in_len = ssl->in_cid + mbedtls_ssl_conf_get_cid_len( ssl->conf );
- ssl->in_iv = ssl->in_msg = ssl->in_len + 2;
+ rec_hdr_cid_len = mbedtls_ssl_conf_get_cid_len( ssl->conf );
+ rec_hdr_len_offset += rec_hdr_cid_len;
+
+ if( len < rec_hdr_len_offset + rec_hdr_len_len )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "datagram of length %u too small to hold DTLS record header including CID, length %u",
+ (unsigned) len,
+ (unsigned)( rec_hdr_len_offset + rec_hdr_len_len ) ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+
+ /* configured CID len is guaranteed at most 255, see
+ * MBEDTLS_SSL_CID_OUT_LEN_MAX in check_config.h */
+ rec->cid_len = (uint8_t) rec_hdr_cid_len;
+ memcpy( rec->cid, buf + rec_hdr_cid_offset, rec_hdr_cid_len );
}
else
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
- if( ssl_check_record_type( ssl->in_msgtype ) )
{
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type" ) );
-
-#if defined(MBEDTLS_SSL_PROTO_TLS)
- /* Silently ignore invalid DTLS records as recommended by RFC 6347
- * Section 4.1.2.7, that is, send alert only with TLS */
- if( MBEDTLS_SSL_TRANSPORT_IS_TLS( ssl->conf->transport ) )
+ if( ssl_check_record_type( rec->type ) )
{
- mbedtls_ssl_pend_fatal_alert( ssl,
- MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE );
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type %u",
+ (unsigned) rec->type ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
}
-#endif /* MBEDTLS_SSL_PROTO_TLS */
-
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
}
- /* Check version */
+ /*
+ * Parse and validate record version
+ */
+
+ rec->ver[0] = buf[ rec_hdr_version_offset + 0 ];
+ rec->ver[1] = buf[ rec_hdr_version_offset + 1 ];
+ mbedtls_ssl_read_version( &major_ver, &minor_ver,
+ ssl->conf->transport,
+ &rec->ver[0] );
+
if( major_ver != mbedtls_ssl_get_major_ver( ssl ) )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "major version mismatch" ) );
@@ -4758,35 +4911,45 @@
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
}
- /* Now that the total length of the record header is known, ensure
- * that the current datagram is large enough to hold it.
- * This would fail, for example, if we received a datagram of
- * size 13 + n Bytes where n is less than the size of incoming CIDs. */
- ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_in_hdr_len( ssl ) );
- if( ret != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret );
- return( ret );
- }
- MBEDTLS_SSL_DEBUG_BUF( 4, "input record header", ssl->in_hdr, mbedtls_ssl_in_hdr_len( ssl ) );
+ /*
+ * Parse/Copy record sequence number.
+ */
- /* Parse and validate record length
- * This must happen after the CID parsing because
- * its position in the record header depends on
- * the presence of a CID. */
-
- ssl->in_msglen = ( ssl->in_len[0] << 8 ) | ssl->in_len[1];
- if( ssl->in_msglen > MBEDTLS_SSL_IN_BUFFER_LEN
- - (size_t)( ssl->in_msg - ssl->in_buf ) )
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+ if( MBEDTLS_SSL_TRANSPORT_IS_DTLS( ssl->conf->transport ) )
{
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ /* Copy explicit record sequence number from input buffer. */
+ memcpy( &rec->ctr[0], buf + rec_hdr_ctr_offset,
+ rec_hdr_ctr_len );
}
+ MBEDTLS_SSL_TRANSPORT_ELSE
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+#if defined(MBEDTLS_SSL_PROTO_TLS)
+ {
+ /* Copy implicit record sequence number from SSL context structure. */
+ memcpy( &rec->ctr[0], ssl->in_ctr, rec_hdr_ctr_len );
+ }
+#endif /* MBEDTLS_SSL_PROTO_TLS */
+
+ /*
+ * Parse record length.
+ */
+
+ rec->data_offset = rec_hdr_len_offset + rec_hdr_len_len;
+ rec->data_len = ( (size_t) buf[ rec_hdr_len_offset + 0 ] << 8 ) |
+ ( (size_t) buf[ rec_hdr_len_offset + 1 ] << 0 );
+ MBEDTLS_SSL_DEBUG_BUF( 4, "input record header", buf, rec->data_offset );
MBEDTLS_SSL_DEBUG_MSG( 3, ( "input record: msgtype = %d, "
"version = [%d:%d], msglen = %d",
- ssl->in_msgtype,
- major_ver, minor_ver, ssl->in_msglen ) );
+ rec->type,
+ major_ver, minor_ver, rec->data_len ) );
+
+ rec->buf = buf;
+ rec->buf_len = rec->data_offset + rec->data_len;
+
+ if( rec->data_len == 0 )
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
/*
* DTLS-related tests.
@@ -4803,52 +4966,41 @@
#if defined(MBEDTLS_SSL_PROTO_DTLS)
if( MBEDTLS_SSL_TRANSPORT_IS_DTLS( ssl->conf->transport ) )
{
- unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1];
+ rec_epoch = ( rec->ctr[0] << 8 ) | rec->ctr[1];
- /* Check epoch (and sequence number) with DTLS */
+ /* Check that the datagram is large enough to contain a record
+ * of the advertised length. */
+ if( len < rec->data_offset + rec->data_len )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "Datagram of length %u too small to contain record of advertised length %u.",
+ (unsigned) len,
+ (unsigned)( rec->data_offset + rec->data_len ) ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+
+ /* Records from other, non-matching epochs are silently discarded.
+ * (The case of same-port Client reconnects must be considered in
+ * the caller). */
if( rec_epoch != ssl->in_epoch )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "record from another epoch: "
"expected %d, received %d",
ssl->in_epoch, rec_epoch ) );
-#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
- /*
- * Check for an epoch 0 ClientHello. We can't use in_msg here to
- * access the first byte of record content (handshake type), as we
- * have an active transform (possibly iv_len != 0), so use the
- * fact that the record header len is 13 instead.
- */
- if( mbedtls_ssl_conf_get_endpoint( ssl->conf ) ==
- MBEDTLS_SSL_IS_SERVER &&
- ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER &&
- rec_epoch == 0 &&
- ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
- ssl->in_left > 13 &&
- ssl->in_buf[13] == MBEDTLS_SSL_HS_CLIENT_HELLO )
+ /* Records from the next epoch are considered for buffering
+ * (concretely: early Finished messages). */
+ if( rec_epoch == (unsigned) ssl->in_epoch + 1 )
{
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "possible client reconnect "
- "from the same port" ) );
- return( ssl_handle_possible_reconnect( ssl ) );
+ MBEDTLS_SSL_DEBUG_MSG( 2, ( "Consider record for buffering" ) );
+ return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
}
- else
-#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */
- {
- /* Consider buffering the record. */
- if( rec_epoch == (unsigned int) ssl->in_epoch + 1 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "Consider record for buffering" ) );
- return( MBEDTLS_ERR_SSL_EARLY_MESSAGE );
- }
- return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
- }
+ return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
}
-
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
- /* Replay detection only works for the current epoch */
- if( rec_epoch == ssl->in_epoch &&
- mbedtls_ssl_dtls_replay_check( ssl ) != 0 )
+ /* For records from the correct epoch, check whether their
+ * sequence number has been seen before. */
+ else if( mbedtls_ssl_dtls_replay_check( ssl ) != 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "replayed record" ) );
return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
@@ -4857,60 +5009,48 @@
}
#endif /* MBEDTLS_SSL_PROTO_DTLS */
+ return( 0 );
+}
- /* 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_IN_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( mbedtls_ssl_get_minor_ver( ssl ) == MBEDTLS_SSL_MINOR_VERSION_0 &&
- ssl->in_msglen > ssl->transform_in->minlen + MBEDTLS_SSL_IN_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( mbedtls_ssl_get_minor_ver( ssl ) >= MBEDTLS_SSL_MINOR_VERSION_1 &&
- ssl->in_msglen > ssl->transform_in->minlen +
- MBEDTLS_SSL_IN_CONTENT_LEN + 256 )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
-#endif
+#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
+static int ssl_check_client_reconnect( mbedtls_ssl_context *ssl )
+{
+ unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1];
+
+ /*
+ * Check for an epoch 0 ClientHello. We can't use in_msg here to
+ * access the first byte of record content (handshake type), as we
+ * have an active transform (possibly iv_len != 0), so use the
+ * fact that the record header len is 13 instead.
+ */
+ if( rec_epoch == 0 &&
+ mbedtls_ssl_conf_get_endpoint( ssl->conf ) ==
+ MBEDTLS_SSL_IS_SERVER &&
+ ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER &&
+ ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
+ ssl->in_left > 13 &&
+ ssl->in_buf[13] == MBEDTLS_SSL_HS_CLIENT_HELLO )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "possible client reconnect "
+ "from the same port" ) );
+ return( ssl_handle_possible_reconnect( ssl ) );
}
return( 0 );
}
+#endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE && MBEDTLS_SSL_SRV_C */
/*
* If applicable, decrypt (and decompress) record content
*/
-static int ssl_prepare_record_content( mbedtls_ssl_context *ssl )
+static int ssl_prepare_record_content( mbedtls_ssl_context *ssl,
+ mbedtls_record *rec )
{
int ret, done = 0;
MBEDTLS_SSL_DEBUG_BUF( 4, "input record from network",
- ssl->in_hdr, mbedtls_ssl_in_hdr_len( ssl ) + ssl->in_msglen );
+ rec->buf, rec->buf_len );
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
if( mbedtls_ssl_hw_record_read != NULL )
@@ -4930,25 +5070,10 @@
#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */
if( !done && ssl->transform_in != NULL )
{
- mbedtls_record rec;
+ unsigned char const old_msg_type = rec->type;
- rec.buf = ssl->in_iv;
- rec.buf_len = MBEDTLS_SSL_IN_BUFFER_LEN
- - ( ssl->in_iv - ssl->in_buf );
- rec.data_len = ssl->in_msglen;
- rec.data_offset = 0;
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID )
- rec.cid_len = (uint8_t)( ssl->in_len - ssl->in_cid );
- memcpy( rec.cid, ssl->in_cid, rec.cid_len );
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-
- memcpy( &rec.ctr[0], ssl->in_ctr, 8 );
- mbedtls_ssl_write_version( mbedtls_ssl_get_major_ver( ssl ),
- mbedtls_ssl_get_minor_ver( ssl ),
- ssl->conf->transport, rec.ver );
- rec.type = ssl->in_msgtype;
if( ( ret = mbedtls_ssl_decrypt_buf( ssl, ssl->transform_in,
- &rec ) ) != 0 )
+ rec ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "ssl_decrypt_buf", ret );
@@ -4965,27 +5090,14 @@
return( ret );
}
- if( ssl->in_msgtype != rec.type )
+ if( old_msg_type != rec->type )
{
MBEDTLS_SSL_DEBUG_MSG( 4, ( "record type after decrypt (before %d): %d",
- ssl->in_msgtype, rec.type ) );
+ old_msg_type, rec->type ) );
}
- /* The record content type may change during decryption,
- * so re-read it. */
- ssl->in_msgtype = rec.type;
- /* Also update the input buffer, because unfortunately
- * the server-side ssl_parse_client_hello() reparses the
- * record header when receiving a ClientHello initiating
- * a renegotiation. */
- ssl->in_hdr[0] = rec.type;
- ssl->in_msg = rec.buf + rec.data_offset;
- ssl->in_msglen = rec.data_len;
- ssl->in_len[0] = (unsigned char)( rec.data_len >> 8 );
- ssl->in_len[1] = (unsigned char)( rec.data_len );
-
MBEDTLS_SSL_DEBUG_BUF( 4, "input payload after decrypt",
- ssl->in_msg, ssl->in_msglen );
+ rec->buf + rec->data_offset, rec->data_len );
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
/* We have already checked the record content type
@@ -4995,23 +5107,18 @@
* Since with the use of CIDs, the record content type
* might change during decryption, re-check the record
* content type, but treat a failure as fatal this time. */
- if( ssl_check_record_type( ssl->in_msgtype ) )
+ if( ssl_check_record_type( rec->type ) )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "unknown record type" ) );
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
}
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
- if( ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
- return( MBEDTLS_ERR_SSL_INVALID_RECORD );
- }
- else if( ssl->in_msglen == 0 )
+ if( rec->data_len == 0 )
{
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
if( mbedtls_ssl_get_minor_ver( ssl ) == MBEDTLS_SSL_MINOR_VERSION_3
- && ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA )
+ && rec->type != MBEDTLS_SSL_MSG_APPLICATION_DATA )
{
/* TLS v1.2 explicitly disallows zero-length messages which are not application data */
MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid zero-length message type: %d", ssl->in_msgtype ) );
@@ -5077,6 +5184,14 @@
}
#endif
+ /* Check actual (decrypted) record content length against
+ * configured maximum. */
+ if( ssl->in_msglen > MBEDTLS_SSL_IN_CONTENT_LEN )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
+ return( MBEDTLS_ERR_SSL_INVALID_RECORD );
+ }
+
return( 0 );
}
@@ -5688,11 +5803,10 @@
return( 0 );
}
-static int ssl_buffer_future_record( mbedtls_ssl_context *ssl )
+static int ssl_buffer_future_record( mbedtls_ssl_context *ssl,
+ mbedtls_record const *rec )
{
mbedtls_ssl_handshake_params * const hs = ssl->handshake;
- size_t const rec_hdr_len = 13;
- size_t const total_buf_sz = rec_hdr_len + ssl->in_msglen;
/* Don't buffer future records outside handshakes. */
if( hs == NULL )
@@ -5700,7 +5814,7 @@
/* Only buffer handshake records (we are only interested
* in Finished messages). */
- if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
+ if( rec->type != MBEDTLS_SSL_MSG_HANDSHAKE )
return( 0 );
/* Don't buffer more than one future epoch record. */
@@ -5708,11 +5822,11 @@
return( 0 );
/* Don't buffer record if there's not enough buffering space remaining. */
- if( total_buf_sz > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
+ if( rec->buf_len > ( MBEDTLS_SSL_DTLS_MAX_BUFFERING -
hs->buffering.total_bytes_buffered ) )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffering of future epoch record of size %u would exceed the compile-time limit %u (already %u bytes buffered) -- ignore\n",
- (unsigned) total_buf_sz, MBEDTLS_SSL_DTLS_MAX_BUFFERING,
+ (unsigned) rec->buf_len, MBEDTLS_SSL_DTLS_MAX_BUFFERING,
(unsigned) hs->buffering.total_bytes_buffered ) );
return( 0 );
}
@@ -5720,13 +5834,12 @@
/* Buffer record */
MBEDTLS_SSL_DEBUG_MSG( 2, ( "Buffer record from epoch %u",
ssl->in_epoch + 1 ) );
- MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered record", ssl->in_hdr,
- rec_hdr_len + ssl->in_msglen );
+ MBEDTLS_SSL_DEBUG_BUF( 3, "Buffered record", rec->buf, rec->buf_len );
/* ssl_parse_record_header() only considers records
* of the next epoch as candidates for buffering. */
hs->buffering.future_record.epoch = ssl->in_epoch + 1;
- hs->buffering.future_record.len = total_buf_sz;
+ hs->buffering.future_record.len = rec->buf_len;
hs->buffering.future_record.data =
mbedtls_calloc( 1, hs->buffering.future_record.len );
@@ -5737,9 +5850,9 @@
return( 0 );
}
- memcpy( hs->buffering.future_record.data, ssl->in_hdr, total_buf_sz );
+ memcpy( hs->buffering.future_record.data, rec->buf, rec->buf_len );
- hs->buffering.total_bytes_buffered += total_buf_sz;
+ hs->buffering.total_bytes_buffered += rec->buf_len;
return( 0 );
}
@@ -5748,6 +5861,7 @@
static int ssl_get_next_record( mbedtls_ssl_context *ssl )
{
int ret;
+ mbedtls_record rec;
#if defined(MBEDTLS_SSL_PROTO_DTLS)
/* We might have buffered a future record; if so,
@@ -5761,11 +5875,6 @@
return( ret );
#endif /* MBEDTLS_SSL_PROTO_DTLS */
- /* Reset in pointers to default state for TLS/DTLS records,
- * assuming no CID and no offset between record content and
- * record plaintext. */
- ssl_update_in_pointers( ssl );
-
/* Ensure that we have enough space available for the default form
* of TLS / DTLS record headers (5 Bytes for TLS, 13 Bytes for DTLS,
* with no space for CIDs counted in). */
@@ -5776,15 +5885,15 @@
return( ret );
}
- if( ( ret = ssl_parse_record_header( ssl ) ) != 0 )
+ ret = ssl_parse_record_header( ssl, ssl->in_hdr, ssl->in_left, &rec );
+ if( ret != 0 )
{
#if defined(MBEDTLS_SSL_PROTO_DTLS)
- if( MBEDTLS_SSL_TRANSPORT_IS_DTLS( ssl->conf->transport ) &&
- ret != MBEDTLS_ERR_SSL_CLIENT_RECONNECT )
+ if( MBEDTLS_SSL_TRANSPORT_IS_DTLS( ssl->conf->transport ) )
{
if( ret == MBEDTLS_ERR_SSL_EARLY_MESSAGE )
{
- ret = ssl_buffer_future_record( ssl );
+ ret = ssl_buffer_future_record( ssl, &rec );
if( ret != 0 )
return( ret );
@@ -5794,9 +5903,27 @@
if( ret == MBEDTLS_ERR_SSL_UNEXPECTED_RECORD )
{
+#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && defined(MBEDTLS_SSL_SRV_C)
+ /* Reset in pointers to default state for TLS/DTLS records,
+ * assuming no CID and no offset between record content and
+ * record plaintext. */
+ ssl_update_in_pointers( ssl );
+
+ /* Setup internal message pointers from record structure. */
+ ssl->in_msgtype = rec.type;
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ ssl->in_len = ssl->in_cid + rec.cid_len;
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+ ssl->in_msg = ssl->in_len + 2;
+ ssl->in_msglen = rec.data_len;
+
+ ret = ssl_check_client_reconnect( ssl );
+ if( ret != 0 )
+ return( ret );
+#endif
+
/* Skip unexpected record (but not whole datagram) */
- ssl->next_record_offset = ssl->in_msglen
- + mbedtls_ssl_in_hdr_len( ssl );
+ ssl->next_record_offset = rec.buf_len;
MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding unexpected record "
"(header)" ) );
@@ -5814,39 +5941,46 @@
/* Get next record */
return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
}
+ else
#endif
- return( ret );
+ {
+ return( ret );
+ }
}
- /*
- * Read and optionally decrypt the message contents
- */
- if( ( ret = mbedtls_ssl_fetch_input( ssl,
- mbedtls_ssl_in_hdr_len( ssl ) + ssl->in_msglen ) ) != 0 )
- {
- MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret );
- return( ret );
- }
-
- /* Done reading this record, get ready for the next one */
#if defined(MBEDTLS_SSL_PROTO_DTLS)
if( MBEDTLS_SSL_TRANSPORT_IS_DTLS( ssl->conf->transport ) )
{
- ssl->next_record_offset = ssl->in_msglen + mbedtls_ssl_in_hdr_len( ssl );
+ /* Remember offset of next record within datagram. */
+ ssl->next_record_offset = rec.buf_len;
if( ssl->next_record_offset < ssl->in_left )
{
MBEDTLS_SSL_DEBUG_MSG( 3, ( "more than one record within datagram" ) );
}
}
MBEDTLS_SSL_TRANSPORT_ELSE
-#endif
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
#if defined(MBEDTLS_SSL_PROTO_TLS)
{
+ /*
+ * Fetch record contents from underlying transport.
+ */
+ ret = mbedtls_ssl_fetch_input( ssl, rec.buf_len );
+ if( ret != 0 )
+ {
+ MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_fetch_input", ret );
+ return( ret );
+ }
+
ssl->in_left = 0;
}
-#endif
+#endif /* MBEDTLS_SSL_PROTO_TLS */
- if( ( ret = ssl_prepare_record_content( ssl ) ) != 0 )
+ /*
+ * Decrypt record contents.
+ */
+
+ if( ( ret = ssl_prepare_record_content( ssl, &rec ) ) != 0 )
{
#if defined(MBEDTLS_SSL_PROTO_DTLS)
if( MBEDTLS_SSL_TRANSPORT_IS_DTLS( ssl->conf->transport ) )
@@ -5908,6 +6042,29 @@
#endif /* MBEDTLS_SSL_PROTO_TLS */
}
+
+ /* Reset in pointers to default state for TLS/DTLS records,
+ * assuming no CID and no offset between record content and
+ * record plaintext. */
+ ssl_update_in_pointers( ssl );
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+ ssl->in_len = ssl->in_cid + rec.cid_len;
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+ ssl->in_msg = ssl->in_len + 2;
+
+ /* The record content type may change during decryption,
+ * so re-read it. */
+ ssl->in_msgtype = rec.type;
+ /* Also update the input buffer, because unfortunately
+ * the server-side ssl_parse_client_hello() reparses the
+ * record header when receiving a ClientHello initiating
+ * a renegotiation. */
+ ssl->in_hdr[0] = rec.type;
+ ssl->in_msg = rec.buf + rec.data_offset;
+ ssl->in_msglen = rec.data_len;
+ ssl->in_len[0] = (unsigned char)( rec.data_len >> 8 );
+ ssl->in_len[1] = (unsigned char)( rec.data_len );
+
return( 0 );
}
@@ -7892,9 +8049,8 @@
static void ssl_update_in_pointers( mbedtls_ssl_context *ssl )
{
/* This function sets the pointers to match the case
- * of unprotected TLS/DTLS records, with both ssl->in_iv
- * and ssl->in_msg pointing to the beginning of the record
- * content.
+ * of unprotected TLS/DTLS records, with ssl->in_msg
+ * pointing to the beginning of the record content.
*
* When decrypting a protected record, ssl->in_msg
* will be shifted to point to the beginning of the
@@ -7915,7 +8071,7 @@
#else /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
ssl->in_len = ssl->in_ctr + 8;
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
- ssl->in_iv = ssl->in_len + 2;
+ ssl->in_msg = ssl->in_len + 2;
}
MBEDTLS_SSL_TRANSPORT_ELSE
#endif /* MBEDTLS_SSL_PROTO_DTLS */
@@ -7926,12 +8082,9 @@
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
ssl->in_cid = ssl->in_len;
#endif
- ssl->in_iv = ssl->in_hdr + 5;
+ ssl->in_msg = ssl->in_hdr + 5;
}
#endif /* MBEDTLS_SSL_PROTO_TLS */
-
- /* This will be adjusted at record decryption time. */
- ssl->in_msg = ssl->in_iv;
}
/*
@@ -8020,7 +8173,6 @@
ssl->in_hdr = NULL;
ssl->in_ctr = NULL;
ssl->in_len = NULL;
- ssl->in_iv = NULL;
ssl->in_msg = NULL;
ssl->out_hdr = NULL;
diff --git a/library/x509_crt.c b/library/x509_crt.c
index 4e5ff43..0c158f8 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -743,11 +743,8 @@
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
return( MBEDTLS_ERR_X509_INVALID_DATE + ret );
- end = *p + len;
-
- if( *p != end )
- return( MBEDTLS_ERR_X509_INVALID_DATE +
- MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
+ /* skip contents of the sequence */
+ *p += len;
return( 0 );
}
@@ -2975,10 +2972,10 @@
#if !defined(MBEDTLS_X509_CRT_REMOVE_TIME)
if( !mbedtls_x509_time_is_past( &parent->valid_to ) &&
!mbedtls_x509_time_is_future( &parent->valid_from ) )
+#endif /* !MBEDTLS_X509_CRT_REMOVE_TIME */
{
parent_valid = 1;
}
-#endif /* !MBEDTLS_X509_CRT_REMOVE_TIME */
/* basic parenting skills (name, CA bit, key usage) */
if( x509_crt_check_parent( child_sig, parent, top ) == 0 )
diff --git a/programs/Makefile b/programs/Makefile
index d09949b..9b01e45 100644
--- a/programs/Makefile
+++ b/programs/Makefile
@@ -298,8 +298,9 @@
rm -f $(APPS)
-rm -f ssl/ssl_pthread_server$(EXEXT)
-rm -f test/cpp_dummy_build$(EXEXT)
+ -rm -f *.su
else
- del /S /Q /F *.o *.exe
+ del /S /Q /F *.o *.su *.exe
endif
list:
diff --git a/programs/ssl/dtls_server.c b/programs/ssl/dtls_server.c
index f2dcd2f..84b905d 100644
--- a/programs/ssl/dtls_server.c
+++ b/programs/ssl/dtls_server.c
@@ -305,8 +305,15 @@
goto exit;
}
+#if !defined(MBEDTLS_SSL_CONF_RECV) && \
+ !defined(MBEDTLS_SSL_CONF_SEND) && \
+ !defined(MBEDTLS_SSL_CONF_RECV_TIMEOUT)
mbedtls_ssl_set_bio( &ssl, &client_fd,
- mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout );
+ mbedtls_net_send, mbedtls_net_recv,
+ mbedtls_net_recv_timeout );
+#else
+ mbedtls_ssl_set_bio_ctx( &ssl, &client_fd );
+#endif
printf( " ok\n" );
diff --git a/programs/ssl/ssl_client1.c b/programs/ssl/ssl_client1.c
index 2554946..5f453dc 100644
--- a/programs/ssl/ssl_client1.c
+++ b/programs/ssl/ssl_client1.c
@@ -196,7 +196,14 @@
goto exit;
}
- mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL );
+#if !defined(MBEDTLS_SSL_CONF_RECV) && \
+ !defined(MBEDTLS_SSL_CONF_SEND) && \
+ !defined(MBEDTLS_SSL_CONF_RECV_TIMEOUT)
+ mbedtls_ssl_set_bio( &ssl, &server_fd,
+ mbedtls_net_send, mbedtls_net_recv, NULL );
+#else
+ mbedtls_ssl_set_bio_ctx( &ssl, &server_fd );
+#endif
/*
* 4. Handshake
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index f6bdc56..716263b 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -524,9 +524,6 @@
first_try = 1; /* Next call will be a new operation */
return( ret );
}
-#endif /* MBEDTLS_SSL_CONF_RECV &&
- MBEDTLS_SSL_CONF_SEND &&
- MBEDTLS_SSL_CONF_RECV_TIMEOUT */
typedef struct
{
@@ -658,6 +655,9 @@
return( mbedtls_net_send( io_ctx->net, buf, len ) );
}
+#endif /* !MBEDTLS_SSL_CONF_RECV &&
+ !MBEDTLS_SSL_CONF_SEND &&
+ !MBEDTLS_SSL_CONF_RECV_TIMEOUT */
#if defined(MBEDTLS_X509_CRT_PARSE_C)
static unsigned char peer_crt_info[1024];
@@ -893,7 +893,11 @@
{
int ret = 0, len, tail_len, i, written, frags, retry_left;
mbedtls_net_context server_fd;
+#if !defined(MBEDTLS_SSL_CONF_RECV) && \
+ !defined(MBEDTLS_SSL_CONF_SEND) && \
+ !defined(MBEDTLS_SSL_CONF_RECV_TIMEOUT)
io_ctx_t io_ctx;
+#endif
unsigned char buf[MAX_REQUEST_SIZE + 1];
@@ -2681,8 +2685,14 @@
goto exit;
}
+#if !defined(MBEDTLS_SSL_CONF_RECV) && \
+ !defined(MBEDTLS_SSL_CONF_SEND) && \
+ !defined(MBEDTLS_SSL_CONF_RECV_TIMEOUT)
mbedtls_ssl_set_bio( &ssl, &io_ctx, send_cb, recv_cb,
opt.nbio == 0 ? recv_timeout_cb : NULL );
+#else
+ mbedtls_ssl_set_bio_ctx( &ssl, &server_fd );
+#endif
#if defined(MBEDTLS_TIMING_C)
#if !defined(MBEDTLS_SSL_CONF_SET_TIMER) && \
diff --git a/programs/ssl/ssl_fork_server.c b/programs/ssl/ssl_fork_server.c
index c716ca9..098761c 100644
--- a/programs/ssl/ssl_fork_server.c
+++ b/programs/ssl/ssl_fork_server.c
@@ -300,7 +300,14 @@
goto exit;
}
- mbedtls_ssl_set_bio( &ssl, &client_fd, mbedtls_net_send, mbedtls_net_recv, NULL );
+#if !defined(MBEDTLS_SSL_CONF_RECV) && \
+ !defined(MBEDTLS_SSL_CONF_SEND) && \
+ !defined(MBEDTLS_SSL_CONF_RECV_TIMEOUT)
+ mbedtls_ssl_set_bio( &ssl, &client_fd,
+ mbedtls_net_send, mbedtls_net_recv, NULL );
+#else
+ mbedtls_ssl_set_bio_ctx( &ssl, &client_fd );
+#endif
mbedtls_printf( "pid %d: SSL setup ok\n", pid );
diff --git a/programs/ssl/ssl_mail_client.c b/programs/ssl/ssl_mail_client.c
index 11b682c..b2e4f7f 100644
--- a/programs/ssl/ssl_mail_client.c
+++ b/programs/ssl/ssl_mail_client.c
@@ -649,7 +649,14 @@
goto exit;
}
- mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL );
+#if !defined(MBEDTLS_SSL_CONF_RECV) && \
+ !defined(MBEDTLS_SSL_CONF_SEND) && \
+ !defined(MBEDTLS_SSL_CONF_RECV_TIMEOUT)
+ mbedtls_ssl_set_bio( &ssl, &server_fd,
+ mbedtls_net_send, mbedtls_net_recv, NULL );
+#else
+ mbedtls_ssl_set_bio_ctx( &ssl, &server_fd );
+#endif
mbedtls_printf( " ok\n" );
diff --git a/programs/ssl/ssl_pthread_server.c b/programs/ssl/ssl_pthread_server.c
index 6ce4faa..fd6ca26 100644
--- a/programs/ssl/ssl_pthread_server.c
+++ b/programs/ssl/ssl_pthread_server.c
@@ -149,7 +149,14 @@
goto thread_exit;
}
- mbedtls_ssl_set_bio( &ssl, client_fd, mbedtls_net_send, mbedtls_net_recv, NULL );
+#if !defined(MBEDTLS_SSL_CONF_RECV) && \
+ !defined(MBEDTLS_SSL_CONF_SEND) && \
+ !defined(MBEDTLS_SSL_CONF_RECV_TIMEOUT)
+ mbedtls_ssl_set_bio( &ssl, &client_fd,
+ mbedtls_net_send, mbedtls_net_recv, NULL );
+#else
+ mbedtls_ssl_set_bio_ctx( &ssl, &client_fd );
+#endif
/*
* 5. Handshake
diff --git a/programs/ssl/ssl_server.c b/programs/ssl/ssl_server.c
index 849c14d..bf502a5 100644
--- a/programs/ssl/ssl_server.c
+++ b/programs/ssl/ssl_server.c
@@ -265,7 +265,14 @@
goto exit;
}
- mbedtls_ssl_set_bio( &ssl, &client_fd, mbedtls_net_send, mbedtls_net_recv, NULL );
+#if !defined(MBEDTLS_SSL_CONF_RECV) && \
+ !defined(MBEDTLS_SSL_CONF_SEND) && \
+ !defined(MBEDTLS_SSL_CONF_RECV_TIMEOUT)
+ mbedtls_ssl_set_bio( &ssl, &client_fd,
+ mbedtls_net_send, mbedtls_net_recv, NULL );
+#else
+ mbedtls_ssl_set_bio_ctx( &ssl, &client_fd );
+#endif
mbedtls_printf( " ok\n" );
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index 2cd00fa..3fa2b15 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -654,9 +654,6 @@
first_try = 1; /* Next call will be a new operation */
return( ret );
}
-#endif /* MBEDTLS_SSL_CONF_RECV &&
- MBEDTLS_SSL_CONF_SEND &&
- MBEDTLS_SSL_CONF_RECV_TIMEOUT */
typedef struct
{
@@ -790,8 +787,11 @@
return( mbedtls_net_send( io_ctx->net, buf, len ) );
}
+#endif /* !MBEDTLS_SSL_CONF_RECV &&
+ !MBEDTLS_SSL_CONF_SEND &&
+ !MBEDTLS_SSL_CONF_RECV_TIMEOUT */
-#if !defined(MBEDTLS_SSL_CONF_AUTHMODE)
+#if defined(SNI_OPTION) || !defined(MBEDTLS_SSL_CONF_AUTHMODE)
/*
* Return authmode from string, or -1 on error
*/
@@ -806,7 +806,7 @@
return( -1 );
}
-#endif /* !MBEDTLS_SSL_CONF_AUTHMODE */
+#endif /* SNI_OPTION || !MBEDTLS_SSL_CONF_AUTHMODE */
/*
* Used by sni_parse and psk_parse to handle coma-separated lists
@@ -1509,7 +1509,11 @@
{
int ret = 0, len, written, frags, exchanges_left;
int version_suites[4][2];
+#if !defined(MBEDTLS_SSL_CONF_RECV) && \
+ !defined(MBEDTLS_SSL_CONF_SEND) && \
+ !defined(MBEDTLS_SSL_CONF_RECV_TIMEOUT)
io_ctx_t io_ctx;
+#endif
unsigned char* buf = 0;
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
unsigned char psk[MBEDTLS_PSK_MAX_LEN];
@@ -3714,12 +3718,19 @@
/*
* This illustrates the minimum amount of things you need to set
- * up, however you could set up much more if desired, for example
- * if you want to share your set up code between the case of
- * establishing a new connection and this case.
+ * up: I/O and timer callbacks/contexts; however you could set up
+ * much more if desired, for example if you want to share your set
+ * up code between the case of establishing a new connection and
+ * this case.
*/
+#if !defined(MBEDTLS_SSL_CONF_RECV) && \
+ !defined(MBEDTLS_SSL_CONF_SEND) && \
+ !defined(MBEDTLS_SSL_CONF_RECV_TIMEOUT)
mbedtls_ssl_set_bio( &ssl, &io_ctx, send_cb, recv_cb,
opt.nbio == 0 ? recv_timeout_cb : NULL );
+#else
+ mbedtls_ssl_set_bio_ctx( &ssl, &client_fd );
+#endif
#if defined(MBEDTLS_TIMING_C)
#if !defined(MBEDTLS_SSL_CONF_SET_TIMER) && \
diff --git a/programs/test/cpp_dummy_build.cpp b/programs/test/cpp_dummy_build.cpp
index c652884..3c9c278 100644
--- a/programs/test/cpp_dummy_build.cpp
+++ b/programs/test/cpp_dummy_build.cpp
@@ -97,6 +97,7 @@
#include "mbedtls/timing.h"
#include "mbedtls/version.h"
#include "mbedtls/x509.h"
+#include "mbedtls/x509_internal.h"
#include "mbedtls/x509_crl.h"
#include "mbedtls/x509_crt.h"
#include "mbedtls/x509_csr.h"
diff --git a/programs/x509/cert_app.c b/programs/x509/cert_app.c
index 0656ce7..cdd77f2 100644
--- a/programs/x509/cert_app.c
+++ b/programs/x509/cert_app.c
@@ -441,7 +441,14 @@
goto ssl_exit;
}
- mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL );
+#if !defined(MBEDTLS_SSL_CONF_RECV) && \
+ !defined(MBEDTLS_SSL_CONF_SEND) && \
+ !defined(MBEDTLS_SSL_CONF_RECV_TIMEOUT)
+ mbedtls_ssl_set_bio( &ssl, &server_fd,
+ mbedtls_net_send, mbedtls_net_recv, NULL );
+#else
+ mbedtls_ssl_set_bio_ctx( &ssl, &server_fd );
+#endif
/*
* 4. Handshake
diff --git a/scripts/baremetal.sh b/scripts/baremetal.sh
index 2fd8b6c..813307a 100755
--- a/scripts/baremetal.sh
+++ b/scripts/baremetal.sh
@@ -214,6 +214,9 @@
make clean
CFLAGS="$BASE_CFLAGS $CFLAGS_CONFIG $CFLAGS_USER_CONFIG"
+ if [ "$build_only" -eq 1 ]; then
+ CFLAGS="$CFLAGS -Werror"
+ fi
echo "Modifications: $BAREMETAL_USER_CONFIG"
cat $BAREMETAL_USER_CONFIG | grep "^#define" | awk '{print "* " $0 }'
@@ -338,7 +341,7 @@
}
show_usage() {
- echo "Usage: $0 [--rom [--check] [--gcc] [--armc5] [--armc6]|--ram [--stack] [--heap]]"
+ echo "Usage: $0 [--rom [--check] [--gcc] [--armc5] [--armc6]|--ram [--build-only] [--stack] [--heap]]"
}
test_build=0
@@ -352,7 +355,7 @@
measure_stack=0
check=0
-
+build_only=0
debug=0
while [ $# -gt 0 ]; do
@@ -362,6 +365,7 @@
--armc6) build_armc6=1;;
--ram) test_build=1;;
--rom) raw_build=1;;
+ --build-only) build_only=1;;
--heap) measure_heap=1;;
--stack) measure_stack=1;;
--check) check=1;;
@@ -385,8 +389,9 @@
if [ "$test_build" -eq 1 ]; then
if [ "$measure_heap" -eq 0 ] &&
- [ "$measure_stack" -eq 0 ]; then
- echo "Need to set either --heap or --stack with --ram"
+ [ "$measure_stack" -eq 0 ] &&
+ [ "$build_only" -eq 0 ]; then
+ echo "Need to set either --build-only, --heap or --stack with --ram"
show_usage
exit 1
fi
diff --git a/tests/Makefile b/tests/Makefile
index 0db4963..20a3fe4 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -114,9 +114,9 @@
clean:
ifndef WINDOWS
- rm -rf $(BINARIES) *.c *.datax TESTS
+ rm -rf $(BINARIES) *.c *.su *.datax TESTS
else
- del /Q /F *.c *.exe *.datax
+ del /Q /F *.c *.su *.exe *.datax
ifneq ($(wildcard TESTS/.*),)
rmdir /Q /S TESTS
endif
diff --git a/tests/compat.sh b/tests/compat.sh
index 0eae1ea..80c2d31 100755
--- a/tests/compat.sh
+++ b/tests/compat.sh
@@ -15,6 +15,10 @@
set -u
+# Limit the size of each log to 10 GiB, in case of failures with this script
+# where it may output seemingly unlimited length error logs.
+ulimit -f 20971520
+
# initialise counters
TESTS=0
FAILED=0
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index a77fe13..2415cdd 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -792,6 +792,84 @@
if_build_succeeded tests/ssl-opt.sh -f '^Default$\|^Default, DTLS$'
}
+component_test_hardcoded_version_cmake_clang() {
+ msg "build: cmake, full config + hardcoded version, clang" # ~ 50s
+ scripts/config.pl full
+ scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE
+ scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
+ scripts/config.pl set MBEDTLS_SSL_CONF_MIN_MINOR_VER MBEDTLS_SSL_MINOR_VERSION_3
+ scripts/config.pl set MBEDTLS_SSL_CONF_MAX_MINOR_VER MBEDTLS_SSL_MINOR_VERSION_3
+ scripts/config.pl set MBEDTLS_SSL_CONF_MIN_MAJOR_VER MBEDTLS_SSL_MAJOR_VERSION_3
+ scripts/config.pl set MBEDTLS_SSL_CONF_MAX_MAJOR_VER MBEDTLS_SSL_MAJOR_VERSION_3
+ CC=clang cmake -D LINK_WITH_PTHREAD=1 -D CMAKE_BUILD_TYPE:String=ASanDbg -D ENABLE_TESTING=On .
+ make
+
+ msg "test: main suites (full config + hardcoded version)" # ~ 5s
+ make test
+
+ msg "test: ssl-opt.sh default (full config + hardcoded version)" # ~ 5s
+ if_build_succeeded tests/ssl-opt.sh -f '^Default$\|^Default, DTLS$'
+}
+
+component_test_hardcoded_io_callbacks_cmake_clang() {
+ msg "build: cmake, full config + hardcoded IO callbacks, clang" # ~ 50s
+ scripts/config.pl full
+ scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE
+ scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
+ scripts/config.pl set MBEDTLS_SSL_CONF_RECV mbedtls_net_recv
+ scripts/config.pl set MBEDTLS_SSL_CONF_SEND mbedtls_net_send
+ scripts/config.pl set MBEDTLS_SSL_CONF_RECV_TIMEOUT mbedtls_net_recv_timeout
+ CC=clang cmake -D LINK_WITH_PTHREAD=1 -D CMAKE_BUILD_TYPE:String=ASanDbg -D ENABLE_TESTING=On .
+ make
+
+ msg "test: main suites (full config + hardcoded IO callbacks)" # ~ 5s
+ make test
+
+ msg "test: ssl-opt.sh default (full config + hardcoded IO callbacks)" # ~ 5s
+ if_build_succeeded tests/ssl-opt.sh -f '^Default$\|^Default, DTLS$'
+}
+
+component_test_hardcoded_misc_options_cmake_clang() {
+ msg "build: cmake, full config + hardcode various SSL config options, clang" # ~ 50s
+ scripts/config.pl full
+ scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE
+ scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
+ scripts/config.pl set MBEDTLS_SSL_CONF_READ_TIMEOUT 0
+ scripts/config.pl set MBEDTLS_SSL_CONF_HS_TIMEOUT_MIN MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN
+ scripts/config.pl set MBEDTLS_SSL_CONF_HS_TIMEOUT_MAX MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX
+ scripts/config.pl set MBEDTLS_SSL_CONF_CERT_REQ_CA_LIST MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED
+ scripts/config.pl set MBEDTLS_SSL_CONF_ANTI_REPLAY MBEDTLS_SSL_ANTI_REPLAY_ENABLED
+ scripts/config.pl set MBEDTLS_SSL_CONF_BADMAC_LIMIT 0
+ scripts/config.pl set MBEDTLS_SSL_CONF_AUTHMODE MBEDTLS_SSL_VERIFY_REQUIRED
+ scripts/config.pl set MBEDTLS_SSL_CONF_ALLOW_LEGACY_RENEGOTIATION MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION
+ CC=clang cmake -D LINK_WITH_PTHREAD=1 -D CMAKE_BUILD_TYPE:String=ASanDbg -D ENABLE_TESTING=On .
+ make
+
+ msg "test: main suites (full config + hardcode various SSL config options)" # ~ 5s
+ make test
+
+ msg "test: ssl-opt.sh default (full config + hardcode various SSL config options)" # ~ 5s
+ if_build_succeeded tests/ssl-opt.sh -f '^Default$\|^Default, DTLS$'
+}
+
+component_test_hardcoded_elliptic_curve_cmake_clang() {
+ msg "build: cmake, full config + hardcode elliptic curve, clang" # ~ 50s
+ scripts/config.pl full
+ scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE
+ scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
+ scripts/config.pl set MBEDTLS_SSL_CONF_SINGLE_EC
+ scripts/config.pl set MBEDTLS_SSL_CONF_SINGLE_EC_GRP_ID MBEDTLS_ECP_DP_SECP256R1
+ scripts/config.pl set MBEDTLS_SSL_CONF_SINGLE_EC_TLS_ID 23
+ CC=clang cmake -D LINK_WITH_PTHREAD=1 -D CMAKE_BUILD_TYPE:String=ASanDbg -D ENABLE_TESTING=On .
+ make
+
+ msg "test: main suites (full config + hardcode elliptic curve)" # ~ 5s
+ make test
+
+ msg "test: ssl-opt.sh default (full config + hardcode elliptic curve)" # ~ 5s
+ if_build_succeeded tests/ssl-opt.sh -f '^Default$\|^Default, DTLS$'
+}
+
component_build_deprecated () {
msg "build: make, full config + DEPRECATED_WARNING, gcc -O" # ~ 30s
scripts/config.pl full
@@ -1263,11 +1341,20 @@
}
# need _armcc in the name for pre_check_tools()
-component_build_baremetal_script_gcc_armcc () {
+component_build_baremetal_raw_armcc () {
msg "build: scripts/baremetal.sh gcc/armc5/armc6"
scripts/baremetal.sh --rom --gcc --armc5 --armc6 --check
}
+component_test_baremetal () {
+ msg "build: lib+test+programs for baremetal.h + baremetal_test.h"
+ record_status scripts/baremetal.sh --ram --build-only
+
+ msg "test: baremetal.h + baremetal_test.h"
+ if_build_succeeded make test
+ if_build_succeeded tests/ssl-opt.sh --filter "^Default, DTLS$"
+}
+
component_build_armcc_tinycrypt_baremetal () {
msg "build: ARM Compiler 5, make with tinycrypt and baremetal"
scripts/config.pl baremetal
diff --git a/tests/scripts/mbedtls_test.py b/tests/scripts/mbedtls_test.py
index ac2912d..6ac68a4 100755
--- a/tests/scripts/mbedtls_test.py
+++ b/tests/scripts/mbedtls_test.py
@@ -79,7 +79,7 @@
split_colon_fn = lambda x: re.sub(r'\\' + split_char, split_char, x)
if len(split_char) > 1:
raise ValueError('Expected split character. Found string!')
- out = map(split_colon_fn, re.split(r'(?<!\\)' + split_char, inp_str))
+ out = list(map(split_colon_fn, re.split(r'(?<!\\)' + split_char, inp_str)))
out = [x for x in out if x]
return out
@@ -99,11 +99,11 @@
# Check dependencies
dependencies = []
- line = data_f.next().strip()
+ line = next(data_f).strip()
match = re.search('depends_on:(.*)', line)
if match:
dependencies = [int(x) for x in match.group(1).split(':')]
- line = data_f.next().strip()
+ line = next(data_f).strip()
# Read test vectors
line = line.replace('\\n', '\n')
@@ -115,7 +115,7 @@
err_str_fmt = "Number of test arguments({}) should be even: {}"
raise TestDataParserError(err_str_fmt.format(args_count, line))
grouped_args = [(args[i * 2], args[(i * 2) + 1])
- for i in range(len(args)/2)]
+ for i in range(int(len(args)/2))]
self.tests.append((name, function_name, dependencies,
grouped_args))
@@ -261,21 +261,21 @@
data_bytes += bytearray([function_id, len(parameters)])
for typ, param in parameters:
if typ == 'int' or typ == 'exp':
- i = int(param)
- data_bytes += 'I' if typ == 'int' else 'E'
+ i = int(param, 0)
+ data_bytes += b'I' if typ == 'int' else b'E'
self.align_32bit(data_bytes)
data_bytes += self.int32_to_big_endian_bytes(i)
elif typ == 'char*':
param = param.strip('"')
i = len(param) + 1 # + 1 for null termination
- data_bytes += 'S'
+ data_bytes += b'S'
self.align_32bit(data_bytes)
data_bytes += self.int32_to_big_endian_bytes(i)
- data_bytes += bytearray(list(param))
- data_bytes += '\0' # Null terminate
+ data_bytes += bytearray(param, encoding='ascii')
+ data_bytes += b'\0' # Null terminate
elif typ == 'hex':
binary_data = self.hex_str_bytes(param)
- data_bytes += 'H'
+ data_bytes += b'H'
self.align_32bit(data_bytes)
i = len(binary_data)
data_bytes += self.int32_to_big_endian_bytes(i)
@@ -310,7 +310,7 @@
param_bytes, length = self.test_vector_to_bytes(function_id,
dependencies, args)
- self.send_kv(length, param_bytes)
+ self.send_kv(''.join('{:02x}'.format(x) for x in length), ''.join('{:02x}'.format(x) for x in param_bytes))
@staticmethod
def get_result(value):
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index 1ea58df..5ad73d6 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -21,6 +21,10 @@
set -u
+# Limit the size of each log to 10 GiB, in case of failures with this script
+# where it may output seemingly unlimited length error logs.
+ulimit -f 20971520
+
if cd $( dirname $0 ); then :; else
echo "cd $( dirname $0 ) failed" >&2
exit 1
@@ -7872,8 +7876,10 @@
0 \
-C "replayed record" \
-S "replayed record" \
- -C "record from another epoch" \
- -S "record from another epoch" \
+ -C "Buffer record from epoch" \
+ -S "Buffer record from epoch" \
+ -C "ssl_buffer_message" \
+ -S "ssl_buffer_message" \
-C "discarding invalid record" \
-S "discarding invalid record" \
-S "resend" \
diff --git a/tests/suites/target_test.function b/tests/suites/target_test.function
index e4c3e30..d430d9d 100644
--- a/tests/suites/target_test.function
+++ b/tests/suites/target_test.function
@@ -59,10 +59,29 @@
return( DEPENDENCY_SUPPORTED );
}
+/**
+ * \brief Receives hex string on serial interface, and converts to a byte.
+ *
+ * \param none
+ *
+ * \return unsigned int8
+ */
+uint8_t receive_byte()
+{
+ uint8_t byte;
+ uint8_t c[3];
+ char *endptr;
+ c[0] = greentea_getc();
+ c[1] = greentea_getc();
+ c[2] = '\0';
+
+ assert( unhexify( &byte, c ) != 2 );
+ return( byte );
+}
/**
* \brief Receives unsigned integer on serial interface.
- * Integers are encoded in network order.
+ * Integers are encoded in network order, and sent as hex ascii string.
*
* \param none
*
@@ -71,10 +90,17 @@
uint32_t receive_uint32()
{
uint32_t value;
- value = (uint8_t)greentea_getc() << 24;
- value |= (uint8_t)greentea_getc() << 16;
- value |= (uint8_t)greentea_getc() << 8;
- value |= (uint8_t)greentea_getc();
+ const uint8_t c[9] = { greentea_getc(),
+ greentea_getc(),
+ greentea_getc(),
+ greentea_getc(),
+ greentea_getc(),
+ greentea_getc(),
+ greentea_getc(),
+ greentea_getc(),
+ '\0'
+ };
+ assert( unhexify( &value, c ) != 8 );
return( (uint32_t)value );
}
@@ -132,7 +158,7 @@
greentea_getc(); // read ';' received after key i.e. *data_len
for( i = 0; i < *data_len; i++ )
- data[i] = greentea_getc();
+ data[i] = receive_byte();
/* Read closing braces */
for( i = 0; i < 2; i++ )