mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2026-10-28 18:07:34 +08:00
Merge bf4df4203bb6e67059184d14d98a78d64782950d into 03e1438089654fb884ac48e0f3cd0049cfe2c102
This commit is contained in:
commit
f8539c4c31
13
ChangeLog.d/runtime-content-len.txt
Normal file
13
ChangeLog.d/runtime-content-len.txt
Normal file
@ -0,0 +1,13 @@
|
||||
Features
|
||||
* Add the MBEDTLS_SSL_RUNTIME_CONTENT_LEN option and the
|
||||
mbedtls_ssl_set_in_content_len() and mbedtls_ssl_set_out_content_len()
|
||||
functions to choose the maximum plaintext fragment length of each
|
||||
connection before mbedtls_ssl_setup(). An application that holds several
|
||||
connections can then size each one's I/O buffers for its own peer
|
||||
instead of for its most demanding peer. MBEDTLS_SSL_IN_CONTENT_LEN and
|
||||
MBEDTLS_SSL_OUT_CONTENT_LEN remain the upper bound, so the worst-case
|
||||
memory footprint is unchanged; enabling the option without calling
|
||||
either function changes nothing. Shrinking the incoming length can break
|
||||
against a conforming peer unless a maximum fragment length or
|
||||
record_size_limit extension is negotiated; see the documentation of
|
||||
mbedtls_ssl_set_in_content_len(). Fixes #4892.
|
||||
@ -844,10 +844,56 @@
|
||||
* When this option is enabled, the SSL buffer will be resized automatically
|
||||
* based on the negotiated maximum fragment length in each direction.
|
||||
*
|
||||
* This option shrinks the buffers only once a Maximum Fragment Length
|
||||
* negotiation has completed, so on its own it leaves the peak allocation of a
|
||||
* connection at the build-time maximum. If you want to bound the allocation
|
||||
* of a connection from the moment it is set up, see
|
||||
* MBEDTLS_SSL_RUNTIME_CONTENT_LEN. The two options may be enabled together;
|
||||
* that option describes how they combine.
|
||||
*
|
||||
* Requires: MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
|
||||
*/
|
||||
//#define MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH
|
||||
|
||||
/**
|
||||
* \def MBEDTLS_SSL_RUNTIME_CONTENT_LEN
|
||||
*
|
||||
* When this option is enabled, the maximum length of a plaintext fragment can
|
||||
* be set per connection, at runtime, with
|
||||
* mbedtls_ssl_set_in_content_len() and mbedtls_ssl_set_out_content_len().
|
||||
* The connection then allocates its I/O buffers from those lengths when it is
|
||||
* set up, so an application holding several connections can size each one for
|
||||
* its own peer instead of for its most demanding peer.
|
||||
*
|
||||
* MBEDTLS_SSL_IN_CONTENT_LEN and MBEDTLS_SSL_OUT_CONTENT_LEN keep their
|
||||
* present meaning as a hard upper bound: a connection may ask for less than
|
||||
* the compiled maximum, never for more. The worst-case build footprint is
|
||||
* therefore unchanged; only the runtime heap of a connection shrinks.
|
||||
*
|
||||
* Enabling this option without calling either setter changes nothing
|
||||
* observable: both lengths default to the corresponding build-time maximum.
|
||||
*
|
||||
* How this differs from MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH:
|
||||
* MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH shrinks the buffers automatically, once
|
||||
* a Maximum Fragment Length has been negotiated, so a connection still
|
||||
* allocates the build-time maximum while it is set up and handshaking.
|
||||
* MBEDTLS_SSL_RUNTIME_CONTENT_LEN bounds the allocation from
|
||||
* mbedtls_ssl_setup() onwards, at a length the application chooses, and does
|
||||
* not require MBEDTLS_SSL_MAX_FRAGMENT_LENGTH. In exchange, the peer learns
|
||||
* of a shrunk incoming length only through a negotiated extension; see
|
||||
* mbedtls_ssl_set_in_content_len() for what happens otherwise.
|
||||
*
|
||||
* The two options may be enabled together: the buffers of a connection then
|
||||
* start at its own lengths, may shrink further after a handshake to a
|
||||
* configured or negotiated Maximum Fragment Length, and grow back at the
|
||||
* start of each later handshake (renegotiation, or after
|
||||
* mbedtls_ssl_session_reset()) only as far as the connection's lengths, never
|
||||
* to the build-time maximum.
|
||||
*
|
||||
* Uncomment this macro to enable per-connection content lengths.
|
||||
*/
|
||||
//#define MBEDTLS_SSL_RUNTIME_CONTENT_LEN
|
||||
|
||||
//#define MBEDTLS_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 or 384 bits) */
|
||||
//#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */
|
||||
//#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */
|
||||
|
||||
@ -1584,6 +1584,20 @@ struct mbedtls_ssl_config {
|
||||
mbedtls_ssl_unused_data_t MBEDTLS_PRIVATE(unused);
|
||||
};
|
||||
|
||||
/**
|
||||
* \def MBEDTLS_SSL_HAVE_BUFFER_LEN_FIELDS
|
||||
*
|
||||
* Defined when an SSL context records the length of each of its I/O buffers,
|
||||
* because at least one enabled option lets a buffer be shorter than the
|
||||
* build-time maximum: #MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH shrinks it after a
|
||||
* Maximum Fragment Length negotiation, and #MBEDTLS_SSL_RUNTIME_CONTENT_LEN
|
||||
* allocates it short in the first place.
|
||||
*/
|
||||
#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) || \
|
||||
defined(MBEDTLS_SSL_RUNTIME_CONTENT_LEN)
|
||||
#define MBEDTLS_SSL_HAVE_BUFFER_LEN_FIELDS
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Warning: whenever a change is applied to "mbedtls_ssl_context" please re-run
|
||||
* the script "tests/scripts/generate_ssl_session_reset_check.py".
|
||||
@ -1721,9 +1735,12 @@ struct mbedtls_ssl_context {
|
||||
int MBEDTLS_PRIVATE(in_msgtype); /*!< record header: message type */
|
||||
size_t MBEDTLS_PRIVATE(in_msglen); /*!< record header: message length */
|
||||
size_t MBEDTLS_PRIVATE(in_left); /*!< amount of data read so far */
|
||||
#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
|
||||
#if defined(MBEDTLS_SSL_HAVE_BUFFER_LEN_FIELDS)
|
||||
size_t MBEDTLS_PRIVATE(in_buf_len); /*!< length of input buffer */
|
||||
#endif
|
||||
#if defined(MBEDTLS_SSL_RUNTIME_CONTENT_LEN)
|
||||
size_t MBEDTLS_PRIVATE(in_content_len); /*!< max incoming plaintext fragment */
|
||||
#endif
|
||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||
uint16_t MBEDTLS_PRIVATE(in_epoch); /*!< DTLS epoch for incoming records */
|
||||
size_t MBEDTLS_PRIVATE(next_record_offset); /*!< offset of the next record in datagram
|
||||
@ -1798,9 +1815,12 @@ struct mbedtls_ssl_context {
|
||||
int MBEDTLS_PRIVATE(out_msgtype); /*!< record header: message type */
|
||||
size_t MBEDTLS_PRIVATE(out_msglen); /*!< record header: message length */
|
||||
size_t MBEDTLS_PRIVATE(out_left); /*!< amount of data not yet written */
|
||||
#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
|
||||
#if defined(MBEDTLS_SSL_HAVE_BUFFER_LEN_FIELDS)
|
||||
size_t MBEDTLS_PRIVATE(out_buf_len); /*!< length of output buffer */
|
||||
#endif
|
||||
#if defined(MBEDTLS_SSL_RUNTIME_CONTENT_LEN)
|
||||
size_t MBEDTLS_PRIVATE(out_content_len); /*!< max outgoing plaintext fragment */
|
||||
#endif
|
||||
|
||||
unsigned char MBEDTLS_PRIVATE(cur_out_ctr)[MBEDTLS_SSL_SEQUENCE_NUMBER_LEN]; /*!< Outgoing record sequence number. */
|
||||
|
||||
@ -1942,6 +1962,11 @@ void mbedtls_ssl_init(mbedtls_ssl_context *ssl);
|
||||
*
|
||||
* \return 0 if successful, or #PSA_ERROR_INSUFFICIENT_MEMORY if
|
||||
* memory allocation failed
|
||||
* \return #MBEDTLS_ERR_SSL_BAD_CONFIG if \p conf is invalid, including,
|
||||
* for a client that may negotiate TLS 1.2, a maximum fragment
|
||||
* length configured with mbedtls_ssl_conf_max_frag_len()
|
||||
* longer than the length set with
|
||||
* mbedtls_ssl_set_in_content_len()
|
||||
*/
|
||||
int mbedtls_ssl_setup(mbedtls_ssl_context *ssl,
|
||||
const mbedtls_ssl_config *conf);
|
||||
@ -2388,6 +2413,95 @@ int mbedtls_ssl_get_peer_cid(mbedtls_ssl_context *ssl,
|
||||
void mbedtls_ssl_set_mtu(mbedtls_ssl_context *ssl, uint16_t mtu);
|
||||
#endif /* MBEDTLS_SSL_PROTO_DTLS */
|
||||
|
||||
#if defined(MBEDTLS_SSL_RUNTIME_CONTENT_LEN)
|
||||
/**
|
||||
* \brief Set the maximum length of a plaintext fragment that this
|
||||
* connection can receive.
|
||||
*
|
||||
* mbedtls_ssl_setup() sizes the input buffer from this
|
||||
* length, so a connection that asks for less than
|
||||
* #MBEDTLS_SSL_IN_CONTENT_LEN allocates less.
|
||||
*
|
||||
* \note This function is valid only after mbedtls_ssl_init() and
|
||||
* before mbedtls_ssl_setup(). It fails once
|
||||
* mbedtls_ssl_setup() has succeeded, and also once
|
||||
* mbedtls_ssl_setup() has rejected the configuration; free
|
||||
* and re-initialise the context to choose another length.
|
||||
* The length is kept across mbedtls_ssl_session_reset().
|
||||
*
|
||||
* \warning Nothing tells the peer about this length unless a
|
||||
* Maximum Fragment Length or record_size_limit no longer
|
||||
* than this length is negotiated. Otherwise a conforming peer
|
||||
* may send a record longer than this length. Over TLS, the
|
||||
* call that reads such a record fails: with
|
||||
* #MBEDTLS_ERR_SSL_INVALID_RECORD if the record still fits in
|
||||
* the input buffer, otherwise with
|
||||
* #MBEDTLS_ERR_SSL_BAD_INPUT_DATA. Over DTLS, the record is
|
||||
* discarded, so its data is lost. A build with
|
||||
* #MBEDTLS_SSL_IN_CONTENT_LEN set to the same length behaves
|
||||
* the same way.
|
||||
*
|
||||
* \warning A server in particular has no standardised way to
|
||||
* announce this length. Only a client requests a Maximum
|
||||
* Fragment Length, and it may request one longer than this
|
||||
* length; a TLS 1.3 server sends record_size_limit only if
|
||||
* the client offered it. Shrink the incoming length of a
|
||||
* server only when you know what its clients will send.
|
||||
*
|
||||
* \note With #MBEDTLS_SSL_RECORD_SIZE_LIMIT, a TLS 1.3 endpoint
|
||||
* advertises this length as its record_size_limit, so a
|
||||
* length below 64, the smallest limit RFC 8449 permits, makes
|
||||
* the handshake fail. A client that may negotiate TLS 1.2
|
||||
* must not configure a maximum fragment length with
|
||||
* mbedtls_ssl_conf_max_frag_len() longer than this length, or
|
||||
* mbedtls_ssl_setup() fails.
|
||||
*
|
||||
* \param ssl SSL context
|
||||
* \param len Maximum incoming plaintext fragment length in bytes.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if \p len is 0 or
|
||||
* exceeds #MBEDTLS_SSL_IN_CONTENT_LEN, or if called outside
|
||||
* the window described above.
|
||||
*/
|
||||
int mbedtls_ssl_set_in_content_len(mbedtls_ssl_context *ssl, size_t len);
|
||||
|
||||
/**
|
||||
* \brief Set the maximum length of a plaintext fragment that this
|
||||
* connection can send.
|
||||
*
|
||||
* mbedtls_ssl_setup() sizes the output buffer from this
|
||||
* length, so a connection that asks for less than
|
||||
* #MBEDTLS_SSL_OUT_CONTENT_LEN allocates less. Application
|
||||
* data longer than this length is treated as it is for a
|
||||
* negotiated maximum fragment length: over TLS,
|
||||
* mbedtls_ssl_write() sends only the first part of it, and
|
||||
* over DTLS, mbedtls_ssl_write() rejects it.
|
||||
*
|
||||
* \note This function is valid only after mbedtls_ssl_init() and
|
||||
* before mbedtls_ssl_setup(). It fails once
|
||||
* mbedtls_ssl_setup() has succeeded, and also once
|
||||
* mbedtls_ssl_setup() has rejected the configuration; free
|
||||
* and re-initialise the context to choose another length.
|
||||
* The length is kept across mbedtls_ssl_session_reset().
|
||||
*
|
||||
* \note The lower bound this function enforces, 12 bytes or the
|
||||
* TLS 1.3 padding granularity if larger, only keeps internal
|
||||
* size arithmetic sound. Whether a handshake fits depends on
|
||||
* the certificate chain, ciphersuites and extensions; a
|
||||
* length too short for them makes the handshake fail.
|
||||
*
|
||||
* \param ssl SSL context
|
||||
* \param len Maximum outgoing plaintext fragment length in bytes.
|
||||
*
|
||||
* \return 0 on success.
|
||||
* \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if \p len is below the
|
||||
* lower bound or exceeds #MBEDTLS_SSL_OUT_CONTENT_LEN, or if
|
||||
* called outside the window described above.
|
||||
*/
|
||||
int mbedtls_ssl_set_out_content_len(mbedtls_ssl_context *ssl, size_t len);
|
||||
#endif /* MBEDTLS_SSL_RUNTIME_CONTENT_LEN */
|
||||
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
/**
|
||||
* \brief Set a connection-specific verification callback (optional).
|
||||
@ -4687,7 +4801,8 @@ int mbedtls_ssl_get_record_expansion(const mbedtls_ssl_context *ssl);
|
||||
*
|
||||
* \note The logic to determine the maximum outgoing record payload is
|
||||
* version-specific. It takes into account various factors, such as
|
||||
* the mbedtls_config.h setting \c MBEDTLS_SSL_OUT_CONTENT_LEN, extensions
|
||||
* the mbedtls_config.h setting \c MBEDTLS_SSL_OUT_CONTENT_LEN or
|
||||
* the length set with \c mbedtls_ssl_set_out_content_len(), extensions
|
||||
* such as the max fragment length or record size limit extension if
|
||||
* used, and for DTLS the path MTU as configured and current
|
||||
* record expansion.
|
||||
@ -4714,7 +4829,8 @@ int mbedtls_ssl_get_max_out_record_payload(const mbedtls_ssl_context *ssl);
|
||||
*
|
||||
* \note The logic to determine the maximum incoming record payload is
|
||||
* version-specific. It takes into account various factors, such as
|
||||
* the mbedtls_config.h setting \c MBEDTLS_SSL_IN_CONTENT_LEN, extensions
|
||||
* the mbedtls_config.h setting \c MBEDTLS_SSL_IN_CONTENT_LEN or
|
||||
* the length set with \c mbedtls_ssl_set_in_content_len(), extensions
|
||||
* such as the max fragment length extension or record size limit
|
||||
* extension if used, and the current record expansion.
|
||||
*
|
||||
|
||||
@ -399,6 +399,185 @@ uint32_t mbedtls_ssl_get_extension_mask(unsigned int extension_type);
|
||||
+ (MBEDTLS_SSL_CID_OUT_LEN_MAX))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Smallest per-connection content lengths that
|
||||
* mbedtls_ssl_set_in_content_len() and mbedtls_ssl_set_out_content_len()
|
||||
* accept, under MBEDTLS_SSL_RUNTIME_CONTENT_LEN. These are not the smallest
|
||||
* lengths a handshake can succeed with, which depend on the
|
||||
* certificate chain, ciphersuite and extensions; they are the points below
|
||||
* which internal size arithmetic stops meaning anything.
|
||||
*
|
||||
* Incoming: nothing subtracts from the incoming length, so any non-zero
|
||||
* value is structurally sound. Keep this below
|
||||
* MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN, so that the runtime check in the TLS 1.3
|
||||
* record_size_limit writer stays reachable.
|
||||
*
|
||||
* Outgoing: 12 covers the DTLS handshake header, which the message layer
|
||||
* subtracts from the outgoing length, and with it the 7-byte handshake header
|
||||
* plus 3-byte length that precede the first certificate. With TLS 1.3 the
|
||||
* maximum outgoing record payload is rounded down to a multiple of the
|
||||
* padding granularity and then decremented, so the length must be at least
|
||||
* one granule.
|
||||
*
|
||||
* The documentation of both setters in ssl.h states these values; update it
|
||||
* if they change.
|
||||
*/
|
||||
#define MBEDTLS_SSL_IN_CONTENT_LEN_MIN 1
|
||||
|
||||
#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \
|
||||
MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY > 12
|
||||
#define MBEDTLS_SSL_OUT_CONTENT_LEN_MIN MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY
|
||||
#else
|
||||
#define MBEDTLS_SSL_OUT_CONTENT_LEN_MIN 12
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Get the maximum length, in bytes, of a plaintext fragment
|
||||
* that may be received on this connection.
|
||||
*
|
||||
* This is the single canonical way for the TLS code to ask
|
||||
* how large an incoming plaintext fragment may be. Without
|
||||
* #MBEDTLS_SSL_RUNTIME_CONTENT_LEN it is the build-time
|
||||
* maximum #MBEDTLS_SSL_IN_CONTENT_LEN; with that option it is
|
||||
* the per-connection length, which defaults to the build-time
|
||||
* maximum and can never exceed it.
|
||||
*
|
||||
* \param ssl SSL context
|
||||
*
|
||||
* \return The maximum incoming plaintext fragment length in bytes.
|
||||
*/
|
||||
static inline size_t mbedtls_ssl_get_in_content_len(const mbedtls_ssl_context *ssl)
|
||||
{
|
||||
#if defined(MBEDTLS_SSL_RUNTIME_CONTENT_LEN)
|
||||
return ssl->in_content_len;
|
||||
#else
|
||||
(void) ssl;
|
||||
return MBEDTLS_SSL_IN_CONTENT_LEN;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the maximum length, in bytes, of a plaintext fragment
|
||||
* that may be sent on this connection.
|
||||
*
|
||||
* This is the single canonical way for the TLS code to ask
|
||||
* how large an outgoing plaintext fragment may be. Without
|
||||
* #MBEDTLS_SSL_RUNTIME_CONTENT_LEN it is the build-time
|
||||
* maximum #MBEDTLS_SSL_OUT_CONTENT_LEN; with that option it is
|
||||
* the per-connection length, which defaults to the build-time
|
||||
* maximum and can never exceed it.
|
||||
*
|
||||
* \param ssl SSL context
|
||||
*
|
||||
* \return The maximum outgoing plaintext fragment length in bytes.
|
||||
*/
|
||||
static inline size_t mbedtls_ssl_get_out_content_len(const mbedtls_ssl_context *ssl)
|
||||
{
|
||||
#if defined(MBEDTLS_SSL_RUNTIME_CONTENT_LEN)
|
||||
return ssl->out_content_len;
|
||||
#else
|
||||
(void) ssl;
|
||||
return MBEDTLS_SSL_OUT_CONTENT_LEN;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the length, in bytes, of this connection's input buffer.
|
||||
*
|
||||
* Valid once the connection has been set up with
|
||||
* mbedtls_ssl_setup(); before that there is no buffer and the
|
||||
* return value is meaningless. Allocation, teardown, the
|
||||
* message-layer reset and the automatic-resize path must all
|
||||
* agree on this one value.
|
||||
*
|
||||
* \param ssl SSL context
|
||||
*
|
||||
* \return The length of \c ssl->in_buf in bytes.
|
||||
*/
|
||||
static inline size_t mbedtls_ssl_get_in_buf_len(const mbedtls_ssl_context *ssl)
|
||||
{
|
||||
#if defined(MBEDTLS_SSL_HAVE_BUFFER_LEN_FIELDS)
|
||||
return ssl->in_buf_len;
|
||||
#else
|
||||
(void) ssl;
|
||||
return MBEDTLS_SSL_IN_BUFFER_LEN;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the length, in bytes, of this connection's output
|
||||
* buffer.
|
||||
*
|
||||
* Valid once the connection has been set up with
|
||||
* mbedtls_ssl_setup(); before that there is no buffer and the
|
||||
* return value is meaningless. Allocation, teardown, the
|
||||
* message-layer reset and the automatic-resize path must all
|
||||
* agree on this one value.
|
||||
*
|
||||
* \param ssl SSL context
|
||||
*
|
||||
* \return The length of \c ssl->out_buf in bytes.
|
||||
*/
|
||||
static inline size_t mbedtls_ssl_get_out_buf_len(const mbedtls_ssl_context *ssl)
|
||||
{
|
||||
#if defined(MBEDTLS_SSL_HAVE_BUFFER_LEN_FIELDS)
|
||||
return ssl->out_buf_len;
|
||||
#else
|
||||
(void) ssl;
|
||||
return MBEDTLS_SSL_OUT_BUFFER_LEN;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Compute the input buffer length that holds a full-size
|
||||
* incoming record for this connection.
|
||||
*
|
||||
* This is what mbedtls_ssl_setup() allocates: the connection's
|
||||
* incoming content length plus the record header, the crypto
|
||||
* expansion and, where enabled, the maximum incoming
|
||||
* connection ID.
|
||||
*
|
||||
* \param ssl SSL context
|
||||
*
|
||||
* \return The required input buffer length in bytes.
|
||||
*/
|
||||
static inline size_t mbedtls_ssl_compute_in_buf_len(const mbedtls_ssl_context *ssl)
|
||||
{
|
||||
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
|
||||
return mbedtls_ssl_get_in_content_len(ssl)
|
||||
+ MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD
|
||||
+ MBEDTLS_SSL_CID_IN_LEN_MAX;
|
||||
#else
|
||||
return mbedtls_ssl_get_in_content_len(ssl)
|
||||
+ MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Compute the output buffer length that holds a full-size
|
||||
* outgoing record for this connection.
|
||||
*
|
||||
* This is what mbedtls_ssl_setup() allocates: the connection's
|
||||
* outgoing content length plus the record header, the crypto
|
||||
* expansion and, where enabled, the maximum outgoing
|
||||
* connection ID.
|
||||
*
|
||||
* \param ssl SSL context
|
||||
*
|
||||
* \return The required output buffer length in bytes.
|
||||
*/
|
||||
static inline size_t mbedtls_ssl_compute_out_buf_len(const mbedtls_ssl_context *ssl)
|
||||
{
|
||||
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
|
||||
return mbedtls_ssl_get_out_content_len(ssl)
|
||||
+ MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD
|
||||
+ MBEDTLS_SSL_CID_OUT_LEN_MAX;
|
||||
#else
|
||||
return mbedtls_ssl_get_out_content_len(ssl)
|
||||
+ MBEDTLS_SSL_HEADER_LEN + MBEDTLS_SSL_PAYLOAD_OVERHEAD;
|
||||
#endif
|
||||
}
|
||||
|
||||
#define MBEDTLS_CLIENT_HELLO_RANDOM_LEN 32
|
||||
#define MBEDTLS_SERVER_HELLO_RANDOM_LEN 32
|
||||
|
||||
@ -407,7 +586,8 @@ uint32_t mbedtls_ssl_get_extension_mask(unsigned int extension_type);
|
||||
* \brief Return the maximum fragment length (payload, in bytes) for
|
||||
* the output buffer. For the client, this is the configured
|
||||
* value. For the server, it is the minimum of two - the
|
||||
* configured value and the negotiated one.
|
||||
* configured value and the negotiated one. Either way it is
|
||||
* no more than the connection's outgoing content length.
|
||||
*
|
||||
* \sa mbedtls_ssl_conf_max_frag_len()
|
||||
* \sa mbedtls_ssl_get_max_out_record_payload()
|
||||
@ -421,9 +601,10 @@ size_t mbedtls_ssl_get_output_max_frag_len(const mbedtls_ssl_context *ssl);
|
||||
/**
|
||||
* \brief Return the maximum fragment length (payload, in bytes) for
|
||||
* the input buffer. This is the negotiated maximum fragment
|
||||
* length, or, if there is none, MBEDTLS_SSL_IN_CONTENT_LEN.
|
||||
* If it is not defined either, the value is 2^14. This function
|
||||
* works as its predecessor, \c mbedtls_ssl_get_max_frag_len().
|
||||
* length, or, if there is none, the connection's incoming
|
||||
* content length, and never more than the latter. This
|
||||
* function works as its predecessor,
|
||||
* \c mbedtls_ssl_get_max_frag_len().
|
||||
*
|
||||
* \sa mbedtls_ssl_conf_max_frag_len()
|
||||
* \sa mbedtls_ssl_get_max_in_record_payload()
|
||||
@ -2665,6 +2846,23 @@ int mbedtls_ssl_tls13_parse_record_size_limit_ext(mbedtls_ssl_context *ssl,
|
||||
const unsigned char *buf,
|
||||
const unsigned char *end);
|
||||
|
||||
/**
|
||||
* \brief Write the record_size_limit extension, advertising this
|
||||
* connection's maximum incoming plaintext fragment length.
|
||||
*
|
||||
* \param ssl SSL context
|
||||
* \param buf Start of the extension write buffer
|
||||
* \param end End of the extension write buffer
|
||||
* \param out_len On success, the number of bytes written
|
||||
*
|
||||
* \return \c 0 on success.
|
||||
* \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if the connection's
|
||||
* incoming content length is below
|
||||
* #MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN, leaving nothing valid
|
||||
* to advertise.
|
||||
* \return #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL if the write buffer is
|
||||
* too small for the extension.
|
||||
*/
|
||||
MBEDTLS_CHECK_RETURN_CRITICAL
|
||||
int mbedtls_ssl_tls13_write_record_size_limit_ext(mbedtls_ssl_context *ssl,
|
||||
unsigned char *buf,
|
||||
|
||||
@ -292,11 +292,7 @@ static int ssl_next_record_is_in_datagram(mbedtls_ssl_context *ssl);
|
||||
static size_t ssl_get_maximum_datagram_size(mbedtls_ssl_context const *ssl)
|
||||
{
|
||||
size_t mtu = mbedtls_ssl_get_current_mtu(ssl);
|
||||
#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
|
||||
size_t out_buf_len = ssl->out_buf_len;
|
||||
#else
|
||||
size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN;
|
||||
#endif
|
||||
size_t out_buf_len = mbedtls_ssl_get_out_buf_len(ssl);
|
||||
|
||||
if (mtu != 0 && mtu < out_buf_len) {
|
||||
return mtu;
|
||||
@ -326,7 +322,7 @@ static int ssl_get_remaining_payload_in_datagram(mbedtls_ssl_context const *ssl)
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
size_t remaining, expansion;
|
||||
size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN;
|
||||
size_t max_len = mbedtls_ssl_get_out_content_len(ssl);
|
||||
|
||||
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
|
||||
const size_t mfl = mbedtls_ssl_get_output_max_frag_len(ssl);
|
||||
@ -830,6 +826,13 @@ int mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl,
|
||||
MBEDTLS_SSL_DEBUG_BUF(4, "before encrypt: output payload",
|
||||
data, rec->data_len);
|
||||
|
||||
/* This is a sanity check against the build-time ceiling, not against this
|
||||
* connection's outgoing length: the ssl parameter is a debugging aid
|
||||
* here and is NULL when MBEDTLS_DEBUG_C is off, so it cannot be asked.
|
||||
* The per-connection bound is enforced before a record reaches this
|
||||
* point: mbedtls_ssl_write_handshake_msg_ext() rejects an over-long
|
||||
* handshake message, and application data is clamped to
|
||||
* mbedtls_ssl_get_max_out_record_payload(). */
|
||||
if (rec->data_len > MBEDTLS_SSL_OUT_CONTENT_LEN) {
|
||||
MBEDTLS_SSL_DEBUG_MSG(1, ("Record content %" MBEDTLS_PRINTF_SIZET
|
||||
" too large, maximum %" MBEDTLS_PRINTF_SIZET,
|
||||
@ -1856,11 +1859,7 @@ int mbedtls_ssl_fetch_input(mbedtls_ssl_context *ssl, size_t nb_want)
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
size_t len;
|
||||
#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
|
||||
size_t in_buf_len = ssl->in_buf_len;
|
||||
#else
|
||||
size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN;
|
||||
#endif
|
||||
size_t in_buf_len = mbedtls_ssl_get_in_buf_len(ssl);
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG(2, ("=> fetch input"));
|
||||
|
||||
@ -2453,7 +2452,7 @@ int mbedtls_ssl_start_handshake_msg(mbedtls_ssl_context *ssl, unsigned char hs_t
|
||||
* ...
|
||||
*/
|
||||
*buf = ssl->out_msg + 4;
|
||||
*buf_len = MBEDTLS_SSL_OUT_CONTENT_LEN - 4;
|
||||
*buf_len = mbedtls_ssl_get_out_content_len(ssl) - 4;
|
||||
|
||||
ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
|
||||
ssl->out_msg[0] = hs_type;
|
||||
@ -2528,12 +2527,12 @@ int mbedtls_ssl_write_handshake_msg_ext(mbedtls_ssl_context *ssl,
|
||||
*
|
||||
* Note: We deliberately do not check for the MTU or MFL here.
|
||||
*/
|
||||
if (ssl->out_msglen > MBEDTLS_SSL_OUT_CONTENT_LEN) {
|
||||
if (ssl->out_msglen > mbedtls_ssl_get_out_content_len(ssl)) {
|
||||
MBEDTLS_SSL_DEBUG_MSG(1, ("Record too large: "
|
||||
"size %" MBEDTLS_PRINTF_SIZET
|
||||
", maximum %" MBEDTLS_PRINTF_SIZET,
|
||||
ssl->out_msglen,
|
||||
(size_t) MBEDTLS_SSL_OUT_CONTENT_LEN));
|
||||
mbedtls_ssl_get_out_content_len(ssl)));
|
||||
return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
@ -2555,12 +2554,12 @@ int mbedtls_ssl_write_handshake_msg_ext(mbedtls_ssl_context *ssl,
|
||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||
if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
|
||||
/* Make room for the additional DTLS fields */
|
||||
if (MBEDTLS_SSL_OUT_CONTENT_LEN - ssl->out_msglen < 8) {
|
||||
if (mbedtls_ssl_get_out_content_len(ssl) - ssl->out_msglen < 8) {
|
||||
MBEDTLS_SSL_DEBUG_MSG(1, ("DTLS handshake message too large: "
|
||||
"size %" MBEDTLS_PRINTF_SIZET ", maximum %"
|
||||
MBEDTLS_PRINTF_SIZET,
|
||||
hs_len,
|
||||
(size_t) (MBEDTLS_SSL_OUT_CONTENT_LEN - 12)));
|
||||
mbedtls_ssl_get_out_content_len(ssl) - 12));
|
||||
return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
@ -2656,11 +2655,7 @@ int mbedtls_ssl_write_record(mbedtls_ssl_context *ssl, int force_flush)
|
||||
if (!done) {
|
||||
unsigned i;
|
||||
size_t protected_record_size;
|
||||
#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
|
||||
size_t out_buf_len = ssl->out_buf_len;
|
||||
#else
|
||||
size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN;
|
||||
#endif
|
||||
size_t out_buf_len = mbedtls_ssl_get_out_buf_len(ssl);
|
||||
/* Skip writing the record content type to after the encryption,
|
||||
* as it may change when using the CID extension. */
|
||||
mbedtls_ssl_protocol_version tls_ver = ssl->tls_version;
|
||||
@ -3107,11 +3102,7 @@ int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl)
|
||||
* after the explicit IV, but here we move it to start where the
|
||||
* IV was.
|
||||
*/
|
||||
#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
|
||||
size_t const in_buf_len = ssl->in_buf_len;
|
||||
#else
|
||||
size_t const in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN;
|
||||
#endif
|
||||
size_t const in_buf_len = mbedtls_ssl_get_in_buf_len(ssl);
|
||||
if (payload_end + ssl->in_msglen > ssl->in_buf + in_buf_len) {
|
||||
MBEDTLS_SSL_DEBUG_MSG(1,
|
||||
("Shouldn't happen: no room to move handshake fragment %"
|
||||
@ -3492,7 +3483,7 @@ static int ssl_handle_possible_reconnect(mbedtls_ssl_context *ssl)
|
||||
ssl,
|
||||
ssl->cli_id, ssl->cli_id_len,
|
||||
ssl->in_buf, ssl->in_left,
|
||||
ssl->out_buf, MBEDTLS_SSL_OUT_CONTENT_LEN, &len);
|
||||
ssl->out_buf, mbedtls_ssl_get_out_content_len(ssl), &len);
|
||||
|
||||
MBEDTLS_SSL_DEBUG_RET(2, "mbedtls_ssl_check_dtls_clihlo_cookie", ret);
|
||||
|
||||
@ -4008,7 +3999,7 @@ static int ssl_prepare_record_content(mbedtls_ssl_context *ssl,
|
||||
|
||||
/* Check actual (decrypted) record content length against
|
||||
* configured maximum. */
|
||||
if (rec->data_len > MBEDTLS_SSL_IN_CONTENT_LEN) {
|
||||
if (rec->data_len > mbedtls_ssl_get_in_content_len(ssl)) {
|
||||
MBEDTLS_SSL_DEBUG_MSG(1, ("bad message length"));
|
||||
return MBEDTLS_ERR_SSL_INVALID_RECORD;
|
||||
}
|
||||
@ -4185,7 +4176,7 @@ static int ssl_load_buffered_message(mbedtls_ssl_context *ssl)
|
||||
|
||||
/* Double-check that we haven't accidentally buffered
|
||||
* a message that doesn't fit into the input buffer. */
|
||||
if (msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN) {
|
||||
if (msg_len + 12 > mbedtls_ssl_get_in_content_len(ssl)) {
|
||||
MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
|
||||
return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
|
||||
}
|
||||
@ -4321,7 +4312,7 @@ static int ssl_buffer_message(mbedtls_ssl_context *ssl)
|
||||
* This is an implementation-specific limitation
|
||||
* and not one from the standard, hence it is not
|
||||
* checked in ssl_check_hs_header(). */
|
||||
if (msg_len + 12 > MBEDTLS_SSL_IN_CONTENT_LEN) {
|
||||
if (msg_len + 12 > mbedtls_ssl_get_in_content_len(ssl)) {
|
||||
/* Ignore message */
|
||||
goto exit;
|
||||
}
|
||||
@ -4583,11 +4574,7 @@ static int ssl_load_buffered_record(mbedtls_ssl_context *ssl)
|
||||
unsigned char *rec;
|
||||
size_t rec_len;
|
||||
unsigned rec_epoch;
|
||||
#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
|
||||
size_t in_buf_len = ssl->in_buf_len;
|
||||
#else
|
||||
size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN;
|
||||
#endif
|
||||
size_t in_buf_len = mbedtls_ssl_get_in_buf_len(ssl);
|
||||
if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1003,8 +1003,11 @@ static int ssl_handshake_init(mbedtls_ssl_context *ssl)
|
||||
#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
|
||||
/* If the buffers are too small - reallocate */
|
||||
|
||||
handle_buffer_resizing(ssl, 0, MBEDTLS_SSL_IN_BUFFER_LEN,
|
||||
MBEDTLS_SSL_OUT_BUFFER_LEN);
|
||||
/* Grow back to what this connection asked for, not to the build-time
|
||||
* maximum: growing to the maximum here would undo the saving that
|
||||
* MBEDTLS_SSL_RUNTIME_CONTENT_LEN made at setup. */
|
||||
handle_buffer_resizing(ssl, 0, mbedtls_ssl_compute_in_buf_len(ssl),
|
||||
mbedtls_ssl_compute_out_buf_len(ssl));
|
||||
#endif
|
||||
|
||||
/* All pointers should exist and can be directly freed without issue */
|
||||
@ -1114,6 +1117,14 @@ static int ssl_cookie_check_dummy(void *ctx,
|
||||
void mbedtls_ssl_init(mbedtls_ssl_context *ssl)
|
||||
{
|
||||
memset(ssl, 0, sizeof(mbedtls_ssl_context));
|
||||
|
||||
#if defined(MBEDTLS_SSL_RUNTIME_CONTENT_LEN)
|
||||
/* Default to the build-time maxima, so that enabling
|
||||
* MBEDTLS_SSL_RUNTIME_CONTENT_LEN without calling either setter is
|
||||
* observably a no-op. */
|
||||
ssl->in_content_len = MBEDTLS_SSL_IN_CONTENT_LEN;
|
||||
ssl->out_content_len = MBEDTLS_SSL_OUT_CONTENT_LEN;
|
||||
#endif
|
||||
}
|
||||
|
||||
MBEDTLS_CHECK_RETURN_CRITICAL
|
||||
@ -1165,6 +1176,26 @@ static int ssl_conf_check(const mbedtls_ssl_context *ssl)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_SSL_RUNTIME_CONTENT_LEN) && \
|
||||
defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && defined(MBEDTLS_SSL_CLI_C)
|
||||
/* A client proposing TLS 1.2 advertises its configured fragment length,
|
||||
* so it must not invite records longer than this connection can take in.
|
||||
* A server's configured fragment length only caps what it sends. */
|
||||
if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
|
||||
ssl->conf->min_tls_version <= MBEDTLS_SSL_VERSION_TLS1_2 &&
|
||||
ssl->conf->mfl_code != MBEDTLS_SSL_MAX_FRAG_LEN_NONE) {
|
||||
const unsigned int mfl = ssl_mfl_code_to_length(ssl->conf->mfl_code);
|
||||
const size_t in_content_len = mbedtls_ssl_get_in_content_len(ssl);
|
||||
|
||||
if (mfl > in_content_len) {
|
||||
MBEDTLS_SSL_DEBUG_MSG(1, ("max_fragment_length %u exceeds the incoming "
|
||||
"content length %" MBEDTLS_PRINTF_SIZET,
|
||||
mfl, in_content_len));
|
||||
return MBEDTLS_ERR_SSL_BAD_CONFIG;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Space for further checks */
|
||||
|
||||
return 0;
|
||||
@ -1178,8 +1209,8 @@ int mbedtls_ssl_setup(mbedtls_ssl_context *ssl,
|
||||
const mbedtls_ssl_config *conf)
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN;
|
||||
size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN;
|
||||
size_t in_buf_len = mbedtls_ssl_compute_in_buf_len(ssl);
|
||||
size_t out_buf_len = mbedtls_ssl_compute_out_buf_len(ssl);
|
||||
|
||||
ssl->conf = conf;
|
||||
|
||||
@ -1195,7 +1226,7 @@ int mbedtls_ssl_setup(mbedtls_ssl_context *ssl,
|
||||
/* Set to NULL in case of an error condition */
|
||||
ssl->out_buf = NULL;
|
||||
|
||||
#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
|
||||
#if defined(MBEDTLS_SSL_HAVE_BUFFER_LEN_FIELDS)
|
||||
ssl->in_buf_len = in_buf_len;
|
||||
#endif
|
||||
ssl->in_buf = mbedtls_calloc(1, in_buf_len);
|
||||
@ -1205,7 +1236,7 @@ int mbedtls_ssl_setup(mbedtls_ssl_context *ssl,
|
||||
goto error;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
|
||||
#if defined(MBEDTLS_SSL_HAVE_BUFFER_LEN_FIELDS)
|
||||
ssl->out_buf_len = out_buf_len;
|
||||
#endif
|
||||
ssl->out_buf = mbedtls_calloc(1, out_buf_len);
|
||||
@ -1234,7 +1265,7 @@ error:
|
||||
|
||||
ssl->conf = NULL;
|
||||
|
||||
#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
|
||||
#if defined(MBEDTLS_SSL_HAVE_BUFFER_LEN_FIELDS)
|
||||
ssl->in_buf_len = 0;
|
||||
ssl->out_buf_len = 0;
|
||||
#endif
|
||||
@ -1266,13 +1297,8 @@ error:
|
||||
void mbedtls_ssl_session_reset_msg_layer(mbedtls_ssl_context *ssl,
|
||||
int partial)
|
||||
{
|
||||
#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
|
||||
size_t in_buf_len = ssl->in_buf_len;
|
||||
size_t out_buf_len = ssl->out_buf_len;
|
||||
#else
|
||||
size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN;
|
||||
size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN;
|
||||
#endif
|
||||
size_t in_buf_len = mbedtls_ssl_get_in_buf_len(ssl);
|
||||
size_t out_buf_len = mbedtls_ssl_get_out_buf_len(ssl);
|
||||
|
||||
#if !defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) || !defined(MBEDTLS_SSL_SRV_C)
|
||||
partial = 0;
|
||||
@ -1501,6 +1527,39 @@ void mbedtls_ssl_set_mtu(mbedtls_ssl_context *ssl, uint16_t mtu)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_SSL_RUNTIME_CONTENT_LEN)
|
||||
int mbedtls_ssl_set_in_content_len(mbedtls_ssl_context *ssl, size_t len)
|
||||
{
|
||||
/* Only before mbedtls_ssl_setup(): afterwards the buffers exist and
|
||||
* may hold data and interior pointers sized from the current length. */
|
||||
if (ssl->conf != NULL) {
|
||||
return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
if (len < MBEDTLS_SSL_IN_CONTENT_LEN_MIN || len > MBEDTLS_SSL_IN_CONTENT_LEN) {
|
||||
return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
ssl->in_content_len = len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mbedtls_ssl_set_out_content_len(mbedtls_ssl_context *ssl, size_t len)
|
||||
{
|
||||
/* Only before mbedtls_ssl_setup(), as for the incoming length. */
|
||||
if (ssl->conf != NULL) {
|
||||
return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
if (len < MBEDTLS_SSL_OUT_CONTENT_LEN_MIN || len > MBEDTLS_SSL_OUT_CONTENT_LEN) {
|
||||
return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
ssl->out_content_len = len;
|
||||
return 0;
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_RUNTIME_CONTENT_LEN */
|
||||
|
||||
void mbedtls_ssl_conf_read_timeout(mbedtls_ssl_config *conf, uint32_t timeout)
|
||||
{
|
||||
conf->read_timeout = timeout;
|
||||
@ -1919,7 +1978,8 @@ static int ssl_conf_set_psk_identity(mbedtls_ssl_config *conf,
|
||||
unsigned char const *psk_identity,
|
||||
size_t psk_identity_len)
|
||||
{
|
||||
/* Identity len will be encoded on two bytes */
|
||||
/* Identity len will be encoded on two bytes.
|
||||
* Configuration-scoped, so this checks the build-time ceiling. */
|
||||
if (psk_identity == NULL ||
|
||||
psk_identity_len == 0 ||
|
||||
(psk_identity_len >> 16) != 0 ||
|
||||
@ -2819,7 +2879,7 @@ const char *mbedtls_ssl_get_version(const mbedtls_ssl_context *ssl)
|
||||
|
||||
size_t mbedtls_ssl_get_output_record_size_limit(const mbedtls_ssl_context *ssl)
|
||||
{
|
||||
const size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN;
|
||||
const size_t max_len = mbedtls_ssl_get_out_content_len(ssl);
|
||||
size_t record_size_limit = max_len;
|
||||
|
||||
if (ssl->session != NULL &&
|
||||
@ -2843,14 +2903,18 @@ size_t mbedtls_ssl_get_output_record_size_limit(const mbedtls_ssl_context *ssl)
|
||||
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
|
||||
size_t mbedtls_ssl_get_input_max_frag_len(const mbedtls_ssl_context *ssl)
|
||||
{
|
||||
size_t max_len = MBEDTLS_SSL_IN_CONTENT_LEN;
|
||||
size_t max_len = mbedtls_ssl_get_in_content_len(ssl);
|
||||
size_t read_mfl;
|
||||
|
||||
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
|
||||
/* Use the configured MFL for the client if we're past SERVER_HELLO_DONE */
|
||||
if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
|
||||
ssl->state >= MBEDTLS_SSL_SERVER_HELLO_DONE) {
|
||||
return ssl_mfl_code_to_length(ssl->conf->mfl_code);
|
||||
read_mfl = ssl_mfl_code_to_length(ssl->conf->mfl_code);
|
||||
if (read_mfl < max_len) {
|
||||
max_len = read_mfl;
|
||||
}
|
||||
return max_len;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -2875,12 +2939,14 @@ size_t mbedtls_ssl_get_input_max_frag_len(const mbedtls_ssl_context *ssl)
|
||||
|
||||
size_t mbedtls_ssl_get_output_max_frag_len(const mbedtls_ssl_context *ssl)
|
||||
{
|
||||
size_t max_len;
|
||||
size_t max_len = mbedtls_ssl_get_out_content_len(ssl);
|
||||
|
||||
/*
|
||||
* Assume mfl_code is correct since it was checked when set
|
||||
*/
|
||||
max_len = ssl_mfl_code_to_length(ssl->conf->mfl_code);
|
||||
if (ssl_mfl_code_to_length(ssl->conf->mfl_code) < max_len) {
|
||||
max_len = ssl_mfl_code_to_length(ssl->conf->mfl_code);
|
||||
}
|
||||
|
||||
/* Check if a smaller max length was negotiated */
|
||||
if (ssl->session_out != NULL &&
|
||||
@ -2916,7 +2982,7 @@ size_t mbedtls_ssl_get_current_mtu(const mbedtls_ssl_context *ssl)
|
||||
|
||||
int mbedtls_ssl_get_max_out_record_payload(const mbedtls_ssl_context *ssl)
|
||||
{
|
||||
size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN;
|
||||
size_t max_len = mbedtls_ssl_get_out_content_len(ssl);
|
||||
|
||||
#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && \
|
||||
!defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) && \
|
||||
@ -2988,7 +3054,7 @@ int mbedtls_ssl_get_max_out_record_payload(const mbedtls_ssl_context *ssl)
|
||||
|
||||
int mbedtls_ssl_get_max_in_record_payload(const mbedtls_ssl_context *ssl)
|
||||
{
|
||||
size_t max_len = MBEDTLS_SSL_IN_CONTENT_LEN;
|
||||
size_t max_len = mbedtls_ssl_get_in_content_len(ssl);
|
||||
|
||||
#if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
|
||||
(void) ssl;
|
||||
@ -5191,22 +5257,14 @@ void mbedtls_ssl_free(mbedtls_ssl_context *ssl)
|
||||
MBEDTLS_SSL_DEBUG_MSG(2, ("=> free"));
|
||||
|
||||
if (ssl->out_buf != NULL) {
|
||||
#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
|
||||
size_t out_buf_len = ssl->out_buf_len;
|
||||
#else
|
||||
size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN;
|
||||
#endif
|
||||
size_t out_buf_len = mbedtls_ssl_get_out_buf_len(ssl);
|
||||
|
||||
mbedtls_zeroize_and_free(ssl->out_buf, out_buf_len);
|
||||
ssl->out_buf = NULL;
|
||||
}
|
||||
|
||||
if (ssl->in_buf != NULL) {
|
||||
#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
|
||||
size_t in_buf_len = ssl->in_buf_len;
|
||||
#else
|
||||
size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN;
|
||||
#endif
|
||||
size_t in_buf_len = mbedtls_ssl_get_in_buf_len(ssl);
|
||||
|
||||
mbedtls_zeroize_and_free(ssl->in_buf, in_buf_len);
|
||||
ssl->in_buf = NULL;
|
||||
@ -6736,13 +6794,17 @@ int mbedtls_ssl_write_certificate(mbedtls_ssl_context *ssl)
|
||||
*/
|
||||
i = 7;
|
||||
crt = mbedtls_ssl_own_cert(ssl);
|
||||
const size_t out_content_len = mbedtls_ssl_get_out_content_len(ssl);
|
||||
|
||||
while (crt != NULL) {
|
||||
n = crt->raw.len;
|
||||
if (n > MBEDTLS_SSL_OUT_CONTENT_LEN - 3 - i) {
|
||||
/* Written as an addition rather than i + 3 subtracted from the
|
||||
* outgoing length, so that a short outgoing length cannot underflow
|
||||
* the bound into a huge value and wave the memcpy below through. */
|
||||
if (i + 3 + n > out_content_len) {
|
||||
MBEDTLS_SSL_DEBUG_MSG(1, ("certificate too large, %" MBEDTLS_PRINTF_SIZET
|
||||
" > %" MBEDTLS_PRINTF_SIZET,
|
||||
i + 3 + n, (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN));
|
||||
i + 3 + n, out_content_len));
|
||||
return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
|
||||
@ -2404,7 +2404,7 @@ static int ssl_write_client_key_exchange(mbedtls_ssl_context *ssl)
|
||||
* The export format is an ECPoint structure as expected by TLS,
|
||||
* but we just need to add a length byte before that. */
|
||||
unsigned char *own_pubkey = ssl->out_msg + header_len + 1;
|
||||
unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
|
||||
unsigned char *end = ssl->out_msg + mbedtls_ssl_get_out_content_len(ssl);
|
||||
size_t own_pubkey_max_len = (size_t) (end - own_pubkey);
|
||||
size_t own_pubkey_len;
|
||||
|
||||
@ -2464,12 +2464,16 @@ static int ssl_write_client_key_exchange(mbedtls_ssl_context *ssl)
|
||||
const size_t ecpoint_max_len =
|
||||
PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(handshake->xxdh_psa_type,
|
||||
handshake->xxdh_psa_bits);
|
||||
const size_t out_content_len = mbedtls_ssl_get_out_content_len(ssl);
|
||||
|
||||
header_len = 4;
|
||||
|
||||
if (ecpoint_max_len > MBEDTLS_SSL_OUT_CONTENT_LEN - ecpoint_len_size ||
|
||||
/* The second comparison is only reached when the first one is false,
|
||||
* that is when ecpoint_len_size + ecpoint_max_len <= out_content_len,
|
||||
* so neither subtraction can wrap. */
|
||||
if (ecpoint_max_len > out_content_len - ecpoint_len_size ||
|
||||
header_len + content_len_size + ssl->conf->psk_identity_len
|
||||
> MBEDTLS_SSL_OUT_CONTENT_LEN - ecpoint_len_size - ecpoint_max_len) {
|
||||
> out_content_len - ecpoint_len_size - ecpoint_max_len) {
|
||||
MBEDTLS_SSL_DEBUG_MSG(1,
|
||||
("psk identity too long or SSL buffer too short"));
|
||||
return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
|
||||
@ -2517,7 +2521,7 @@ static int ssl_write_client_key_exchange(mbedtls_ssl_context *ssl)
|
||||
* The export format is an ECPoint structure as expected by TLS,
|
||||
* but we just need to add a length byte before that. */
|
||||
unsigned char *own_pubkey = p + 1;
|
||||
unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
|
||||
unsigned char *end = ssl->out_msg + mbedtls_ssl_get_out_content_len(ssl);
|
||||
size_t own_pubkey_max_len = (size_t) (end - own_pubkey);
|
||||
size_t own_pubkey_len = 0;
|
||||
|
||||
@ -2584,7 +2588,7 @@ static int ssl_write_client_key_exchange(mbedtls_ssl_context *ssl)
|
||||
header_len = 4;
|
||||
content_len = ssl->conf->psk_identity_len;
|
||||
|
||||
if (header_len + 2 + content_len > MBEDTLS_SSL_OUT_CONTENT_LEN) {
|
||||
if (header_len + 2 + content_len > mbedtls_ssl_get_out_content_len(ssl)) {
|
||||
MBEDTLS_SSL_DEBUG_MSG(1,
|
||||
("psk identity too long or SSL buffer too short"));
|
||||
return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
|
||||
@ -2615,7 +2619,7 @@ static int ssl_write_client_key_exchange(mbedtls_ssl_context *ssl)
|
||||
header_len = 4;
|
||||
|
||||
unsigned char *out_p = ssl->out_msg + header_len;
|
||||
unsigned char *end_p = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN -
|
||||
unsigned char *end_p = ssl->out_msg + mbedtls_ssl_get_out_content_len(ssl) -
|
||||
header_len;
|
||||
ret = mbedtls_psa_ecjpake_write_round(&ssl->handshake->psa_pake_ctx,
|
||||
out_p, end_p - out_p, &content_len,
|
||||
@ -2687,11 +2691,8 @@ static int ssl_write_certificate_verify(mbedtls_ssl_context *ssl)
|
||||
mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE;
|
||||
size_t hashlen;
|
||||
void *rs_ctx = NULL;
|
||||
#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
|
||||
size_t out_buf_len = ssl->out_buf_len - (size_t) (ssl->out_msg - ssl->out_buf);
|
||||
#else
|
||||
size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN - (size_t) (ssl->out_msg - ssl->out_buf);
|
||||
#endif
|
||||
size_t out_buf_len = mbedtls_ssl_get_out_buf_len(ssl)
|
||||
- (size_t) (ssl->out_msg - ssl->out_buf);
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate verify"));
|
||||
|
||||
|
||||
@ -1545,7 +1545,7 @@ static void ssl_write_cid_ext(mbedtls_ssl_context *ssl,
|
||||
{
|
||||
unsigned char *p = buf;
|
||||
size_t ext_len;
|
||||
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
|
||||
const unsigned char *end = ssl->out_msg + mbedtls_ssl_get_out_content_len(ssl);
|
||||
|
||||
*olen = 0;
|
||||
|
||||
@ -1780,7 +1780,7 @@ static int ssl_write_ecjpake_kkpp_ext(mbedtls_ssl_context *ssl,
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
unsigned char *p = buf;
|
||||
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
|
||||
const unsigned char *end = ssl->out_msg + mbedtls_ssl_get_out_content_len(ssl);
|
||||
size_t kkpp_len;
|
||||
|
||||
*olen = 0;
|
||||
@ -1826,7 +1826,7 @@ static void ssl_write_use_srtp_ext(mbedtls_ssl_context *ssl,
|
||||
{
|
||||
size_t mki_len = 0, ext_len = 0;
|
||||
uint16_t profile_value = 0;
|
||||
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
|
||||
const unsigned char *end = ssl->out_msg + mbedtls_ssl_get_out_content_len(ssl);
|
||||
|
||||
*olen = 0;
|
||||
|
||||
@ -1915,7 +1915,8 @@ static int ssl_write_hello_verify_request(mbedtls_ssl_context *ssl)
|
||||
cookie_len_byte = p++;
|
||||
|
||||
if ((ret = ssl->conf->f_cookie_write(ssl->conf->p_cookie,
|
||||
&p, ssl->out_buf + MBEDTLS_SSL_OUT_BUFFER_LEN,
|
||||
&p,
|
||||
ssl->out_buf + mbedtls_ssl_get_out_buf_len(ssl),
|
||||
ssl->cli_id, ssl->cli_id_len)) != 0) {
|
||||
MBEDTLS_SSL_DEBUG_RET(1, "f_cookie_write", ret);
|
||||
return ret;
|
||||
@ -2207,7 +2208,7 @@ static int ssl_write_server_hello(mbedtls_ssl_context *ssl)
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_SSL_ALPN)
|
||||
unsigned char *end = buf + MBEDTLS_SSL_OUT_CONTENT_LEN - 4;
|
||||
unsigned char *end = buf + mbedtls_ssl_get_out_content_len(ssl) - 4;
|
||||
if ((ret = mbedtls_ssl_write_alpn_ext(ssl, p + 2 + ext_len, end, &olen))
|
||||
!= 0) {
|
||||
return ret;
|
||||
@ -2268,7 +2269,7 @@ static int ssl_write_certificate_request(mbedtls_ssl_context *ssl)
|
||||
uint16_t dn_size, total_dn_size; /* excluding length bytes */
|
||||
size_t ct_len, sa_len; /* including length bytes */
|
||||
unsigned char *buf, *p;
|
||||
const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
|
||||
const unsigned char * const end = ssl->out_msg + mbedtls_ssl_get_out_content_len(ssl);
|
||||
const mbedtls_x509_crt *crt;
|
||||
int authmode;
|
||||
|
||||
@ -2443,8 +2444,16 @@ static int ssl_resume_server_key_exchange(mbedtls_ssl_context *ssl,
|
||||
* ssl_write_server_key_exchange also takes care of incrementing
|
||||
* ssl->out_msglen. */
|
||||
unsigned char *sig_start = ssl->out_msg + ssl->out_msglen + 2;
|
||||
size_t sig_max_len = (ssl->out_buf + MBEDTLS_SSL_OUT_CONTENT_LEN
|
||||
- sig_start);
|
||||
/* Deliberately based on out_buf rather than out_msg: this bound therefore
|
||||
* stops short of the end of the content area by the record header, which
|
||||
* is conservative. Do not "simplify" it to out_msg without checking the
|
||||
* non-async path below, which bounds the same write more loosely. */
|
||||
const unsigned char *end = ssl->out_buf + mbedtls_ssl_get_out_content_len(ssl);
|
||||
/* Compare before subtracting: with a short per-connection outgoing
|
||||
* length, sig_start can lie past end, and the difference would wrap.
|
||||
* A zero budget leaves the callback no room, so the handshake fails
|
||||
* instead. */
|
||||
size_t sig_max_len = sig_start < end ? (size_t) (end - sig_start) : 0;
|
||||
int ret = ssl->conf->f_async_resume(ssl,
|
||||
sig_start, signature_len, sig_max_len);
|
||||
if (ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) {
|
||||
@ -2479,11 +2488,8 @@ static int ssl_prepare_server_key_exchange(mbedtls_ssl_context *ssl,
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)
|
||||
#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
|
||||
size_t out_buf_len = ssl->out_buf_len - (size_t) (ssl->out_msg - ssl->out_buf);
|
||||
#else
|
||||
size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN - (size_t) (ssl->out_msg - ssl->out_buf);
|
||||
#endif
|
||||
size_t out_buf_len = mbedtls_ssl_get_out_buf_len(ssl)
|
||||
- (size_t) (ssl->out_msg - ssl->out_buf);
|
||||
#endif
|
||||
|
||||
ssl->out_msglen = 4; /* header (type:1, length:3) to be written later */
|
||||
@ -2501,7 +2507,7 @@ static int ssl_prepare_server_key_exchange(mbedtls_ssl_context *ssl,
|
||||
if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) {
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
unsigned char *out_p = ssl->out_msg + ssl->out_msglen;
|
||||
unsigned char *end_p = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN -
|
||||
unsigned char *end_p = ssl->out_msg + mbedtls_ssl_get_out_content_len(ssl) -
|
||||
ssl->out_msglen;
|
||||
size_t output_offset = 0;
|
||||
size_t output_len = 0;
|
||||
@ -2652,7 +2658,7 @@ curve_matching_done:
|
||||
*/
|
||||
unsigned char *own_pubkey = p + data_length_size;
|
||||
|
||||
size_t own_pubkey_max_len = (size_t) (MBEDTLS_SSL_OUT_CONTENT_LEN
|
||||
size_t own_pubkey_max_len = (size_t) (mbedtls_ssl_get_out_content_len(ssl)
|
||||
- (own_pubkey - ssl->out_msg));
|
||||
|
||||
status = psa_export_public_key(handshake->xxdh_psa_privkey,
|
||||
@ -3424,7 +3430,7 @@ static int ssl_write_new_session_ticket(mbedtls_ssl_context *ssl)
|
||||
if ((ret = ssl->conf->f_ticket_write(ssl->conf->p_ticket,
|
||||
ssl->session_negotiate,
|
||||
ssl->out_msg + 10,
|
||||
ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN,
|
||||
ssl->out_msg + mbedtls_ssl_get_out_content_len(ssl),
|
||||
&tlen, &lifetime)) != 0) {
|
||||
MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_ticket_write", ret);
|
||||
}
|
||||
|
||||
@ -1307,7 +1307,7 @@ int mbedtls_ssl_tls13_write_change_cipher_spec(mbedtls_ssl_context *ssl)
|
||||
/* Write CCS message */
|
||||
MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_change_cipher_spec_body(
|
||||
ssl, ssl->out_msg,
|
||||
ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN,
|
||||
ssl->out_msg + mbedtls_ssl_get_out_content_len(ssl),
|
||||
&ssl->out_msglen));
|
||||
|
||||
ssl->out_msgtype = MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC;
|
||||
@ -1746,23 +1746,31 @@ int mbedtls_ssl_tls13_write_record_size_limit_ext(mbedtls_ssl_context *ssl,
|
||||
size_t *out_len)
|
||||
{
|
||||
unsigned char *p = buf;
|
||||
const size_t record_size_limit = mbedtls_ssl_get_in_content_len(ssl);
|
||||
*out_len = 0;
|
||||
|
||||
MBEDTLS_STATIC_ASSERT(MBEDTLS_SSL_IN_CONTENT_LEN >= MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN,
|
||||
"MBEDTLS_SSL_IN_CONTENT_LEN is less than the "
|
||||
"minimum record size limit");
|
||||
/* The incoming content length is a runtime value, so this bound cannot be
|
||||
* checked at compile time. A connection that cannot hold the smallest
|
||||
* record RFC 8449 permits has nothing valid to advertise. */
|
||||
if (record_size_limit < MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN) {
|
||||
MBEDTLS_SSL_DEBUG_MSG(1, ("incoming content length %" MBEDTLS_PRINTF_SIZET
|
||||
" is less than the minimum record size limit %d",
|
||||
record_size_limit,
|
||||
MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN));
|
||||
return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6);
|
||||
|
||||
MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT, p, 0);
|
||||
MBEDTLS_PUT_UINT16_BE(MBEDTLS_SSL_RECORD_SIZE_LIMIT_EXTENSION_DATA_LENGTH,
|
||||
p, 2);
|
||||
MBEDTLS_PUT_UINT16_BE(MBEDTLS_SSL_IN_CONTENT_LEN, p, 4);
|
||||
MBEDTLS_PUT_UINT16_BE(record_size_limit, p, 4);
|
||||
|
||||
*out_len = 6;
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG(2, ("Sent RecordSizeLimit: %d Bytes",
|
||||
MBEDTLS_SSL_IN_CONTENT_LEN));
|
||||
MBEDTLS_SSL_DEBUG_MSG(2, ("Sent RecordSizeLimit: %" MBEDTLS_PRINTF_SIZET " Bytes",
|
||||
record_size_limit));
|
||||
|
||||
mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT);
|
||||
|
||||
|
||||
@ -67,6 +67,8 @@ int main(void)
|
||||
#define DFL_AUTH_MODE -1
|
||||
#define DFL_SET_HOSTNAME 1
|
||||
#define DFL_MFL_CODE MBEDTLS_SSL_MAX_FRAG_LEN_NONE
|
||||
#define DFL_IN_CONTENT_LEN 0
|
||||
#define DFL_OUT_CONTENT_LEN 0
|
||||
#define DFL_TRUNC_HMAC -1
|
||||
#define DFL_RECSPLIT -1
|
||||
#define DFL_RECONNECT 0
|
||||
@ -231,6 +233,14 @@ int main(void)
|
||||
#define USAGE_MAX_FRAG_LEN ""
|
||||
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
|
||||
|
||||
#if defined(MBEDTLS_SSL_RUNTIME_CONTENT_LEN)
|
||||
#define USAGE_CONTENT_LEN \
|
||||
" in_content_len=%%d default: MBEDTLS_SSL_IN_CONTENT_LEN\n" \
|
||||
" out_content_len=%%d default: MBEDTLS_SSL_OUT_CONTENT_LEN\n"
|
||||
#else
|
||||
#define USAGE_CONTENT_LEN ""
|
||||
#endif /* MBEDTLS_SSL_RUNTIME_CONTENT_LEN */
|
||||
|
||||
#if defined(MBEDTLS_SSL_ALPN)
|
||||
#define USAGE_ALPN \
|
||||
" alpn=%%s default: \"\" (disabled)\n" \
|
||||
@ -425,6 +435,7 @@ int main(void)
|
||||
USAGE_TICKETS \
|
||||
USAGE_EAP_TLS \
|
||||
USAGE_MAX_FRAG_LEN \
|
||||
USAGE_CONTENT_LEN \
|
||||
USAGE_CONTEXT_CRT_CB \
|
||||
USAGE_ALPN \
|
||||
USAGE_EMS \
|
||||
@ -504,6 +515,8 @@ struct options {
|
||||
int set_hostname; /* call mbedtls_ssl_set_hostname()? */
|
||||
/* 0=no, 1=yes, -1=NULL */
|
||||
unsigned char mfl_code; /* code for maximum fragment length */
|
||||
int in_content_len; /* incoming content length (0: default) */
|
||||
int out_content_len; /* outgoing content length (0: default) */
|
||||
int trunc_hmac; /* negotiate truncated hmac or not */
|
||||
int recsplit; /* enable record splitting? */
|
||||
int reconnect; /* attempt to resume session */
|
||||
@ -941,6 +954,8 @@ int main(int argc, char *argv[])
|
||||
opt.auth_mode = DFL_AUTH_MODE;
|
||||
opt.set_hostname = DFL_SET_HOSTNAME;
|
||||
opt.mfl_code = DFL_MFL_CODE;
|
||||
opt.in_content_len = DFL_IN_CONTENT_LEN;
|
||||
opt.out_content_len = DFL_OUT_CONTENT_LEN;
|
||||
opt.trunc_hmac = DFL_TRUNC_HMAC;
|
||||
opt.recsplit = DFL_RECSPLIT;
|
||||
opt.reconnect = DFL_RECONNECT;
|
||||
@ -1350,6 +1365,18 @@ usage:
|
||||
} else {
|
||||
goto usage;
|
||||
}
|
||||
#if defined(MBEDTLS_SSL_RUNTIME_CONTENT_LEN)
|
||||
} else if (strcmp(p, "in_content_len") == 0) {
|
||||
opt.in_content_len = atoi(q);
|
||||
if (opt.in_content_len <= 0) {
|
||||
goto usage;
|
||||
}
|
||||
} else if (strcmp(p, "out_content_len") == 0) {
|
||||
opt.out_content_len = atoi(q);
|
||||
if (opt.out_content_len <= 0) {
|
||||
goto usage;
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_RUNTIME_CONTENT_LEN */
|
||||
} else if (strcmp(p, "trunc_hmac") == 0) {
|
||||
switch (atoi(q)) {
|
||||
case 0: opt.trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_DISABLED; break;
|
||||
@ -2020,6 +2047,22 @@ usage:
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_EARLY_DATA */
|
||||
|
||||
#if defined(MBEDTLS_SSL_RUNTIME_CONTENT_LEN)
|
||||
if (opt.in_content_len != DFL_IN_CONTENT_LEN &&
|
||||
(ret = mbedtls_ssl_set_in_content_len(&ssl, opt.in_content_len)) != 0) {
|
||||
mbedtls_printf(" failed\n ! mbedtls_ssl_set_in_content_len returned -0x%x\n\n",
|
||||
(unsigned int) -ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (opt.out_content_len != DFL_OUT_CONTENT_LEN &&
|
||||
(ret = mbedtls_ssl_set_out_content_len(&ssl, opt.out_content_len)) != 0) {
|
||||
mbedtls_printf(" failed\n ! mbedtls_ssl_set_out_content_len returned -0x%x\n\n",
|
||||
(unsigned int) -ret);
|
||||
goto exit;
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_RUNTIME_CONTENT_LEN */
|
||||
|
||||
if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) {
|
||||
mbedtls_printf(" failed\n ! mbedtls_ssl_setup returned -0x%x\n\n",
|
||||
(unsigned int) -ret);
|
||||
|
||||
@ -111,6 +111,8 @@ int main(void)
|
||||
#define DFL_CERT_REQ_CA_LIST MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED
|
||||
#define DFL_CERT_REQ_DN_HINT 0
|
||||
#define DFL_MFL_CODE MBEDTLS_SSL_MAX_FRAG_LEN_NONE
|
||||
#define DFL_IN_CONTENT_LEN 0
|
||||
#define DFL_OUT_CONTENT_LEN 0
|
||||
#define DFL_TRUNC_HMAC -1
|
||||
#define DFL_TICKETS MBEDTLS_SSL_SESSION_TICKETS_ENABLED
|
||||
#define DFL_DUMMY_TICKET 0
|
||||
@ -345,6 +347,14 @@ int main(void)
|
||||
#define USAGE_MAX_FRAG_LEN ""
|
||||
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
|
||||
|
||||
#if defined(MBEDTLS_SSL_RUNTIME_CONTENT_LEN)
|
||||
#define USAGE_CONTENT_LEN \
|
||||
" in_content_len=%%d default: MBEDTLS_SSL_IN_CONTENT_LEN\n" \
|
||||
" out_content_len=%%d default: MBEDTLS_SSL_OUT_CONTENT_LEN\n"
|
||||
#else
|
||||
#define USAGE_CONTENT_LEN ""
|
||||
#endif /* MBEDTLS_SSL_RUNTIME_CONTENT_LEN */
|
||||
|
||||
#if defined(MBEDTLS_SSL_ALPN)
|
||||
#define USAGE_ALPN \
|
||||
" alpn=%%s default: \"\" (disabled)\n" \
|
||||
@ -550,6 +560,7 @@ int main(void)
|
||||
USAGE_CACHE \
|
||||
USAGE_CACHE_TIME \
|
||||
USAGE_MAX_FRAG_LEN \
|
||||
USAGE_CONTENT_LEN \
|
||||
USAGE_ALPN \
|
||||
USAGE_EMS \
|
||||
USAGE_ETM \
|
||||
@ -650,6 +661,8 @@ struct options {
|
||||
int cert_req_ca_list; /* should we send the CA list? */
|
||||
int cert_req_dn_hint; /* mode to set DN hints for CA list to send */
|
||||
unsigned char mfl_code; /* code for maximum fragment length */
|
||||
int in_content_len; /* incoming content length (0: default) */
|
||||
int out_content_len; /* outgoing content length (0: default) */
|
||||
int trunc_hmac; /* accept truncated hmac? */
|
||||
int tickets; /* enable / disable session tickets */
|
||||
int dummy_ticket; /* enable / disable dummy ticket generator */
|
||||
@ -1718,6 +1731,8 @@ int main(int argc, char *argv[])
|
||||
opt.cert_req_ca_list = DFL_CERT_REQ_CA_LIST;
|
||||
opt.cert_req_dn_hint = DFL_CERT_REQ_DN_HINT;
|
||||
opt.mfl_code = DFL_MFL_CODE;
|
||||
opt.in_content_len = DFL_IN_CONTENT_LEN;
|
||||
opt.out_content_len = DFL_OUT_CONTENT_LEN;
|
||||
opt.trunc_hmac = DFL_TRUNC_HMAC;
|
||||
opt.tickets = DFL_TICKETS;
|
||||
opt.dummy_ticket = DFL_DUMMY_TICKET;
|
||||
@ -2125,6 +2140,18 @@ usage:
|
||||
} else {
|
||||
goto usage;
|
||||
}
|
||||
#if defined(MBEDTLS_SSL_RUNTIME_CONTENT_LEN)
|
||||
} else if (strcmp(p, "in_content_len") == 0) {
|
||||
opt.in_content_len = atoi(q);
|
||||
if (opt.in_content_len <= 0) {
|
||||
goto usage;
|
||||
}
|
||||
} else if (strcmp(p, "out_content_len") == 0) {
|
||||
opt.out_content_len = atoi(q);
|
||||
if (opt.out_content_len <= 0) {
|
||||
goto usage;
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_RUNTIME_CONTENT_LEN */
|
||||
} else if (strcmp(p, "alpn") == 0) {
|
||||
opt.alpn_string = q;
|
||||
} else if (strcmp(p, "trunc_hmac") == 0) {
|
||||
@ -3179,6 +3206,22 @@ usage:
|
||||
mbedtls_ssl_conf_max_tls_version(&conf, opt.max_version);
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_SSL_RUNTIME_CONTENT_LEN)
|
||||
if (opt.in_content_len != DFL_IN_CONTENT_LEN &&
|
||||
(ret = mbedtls_ssl_set_in_content_len(&ssl, opt.in_content_len)) != 0) {
|
||||
mbedtls_printf(" failed\n ! mbedtls_ssl_set_in_content_len returned -0x%x\n\n",
|
||||
(unsigned int) -ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (opt.out_content_len != DFL_OUT_CONTENT_LEN &&
|
||||
(ret = mbedtls_ssl_set_out_content_len(&ssl, opt.out_content_len)) != 0) {
|
||||
mbedtls_printf(" failed\n ! mbedtls_ssl_set_out_content_len returned -0x%x\n\n",
|
||||
(unsigned int) -ret);
|
||||
goto exit;
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_RUNTIME_CONTENT_LEN */
|
||||
|
||||
if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) {
|
||||
mbedtls_printf(" failed\n ! mbedtls_ssl_setup returned -0x%x\n\n", (unsigned int) -ret);
|
||||
goto exit;
|
||||
|
||||
@ -47,6 +47,7 @@ MBEDTLS_SSL_PROTO_TLS1_2
|
||||
MBEDTLS_SSL_PROTO_TLS1_3
|
||||
MBEDTLS_SSL_RECORD_SIZE_LIMIT
|
||||
MBEDTLS_SSL_RENEGOTIATION
|
||||
MBEDTLS_SSL_RUNTIME_CONTENT_LEN
|
||||
MBEDTLS_SSL_SERVER_NAME_INDICATION
|
||||
MBEDTLS_SSL_SESSION_TICKETS
|
||||
MBEDTLS_SSL_SRV_C
|
||||
|
||||
@ -344,6 +344,22 @@ component_test_variable_ssl_in_out_buffer_len () {
|
||||
tests/compat.sh
|
||||
}
|
||||
|
||||
component_test_ssl_runtime_content_len () {
|
||||
msg "build: MBEDTLS_SSL_RUNTIME_CONTENT_LEN enabled (ASan build)"
|
||||
scripts/config.py set MBEDTLS_SSL_RUNTIME_CONTENT_LEN
|
||||
CC=$ASAN_CC cmake -D CMAKE_BUILD_TYPE:String=Asan .
|
||||
make
|
||||
|
||||
msg "test: MBEDTLS_SSL_RUNTIME_CONTENT_LEN enabled"
|
||||
make test
|
||||
|
||||
msg "test: ssl-opt.sh, MBEDTLS_SSL_RUNTIME_CONTENT_LEN enabled"
|
||||
tests/ssl-opt.sh
|
||||
|
||||
msg "test: compat.sh, MBEDTLS_SSL_RUNTIME_CONTENT_LEN enabled"
|
||||
tests/compat.sh
|
||||
}
|
||||
|
||||
component_test_ssl_alloc_buffer_and_mfl () {
|
||||
msg "build: default config with memory buffer allocator and MFL extension"
|
||||
scripts/config.py set MBEDTLS_MEMORY_BUFFER_ALLOC_C
|
||||
@ -361,6 +377,24 @@ component_test_ssl_alloc_buffer_and_mfl () {
|
||||
tests/ssl-opt.sh -f "Handshake memory usage"
|
||||
}
|
||||
|
||||
component_test_ssl_alloc_buffer_and_runtime_content_len () {
|
||||
msg "build: default config with memory buffer allocator and runtime content lengths"
|
||||
scripts/config.py set MBEDTLS_MEMORY_BUFFER_ALLOC_C
|
||||
scripts/config.py set MBEDTLS_PLATFORM_MEMORY
|
||||
scripts/config.py set MBEDTLS_MEMORY_DEBUG
|
||||
scripts/config.py set MBEDTLS_SSL_RUNTIME_CONTENT_LEN
|
||||
scripts/config.py set MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH
|
||||
scripts/config.py set MBEDTLS_SSL_RECORD_SIZE_LIMIT
|
||||
cmake -DCMAKE_BUILD_TYPE:String=Release .
|
||||
make
|
||||
|
||||
msg "test: MBEDTLS_SSL_RUNTIME_CONTENT_LEN, MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH, MBEDTLS_MEMORY_BUFFER_ALLOC_C and MBEDTLS_MEMORY_DEBUG"
|
||||
make test
|
||||
|
||||
msg "test: ssl-opt.sh memory usage and runtime content length, MBEDTLS_SSL_RUNTIME_CONTENT_LEN and MBEDTLS_SSL_RECORD_SIZE_LIMIT"
|
||||
tests/ssl-opt.sh -f "Handshake memory usage\|Runtime content length"
|
||||
}
|
||||
|
||||
component_test_when_no_ciphersuites_have_mac () {
|
||||
msg "build: when no ciphersuites have MAC"
|
||||
scripts/config.py unset PSA_WANT_ALG_CBC_NO_PADDING
|
||||
|
||||
@ -48,6 +48,7 @@ RULES = {
|
||||
'in_msglen': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'in_left': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'in_buf_len': ssl_session_reset_check.ResetBehavior.SPECIAL,
|
||||
'in_content_len': ssl_session_reset_check.ResetBehavior.KEEP,
|
||||
'in_epoch': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'next_record_offset': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'in_window_top': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
@ -75,6 +76,7 @@ RULES = {
|
||||
'out_msglen': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'out_left': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'out_buf_len': ssl_session_reset_check.ResetBehavior.SPECIAL,
|
||||
'out_content_len': ssl_session_reset_check.ResetBehavior.KEEP,
|
||||
'cur_out_ctr': ssl_session_reset_check.ResetBehavior.RESET,
|
||||
'mtu': ssl_session_reset_check.ResetBehavior.KEEP,
|
||||
'hostname': ssl_session_reset_check.ResetBehavior.KEEP,
|
||||
@ -102,8 +104,18 @@ SPECIAL_BEHAVIORS = {
|
||||
'(after->flags & MBEDTLS_SSL_CONTEXT_FLAGS_KEEP_AT_SESSION));'],
|
||||
'tls_version': ['TEST_ASSERT(after->tls_version == after->conf->max_tls_version);'],
|
||||
'user_data': ['TEST_ASSERT(before->user_data.n == after->user_data.n);'],
|
||||
'in_buf_len': ['TEST_ASSERT(after->in_buf_len == MBEDTLS_SSL_IN_BUFFER_LEN);'],
|
||||
'out_buf_len': ['TEST_ASSERT(after->out_buf_len == MBEDTLS_SSL_OUT_BUFFER_LEN);'],
|
||||
'in_buf_len': ['#if defined(MBEDTLS_SSL_RUNTIME_CONTENT_LEN)',
|
||||
'TEST_ASSERT(after->in_buf_len == MBEDTLS_SSL_IN_BUFFER_LEN -',
|
||||
' (MBEDTLS_SSL_IN_CONTENT_LEN - after->in_content_len));',
|
||||
'#else',
|
||||
'TEST_ASSERT(after->in_buf_len == MBEDTLS_SSL_IN_BUFFER_LEN);',
|
||||
'#endif'],
|
||||
'out_buf_len': ['#if defined(MBEDTLS_SSL_RUNTIME_CONTENT_LEN)',
|
||||
'TEST_ASSERT(after->out_buf_len == MBEDTLS_SSL_OUT_BUFFER_LEN -',
|
||||
' (MBEDTLS_SSL_OUT_CONTENT_LEN - after->out_content_len));',
|
||||
'#else',
|
||||
'TEST_ASSERT(after->out_buf_len == MBEDTLS_SSL_OUT_BUFFER_LEN);',
|
||||
'#endif'],
|
||||
}
|
||||
|
||||
NAMED_STRUCTURES = frozenset([
|
||||
|
||||
@ -84,8 +84,16 @@ int mbedtls_test_ssl_check_context_after_session_reset(const mbedtls_ssl_context
|
||||
TEST_ASSERT(after->in_msgtype == initial.in_msgtype);
|
||||
TEST_ASSERT(after->in_msglen == initial.in_msglen);
|
||||
TEST_ASSERT(after->in_left == initial.in_left);
|
||||
#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
|
||||
#if defined(MBEDTLS_SSL_HAVE_BUFFER_LEN_FIELDS)
|
||||
#if defined(MBEDTLS_SSL_RUNTIME_CONTENT_LEN)
|
||||
TEST_ASSERT(after->in_buf_len == MBEDTLS_SSL_IN_BUFFER_LEN -
|
||||
(MBEDTLS_SSL_IN_CONTENT_LEN - after->in_content_len));
|
||||
#else
|
||||
TEST_ASSERT(after->in_buf_len == MBEDTLS_SSL_IN_BUFFER_LEN);
|
||||
#endif
|
||||
#endif
|
||||
#if defined(MBEDTLS_SSL_RUNTIME_CONTENT_LEN)
|
||||
TEST_EQUAL(before->in_content_len, after->in_content_len);
|
||||
#endif
|
||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||
TEST_ASSERT(after->in_epoch == initial.in_epoch);
|
||||
@ -132,8 +140,16 @@ int mbedtls_test_ssl_check_context_after_session_reset(const mbedtls_ssl_context
|
||||
TEST_ASSERT(after->out_msgtype == initial.out_msgtype);
|
||||
TEST_ASSERT(after->out_msglen == initial.out_msglen);
|
||||
TEST_ASSERT(after->out_left == initial.out_left);
|
||||
#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
|
||||
#if defined(MBEDTLS_SSL_HAVE_BUFFER_LEN_FIELDS)
|
||||
#if defined(MBEDTLS_SSL_RUNTIME_CONTENT_LEN)
|
||||
TEST_ASSERT(after->out_buf_len == MBEDTLS_SSL_OUT_BUFFER_LEN -
|
||||
(MBEDTLS_SSL_OUT_CONTENT_LEN - after->out_content_len));
|
||||
#else
|
||||
TEST_ASSERT(after->out_buf_len == MBEDTLS_SSL_OUT_BUFFER_LEN);
|
||||
#endif
|
||||
#endif
|
||||
#if defined(MBEDTLS_SSL_RUNTIME_CONTENT_LEN)
|
||||
TEST_EQUAL(before->out_content_len, after->out_content_len);
|
||||
#endif
|
||||
TEST_MEMORY_COMPARE(after->cur_out_ctr, sizeof(after->cur_out_ctr), initial.cur_out_ctr, sizeof(initial.cur_out_ctr));
|
||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||
|
||||
@ -2152,9 +2152,14 @@ static int test_renegotiation(const mbedtls_test_handshake_test_options *options
|
||||
ret = mbedtls_ssl_renegotiate(&(client->ssl));
|
||||
#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
|
||||
if (options->resize_buffers != 0) {
|
||||
/* Ensure that the buffer sizes are appropriate before resizes */
|
||||
TEST_EQUAL(client->ssl.out_buf_len, MBEDTLS_SSL_OUT_BUFFER_LEN);
|
||||
TEST_EQUAL(client->ssl.in_buf_len, MBEDTLS_SSL_IN_BUFFER_LEN);
|
||||
/* Starting the renegotiation grew the buffers back to the full size
|
||||
* of this connection: its own content lengths, not the build-time
|
||||
* maximum, so that MBEDTLS_SSL_RUNTIME_CONTENT_LEN keeps its saving.
|
||||
* Without that option the two are the same. */
|
||||
TEST_EQUAL(client->ssl.out_buf_len,
|
||||
mbedtls_ssl_compute_out_buf_len(&client->ssl));
|
||||
TEST_EQUAL(client->ssl.in_buf_len,
|
||||
mbedtls_ssl_compute_in_buf_len(&client->ssl));
|
||||
}
|
||||
#endif
|
||||
TEST_ASSERT(ret == 0 ||
|
||||
@ -2233,9 +2238,11 @@ static int test_serialization(const mbedtls_test_handshake_test_options *options
|
||||
#endif
|
||||
#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
|
||||
if (options->resize_buffers != 0) {
|
||||
/* Ensure that the buffer sizes are appropriate before resizes */
|
||||
TEST_EQUAL(server->ssl.out_buf_len, MBEDTLS_SSL_OUT_BUFFER_LEN);
|
||||
TEST_EQUAL(server->ssl.in_buf_len, MBEDTLS_SSL_IN_BUFFER_LEN);
|
||||
/* The freshly set up connection starts at its own full size. */
|
||||
TEST_EQUAL(server->ssl.out_buf_len,
|
||||
mbedtls_ssl_compute_out_buf_len(&server->ssl));
|
||||
TEST_EQUAL(server->ssl.in_buf_len,
|
||||
mbedtls_ssl_compute_in_buf_len(&server->ssl));
|
||||
}
|
||||
#endif
|
||||
TEST_EQUAL(mbedtls_ssl_context_load(&(server->ssl), context_buf,
|
||||
@ -2283,11 +2290,18 @@ int mbedtls_test_ssl_perform_connection(
|
||||
|
||||
#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
|
||||
if (options->resize_buffers != 0) {
|
||||
/* Ensure that the buffer sizes are appropriate before resizes */
|
||||
TEST_EQUAL(client->ssl.out_buf_len, MBEDTLS_SSL_OUT_BUFFER_LEN);
|
||||
TEST_EQUAL(client->ssl.in_buf_len, MBEDTLS_SSL_IN_BUFFER_LEN);
|
||||
TEST_EQUAL(server->ssl.out_buf_len, MBEDTLS_SSL_OUT_BUFFER_LEN);
|
||||
TEST_EQUAL(server->ssl.in_buf_len, MBEDTLS_SSL_IN_BUFFER_LEN);
|
||||
/* Before the handshake, including after a session reset, each
|
||||
* buffer is the full size of its connection: its own content length,
|
||||
* which is the build-time maximum unless
|
||||
* MBEDTLS_SSL_RUNTIME_CONTENT_LEN shrank it. */
|
||||
TEST_EQUAL(client->ssl.out_buf_len,
|
||||
mbedtls_ssl_compute_out_buf_len(&client->ssl));
|
||||
TEST_EQUAL(client->ssl.in_buf_len,
|
||||
mbedtls_ssl_compute_in_buf_len(&client->ssl));
|
||||
TEST_EQUAL(server->ssl.out_buf_len,
|
||||
mbedtls_ssl_compute_out_buf_len(&server->ssl));
|
||||
TEST_EQUAL(server->ssl.in_buf_len,
|
||||
mbedtls_ssl_compute_in_buf_len(&server->ssl));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
195
tests/ssl-opt.sh
195
tests/ssl-opt.sh
@ -1235,6 +1235,45 @@ handshake_memory_check() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Get peak memory usage from server output and put it into the variable specified by the first argument
|
||||
handshake_peak_memory_get() {
|
||||
OUTPUT_VARIABLE="$1"
|
||||
OUTPUT_FILE="$2"
|
||||
|
||||
# Get peak memory usage from a pattern like "Heap memory usage after handshake: 23112 bytes. Peak memory usage was 33112"
|
||||
MEM_USAGE=$(sed -n 's/.*Peak memory usage was //p' < "$OUTPUT_FILE" | grep -o "[0-9]*" | head -1)
|
||||
|
||||
# Check if peak memory usage was read
|
||||
if [ -z "$MEM_USAGE" ]; then
|
||||
echo "Error: Can not read the value of peak memory usage"
|
||||
return 1
|
||||
else
|
||||
eval "$OUTPUT_VARIABLE=$MEM_USAGE"
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
# Get peak memory usage from server output and check if this value
|
||||
# is not higher than the maximum given by the first argument
|
||||
handshake_peak_memory_check() {
|
||||
MAX_MEMORY="$1"
|
||||
OUTPUT_FILE="$2"
|
||||
|
||||
# Get peak memory usage
|
||||
if ! handshake_peak_memory_get "MEMORY_USAGE" "$OUTPUT_FILE"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Check if peak memory usage is below max value
|
||||
if [ "$MEMORY_USAGE" -gt "$MAX_MEMORY" ]; then
|
||||
echo "\nFailed: Peak memory usage was $MEMORY_USAGE bytes," \
|
||||
"but should be below $MAX_MEMORY bytes"
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
# wait for client to terminate and set CLI_EXIT
|
||||
# must be called right after starting the client
|
||||
wait_client_done() {
|
||||
@ -1910,6 +1949,55 @@ run_tests_memory_after_handshake()
|
||||
run_test_memory_after_handshake_with_mfl 512 "$MEMORY_USAGE_MFL_16K"
|
||||
}
|
||||
|
||||
# Test that the server's peak memory usage falls when it shrinks its own content
|
||||
# lengths at runtime.
|
||||
# first argument ($1) is the server's incoming content length
|
||||
# second argument ($2) is the server's outgoing content length
|
||||
# third argument ($3) is the server's peak memory usage with the default lengths
|
||||
run_test_memory_with_runtime_content_len()
|
||||
{
|
||||
# The I/O buffers shrink by exactly (16384 - $1) + (16384 - $2). Require
|
||||
# most of that saving, so that the test fails if the lengths never reach
|
||||
# the allocation.
|
||||
MEMORY_USAGE_LIMIT="$(( $3 - ( ( 16384 - $1 ) + ( 16384 - $2 ) ) * 9 / 10 ))"
|
||||
|
||||
run_test "Handshake memory usage (runtime content length in $1, out $2)" \
|
||||
"$P_SRV debug_level=3 auth_mode=required force_version=tls12 \
|
||||
in_content_len=$1 out_content_len=$2" \
|
||||
"$P_CLI debug_level=3 \
|
||||
crt_file=$DATA_FILES_PATH/server5.crt key_file=$DATA_FILES_PATH/server5.key \
|
||||
force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-CCM" \
|
||||
0 \
|
||||
-F "handshake_peak_memory_check $MEMORY_USAGE_LIMIT"
|
||||
}
|
||||
|
||||
# Test that the server's peak memory usage falls when it shrinks its incoming
|
||||
# length, its outgoing length, or both
|
||||
run_tests_memory_with_runtime_content_len()
|
||||
{
|
||||
# all tests in this sequence requires the same configuration (see requires_config_enabled())
|
||||
SKIP_THIS_TESTS="$SKIP_NEXT"
|
||||
|
||||
# first test with the default lengths is to get reference memory usage
|
||||
PEAK_MEMORY_USAGE_16K=0
|
||||
run_test "Handshake memory usage initial (runtime content length default)" \
|
||||
"$P_SRV debug_level=3 auth_mode=required force_version=tls12" \
|
||||
"$P_CLI debug_level=3 \
|
||||
crt_file=$DATA_FILES_PATH/server5.crt key_file=$DATA_FILES_PATH/server5.key \
|
||||
force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-CCM" \
|
||||
0 \
|
||||
-F "handshake_peak_memory_get PEAK_MEMORY_USAGE_16K"
|
||||
|
||||
SKIP_NEXT="$SKIP_THIS_TESTS"
|
||||
run_test_memory_with_runtime_content_len 4096 4096 "$PEAK_MEMORY_USAGE_16K"
|
||||
|
||||
SKIP_NEXT="$SKIP_THIS_TESTS"
|
||||
run_test_memory_with_runtime_content_len 1024 16384 "$PEAK_MEMORY_USAGE_16K"
|
||||
|
||||
SKIP_NEXT="$SKIP_THIS_TESTS"
|
||||
run_test_memory_with_runtime_content_len 16384 1024 "$PEAK_MEMORY_USAGE_16K"
|
||||
}
|
||||
|
||||
run_test_export_keying_material() {
|
||||
unset EXPORTED_KEY1
|
||||
unset EXPORTED_KEY2
|
||||
@ -5134,6 +5222,105 @@ run_test "Record Size Limit: TLS 1.3 m->m: both peer comply with record size
|
||||
|
||||
# End of Record size limit tests
|
||||
|
||||
# Tests for runtime content lengths: a client that shrinks its incoming length
|
||||
# against a full-size server. Only a negotiated max_fragment_length or
|
||||
# record_size_limit tells the server about it; without either, a record longer
|
||||
# than the client's incoming length makes the read fail cleanly, the same way
|
||||
# it does when MBEDTLS_SSL_IN_CONTENT_LEN is set to that length at build time.
|
||||
|
||||
requires_config_enabled MBEDTLS_SSL_RUNTIME_CONTENT_LEN
|
||||
requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
|
||||
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
|
||||
requires_max_content_len 2048
|
||||
run_test "Runtime content length: client in 1024, MFL 1024" \
|
||||
"$P_SRV debug_level=3 response_size=2000" \
|
||||
"$P_CLI debug_level=3 force_version=tls12 in_content_len=1024 max_frag_len=1024" \
|
||||
0 \
|
||||
-c "client hello, adding max_fragment_length extension" \
|
||||
-s "server hello, max_fragment_length extension" \
|
||||
-c "Maximum incoming record payload length is 1024" \
|
||||
-s "Maximum outgoing record payload length is 1024" \
|
||||
-s "2000 bytes written in 2 fragments" \
|
||||
-c "1024 bytes read" \
|
||||
-c "976 bytes read"
|
||||
|
||||
requires_config_enabled MBEDTLS_SSL_RUNTIME_CONTENT_LEN
|
||||
requires_config_enabled MBEDTLS_SSL_CLI_C
|
||||
requires_config_enabled MBEDTLS_SSL_SRV_C
|
||||
requires_config_enabled MBEDTLS_DEBUG_C
|
||||
requires_config_enabled MBEDTLS_SSL_RECORD_SIZE_LIMIT
|
||||
requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
|
||||
requires_max_content_len 2048
|
||||
run_test "Runtime content length: client in 1024, record_size_limit" \
|
||||
"$P_SRV debug_level=3 response_size=2000" \
|
||||
"$P_CLI debug_level=3 force_version=tls13 in_content_len=1024" \
|
||||
0 \
|
||||
-c "Sent RecordSizeLimit: 1024 Bytes" \
|
||||
-s "RecordSizeLimit: 1024 Bytes" \
|
||||
-c "Maximum incoming record payload length is 1024" \
|
||||
-s "Maximum outgoing record payload length is 1023" \
|
||||
-s "2000 bytes written in 2 fragments" \
|
||||
-c "1023 bytes read" \
|
||||
-c "977 bytes read"
|
||||
|
||||
requires_config_enabled MBEDTLS_SSL_RUNTIME_CONTENT_LEN
|
||||
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
|
||||
requires_max_content_len 2048
|
||||
run_test "Runtime content length: client in 1024, no extension, short record" \
|
||||
"$P_SRV debug_level=3" \
|
||||
"$P_CLI debug_level=3 force_version=tls12 in_content_len=1024" \
|
||||
0 \
|
||||
-C "client hello, adding max_fragment_length extension" \
|
||||
-c "Maximum incoming record payload length is 1024" \
|
||||
-s "Maximum outgoing record payload length is 16384" \
|
||||
-c "[0-9]\+ bytes read"
|
||||
|
||||
requires_config_enabled MBEDTLS_SSL_RUNTIME_CONTENT_LEN
|
||||
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
|
||||
requires_max_content_len 2048
|
||||
run_test "Runtime content length: client in 1024, no extension, 1025 bytes" \
|
||||
"$P_SRV debug_level=3 response_size=1025" \
|
||||
"$P_CLI debug_level=3 force_version=tls12 in_content_len=1024" \
|
||||
1 \
|
||||
-C "client hello, adding max_fragment_length extension" \
|
||||
-s "Maximum outgoing record payload length is 16384" \
|
||||
-s "1025 bytes written in 1 fragments" \
|
||||
-c "bad message length" \
|
||||
-c "mbedtls_ssl_read returned -0x7200" \
|
||||
-C "[0-9]\+ bytes read"
|
||||
|
||||
requires_config_enabled MBEDTLS_SSL_RUNTIME_CONTENT_LEN
|
||||
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
|
||||
requires_max_content_len 2048
|
||||
run_test "Runtime content length: client in 1024, no extension, 2000 bytes" \
|
||||
"$P_SRV debug_level=3 response_size=2000" \
|
||||
"$P_CLI debug_level=3 force_version=tls12 in_content_len=1024" \
|
||||
1 \
|
||||
-C "client hello, adding max_fragment_length extension" \
|
||||
-s "Maximum outgoing record payload length is 16384" \
|
||||
-s "2000 bytes written in 1 fragments" \
|
||||
-c "requesting more data than fits" \
|
||||
-c "mbedtls_ssl_read returned -0x87" \
|
||||
-C "[0-9]\+ bytes read"
|
||||
|
||||
requires_config_enabled MBEDTLS_SSL_RUNTIME_CONTENT_LEN
|
||||
requires_config_enabled MBEDTLS_SSL_CLI_C
|
||||
requires_config_enabled MBEDTLS_SSL_SRV_C
|
||||
requires_config_disabled MBEDTLS_SSL_RECORD_SIZE_LIMIT
|
||||
requires_config_enabled MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
|
||||
requires_max_content_len 2048
|
||||
run_test "Runtime content length: client in 1024, TLS 1.3, no extension" \
|
||||
"$P_SRV debug_level=3 response_size=2000" \
|
||||
"$P_CLI debug_level=3 force_version=tls13 in_content_len=1024" \
|
||||
1 \
|
||||
-s "Maximum outgoing record payload length is 16383" \
|
||||
-s "2000 bytes written in 1 fragments" \
|
||||
-c "requesting more data than fits" \
|
||||
-c "mbedtls_ssl_read returned -0x87" \
|
||||
-C "[0-9]\+ bytes read"
|
||||
|
||||
# End of runtime content length tests
|
||||
|
||||
# Tests for renegotiation
|
||||
|
||||
# G_NEXT_SRV is used in renegotiation tests becuase of the increased
|
||||
@ -14440,6 +14627,14 @@ requires_config_enabled MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
|
||||
requires_max_content_len 16384
|
||||
run_tests_memory_after_handshake
|
||||
|
||||
# Test peak heap memory usage with runtime content lengths
|
||||
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
|
||||
requires_config_enabled MBEDTLS_MEMORY_DEBUG
|
||||
requires_config_enabled MBEDTLS_MEMORY_BUFFER_ALLOC_C
|
||||
requires_config_enabled MBEDTLS_SSL_RUNTIME_CONTENT_LEN
|
||||
requires_max_content_len 16384
|
||||
run_tests_memory_with_runtime_content_len
|
||||
|
||||
if [ "$LIST_TESTS" -eq 0 ]; then
|
||||
|
||||
# Final report
|
||||
|
||||
@ -3653,3 +3653,194 @@ tls13_record_boundary_alignment:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_HS_FINISHED
|
||||
TLS 1.3 EndOfEarlyData record boundary alignment enforcement
|
||||
depends_on:MBEDTLS_SSL_EARLY_DATA:MBEDTLS_SSL_SESSION_TICKETS
|
||||
tls13_record_boundary_alignment:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_HS_END_OF_EARLY_DATA
|
||||
|
||||
Runtime content length: enabling the option alone changes nothing, TLS
|
||||
depends_on:MBEDTLS_SSL_PROTO_TLS1_2
|
||||
ssl_runtime_content_len_default_is_noop:0
|
||||
|
||||
Runtime content length: enabling the option alone changes nothing, DTLS
|
||||
depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SSL_PROTO_DTLS
|
||||
ssl_runtime_content_len_default_is_noop:1
|
||||
|
||||
Runtime content length: incoming above the build-time ceiling is rejected
|
||||
ssl_runtime_content_len_set:0:0:MBEDTLS_SSL_IN_CONTENT_LEN + 1:MBEDTLS_ERR_SSL_BAD_INPUT_DATA
|
||||
|
||||
Runtime content length: outgoing above the build-time ceiling is rejected
|
||||
ssl_runtime_content_len_set:1:0:MBEDTLS_SSL_OUT_CONTENT_LEN + 1:MBEDTLS_ERR_SSL_BAD_INPUT_DATA
|
||||
|
||||
Runtime content length: incoming at the build-time ceiling is accepted
|
||||
ssl_runtime_content_len_set:0:0:MBEDTLS_SSL_IN_CONTENT_LEN:0
|
||||
|
||||
Runtime content length: outgoing at the build-time ceiling is accepted
|
||||
ssl_runtime_content_len_set:1:0:MBEDTLS_SSL_OUT_CONTENT_LEN:0
|
||||
|
||||
Runtime content length: incoming below the floor is rejected
|
||||
ssl_runtime_content_len_set:0:0:MBEDTLS_SSL_IN_CONTENT_LEN_MIN - 1:MBEDTLS_ERR_SSL_BAD_INPUT_DATA
|
||||
|
||||
Runtime content length: incoming at the floor is accepted
|
||||
ssl_runtime_content_len_set:0:0:MBEDTLS_SSL_IN_CONTENT_LEN_MIN:0
|
||||
|
||||
Runtime content length: outgoing below the floor is rejected
|
||||
ssl_runtime_content_len_set:1:0:MBEDTLS_SSL_OUT_CONTENT_LEN_MIN - 1:MBEDTLS_ERR_SSL_BAD_INPUT_DATA
|
||||
|
||||
Runtime content length: outgoing at the floor is accepted
|
||||
ssl_runtime_content_len_set:1:0:MBEDTLS_SSL_OUT_CONTENT_LEN_MIN:0
|
||||
|
||||
Runtime content length: zero incoming is rejected
|
||||
ssl_runtime_content_len_set:0:0:0:MBEDTLS_ERR_SSL_BAD_INPUT_DATA
|
||||
|
||||
Runtime content length: outgoing too short for a certificate header is rejected
|
||||
ssl_runtime_content_len_set:1:0:10:MBEDTLS_ERR_SSL_BAD_INPUT_DATA
|
||||
|
||||
Runtime content length: outgoing too short for a DTLS handshake header is rejected
|
||||
ssl_runtime_content_len_set:1:0:11:MBEDTLS_ERR_SSL_BAD_INPUT_DATA
|
||||
|
||||
Runtime content length: outgoing below TLS 1.3 padding granularity is rejected
|
||||
depends_on:MBEDTLS_SSL_PROTO_TLS1_3
|
||||
ssl_runtime_content_len_set:1:0:MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY - 1:MBEDTLS_ERR_SSL_BAD_INPUT_DATA
|
||||
|
||||
Runtime content length: incoming after setup is rejected
|
||||
ssl_runtime_content_len_set:0:1:MBEDTLS_SSL_IN_CONTENT_LEN / 2:MBEDTLS_ERR_SSL_BAD_INPUT_DATA
|
||||
|
||||
Runtime content length: outgoing after setup is rejected
|
||||
ssl_runtime_content_len_set:1:1:MBEDTLS_SSL_OUT_CONTENT_LEN / 2:MBEDTLS_ERR_SSL_BAD_INPUT_DATA
|
||||
|
||||
Runtime content length: incoming after session reset is rejected
|
||||
ssl_runtime_content_len_set:0:2:MBEDTLS_SSL_IN_CONTENT_LEN / 2:MBEDTLS_ERR_SSL_BAD_INPUT_DATA
|
||||
|
||||
Runtime content length: outgoing after session reset is rejected
|
||||
ssl_runtime_content_len_set:1:2:MBEDTLS_SSL_OUT_CONTENT_LEN / 2:MBEDTLS_ERR_SSL_BAD_INPUT_DATA
|
||||
|
||||
Runtime content length: one connection, different incoming and outgoing, TLS 1.2
|
||||
depends_on:MBEDTLS_SSL_PROTO_TLS1_2
|
||||
ssl_runtime_content_len_handshake:MBEDTLS_SSL_VERSION_TLS1_2:0:2048:512:0:0:1024:2:2048:1:0
|
||||
|
||||
Runtime content length: two peers with different lengths, TLS 1.2
|
||||
depends_on:MBEDTLS_SSL_PROTO_TLS1_2
|
||||
ssl_runtime_content_len_handshake:MBEDTLS_SSL_VERSION_TLS1_2:0:4096:1024:1024:4096:2048:2:4096:1:0
|
||||
|
||||
Runtime content length: two peers with different lengths, DTLS 1.2
|
||||
depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SSL_PROTO_DTLS
|
||||
ssl_runtime_content_len_handshake:MBEDTLS_SSL_VERSION_TLS1_2:1:4096:1024:1024:4096:1024:1:4096:1:0
|
||||
|
||||
Runtime content length: DTLS 1.2 refuses a message above the outgoing length
|
||||
depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SSL_PROTO_DTLS
|
||||
ssl_runtime_content_len_handshake:MBEDTLS_SSL_VERSION_TLS1_2:1:4096:1024:1024:4096:1025:0:4096:1:0
|
||||
|
||||
Runtime content length: two peers with different lengths, TLS 1.3
|
||||
depends_on:MBEDTLS_SSL_PROTO_TLS1_3
|
||||
ssl_runtime_content_len_handshake:MBEDTLS_SSL_VERSION_TLS1_3:0:4096:1024:1024:4096:2048:3:4095:1:0
|
||||
|
||||
Runtime content length: lengths survive a session reset, TLS 1.2
|
||||
depends_on:MBEDTLS_SSL_PROTO_TLS1_2
|
||||
ssl_runtime_content_len_handshake:MBEDTLS_SSL_VERSION_TLS1_2:0:0:1024:0:1024:2048:2:2048:2:1
|
||||
|
||||
Runtime content length: lengths survive a session reset, TLS 1.3
|
||||
depends_on:MBEDTLS_SSL_PROTO_TLS1_3
|
||||
ssl_runtime_content_len_handshake:MBEDTLS_SSL_VERSION_TLS1_3:0:0:1024:0:1024:2046:2:2046:2:1
|
||||
|
||||
Runtime content length: resize, TLS 1.2
|
||||
ssl_runtime_content_len_resize_buffers:0:MBEDTLS_SSL_MAX_FRAG_LEN_NONE:0:2048:1024:1024:2048
|
||||
|
||||
Runtime content length: resize, MFL=512, TLS 1.2
|
||||
ssl_runtime_content_len_resize_buffers:0:MBEDTLS_SSL_MAX_FRAG_LEN_512:0:2048:1024:1024:2048
|
||||
|
||||
Runtime content length: resize, reneg, DTLS 1.2
|
||||
depends_on:MBEDTLS_SSL_RENEGOTIATION:MBEDTLS_SSL_PROTO_DTLS
|
||||
ssl_runtime_content_len_resize_buffers:1:MBEDTLS_SSL_MAX_FRAG_LEN_NONE:1:2048:1024:1024:2048
|
||||
|
||||
Runtime content length: resize, MFL=512, reneg, DTLS 1.2
|
||||
depends_on:MBEDTLS_SSL_RENEGOTIATION:MBEDTLS_SSL_PROTO_DTLS
|
||||
ssl_runtime_content_len_resize_buffers:1:MBEDTLS_SSL_MAX_FRAG_LEN_512:1:2048:1024:1024:2048
|
||||
|
||||
Runtime content length: resize, MFL above out len, reneg, DTLS 1.2
|
||||
depends_on:MBEDTLS_SSL_RENEGOTIATION:MBEDTLS_SSL_PROTO_DTLS
|
||||
ssl_runtime_content_len_resize_buffers:1:MBEDTLS_SSL_MAX_FRAG_LEN_4096:1:4096:1024:1024:2048
|
||||
|
||||
Runtime content length: resize, server shrunk, reneg, DTLS 1.2
|
||||
depends_on:MBEDTLS_SSL_RENEGOTIATION:MBEDTLS_SSL_PROTO_DTLS
|
||||
ssl_runtime_content_len_resize_buffers:1:MBEDTLS_SSL_MAX_FRAG_LEN_1024:1:0:0:2048:1024
|
||||
|
||||
Runtime content length: record at the incoming length is accepted, TLS 1.2
|
||||
depends_on:MBEDTLS_SSL_PROTO_TLS1_2
|
||||
ssl_runtime_content_len_oversized_record:MBEDTLS_SSL_VERSION_TLS1_2:1024:1024:0
|
||||
|
||||
Runtime content length: record above the incoming length is rejected, TLS 1.2
|
||||
depends_on:MBEDTLS_SSL_PROTO_TLS1_2
|
||||
ssl_runtime_content_len_oversized_record:MBEDTLS_SSL_VERSION_TLS1_2:1024:1025:MBEDTLS_ERR_SSL_INVALID_RECORD
|
||||
|
||||
Runtime content length: record at the incoming length is accepted, TLS 1.3
|
||||
depends_on:MBEDTLS_SSL_PROTO_TLS1_3:!MBEDTLS_SSL_RECORD_SIZE_LIMIT
|
||||
ssl_runtime_content_len_oversized_record:MBEDTLS_SSL_VERSION_TLS1_3:1024:1024:0
|
||||
|
||||
Runtime content length: record above the incoming length is rejected, TLS 1.3
|
||||
depends_on:MBEDTLS_SSL_PROTO_TLS1_3:!MBEDTLS_SSL_RECORD_SIZE_LIMIT
|
||||
ssl_runtime_content_len_oversized_record:MBEDTLS_SSL_VERSION_TLS1_3:1024:1025:MBEDTLS_ERR_SSL_INVALID_RECORD
|
||||
|
||||
Runtime content length: client setup accepts a fragment length at the incoming length
|
||||
depends_on:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_PROTO_TLS1_2
|
||||
ssl_runtime_content_len_setup_mfl:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_2:1024:MBEDTLS_SSL_MAX_FRAG_LEN_1024:0
|
||||
|
||||
Runtime content length: client setup rejects a fragment length above the incoming length
|
||||
depends_on:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_PROTO_TLS1_2
|
||||
ssl_runtime_content_len_setup_mfl:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_2:1023:MBEDTLS_SSL_MAX_FRAG_LEN_1024:MBEDTLS_ERR_SSL_BAD_CONFIG
|
||||
|
||||
Runtime content length: client setup rejects the largest fragment length above the incoming length
|
||||
depends_on:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_PROTO_TLS1_2
|
||||
ssl_runtime_content_len_setup_mfl:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_2:4095:MBEDTLS_SSL_MAX_FRAG_LEN_4096:MBEDTLS_ERR_SSL_BAD_CONFIG
|
||||
|
||||
Runtime content length: client setup accepts a short incoming length without a fragment length
|
||||
depends_on:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_PROTO_TLS1_2
|
||||
ssl_runtime_content_len_setup_mfl:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_2:512:MBEDTLS_SSL_MAX_FRAG_LEN_NONE:0
|
||||
|
||||
Runtime content length: TLS 1.3-only client setup accepts a fragment length above the incoming length
|
||||
depends_on:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_PROTO_TLS1_3
|
||||
ssl_runtime_content_len_setup_mfl:MBEDTLS_SSL_IS_CLIENT:MBEDTLS_SSL_VERSION_TLS1_3:1023:MBEDTLS_SSL_MAX_FRAG_LEN_1024:0
|
||||
|
||||
Runtime content length: server setup accepts a fragment length above the incoming length
|
||||
depends_on:MBEDTLS_SSL_SRV_C:MBEDTLS_SSL_PROTO_TLS1_2
|
||||
ssl_runtime_content_len_setup_mfl:MBEDTLS_SSL_IS_SERVER:MBEDTLS_SSL_VERSION_TLS1_2:1024:MBEDTLS_SSL_MAX_FRAG_LEN_4096:0
|
||||
|
||||
Runtime content length: ClientHello max_fragment_length at the incoming length
|
||||
depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
|
||||
ssl_runtime_content_len_client_hello_ext:MBEDTLS_SSL_VERSION_TLS1_2:1024:MBEDTLS_SSL_MAX_FRAG_LEN_1024:MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH:0:MBEDTLS_SSL_MAX_FRAG_LEN_1024
|
||||
|
||||
Runtime content length: ClientHello max_fragment_length below the incoming length
|
||||
depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
|
||||
ssl_runtime_content_len_client_hello_ext:MBEDTLS_SSL_VERSION_TLS1_2:1024:MBEDTLS_SSL_MAX_FRAG_LEN_512:MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH:0:MBEDTLS_SSL_MAX_FRAG_LEN_512
|
||||
|
||||
Runtime content length: ClientHello has no max_fragment_length unless configured
|
||||
depends_on:MBEDTLS_SSL_PROTO_TLS1_2
|
||||
ssl_runtime_content_len_client_hello_ext:MBEDTLS_SSL_VERSION_TLS1_2:1024:MBEDTLS_SSL_MAX_FRAG_LEN_NONE:MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH:0:-1
|
||||
|
||||
Runtime content length: ClientHello record_size_limit, build-time incoming length
|
||||
depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_RECORD_SIZE_LIMIT
|
||||
ssl_runtime_content_len_client_hello_ext:MBEDTLS_SSL_VERSION_TLS1_3:MBEDTLS_SSL_IN_CONTENT_LEN:MBEDTLS_SSL_MAX_FRAG_LEN_NONE:MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT:0:MBEDTLS_SSL_IN_CONTENT_LEN
|
||||
|
||||
Runtime content length: ClientHello record_size_limit carries the incoming length
|
||||
depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_RECORD_SIZE_LIMIT
|
||||
ssl_runtime_content_len_client_hello_ext:MBEDTLS_SSL_VERSION_TLS1_3:1024:MBEDTLS_SSL_MAX_FRAG_LEN_NONE:MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT:0:1024
|
||||
|
||||
Runtime content length: ClientHello record_size_limit at the RFC 8449 minimum
|
||||
depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_RECORD_SIZE_LIMIT
|
||||
ssl_runtime_content_len_client_hello_ext:MBEDTLS_SSL_VERSION_TLS1_3:64:MBEDTLS_SSL_MAX_FRAG_LEN_NONE:MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT:0:64
|
||||
|
||||
Runtime content length: ClientHello record_size_limit below the RFC 8449 minimum is refused
|
||||
depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_RECORD_SIZE_LIMIT
|
||||
ssl_runtime_content_len_client_hello_ext:MBEDTLS_SSL_VERSION_TLS1_3:63:MBEDTLS_SSL_MAX_FRAG_LEN_NONE:MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT:MBEDTLS_ERR_SSL_BAD_INPUT_DATA:-1
|
||||
|
||||
Runtime content length: max record payload reports the connection's lengths, TLS 1.2
|
||||
depends_on:MBEDTLS_SSL_PROTO_TLS1_2
|
||||
ssl_runtime_content_len_max_payload:MBEDTLS_SSL_VERSION_TLS1_2:2048:1024:MBEDTLS_SSL_MAX_FRAG_LEN_NONE:1024:2048:1024
|
||||
|
||||
Runtime content length: max record payload with a fragment length below both lengths, TLS 1.2
|
||||
depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
|
||||
ssl_runtime_content_len_max_payload:MBEDTLS_SSL_VERSION_TLS1_2:2048:1024:MBEDTLS_SSL_MAX_FRAG_LEN_512:512:512:512
|
||||
|
||||
Runtime content length: max record payload with a fragment length at the incoming length, TLS 1.2
|
||||
depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
|
||||
ssl_runtime_content_len_max_payload:MBEDTLS_SSL_VERSION_TLS1_2:2048:4096:MBEDTLS_SSL_MAX_FRAG_LEN_2048:2048:2048:2048
|
||||
|
||||
Runtime content length: max record payload reports the connection's lengths, TLS 1.3
|
||||
depends_on:MBEDTLS_SSL_PROTO_TLS1_3
|
||||
ssl_runtime_content_len_max_payload:MBEDTLS_SSL_VERSION_TLS1_3:2048:1024:MBEDTLS_SSL_MAX_FRAG_LEN_NONE:1024:2048:1023
|
||||
|
||||
@ -4071,6 +4071,567 @@ void resize_buffers_renegotiate_mfl(int mfl, int legacy_renegotiation,
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_SSL_RUNTIME_CONTENT_LEN:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_ALG_SHA_256 */
|
||||
void ssl_runtime_content_len_default_is_noop(int dtls)
|
||||
{
|
||||
/* MBEDTLS_SSL_RUNTIME_CONTENT_LEN promises that enabling it, without
|
||||
* calling either setter, changes nothing. Prove it at the two places the
|
||||
* option could leak: the lengths a fresh connection starts with, and the
|
||||
* buffers that setting one up allocates. Then run a handshake and an
|
||||
* application-data exchange over those buffers, and reset the connection,
|
||||
* so that a length recorded wrongly shows up as a failure rather than as
|
||||
* a number nobody reads. */
|
||||
mbedtls_test_ssl_endpoint client;
|
||||
memset(&client, 0, sizeof(client));
|
||||
mbedtls_test_ssl_endpoint server;
|
||||
memset(&server, 0, sizeof(server));
|
||||
mbedtls_test_handshake_test_options options;
|
||||
mbedtls_test_init_handshake_options(&options);
|
||||
mbedtls_ssl_context fresh;
|
||||
mbedtls_ssl_init(&fresh);
|
||||
|
||||
MD_OR_USE_PSA_INIT();
|
||||
|
||||
/* An initialised connection starts at the build-time maxima. */
|
||||
TEST_EQUAL(fresh.in_content_len, MBEDTLS_SSL_IN_CONTENT_LEN);
|
||||
TEST_EQUAL(fresh.out_content_len, MBEDTLS_SSL_OUT_CONTENT_LEN);
|
||||
|
||||
options.pk_alg = MBEDTLS_PK_ECDSA;
|
||||
options.dtls = dtls;
|
||||
if (dtls) {
|
||||
options.expected_negotiated_version = MBEDTLS_SSL_VERSION_TLS1_2;
|
||||
}
|
||||
|
||||
TEST_EQUAL(mbedtls_test_ssl_endpoint_init(&client, MBEDTLS_SSL_IS_CLIENT,
|
||||
&options), 0);
|
||||
TEST_EQUAL(mbedtls_test_ssl_endpoint_init(&server, MBEDTLS_SSL_IS_SERVER,
|
||||
&options), 0);
|
||||
|
||||
/* Setting up a connection that asked for nothing allocates exactly what
|
||||
* it allocated before the option existed. */
|
||||
TEST_EQUAL(client.ssl.in_buf_len, MBEDTLS_SSL_IN_BUFFER_LEN);
|
||||
TEST_EQUAL(client.ssl.out_buf_len, MBEDTLS_SSL_OUT_BUFFER_LEN);
|
||||
TEST_EQUAL(server.ssl.in_buf_len, MBEDTLS_SSL_IN_BUFFER_LEN);
|
||||
TEST_EQUAL(server.ssl.out_buf_len, MBEDTLS_SSL_OUT_BUFFER_LEN);
|
||||
|
||||
if (dtls) {
|
||||
TEST_EQUAL(mbedtls_test_ssl_dtls_join_endpoints(&client, &server), 0);
|
||||
}
|
||||
|
||||
/* A full handshake plus an application-data exchange over those buffers.
|
||||
* The handshake is where the automatic-resize path, when it is compiled
|
||||
* in, would grow the buffers; either way they must land back on the same
|
||||
* lengths as a connection that never asked for anything. */
|
||||
TEST_ASSERT(mbedtls_test_ssl_perform_connection(&options, &client, &server));
|
||||
|
||||
TEST_EQUAL(client.ssl.in_buf_len, MBEDTLS_SSL_IN_BUFFER_LEN);
|
||||
TEST_EQUAL(client.ssl.out_buf_len, MBEDTLS_SSL_OUT_BUFFER_LEN);
|
||||
TEST_EQUAL(server.ssl.in_buf_len, MBEDTLS_SSL_IN_BUFFER_LEN);
|
||||
TEST_EQUAL(server.ssl.out_buf_len, MBEDTLS_SSL_OUT_BUFFER_LEN);
|
||||
|
||||
/* Reset uses the recorded lengths to rebase the buffers; a disagreement
|
||||
* between what was allocated and what reset believes was allocated shows
|
||||
* up here. */
|
||||
TEST_EQUAL(mbedtls_ssl_session_reset(&client.ssl), 0);
|
||||
TEST_EQUAL(client.ssl.in_buf_len, MBEDTLS_SSL_IN_BUFFER_LEN);
|
||||
TEST_EQUAL(client.ssl.out_buf_len, MBEDTLS_SSL_OUT_BUFFER_LEN);
|
||||
TEST_EQUAL(client.ssl.in_content_len, MBEDTLS_SSL_IN_CONTENT_LEN);
|
||||
TEST_EQUAL(client.ssl.out_content_len, MBEDTLS_SSL_OUT_CONTENT_LEN);
|
||||
|
||||
exit:
|
||||
mbedtls_ssl_free(&fresh);
|
||||
mbedtls_test_ssl_endpoint_free(&client);
|
||||
mbedtls_test_ssl_endpoint_free(&server);
|
||||
mbedtls_test_free_handshake_options(&options);
|
||||
MD_OR_USE_PSA_DONE();
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_SSL_RUNTIME_CONTENT_LEN:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_ALG_SHA_256 */
|
||||
void ssl_runtime_content_len_set(int outgoing, int after_setup, int len,
|
||||
int expected_ret)
|
||||
{
|
||||
/* Ask for a content length either in the window the setters allow,
|
||||
* between configuring the connection and setting it up, or once the
|
||||
* connection is set up (after_setup 1), or once it is set up and then
|
||||
* recycled with mbedtls_ssl_session_reset() (after_setup 2), and check
|
||||
* the verdict. A reset does not reopen the window. */
|
||||
mbedtls_test_ssl_endpoint ep;
|
||||
memset(&ep, 0, sizeof(ep));
|
||||
mbedtls_test_handshake_test_options options;
|
||||
mbedtls_test_init_handshake_options(&options);
|
||||
|
||||
MD_OR_USE_PSA_INIT();
|
||||
|
||||
options.pk_alg = MBEDTLS_PK_ECDSA;
|
||||
TEST_EQUAL(mbedtls_test_ssl_endpoint_init_conf(&ep, MBEDTLS_SSL_IS_CLIENT,
|
||||
&options), 0);
|
||||
if (after_setup) {
|
||||
TEST_EQUAL(mbedtls_test_ssl_endpoint_init_ssl(&ep, &options), 0);
|
||||
}
|
||||
if (after_setup == 2) {
|
||||
TEST_EQUAL(mbedtls_ssl_session_reset(&ep.ssl), 0);
|
||||
}
|
||||
|
||||
if (outgoing) {
|
||||
TEST_EQUAL(mbedtls_ssl_set_out_content_len(&ep.ssl, len), expected_ret);
|
||||
} else {
|
||||
TEST_EQUAL(mbedtls_ssl_set_in_content_len(&ep.ssl, len), expected_ret);
|
||||
}
|
||||
|
||||
exit:
|
||||
mbedtls_test_ssl_endpoint_free(&ep);
|
||||
mbedtls_test_free_handshake_options(&options);
|
||||
MD_OR_USE_PSA_DONE();
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_SSL_RUNTIME_CONTENT_LEN:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_ALG_SHA_256 */
|
||||
void ssl_runtime_content_len_handshake(int version, int dtls,
|
||||
int cli_in, int cli_out,
|
||||
int srv_in, int srv_out,
|
||||
int cli_msg_len, int expected_cli_fragments,
|
||||
int srv_msg_len, int expected_srv_fragments,
|
||||
int reset)
|
||||
{
|
||||
/* Give each peer its own content lengths (0 leaves one at the build-time
|
||||
* maximum), run a full handshake, then exchange application data. The
|
||||
* number of records each message is split into is what shows the lengths
|
||||
* took effect: a sender splits at its own outgoing length, and a message
|
||||
* that arrives in one record fit the receiver's incoming length.
|
||||
*
|
||||
* With reset set (stream transport only), recycle both connections with
|
||||
* mbedtls_ssl_session_reset() over fresh sockets and do it all again: a
|
||||
* recycled connection keeps the lengths it was set up with. */
|
||||
mbedtls_test_ssl_endpoint client;
|
||||
memset(&client, 0, sizeof(client));
|
||||
mbedtls_test_ssl_endpoint server;
|
||||
memset(&server, 0, sizeof(server));
|
||||
mbedtls_test_handshake_test_options options;
|
||||
mbedtls_test_init_handshake_options(&options);
|
||||
|
||||
MD_OR_USE_PSA_INIT();
|
||||
|
||||
options.pk_alg = MBEDTLS_PK_ECDSA;
|
||||
options.dtls = dtls;
|
||||
options.client_min_version = version;
|
||||
options.client_max_version = version;
|
||||
options.expected_negotiated_version = version;
|
||||
options.cli_msg_len = cli_msg_len;
|
||||
options.expected_cli_fragments = expected_cli_fragments;
|
||||
options.srv_msg_len = srv_msg_len;
|
||||
options.expected_srv_fragments = expected_srv_fragments;
|
||||
TEST_EQUAL(mbedtls_test_ssl_endpoint_init_conf(&client, MBEDTLS_SSL_IS_CLIENT,
|
||||
&options), 0);
|
||||
TEST_EQUAL(mbedtls_test_ssl_endpoint_init_conf(&server, MBEDTLS_SSL_IS_SERVER,
|
||||
&options), 0);
|
||||
|
||||
if (cli_in != 0) {
|
||||
TEST_EQUAL(mbedtls_ssl_set_in_content_len(&client.ssl, cli_in), 0);
|
||||
}
|
||||
if (cli_out != 0) {
|
||||
TEST_EQUAL(mbedtls_ssl_set_out_content_len(&client.ssl, cli_out), 0);
|
||||
}
|
||||
if (srv_in != 0) {
|
||||
TEST_EQUAL(mbedtls_ssl_set_in_content_len(&server.ssl, srv_in), 0);
|
||||
}
|
||||
if (srv_out != 0) {
|
||||
TEST_EQUAL(mbedtls_ssl_set_out_content_len(&server.ssl, srv_out), 0);
|
||||
}
|
||||
|
||||
TEST_EQUAL(mbedtls_test_ssl_endpoint_init_ssl(&client, &options), 0);
|
||||
TEST_EQUAL(mbedtls_test_ssl_endpoint_init_ssl(&server, &options), 0);
|
||||
|
||||
if (dtls) {
|
||||
TEST_EQUAL(mbedtls_test_ssl_dtls_join_endpoints(&client, &server), 0);
|
||||
}
|
||||
|
||||
TEST_ASSERT(mbedtls_test_ssl_perform_connection(&options, &client, &server));
|
||||
|
||||
if (reset) {
|
||||
mbedtls_test_mock_socket_close(&client.socket);
|
||||
mbedtls_test_mock_socket_close(&server.socket);
|
||||
TEST_EQUAL(mbedtls_ssl_session_reset(&client.ssl), 0);
|
||||
TEST_EQUAL(mbedtls_ssl_session_reset(&server.ssl), 0);
|
||||
|
||||
TEST_ASSERT(mbedtls_test_ssl_perform_connection(&options, &client, &server));
|
||||
}
|
||||
|
||||
exit:
|
||||
mbedtls_test_ssl_endpoint_free(&client);
|
||||
mbedtls_test_ssl_endpoint_free(&server);
|
||||
mbedtls_test_free_handshake_options(&options);
|
||||
MD_OR_USE_PSA_DONE();
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_SSL_RUNTIME_CONTENT_LEN:MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:MBEDTLS_SSL_PROTO_TLS1_2:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_ALG_SHA_256 */
|
||||
void ssl_runtime_content_len_resize_buffers(int dtls, int mfl, int renegotiate,
|
||||
int cli_in, int cli_out,
|
||||
int srv_in, int srv_out)
|
||||
{
|
||||
/* With automatic buffer resizing as well, give each peer its own content
|
||||
* lengths (0 leaves one at the build-time maximum) and run a handshake,
|
||||
* optionally with a negotiated fragment length and a renegotiation, then
|
||||
* recycle both connections with mbedtls_ssl_session_reset().
|
||||
*
|
||||
* Every handshake starts by growing the buffers back to full size, and
|
||||
* full size is this connection's own length: growing to the build-time
|
||||
* maximum would undo the saving. mbedtls_test_ssl_perform_connection()
|
||||
* checks the buffers at each resize, including in the middle of the
|
||||
* renegotiation; this test checks them after setup and after reset. */
|
||||
mbedtls_test_ssl_endpoint client;
|
||||
memset(&client, 0, sizeof(client));
|
||||
mbedtls_test_ssl_endpoint server;
|
||||
memset(&server, 0, sizeof(server));
|
||||
mbedtls_test_handshake_test_options options;
|
||||
mbedtls_test_init_handshake_options(&options);
|
||||
/* A buffer is its content length plus a fixed overhead for the header,
|
||||
* the crypto expansion and any connection ID. */
|
||||
const size_t cli_in_buf_len = (cli_in ? cli_in : MBEDTLS_SSL_IN_CONTENT_LEN)
|
||||
+ MBEDTLS_SSL_IN_BUFFER_LEN - MBEDTLS_SSL_IN_CONTENT_LEN;
|
||||
const size_t cli_out_buf_len = (cli_out ? cli_out : MBEDTLS_SSL_OUT_CONTENT_LEN)
|
||||
+ MBEDTLS_SSL_OUT_BUFFER_LEN - MBEDTLS_SSL_OUT_CONTENT_LEN;
|
||||
const size_t srv_in_buf_len = (srv_in ? srv_in : MBEDTLS_SSL_IN_CONTENT_LEN)
|
||||
+ MBEDTLS_SSL_IN_BUFFER_LEN - MBEDTLS_SSL_IN_CONTENT_LEN;
|
||||
const size_t srv_out_buf_len = (srv_out ? srv_out : MBEDTLS_SSL_OUT_CONTENT_LEN)
|
||||
+ MBEDTLS_SSL_OUT_BUFFER_LEN - MBEDTLS_SSL_OUT_CONTENT_LEN;
|
||||
|
||||
MD_OR_USE_PSA_INIT();
|
||||
|
||||
options.pk_alg = MBEDTLS_PK_ECDSA;
|
||||
options.dtls = dtls;
|
||||
options.client_min_version = MBEDTLS_SSL_VERSION_TLS1_2;
|
||||
options.client_max_version = MBEDTLS_SSL_VERSION_TLS1_2;
|
||||
options.expected_negotiated_version = MBEDTLS_SSL_VERSION_TLS1_2;
|
||||
options.mfl = mfl;
|
||||
options.renegotiate = renegotiate;
|
||||
options.legacy_renegotiation = MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION;
|
||||
options.resize_buffers = 1;
|
||||
|
||||
TEST_EQUAL(mbedtls_test_ssl_endpoint_init_conf(&client, MBEDTLS_SSL_IS_CLIENT,
|
||||
&options), 0);
|
||||
TEST_EQUAL(mbedtls_test_ssl_endpoint_init_conf(&server, MBEDTLS_SSL_IS_SERVER,
|
||||
&options), 0);
|
||||
|
||||
if (cli_in != 0) {
|
||||
TEST_EQUAL(mbedtls_ssl_set_in_content_len(&client.ssl, cli_in), 0);
|
||||
}
|
||||
if (cli_out != 0) {
|
||||
TEST_EQUAL(mbedtls_ssl_set_out_content_len(&client.ssl, cli_out), 0);
|
||||
}
|
||||
if (srv_in != 0) {
|
||||
TEST_EQUAL(mbedtls_ssl_set_in_content_len(&server.ssl, srv_in), 0);
|
||||
}
|
||||
if (srv_out != 0) {
|
||||
TEST_EQUAL(mbedtls_ssl_set_out_content_len(&server.ssl, srv_out), 0);
|
||||
}
|
||||
|
||||
TEST_EQUAL(mbedtls_test_ssl_endpoint_init_ssl(&client, &options), 0);
|
||||
TEST_EQUAL(mbedtls_test_ssl_endpoint_init_ssl(&server, &options), 0);
|
||||
|
||||
/* Setup allocates from the connection's lengths, then runs the grow step
|
||||
* of the first handshake, which must leave them alone. */
|
||||
TEST_EQUAL(client.ssl.in_buf_len, cli_in_buf_len);
|
||||
TEST_EQUAL(client.ssl.out_buf_len, cli_out_buf_len);
|
||||
TEST_EQUAL(server.ssl.in_buf_len, srv_in_buf_len);
|
||||
TEST_EQUAL(server.ssl.out_buf_len, srv_out_buf_len);
|
||||
|
||||
if (dtls) {
|
||||
TEST_EQUAL(mbedtls_test_ssl_dtls_join_endpoints(&client, &server), 0);
|
||||
}
|
||||
|
||||
TEST_ASSERT(mbedtls_test_ssl_perform_connection(&options, &client, &server));
|
||||
|
||||
/* Resizing after the handshake may have shrunk the buffers further, to a
|
||||
* negotiated fragment length, but never grown them. */
|
||||
TEST_LE_U(client.ssl.in_buf_len, cli_in_buf_len);
|
||||
TEST_LE_U(client.ssl.out_buf_len, cli_out_buf_len);
|
||||
TEST_LE_U(server.ssl.in_buf_len, srv_in_buf_len);
|
||||
TEST_LE_U(server.ssl.out_buf_len, srv_out_buf_len);
|
||||
|
||||
/* A reset prepares the next handshake, growing the buffers back to the
|
||||
* connection's lengths and no further. */
|
||||
TEST_EQUAL(mbedtls_ssl_session_reset(&client.ssl), 0);
|
||||
TEST_EQUAL(mbedtls_ssl_session_reset(&server.ssl), 0);
|
||||
TEST_EQUAL(client.ssl.in_buf_len, cli_in_buf_len);
|
||||
TEST_EQUAL(client.ssl.out_buf_len, cli_out_buf_len);
|
||||
TEST_EQUAL(server.ssl.in_buf_len, srv_in_buf_len);
|
||||
TEST_EQUAL(server.ssl.out_buf_len, srv_out_buf_len);
|
||||
|
||||
exit:
|
||||
mbedtls_test_ssl_endpoint_free(&client);
|
||||
mbedtls_test_ssl_endpoint_free(&server);
|
||||
mbedtls_test_free_handshake_options(&options);
|
||||
MD_OR_USE_PSA_DONE();
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_SSL_RUNTIME_CONTENT_LEN:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_ALG_SHA_256 */
|
||||
void ssl_runtime_content_len_oversized_record(int version, int srv_in,
|
||||
int msg_len, int expected_ret)
|
||||
{
|
||||
/* Shrink only the server's incoming length, so that nothing on the
|
||||
* wire tells the client (the TLS 1.3 cases therefore exclude
|
||||
* MBEDTLS_SSL_RECORD_SIZE_LIMIT, which would), and have the full-size
|
||||
* client send one record of msg_len bytes after the handshake. The
|
||||
* server's verdict on that record is what shows its incoming length took
|
||||
* effect. */
|
||||
enum { BUFFSIZE = 17000 };
|
||||
mbedtls_test_ssl_endpoint client;
|
||||
memset(&client, 0, sizeof(client));
|
||||
mbedtls_test_ssl_endpoint server;
|
||||
memset(&server, 0, sizeof(server));
|
||||
mbedtls_test_handshake_test_options options;
|
||||
mbedtls_test_init_handshake_options(&options);
|
||||
unsigned char *msg = NULL;
|
||||
unsigned char *received = NULL;
|
||||
|
||||
MD_OR_USE_PSA_INIT();
|
||||
|
||||
TEST_CALLOC(msg, msg_len);
|
||||
TEST_CALLOC(received, msg_len);
|
||||
memset(msg, 'x', msg_len);
|
||||
|
||||
options.pk_alg = MBEDTLS_PK_ECDSA;
|
||||
options.client_min_version = version;
|
||||
options.client_max_version = version;
|
||||
options.expected_negotiated_version = version;
|
||||
|
||||
TEST_EQUAL(mbedtls_test_ssl_endpoint_init(&client, MBEDTLS_SSL_IS_CLIENT,
|
||||
&options), 0);
|
||||
TEST_EQUAL(mbedtls_test_ssl_endpoint_init_conf(&server, MBEDTLS_SSL_IS_SERVER,
|
||||
&options), 0);
|
||||
TEST_EQUAL(mbedtls_ssl_set_in_content_len(&server.ssl, srv_in), 0);
|
||||
TEST_EQUAL(mbedtls_test_ssl_endpoint_init_ssl(&server, &options), 0);
|
||||
|
||||
TEST_EQUAL(mbedtls_test_mock_socket_connect(&client.socket, &server.socket,
|
||||
BUFFSIZE), 0);
|
||||
TEST_EQUAL(mbedtls_test_move_handshake_to_state(&client.ssl, &server.ssl,
|
||||
MBEDTLS_SSL_HANDSHAKE_OVER),
|
||||
0);
|
||||
TEST_EQUAL(mbedtls_test_move_handshake_to_state(&server.ssl, &client.ssl,
|
||||
MBEDTLS_SSL_HANDSHAKE_OVER),
|
||||
0);
|
||||
|
||||
TEST_EQUAL(mbedtls_ssl_write(&client.ssl, msg, msg_len), msg_len);
|
||||
|
||||
if (expected_ret == 0) {
|
||||
TEST_EQUAL(mbedtls_ssl_read(&server.ssl, received, msg_len), msg_len);
|
||||
TEST_MEMORY_COMPARE(received, msg_len, msg, msg_len);
|
||||
} else {
|
||||
TEST_EQUAL(mbedtls_ssl_read(&server.ssl, received, msg_len),
|
||||
expected_ret);
|
||||
}
|
||||
|
||||
exit:
|
||||
mbedtls_free(msg);
|
||||
mbedtls_free(received);
|
||||
mbedtls_test_ssl_endpoint_free(&client);
|
||||
mbedtls_test_ssl_endpoint_free(&server);
|
||||
mbedtls_test_free_handshake_options(&options);
|
||||
MD_OR_USE_PSA_DONE();
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_SSL_RUNTIME_CONTENT_LEN:MBEDTLS_SSL_MAX_FRAGMENT_LENGTH:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_ALG_SHA_256 */
|
||||
void ssl_runtime_content_len_setup_mfl(int endpoint, int min_version,
|
||||
int in_len, int mfl, int expected_ret)
|
||||
{
|
||||
/* A client whose configuration negotiates a fragment length above the
|
||||
* connection's incoming length would invite records it cannot hold, so
|
||||
* mbedtls_ssl_setup() refuses it. A client that only offers TLS 1.3 never
|
||||
* sends a fragment length, and a server's configured fragment length only
|
||||
* caps what it sends, so neither is a contradiction. */
|
||||
mbedtls_test_ssl_endpoint ep;
|
||||
memset(&ep, 0, sizeof(ep));
|
||||
mbedtls_test_handshake_test_options options;
|
||||
mbedtls_test_init_handshake_options(&options);
|
||||
|
||||
MD_OR_USE_PSA_INIT();
|
||||
|
||||
options.pk_alg = MBEDTLS_PK_ECDSA;
|
||||
options.client_min_version = min_version;
|
||||
options.server_min_version = min_version;
|
||||
options.mfl = mfl;
|
||||
TEST_EQUAL(mbedtls_test_ssl_endpoint_init_conf(&ep, endpoint, &options), 0);
|
||||
TEST_EQUAL(mbedtls_ssl_set_in_content_len(&ep.ssl, in_len), 0);
|
||||
|
||||
TEST_EQUAL(mbedtls_ssl_setup(&ep.ssl, &ep.conf), expected_ret);
|
||||
|
||||
if (expected_ret != 0) {
|
||||
/* A refused connection has no buffers, and cannot be recycled the way
|
||||
* mbedtls_test_ssl_endpoint_free() recycles a set-up one. */
|
||||
mbedtls_ssl_free(&ep.ssl);
|
||||
mbedtls_ssl_init(&ep.ssl);
|
||||
}
|
||||
|
||||
exit:
|
||||
mbedtls_test_ssl_endpoint_free(&ep);
|
||||
mbedtls_test_free_handshake_options(&options);
|
||||
MD_OR_USE_PSA_DONE();
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_SSL_RUNTIME_CONTENT_LEN:MBEDTLS_SSL_CLI_C:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_ALG_SHA_256 */
|
||||
void ssl_runtime_content_len_client_hello_ext(int version, int cli_in, int mfl,
|
||||
int ext_type, int expected_ret,
|
||||
int expected_value)
|
||||
{
|
||||
/* Set the client's incoming length, have it send its ClientHello, and
|
||||
* read the extension of type ext_type off the wire: its value (a
|
||||
* max_fragment_length code or a record_size_limit) is what the client
|
||||
* invites its peer to send. expected_value -1 means the extension must
|
||||
* be absent. expected_ret is the handshake's verdict before anything is
|
||||
* sent; 0 means the ClientHello went out and the client waits for the
|
||||
* server. */
|
||||
enum { BUFFSIZE = 17000 };
|
||||
mbedtls_test_ssl_endpoint client;
|
||||
memset(&client, 0, sizeof(client));
|
||||
mbedtls_test_mock_socket peer;
|
||||
mbedtls_test_mock_socket_init(&peer);
|
||||
mbedtls_test_handshake_test_options options;
|
||||
mbedtls_test_init_handshake_options(&options);
|
||||
unsigned char buf[BUFFSIZE];
|
||||
size_t len = 0;
|
||||
size_t off = 0;
|
||||
size_t end = 0;
|
||||
int ext_value = -1;
|
||||
int ret;
|
||||
|
||||
MD_OR_USE_PSA_INIT();
|
||||
|
||||
options.pk_alg = MBEDTLS_PK_ECDSA;
|
||||
options.client_min_version = version;
|
||||
options.client_max_version = version;
|
||||
options.mfl = mfl;
|
||||
|
||||
TEST_EQUAL(mbedtls_test_ssl_endpoint_init_conf(&client, MBEDTLS_SSL_IS_CLIENT,
|
||||
&options), 0);
|
||||
TEST_EQUAL(mbedtls_ssl_set_in_content_len(&client.ssl, cli_in), 0);
|
||||
TEST_EQUAL(mbedtls_test_ssl_endpoint_init_ssl(&client, &options), 0);
|
||||
TEST_EQUAL(mbedtls_test_mock_socket_connect(&client.socket, &peer,
|
||||
BUFFSIZE), 0);
|
||||
|
||||
if (expected_ret != 0) {
|
||||
TEST_EQUAL(mbedtls_ssl_handshake(&client.ssl), expected_ret);
|
||||
TEST_EQUAL(mbedtls_test_mock_tcp_recv_nb(&peer, buf, sizeof(buf)),
|
||||
MBEDTLS_ERR_SSL_WANT_READ);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
TEST_EQUAL(mbedtls_ssl_handshake(&client.ssl), MBEDTLS_ERR_SSL_WANT_READ);
|
||||
ret = mbedtls_test_mock_tcp_recv_nb(&peer, buf, sizeof(buf));
|
||||
TEST_LE_S(1, ret);
|
||||
len = (size_t) ret;
|
||||
|
||||
/* Record header (5), then handshake header (4): one ClientHello record. */
|
||||
TEST_LE_U(9, len);
|
||||
TEST_EQUAL(buf[0], MBEDTLS_SSL_MSG_HANDSHAKE);
|
||||
TEST_EQUAL(MBEDTLS_GET_UINT16_BE(buf, 3), len - 5);
|
||||
TEST_EQUAL(buf[5], MBEDTLS_SSL_HS_CLIENT_HELLO);
|
||||
/* legacy_version (2) and random (32) */
|
||||
off = 9 + 2 + 32;
|
||||
/* legacy_session_id */
|
||||
TEST_LE_U(off + 1, len);
|
||||
off += 1 + buf[off];
|
||||
/* cipher_suites */
|
||||
TEST_LE_U(off + 2, len);
|
||||
off += 2 + MBEDTLS_GET_UINT16_BE(buf, off);
|
||||
/* legacy_compression_methods */
|
||||
TEST_LE_U(off + 1, len);
|
||||
off += 1 + buf[off];
|
||||
/* extensions */
|
||||
TEST_LE_U(off + 2, len);
|
||||
end = off + 2 + MBEDTLS_GET_UINT16_BE(buf, off);
|
||||
TEST_EQUAL(end, len);
|
||||
off += 2;
|
||||
while (off < end) {
|
||||
size_t ext_len;
|
||||
TEST_LE_U(off + 4, end);
|
||||
ext_len = MBEDTLS_GET_UINT16_BE(buf, off + 2);
|
||||
TEST_LE_U(off + 4 + ext_len, end);
|
||||
if (MBEDTLS_GET_UINT16_BE(buf, off) == ext_type) {
|
||||
TEST_EQUAL(ext_value, -1);
|
||||
TEST_ASSERT(ext_len == 1 || ext_len == 2);
|
||||
ext_value = ext_len == 1 ? buf[off + 4] : MBEDTLS_GET_UINT16_BE(buf, off + 4);
|
||||
}
|
||||
off += 4 + ext_len;
|
||||
}
|
||||
|
||||
TEST_EQUAL(ext_value, expected_value);
|
||||
|
||||
exit:
|
||||
mbedtls_test_ssl_endpoint_free(&client);
|
||||
mbedtls_test_mock_socket_close(&peer);
|
||||
mbedtls_test_free_handshake_options(&options);
|
||||
MD_OR_USE_PSA_DONE();
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_SSL_RUNTIME_CONTENT_LEN:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_ALG_SHA_256 */
|
||||
void ssl_runtime_content_len_max_payload(int version, int cli_in, int cli_out,
|
||||
int mfl, int pre_handshake_out,
|
||||
int expected_in, int expected_out)
|
||||
{
|
||||
/* Give the client its own lengths (and optionally a fragment length to
|
||||
* negotiate) and check what the public maximum-record-payload queries
|
||||
* report on it, once set up and again once the handshake is over. The
|
||||
* server sends no more than the client can take in, so that the
|
||||
* handshake itself does not depend on negotiating anything. */
|
||||
enum { BUFFSIZE = 17000 };
|
||||
mbedtls_test_ssl_endpoint client;
|
||||
memset(&client, 0, sizeof(client));
|
||||
mbedtls_test_ssl_endpoint server;
|
||||
memset(&server, 0, sizeof(server));
|
||||
mbedtls_test_handshake_test_options options;
|
||||
mbedtls_test_init_handshake_options(&options);
|
||||
|
||||
MD_OR_USE_PSA_INIT();
|
||||
|
||||
options.pk_alg = MBEDTLS_PK_ECDSA;
|
||||
options.client_min_version = version;
|
||||
options.client_max_version = version;
|
||||
options.expected_negotiated_version = version;
|
||||
options.mfl = mfl;
|
||||
|
||||
TEST_EQUAL(mbedtls_test_ssl_endpoint_init_conf(&client, MBEDTLS_SSL_IS_CLIENT,
|
||||
&options), 0);
|
||||
TEST_EQUAL(mbedtls_ssl_set_in_content_len(&client.ssl, cli_in), 0);
|
||||
TEST_EQUAL(mbedtls_ssl_set_out_content_len(&client.ssl, cli_out), 0);
|
||||
TEST_EQUAL(mbedtls_test_ssl_endpoint_init_ssl(&client, &options), 0);
|
||||
TEST_EQUAL(mbedtls_test_ssl_endpoint_init_conf(&server, MBEDTLS_SSL_IS_SERVER,
|
||||
&options), 0);
|
||||
TEST_EQUAL(mbedtls_ssl_set_out_content_len(&server.ssl, cli_in), 0);
|
||||
TEST_EQUAL(mbedtls_test_ssl_endpoint_init_ssl(&server, &options), 0);
|
||||
|
||||
/* Before the handshake nothing is negotiated: the incoming length is the
|
||||
* client's own, and the outgoing one is capped only by what the client
|
||||
* itself configured. */
|
||||
TEST_EQUAL(mbedtls_ssl_get_max_in_record_payload(&client.ssl), cli_in);
|
||||
TEST_EQUAL(mbedtls_ssl_get_max_out_record_payload(&client.ssl),
|
||||
pre_handshake_out);
|
||||
|
||||
TEST_EQUAL(mbedtls_test_mock_socket_connect(&client.socket, &server.socket,
|
||||
BUFFSIZE), 0);
|
||||
TEST_EQUAL(mbedtls_test_move_handshake_to_state(&client.ssl, &server.ssl,
|
||||
MBEDTLS_SSL_HANDSHAKE_OVER),
|
||||
0);
|
||||
TEST_EQUAL(mbedtls_test_move_handshake_to_state(&server.ssl, &client.ssl,
|
||||
MBEDTLS_SSL_HANDSHAKE_OVER),
|
||||
0);
|
||||
|
||||
TEST_EQUAL(mbedtls_ssl_get_max_in_record_payload(&client.ssl), expected_in);
|
||||
TEST_EQUAL(mbedtls_ssl_get_max_out_record_payload(&client.ssl), expected_out);
|
||||
|
||||
exit:
|
||||
mbedtls_test_ssl_endpoint_free(&client);
|
||||
mbedtls_test_ssl_endpoint_free(&server);
|
||||
mbedtls_test_free_handshake_options(&options);
|
||||
MD_OR_USE_PSA_DONE();
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */
|
||||
void test_multiple_psks()
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user