mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2025-07-30 22:43:08 +03:00
Test split, coalesced-split and empty handshake records
Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
This commit is contained in:
committed by
Manuel Pégourié-Gonnard
parent
92122edf4b
commit
7c1dbeff49
@ -3699,6 +3699,7 @@ static int ssl_parse_record_header(mbedtls_ssl_context const *ssl,
|
|||||||
rec->buf_len = rec->data_offset + rec->data_len;
|
rec->buf_len = rec->data_offset + rec->data_len;
|
||||||
|
|
||||||
if (rec->data_len == 0) {
|
if (rec->data_len == 0) {
|
||||||
|
MBEDTLS_SSL_DEBUG_MSG(1, ("rejecting empty record"));
|
||||||
return MBEDTLS_ERR_SSL_INVALID_RECORD;
|
return MBEDTLS_ERR_SSL_INVALID_RECORD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,9 +108,100 @@ static void resize_buffers(int mfl, int renegotiation, int legacy_renegotiation,
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
RECOMBINE_NOMINAL, /* param: ignored */
|
RECOMBINE_NOMINAL, /* param: ignored */
|
||||||
|
RECOMBINE_SPLIT_FIRST, /* param: offset of split (<=0 means from end) */
|
||||||
|
RECOMBINE_INSERT_EMPTY, /* param: offset (<0 means from end) */
|
||||||
RECOMBINE_COALESCE, /* param: min number of records */
|
RECOMBINE_COALESCE, /* param: min number of records */
|
||||||
|
RECOMBINE_COALESCE_SPLIT_ONCE, /* param: offset of split (<=0 means from end) */
|
||||||
|
RECOMBINE_COALESCE_SPLIT_ENDS, /* the hairiest one? param: offset, must be >0 */
|
||||||
} recombine_records_instruction_t;
|
} recombine_records_instruction_t;
|
||||||
|
|
||||||
|
/* Split the first record into two pieces of lengths offset and
|
||||||
|
* record_length-offset. If offset is zero or negative, count from the end of
|
||||||
|
* the record. */
|
||||||
|
static int recombine_split_first_record(mbedtls_test_ssl_buffer *buf,
|
||||||
|
int offset)
|
||||||
|
{
|
||||||
|
const size_t header_length = 5;
|
||||||
|
TEST_LE_U(header_length, buf->content_length);
|
||||||
|
size_t record_length = MBEDTLS_GET_UINT16_BE(buf->buffer, header_length - 2);
|
||||||
|
|
||||||
|
if (offset > 0) {
|
||||||
|
TEST_LE_S(offset, record_length);
|
||||||
|
} else {
|
||||||
|
TEST_LE_S(-offset, record_length);
|
||||||
|
offset = record_length + offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that we have room to insert a record header */
|
||||||
|
TEST_LE_U(buf->content_length + header_length, buf->capacity);
|
||||||
|
|
||||||
|
/* Make room for a record header */
|
||||||
|
size_t new_record_start = header_length + offset;
|
||||||
|
size_t new_content_start = new_record_start + header_length;
|
||||||
|
memmove(buf->buffer + new_content_start,
|
||||||
|
buf->buffer + new_record_start,
|
||||||
|
buf->content_length - new_record_start);
|
||||||
|
buf->content_length += header_length;
|
||||||
|
|
||||||
|
/* Construct a header for the new record based on the existing one */
|
||||||
|
memcpy(buf->buffer + new_record_start, buf->buffer, header_length);
|
||||||
|
MBEDTLS_PUT_UINT16_BE(record_length - offset,
|
||||||
|
buf->buffer, new_content_start - 2);
|
||||||
|
|
||||||
|
/* Adjust the length of the first record */
|
||||||
|
MBEDTLS_PUT_UINT16_BE(offset, buf->buffer, header_length - 2);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Insert an empty record at the given offset. If offset is negative,
|
||||||
|
* count from the end of the first record. */
|
||||||
|
static int recombine_insert_empty_record(mbedtls_test_ssl_buffer *buf,
|
||||||
|
int offset)
|
||||||
|
{
|
||||||
|
const size_t header_length = 5;
|
||||||
|
TEST_LE_U(header_length, buf->content_length);
|
||||||
|
size_t record_length = MBEDTLS_GET_UINT16_BE(buf->buffer, header_length - 2);
|
||||||
|
|
||||||
|
if (offset >= 0) {
|
||||||
|
TEST_LE_S(offset, record_length);
|
||||||
|
} else {
|
||||||
|
TEST_LE_S(-offset, record_length);
|
||||||
|
offset = record_length + offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that we have room to insert two record headers */
|
||||||
|
TEST_LE_U(buf->content_length + 2 * header_length, buf->capacity);
|
||||||
|
|
||||||
|
/* Make room for an empty record and a record header */
|
||||||
|
size_t empty_record_start = header_length + offset;
|
||||||
|
size_t empty_content_start = empty_record_start + header_length;
|
||||||
|
size_t tail_record_start = empty_content_start;
|
||||||
|
size_t tail_content_start = tail_record_start + header_length;
|
||||||
|
memmove(buf->buffer + tail_content_start,
|
||||||
|
buf->buffer + tail_record_start,
|
||||||
|
buf->content_length - tail_record_start);
|
||||||
|
buf->content_length += 2 * header_length;
|
||||||
|
|
||||||
|
/* Construct headers for the new records based on the existing one */
|
||||||
|
memcpy(buf->buffer + empty_record_start, buf->buffer, header_length);
|
||||||
|
MBEDTLS_PUT_UINT16_BE(0, buf->buffer, empty_content_start - 2);
|
||||||
|
memcpy(buf->buffer + tail_record_start, buf->buffer, header_length);
|
||||||
|
MBEDTLS_PUT_UINT16_BE(record_length - offset,
|
||||||
|
buf->buffer, tail_content_start - 2);
|
||||||
|
|
||||||
|
/* Adjust the length of the first record */
|
||||||
|
MBEDTLS_PUT_UINT16_BE(offset, buf->buffer, header_length - 2);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Coalesce TLS handshake records.
|
/* Coalesce TLS handshake records.
|
||||||
* DTLS is not supported.
|
* DTLS is not supported.
|
||||||
* Encrypted or authenticated handshake records are not supported.
|
* Encrypted or authenticated handshake records are not supported.
|
||||||
@ -179,6 +270,16 @@ static int recombine_records(mbedtls_test_ssl_endpoint *server,
|
|||||||
case RECOMBINE_NOMINAL:
|
case RECOMBINE_NOMINAL:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case RECOMBINE_SPLIT_FIRST:
|
||||||
|
ret = recombine_split_first_record(buf, param);
|
||||||
|
TEST_LE_S(0, ret);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RECOMBINE_INSERT_EMPTY:
|
||||||
|
ret = recombine_insert_empty_record(buf, param);
|
||||||
|
TEST_LE_S(0, ret);
|
||||||
|
break;
|
||||||
|
|
||||||
case RECOMBINE_COALESCE:
|
case RECOMBINE_COALESCE:
|
||||||
ret = recombine_coalesce_handshake_records(buf, param);
|
ret = recombine_coalesce_handshake_records(buf, param);
|
||||||
if (param == INT_MAX) {
|
if (param == INT_MAX) {
|
||||||
@ -188,6 +289,27 @@ static int recombine_records(mbedtls_test_ssl_endpoint *server,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case RECOMBINE_COALESCE_SPLIT_ONCE:
|
||||||
|
ret = recombine_coalesce_handshake_records(buf, INT_MAX);
|
||||||
|
/* Require at least two coalesced records, otherwise this
|
||||||
|
* doesn't lead to a meaningful test (use
|
||||||
|
* RECOMBINE_SPLIT_FIRST instead). */
|
||||||
|
TEST_LE_S(2, ret);
|
||||||
|
ret = recombine_split_first_record(buf, param);
|
||||||
|
TEST_LE_S(0, ret);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RECOMBINE_COALESCE_SPLIT_ENDS:
|
||||||
|
ret = recombine_coalesce_handshake_records(buf, INT_MAX);
|
||||||
|
/* Accept a single record, which will be split at both ends */
|
||||||
|
TEST_LE_S(1, ret);
|
||||||
|
TEST_LE_S(1, param);
|
||||||
|
ret = recombine_split_first_record(buf, -param);
|
||||||
|
TEST_LE_S(0, ret);
|
||||||
|
ret = recombine_split_first_record(buf, param);
|
||||||
|
TEST_LE_S(0, ret);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
TEST_FAIL("Instructions not understood");
|
TEST_FAIL("Instructions not understood");
|
||||||
}
|
}
|
||||||
|
@ -24,3 +24,91 @@ recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_COALESCE:INT_
|
|||||||
Recombine server flight 1: TLS 1.3, coalesce all
|
Recombine server flight 1: TLS 1.3, coalesce all
|
||||||
depends_on:MBEDTLS_SSL_PROTO_TLS1_3
|
depends_on:MBEDTLS_SSL_PROTO_TLS1_3
|
||||||
recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_3:RECOMBINE_COALESCE:INT_MAX:"<= handshake wrapup":"<= handshake wrapup":MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH:0
|
recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_3:RECOMBINE_COALESCE:INT_MAX:"<= handshake wrapup":"<= handshake wrapup":MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH:0
|
||||||
|
|
||||||
|
Recombine server flight 1: TLS 1.2, split first at 4
|
||||||
|
depends_on:MBEDTLS_SSL_PROTO_TLS1_2
|
||||||
|
recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_SPLIT_FIRST:4:"initial handshake fragment\: 4, 0..4 of":"<= handshake wrapup":MBEDTLS_SSL_HANDSHAKE_OVER:0
|
||||||
|
|
||||||
|
Recombine server flight 1: TLS 1.3, split first at 4
|
||||||
|
depends_on:MBEDTLS_SSL_PROTO_TLS1_3
|
||||||
|
recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_3:RECOMBINE_SPLIT_FIRST:4:"initial handshake fragment\: 4, 0..4 of":"<= handshake wrapup":MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH:0
|
||||||
|
|
||||||
|
Recombine server flight 1: TLS 1.2, split first at end-1
|
||||||
|
depends_on:MBEDTLS_SSL_PROTO_TLS1_2
|
||||||
|
recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_SPLIT_FIRST:-1:"subsequent handshake fragment\: 1,":"<= handshake wrapup":MBEDTLS_SSL_HANDSHAKE_OVER:0
|
||||||
|
|
||||||
|
Recombine server flight 1: TLS 1.3, split first at end-1
|
||||||
|
depends_on:MBEDTLS_SSL_PROTO_TLS1_3
|
||||||
|
recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_3:RECOMBINE_SPLIT_FIRST:-1:"subsequent handshake fragment\: 1,":"<= handshake wrapup":MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH:0
|
||||||
|
|
||||||
|
# The library doesn't support an initial handshake fragment that doesn't
|
||||||
|
# contain the full 4-byte handshake header.
|
||||||
|
Recombine server flight 1: TLS 1.2, split first at 3 (bad)
|
||||||
|
depends_on:MBEDTLS_SSL_PROTO_TLS1_2
|
||||||
|
recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_SPLIT_FIRST:3:"handshake message too short\: 3":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_INVALID_RECORD
|
||||||
|
|
||||||
|
Recombine server flight 1: TLS 1.3, split first at 3 (bad)
|
||||||
|
depends_on:MBEDTLS_SSL_PROTO_TLS1_3
|
||||||
|
recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_3:RECOMBINE_SPLIT_FIRST:3:"handshake message too short\: 3":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_INVALID_RECORD
|
||||||
|
|
||||||
|
Recombine server flight 1: TLS 1.2, split first at 2 (bad)
|
||||||
|
depends_on:MBEDTLS_SSL_PROTO_TLS1_2
|
||||||
|
recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_SPLIT_FIRST:2:"handshake message too short\: 2":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_INVALID_RECORD
|
||||||
|
|
||||||
|
Recombine server flight 1: TLS 1.3, split first at 2 (bad)
|
||||||
|
depends_on:MBEDTLS_SSL_PROTO_TLS1_3
|
||||||
|
recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_3:RECOMBINE_SPLIT_FIRST:2:"handshake message too short\: 2":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_INVALID_RECORD
|
||||||
|
|
||||||
|
Recombine server flight 1: TLS 1.2, split first at 1 (bad)
|
||||||
|
depends_on:MBEDTLS_SSL_PROTO_TLS1_2
|
||||||
|
recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_SPLIT_FIRST:1:"handshake message too short\: 1":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_INVALID_RECORD
|
||||||
|
|
||||||
|
Recombine server flight 1: TLS 1.3, split first at 1 (bad)
|
||||||
|
depends_on:MBEDTLS_SSL_PROTO_TLS1_3
|
||||||
|
recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_3:RECOMBINE_SPLIT_FIRST:1:"handshake message too short\: 1":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_INVALID_RECORD
|
||||||
|
|
||||||
|
Recombine server flight 1: TLS 1.2, insert empty record after first (bad)
|
||||||
|
depends_on:MBEDTLS_SSL_PROTO_TLS1_2
|
||||||
|
recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_SPLIT_FIRST:0:"rejecting empty record":"":MBEDTLS_SSL_SERVER_CERTIFICATE:MBEDTLS_ERR_SSL_INVALID_RECORD
|
||||||
|
|
||||||
|
Recombine server flight 1: TLS 1.3, insert empty record after first (bad)
|
||||||
|
depends_on:MBEDTLS_SSL_PROTO_TLS1_3
|
||||||
|
recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_3:RECOMBINE_SPLIT_FIRST:0:"rejecting empty record":"":MBEDTLS_SSL_ENCRYPTED_EXTENSIONS:MBEDTLS_ERR_SSL_INVALID_RECORD
|
||||||
|
|
||||||
|
Recombine server flight 1: TLS 1.2, insert empty record at start (bad)
|
||||||
|
depends_on:MBEDTLS_SSL_PROTO_TLS1_2
|
||||||
|
recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_INSERT_EMPTY:0:"rejecting empty record":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_INVALID_RECORD
|
||||||
|
|
||||||
|
Recombine server flight 1: TLS 1.3, insert empty record at start (bad)
|
||||||
|
depends_on:MBEDTLS_SSL_PROTO_TLS1_3
|
||||||
|
recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_3:RECOMBINE_INSERT_EMPTY:0:"rejecting empty record":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_INVALID_RECORD
|
||||||
|
|
||||||
|
Recombine server flight 1: TLS 1.2, insert empty record at 42 (bad)
|
||||||
|
depends_on:MBEDTLS_SSL_PROTO_TLS1_2
|
||||||
|
recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_INSERT_EMPTY:42:"rejecting empty record":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_INVALID_RECORD
|
||||||
|
|
||||||
|
Recombine server flight 1: TLS 1.3, insert empty record at 42 (bad)
|
||||||
|
depends_on:MBEDTLS_SSL_PROTO_TLS1_3
|
||||||
|
recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_3:RECOMBINE_INSERT_EMPTY:42:"rejecting empty record":"":MBEDTLS_SSL_SERVER_HELLO:MBEDTLS_ERR_SSL_INVALID_RECORD
|
||||||
|
|
||||||
|
# Since there is a single unencrypted handshake message in the first flight
|
||||||
|
# from the server, and the test code that recombines handshake records can only
|
||||||
|
# handle plaintext records, we can't have TLS 1.3 tests with coalesced
|
||||||
|
# handshake messages. Hence most coalesce-and-split test cases are 1.2-only.
|
||||||
|
|
||||||
|
Recombine server flight 1: TLS 1.2, coalesce and split at 4
|
||||||
|
depends_on:MBEDTLS_SSL_PROTO_TLS1_2
|
||||||
|
recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_COALESCE_SPLIT_ONCE:4:"initial handshake fragment\: 4, 0..4 of":"<= handshake wrapup":MBEDTLS_SSL_HANDSHAKE_OVER:0
|
||||||
|
|
||||||
|
# The last message of the first flight from the server is ServerHelloDone,
|
||||||
|
# which is an empty handshake message, i.e. of length 4. The library doesn't
|
||||||
|
# support fragmentation of a handshake message, so the last place where we
|
||||||
|
# can split the flight is 4+1 = 5 bytes before it ends, with 1 byte in the
|
||||||
|
# previous handshake message and 4 bytes of ServerHelloDone including header.
|
||||||
|
Recombine server flight 1: TLS 1.2, coalesce and split at end-5
|
||||||
|
depends_on:MBEDTLS_SSL_PROTO_TLS1_2
|
||||||
|
recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_COALESCE_SPLIT_ONCE:-5:"subsequent handshake fragment\: 5,":"<= handshake wrapup":MBEDTLS_SSL_HANDSHAKE_OVER:0
|
||||||
|
|
||||||
|
Recombine server flight 1: TLS 1.2, coalesce and split at both ends
|
||||||
|
depends_on:MBEDTLS_SSL_PROTO_TLS1_2
|
||||||
|
recombine_server_first_flight:MBEDTLS_SSL_VERSION_TLS1_2:RECOMBINE_COALESCE_SPLIT_ENDS:5:"subsequent handshake fragment\: 5,":"<= handshake wrapup":MBEDTLS_SSL_HANDSHAKE_OVER:0
|
||||||
|
Reference in New Issue
Block a user