mirror of
https://github.com/yuzu-emu/mbedtls.git
synced 2024-11-22 17:25:37 +01:00
Merge branch 'pr_946' into development-proposed
This commit is contained in:
commit
80aa3b8d65
16
ChangeLog
16
ChangeLog
@ -19,6 +19,14 @@ Features
|
|||||||
mbedtls_ecdh_compute_shared()) are supported for now. Contributed by
|
mbedtls_ecdh_compute_shared()) are supported for now. Contributed by
|
||||||
Nicholas Wilson (#348).
|
Nicholas Wilson (#348).
|
||||||
|
|
||||||
|
API Changes
|
||||||
|
* Add function mbedtls_net_poll to public API allowing to wait for a
|
||||||
|
network context to become ready for reading or writing.
|
||||||
|
* Add function mbedtls_ssl_check_pending to public API allowing to check
|
||||||
|
if more data is pending to be processed in the internal message buffers.
|
||||||
|
This function is necessary to determine when it is safe to idle on the
|
||||||
|
underlying transport in case event-driven IO is used.
|
||||||
|
|
||||||
Bugfix
|
Bugfix
|
||||||
* Fix spurious uninitialized variable warning in cmac.c. Fix independently
|
* Fix spurious uninitialized variable warning in cmac.c. Fix independently
|
||||||
contributed by Brian J Murray and David Brown.
|
contributed by Brian J Murray and David Brown.
|
||||||
@ -39,6 +47,14 @@ Bugfix
|
|||||||
the mbedtls_cipher_update() documentation. Contributed by Andy Leiserson.
|
the mbedtls_cipher_update() documentation. Contributed by Andy Leiserson.
|
||||||
* Fix overriding and ignoring return values when parsing and writing to
|
* Fix overriding and ignoring return values when parsing and writing to
|
||||||
a file in pk_sign program. Found by kevlut in #1142.
|
a file in pk_sign program. Found by kevlut in #1142.
|
||||||
|
* Restrict usage of error code MBEDTLS_ERR_SSL_WANT_READ to situations
|
||||||
|
where data needs to be fetched from the underlying transport in order
|
||||||
|
to make progress. Previously, this error code was also occasionally
|
||||||
|
returned when unexpected messages were being discarded, ignoring that
|
||||||
|
further messages could potentially already be pending to be processed
|
||||||
|
in the internal buffers; these cases lead to deadlocks in case
|
||||||
|
event-driven I/O was used.
|
||||||
|
Found and reported by Hubert Mis in #772.
|
||||||
|
|
||||||
Changes
|
Changes
|
||||||
* Remove some redundant code in bignum.c. Contributed by Alexey Skalozub.
|
* Remove some redundant code in bignum.c. Contributed by Alexey Skalozub.
|
||||||
|
@ -46,12 +46,17 @@
|
|||||||
#define MBEDTLS_ERR_NET_UNKNOWN_HOST -0x0052 /**< Failed to get an IP address for the given hostname. */
|
#define MBEDTLS_ERR_NET_UNKNOWN_HOST -0x0052 /**< Failed to get an IP address for the given hostname. */
|
||||||
#define MBEDTLS_ERR_NET_BUFFER_TOO_SMALL -0x0043 /**< Buffer is too small to hold the data. */
|
#define MBEDTLS_ERR_NET_BUFFER_TOO_SMALL -0x0043 /**< Buffer is too small to hold the data. */
|
||||||
#define MBEDTLS_ERR_NET_INVALID_CONTEXT -0x0045 /**< The context is invalid, eg because it was free()ed. */
|
#define MBEDTLS_ERR_NET_INVALID_CONTEXT -0x0045 /**< The context is invalid, eg because it was free()ed. */
|
||||||
|
#define MBEDTLS_ERR_NET_POLL_FAILED -0x0047 /**< Polling the net context failed. */
|
||||||
|
#define MBEDTLS_ERR_NET_BAD_INPUT_DATA -0x0049 /**< Input invalid. */
|
||||||
|
|
||||||
#define MBEDTLS_NET_LISTEN_BACKLOG 10 /**< The backlog that listen() should use. */
|
#define MBEDTLS_NET_LISTEN_BACKLOG 10 /**< The backlog that listen() should use. */
|
||||||
|
|
||||||
#define MBEDTLS_NET_PROTO_TCP 0 /**< The TCP transport protocol */
|
#define MBEDTLS_NET_PROTO_TCP 0 /**< The TCP transport protocol */
|
||||||
#define MBEDTLS_NET_PROTO_UDP 1 /**< The UDP transport protocol */
|
#define MBEDTLS_NET_PROTO_UDP 1 /**< The UDP transport protocol */
|
||||||
|
|
||||||
|
#define MBEDTLS_NET_POLL_READ 1 /**< Used in \c mbedtls_net_poll to check for pending data */
|
||||||
|
#define MBEDTLS_NET_POLL_WRITE 2 /**< Used in \c mbedtls_net_poll to check if write possible */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
@ -133,6 +138,29 @@ int mbedtls_net_accept( mbedtls_net_context *bind_ctx,
|
|||||||
mbedtls_net_context *client_ctx,
|
mbedtls_net_context *client_ctx,
|
||||||
void *client_ip, size_t buf_size, size_t *ip_len );
|
void *client_ip, size_t buf_size, size_t *ip_len );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Check and wait for the context to be ready for read/write
|
||||||
|
*
|
||||||
|
* \param ctx Socket to check
|
||||||
|
* \param rw Bitflag composed of MBEDTLS_NET_POLL_READ and
|
||||||
|
* MBEDTLS_NET_POLL_WRITE specifying the events
|
||||||
|
* to wait for:
|
||||||
|
* - If MBEDTLS_NET_POLL_READ is set, the function
|
||||||
|
* will return as soon as the net context is available
|
||||||
|
* for reading.
|
||||||
|
* - If MBEDTLS_NET_POLL_WRITE is set, the function
|
||||||
|
* will return as soon as the net context is available
|
||||||
|
* for writing.
|
||||||
|
* \param timeout Maximal amount of time to wait before returning,
|
||||||
|
* in milliseconds. If \c timeout is zero, the
|
||||||
|
* function returns immediately. If \c timeout is
|
||||||
|
* -1u, the function blocks potentially indefinitely.
|
||||||
|
*
|
||||||
|
* \return Bitmask composed of MBEDTLS_NET_POLL_READ/WRITE
|
||||||
|
* on success or timeout, or a negative return code otherwise.
|
||||||
|
*/
|
||||||
|
int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Set the socket blocking
|
* \brief Set the socket blocking
|
||||||
*
|
*
|
||||||
|
@ -112,13 +112,14 @@
|
|||||||
#define MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED -0x6A80 /**< DTLS client must retry for hello verification */
|
#define MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED -0x6A80 /**< DTLS client must retry for hello verification */
|
||||||
#define MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL -0x6A00 /**< A buffer is too small to receive or write a message */
|
#define MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL -0x6A00 /**< A buffer is too small to receive or write a message */
|
||||||
#define MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE -0x6980 /**< None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages). */
|
#define MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE -0x6980 /**< None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages). */
|
||||||
#define MBEDTLS_ERR_SSL_WANT_READ -0x6900 /**< Connection requires a read call. */
|
#define MBEDTLS_ERR_SSL_WANT_READ -0x6900 /**< No data of requested type currently available on underlying transport. */
|
||||||
#define MBEDTLS_ERR_SSL_WANT_WRITE -0x6880 /**< Connection requires a write call. */
|
#define MBEDTLS_ERR_SSL_WANT_WRITE -0x6880 /**< Connection requires a write call. */
|
||||||
#define MBEDTLS_ERR_SSL_TIMEOUT -0x6800 /**< The operation timed out. */
|
#define MBEDTLS_ERR_SSL_TIMEOUT -0x6800 /**< The operation timed out. */
|
||||||
#define MBEDTLS_ERR_SSL_CLIENT_RECONNECT -0x6780 /**< The client initiated a reconnect from the same port. */
|
#define MBEDTLS_ERR_SSL_CLIENT_RECONNECT -0x6780 /**< The client initiated a reconnect from the same port. */
|
||||||
#define MBEDTLS_ERR_SSL_UNEXPECTED_RECORD -0x6700 /**< Record header looks valid but is not expected. */
|
#define MBEDTLS_ERR_SSL_UNEXPECTED_RECORD -0x6700 /**< Record header looks valid but is not expected. */
|
||||||
#define MBEDTLS_ERR_SSL_NON_FATAL -0x6680 /**< The alert message received indicates a non-fatal error. */
|
#define MBEDTLS_ERR_SSL_NON_FATAL -0x6680 /**< The alert message received indicates a non-fatal error. */
|
||||||
#define MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH -0x6600 /**< Couldn't set the hash for verifying CertificateVerify */
|
#define MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH -0x6600 /**< Couldn't set the hash for verifying CertificateVerify */
|
||||||
|
#define MBEDTLS_ERR_SSL_CONTINUE_PROCESSING -0x6580 /**< Internal-only message signaling that further message-processing should be done */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Various constants
|
* Various constants
|
||||||
@ -2301,11 +2302,59 @@ void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf,
|
|||||||
#endif /* MBEDTLS_SSL_RENEGOTIATION */
|
#endif /* MBEDTLS_SSL_RENEGOTIATION */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Return the number of data bytes available to read
|
* \brief Check if there is data already read from the
|
||||||
|
* underlying transport but not yet processed.
|
||||||
*
|
*
|
||||||
* \param ssl SSL context
|
* \param ssl SSL context
|
||||||
*
|
*
|
||||||
* \return how many bytes are available in the read buffer
|
* \return 0 if nothing's pending, 1 otherwise.
|
||||||
|
*
|
||||||
|
* \note This is different in purpose and behaviour from
|
||||||
|
* \c mbedtls_ssl_get_bytes_avail in that it considers
|
||||||
|
* any kind of unprocessed data, not only unread
|
||||||
|
* application data. If \c mbedtls_ssl_get_bytes
|
||||||
|
* returns a non-zero value, this function will
|
||||||
|
* also signal pending data, but the converse does
|
||||||
|
* not hold. For example, in DTLS there might be
|
||||||
|
* further records waiting to be processed from
|
||||||
|
* the current underlying transport's datagram.
|
||||||
|
*
|
||||||
|
* \note If this function returns 1 (data pending), this
|
||||||
|
* does not imply that a subsequent call to
|
||||||
|
* \c mbedtls_ssl_read will provide any data;
|
||||||
|
* e.g., the unprocessed data might turn out
|
||||||
|
* to be an alert or a handshake message.
|
||||||
|
*
|
||||||
|
* \note This function is useful in the following situation:
|
||||||
|
* If the SSL/TLS module successfully returns from an
|
||||||
|
* operation - e.g. a handshake or an application record
|
||||||
|
* read - and you're awaiting incoming data next, you
|
||||||
|
* must not immediately idle on the underlying transport
|
||||||
|
* to have data ready, but you need to check the value
|
||||||
|
* of this function first. The reason is that the desired
|
||||||
|
* data might already be read but not yet processed.
|
||||||
|
* If, in contrast, a previous call to the SSL/TLS module
|
||||||
|
* returned MBEDTLS_ERR_SSL_WANT_READ, it is not necessary
|
||||||
|
* to call this function, as the latter error code entails
|
||||||
|
* that all internal data has been processed.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int mbedtls_ssl_check_pending( const mbedtls_ssl_context *ssl );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Return the number of application data bytes
|
||||||
|
* remaining to be read from the current record.
|
||||||
|
*
|
||||||
|
* \param ssl SSL context
|
||||||
|
*
|
||||||
|
* \return How many bytes are available in the application
|
||||||
|
* data record read buffer.
|
||||||
|
*
|
||||||
|
* \note When working over a datagram transport, this is
|
||||||
|
* useful to detect the current datagram's boundary
|
||||||
|
* in case \c mbedtls_ssl_read has written the maximal
|
||||||
|
* amount of data fitting into the input buffer.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl );
|
size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl );
|
||||||
|
|
||||||
@ -2420,11 +2469,25 @@ int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session
|
|||||||
* MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED (see below), or
|
* MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED (see below), or
|
||||||
* a specific SSL error code.
|
* a specific SSL error code.
|
||||||
*
|
*
|
||||||
|
* If this function returns MBEDTLS_ERR_SSL_WANT_READ, the
|
||||||
|
* handshake is unfinished and no further data is available
|
||||||
|
* from the underlying transport. In this case, you must call
|
||||||
|
* the function again at some later stage.
|
||||||
|
*
|
||||||
|
* \note Remarks regarding event-driven DTLS:
|
||||||
|
* If the function returns MBEDTLS_ERR_SSL_WANT_READ, no datagram
|
||||||
|
* from the underlying transport layer is currently being processed,
|
||||||
|
* and it is safe to idle until the timer or the underlying transport
|
||||||
|
* signal a new event. This is not true for a successful handshake,
|
||||||
|
* in which case the datagram of the underlying transport that is
|
||||||
|
* currently being processed might or might not contain further
|
||||||
|
* DTLS records.
|
||||||
|
*
|
||||||
* \note If this function returns something other than 0 or
|
* \note If this function returns something other than 0 or
|
||||||
* MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context
|
* MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using
|
||||||
* becomes unusable, and you should either free it or call
|
* the SSL context for reading or writing, and either free it or
|
||||||
* \c mbedtls_ssl_session_reset() on it before re-using it for
|
* call \c mbedtls_ssl_session_reset() on it before re-using it
|
||||||
* a new connection; the current connection must be closed.
|
* for a new connection; the current connection must be closed.
|
||||||
*
|
*
|
||||||
* \note If DTLS is in use, then you may choose to handle
|
* \note If DTLS is in use, then you may choose to handle
|
||||||
* MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging
|
* MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging
|
||||||
@ -2441,10 +2504,10 @@ int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl );
|
|||||||
* call this function if state is MBEDTLS_SSL_HANDSHAKE_OVER.
|
* call this function if state is MBEDTLS_SSL_HANDSHAKE_OVER.
|
||||||
*
|
*
|
||||||
* \note If this function returns something other than 0 or
|
* \note If this function returns something other than 0 or
|
||||||
* MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context
|
* MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using
|
||||||
* becomes unusable, and you should either free it or call
|
* the SSL context for reading or writing, and either free it or
|
||||||
* \c mbedtls_ssl_session_reset() on it before re-using it for
|
* call \c mbedtls_ssl_session_reset() on it before re-using it
|
||||||
* a new connection; the current connection must be closed.
|
* for a new connection; the current connection must be closed.
|
||||||
*
|
*
|
||||||
* \param ssl SSL context
|
* \param ssl SSL context
|
||||||
*
|
*
|
||||||
@ -2468,10 +2531,10 @@ int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl );
|
|||||||
* value.
|
* value.
|
||||||
*
|
*
|
||||||
* \note If this function returns something other than 0 or
|
* \note If this function returns something other than 0 or
|
||||||
* MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context
|
* MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using
|
||||||
* becomes unusable, and you should either free it or call
|
* the SSL context for reading or writing, and either free it or
|
||||||
* \c mbedtls_ssl_session_reset() on it before re-using it for
|
* call \c mbedtls_ssl_session_reset() on it before re-using it
|
||||||
* a new connection; the current connection must be closed.
|
* for a new connection; the current connection must be closed.
|
||||||
*/
|
*/
|
||||||
int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl );
|
int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl );
|
||||||
#endif /* MBEDTLS_SSL_RENEGOTIATION */
|
#endif /* MBEDTLS_SSL_RENEGOTIATION */
|
||||||
@ -2483,20 +2546,20 @@ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl );
|
|||||||
* \param buf buffer that will hold the data
|
* \param buf buffer that will hold the data
|
||||||
* \param len maximum number of bytes to read
|
* \param len maximum number of bytes to read
|
||||||
*
|
*
|
||||||
* \return the number of bytes read, or
|
* \return One of the following:
|
||||||
* 0 for EOF, or
|
* - 0 if the read end of the underlying transport was closed,
|
||||||
* MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or
|
* - the (positive) number of bytes read, or
|
||||||
* MBEDTLS_ERR_SSL_CLIENT_RECONNECT (see below), or
|
* - a negative error code on failure.
|
||||||
* another negative error code.
|
|
||||||
*
|
*
|
||||||
* \note If this function returns something other than a positive
|
* If MBEDTLS_ERR_SSL_WANT_READ is returned, no application data
|
||||||
* value or MBEDTLS_ERR_SSL_WANT_READ/WRITE or
|
* is available from the underlying transport. In this case,
|
||||||
* MBEDTLS_ERR_SSL_CLIENT_RECONNECT, then the ssl context
|
* the function needs to be called again at some later stage.
|
||||||
* becomes unusable, and you should either free it or call
|
|
||||||
* \c mbedtls_ssl_session_reset() on it before re-using it for
|
|
||||||
* a new connection; the current connection must be closed.
|
|
||||||
*
|
*
|
||||||
* \note When this function return MBEDTLS_ERR_SSL_CLIENT_RECONNECT
|
* If MBEDTLS_ERR_SSL_WANT_WRITE is returned, a write is pending
|
||||||
|
* but the underlying transport isn't available for writing. In this
|
||||||
|
* case, the function needs to be called again at some later stage.
|
||||||
|
*
|
||||||
|
* When this function return MBEDTLS_ERR_SSL_CLIENT_RECONNECT
|
||||||
* (which can only happen server-side), it means that a client
|
* (which can only happen server-side), it means that a client
|
||||||
* is initiating a new connection using the same source port.
|
* is initiating a new connection using the same source port.
|
||||||
* You can either treat that as a connection close and wait
|
* You can either treat that as a connection close and wait
|
||||||
@ -2509,6 +2572,28 @@ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl );
|
|||||||
* again. WARNING: not validating the identity of the client
|
* again. WARNING: not validating the identity of the client
|
||||||
* again, or not transmitting the new identity to the
|
* again, or not transmitting the new identity to the
|
||||||
* application layer, would allow authentication bypass!
|
* application layer, would allow authentication bypass!
|
||||||
|
*
|
||||||
|
* \note If this function returns something other than a positive value
|
||||||
|
* or MBEDTLS_ERR_SSL_WANT_READ/WRITE or MBEDTLS_ERR_SSL_CLIENT_RECONNECT,
|
||||||
|
* you must stop using the SSL context for reading or writing,
|
||||||
|
* and either free it or call \c mbedtls_ssl_session_reset() on it
|
||||||
|
* before re-using it for a new connection; the current connection
|
||||||
|
* must be closed.
|
||||||
|
*
|
||||||
|
* \note Remarks regarding event-driven DTLS:
|
||||||
|
* - If the function returns MBEDTLS_ERR_SSL_WANT_READ, no datagram
|
||||||
|
* from the underlying transport layer is currently being processed,
|
||||||
|
* and it is safe to idle until the timer or the underlying transport
|
||||||
|
* signal a new event.
|
||||||
|
* - This function may return MBEDTLS_ERR_SSL_WANT_READ even if data was
|
||||||
|
* initially available on the underlying transport, as this data may have
|
||||||
|
* been only e.g. duplicated messages or a renegotiation request.
|
||||||
|
* Therefore, you must be prepared to receive MBEDTLS_ERR_SSL_WANT_READ even
|
||||||
|
* when reacting to an incoming-data event from the underlying transport.
|
||||||
|
* - On success, the datagram of the underlying transport that is currently
|
||||||
|
* being processed may contain further DTLS records. You should call
|
||||||
|
* \c mbedtls_ssl_check_pending to check for remaining records.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len );
|
int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len );
|
||||||
|
|
||||||
@ -2529,11 +2614,11 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
|
|||||||
* or MBEDTLS_ERR_SSL_WANT_WRITE or MBEDTLS_ERR_SSL_WANT_READ,
|
* or MBEDTLS_ERR_SSL_WANT_WRITE or MBEDTLS_ERR_SSL_WANT_READ,
|
||||||
* or another negative error code.
|
* or another negative error code.
|
||||||
*
|
*
|
||||||
* \note If this function returns something other than a positive
|
* \note If this function returns something other than a positive value
|
||||||
* value or MBEDTLS_ERR_SSL_WANT_READ/WRITE, the ssl context
|
* or MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using
|
||||||
* becomes unusable, and you should either free it or call
|
* the SSL context for reading or writing, and either free it or
|
||||||
* \c mbedtls_ssl_session_reset() on it before re-using it for
|
* call \c mbedtls_ssl_session_reset() on it before re-using it
|
||||||
* a new connection; the current connection must be closed.
|
* for a new connection; the current connection must be closed.
|
||||||
*
|
*
|
||||||
* \note When this function returns MBEDTLS_ERR_SSL_WANT_WRITE/READ,
|
* \note When this function returns MBEDTLS_ERR_SSL_WANT_WRITE/READ,
|
||||||
* it must be called later with the *same* arguments,
|
* it must be called later with the *same* arguments,
|
||||||
@ -2562,10 +2647,10 @@ int mbedtls_ssl_write( mbedtls_ssl_context *ssl, const unsigned char *buf, size_
|
|||||||
* \return 0 if successful, or a specific SSL error code.
|
* \return 0 if successful, or a specific SSL error code.
|
||||||
*
|
*
|
||||||
* \note If this function returns something other than 0 or
|
* \note If this function returns something other than 0 or
|
||||||
* MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context
|
* MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using
|
||||||
* becomes unusable, and you should either free it or call
|
* the SSL context for reading or writing, and either free it or
|
||||||
* \c mbedtls_ssl_session_reset() on it before re-using it for
|
* call \c mbedtls_ssl_session_reset() on it before re-using it
|
||||||
* a new connection; the current connection must be closed.
|
* for a new connection; the current connection must be closed.
|
||||||
*/
|
*/
|
||||||
int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl,
|
int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl,
|
||||||
unsigned char level,
|
unsigned char level,
|
||||||
@ -2578,10 +2663,10 @@ int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl,
|
|||||||
* \return 0 if successful, or a specific SSL error code.
|
* \return 0 if successful, or a specific SSL error code.
|
||||||
*
|
*
|
||||||
* \note If this function returns something other than 0 or
|
* \note If this function returns something other than 0 or
|
||||||
* MBEDTLS_ERR_SSL_WANT_READ/WRITE, then the ssl context
|
* MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using
|
||||||
* becomes unusable, and you should either free it or call
|
* the SSL context for reading or writing, and either free it or
|
||||||
* \c mbedtls_ssl_session_reset() on it before re-using it for
|
* call \c mbedtls_ssl_session_reset() on it before re-using it
|
||||||
* a new connection; the current connection must be closed.
|
* for a new connection; the current connection must be closed.
|
||||||
*/
|
*/
|
||||||
int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl );
|
int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl );
|
||||||
|
|
||||||
|
@ -478,7 +478,7 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
|
|||||||
if( use_ret == -(MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE) )
|
if( use_ret == -(MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE) )
|
||||||
mbedtls_snprintf( buf, buflen, "SSL - None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages)" );
|
mbedtls_snprintf( buf, buflen, "SSL - None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages)" );
|
||||||
if( use_ret == -(MBEDTLS_ERR_SSL_WANT_READ) )
|
if( use_ret == -(MBEDTLS_ERR_SSL_WANT_READ) )
|
||||||
mbedtls_snprintf( buf, buflen, "SSL - Connection requires a read call" );
|
mbedtls_snprintf( buf, buflen, "SSL - No data of requested type currently available on underlying transport" );
|
||||||
if( use_ret == -(MBEDTLS_ERR_SSL_WANT_WRITE) )
|
if( use_ret == -(MBEDTLS_ERR_SSL_WANT_WRITE) )
|
||||||
mbedtls_snprintf( buf, buflen, "SSL - Connection requires a write call" );
|
mbedtls_snprintf( buf, buflen, "SSL - Connection requires a write call" );
|
||||||
if( use_ret == -(MBEDTLS_ERR_SSL_TIMEOUT) )
|
if( use_ret == -(MBEDTLS_ERR_SSL_TIMEOUT) )
|
||||||
@ -491,6 +491,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
|
|||||||
mbedtls_snprintf( buf, buflen, "SSL - The alert message received indicates a non-fatal error" );
|
mbedtls_snprintf( buf, buflen, "SSL - The alert message received indicates a non-fatal error" );
|
||||||
if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH) )
|
if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH) )
|
||||||
mbedtls_snprintf( buf, buflen, "SSL - Couldn't set the hash for verifying CertificateVerify" );
|
mbedtls_snprintf( buf, buflen, "SSL - Couldn't set the hash for verifying CertificateVerify" );
|
||||||
|
if( use_ret == -(MBEDTLS_ERR_SSL_CONTINUE_PROCESSING) )
|
||||||
|
mbedtls_snprintf( buf, buflen, "SSL - Internal-only message signaling that further message-processing should be done" );
|
||||||
#endif /* MBEDTLS_SSL_TLS_C */
|
#endif /* MBEDTLS_SSL_TLS_C */
|
||||||
|
|
||||||
#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
|
#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
|
||||||
@ -745,6 +747,10 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
|
|||||||
mbedtls_snprintf( buf, buflen, "NET - Buffer is too small to hold the data" );
|
mbedtls_snprintf( buf, buflen, "NET - Buffer is too small to hold the data" );
|
||||||
if( use_ret == -(MBEDTLS_ERR_NET_INVALID_CONTEXT) )
|
if( use_ret == -(MBEDTLS_ERR_NET_INVALID_CONTEXT) )
|
||||||
mbedtls_snprintf( buf, buflen, "NET - The context is invalid, eg because it was free()ed" );
|
mbedtls_snprintf( buf, buflen, "NET - The context is invalid, eg because it was free()ed" );
|
||||||
|
if( use_ret == -(MBEDTLS_ERR_NET_POLL_FAILED) )
|
||||||
|
mbedtls_snprintf( buf, buflen, "NET - Polling the net context failed" );
|
||||||
|
if( use_ret == -(MBEDTLS_ERR_NET_BAD_INPUT_DATA) )
|
||||||
|
mbedtls_snprintf( buf, buflen, "NET - Input invalid" );
|
||||||
#endif /* MBEDTLS_NET_C */
|
#endif /* MBEDTLS_NET_C */
|
||||||
|
|
||||||
#if defined(MBEDTLS_OID_C)
|
#if defined(MBEDTLS_OID_C)
|
||||||
|
@ -45,6 +45,8 @@
|
|||||||
#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
|
#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
|
||||||
!defined(EFI32)
|
!defined(EFI32)
|
||||||
|
|
||||||
|
#define IS_EINTR( ret ) ( ( ret ) == WSAEINTR )
|
||||||
|
|
||||||
#ifdef _WIN32_WINNT
|
#ifdef _WIN32_WINNT
|
||||||
#undef _WIN32_WINNT
|
#undef _WIN32_WINNT
|
||||||
#endif
|
#endif
|
||||||
@ -82,6 +84,8 @@ static int wsa_init_done = 0;
|
|||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
#define IS_EINTR( ret ) ( ( ret ) == EINTR )
|
||||||
|
|
||||||
#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
|
#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
|
||||||
|
|
||||||
/* Some MS functions want int and MSVC warns if we pass size_t,
|
/* Some MS functions want int and MSVC warns if we pass size_t,
|
||||||
@ -438,6 +442,68 @@ int mbedtls_net_set_nonblock( mbedtls_net_context *ctx )
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if data is available on the socket
|
||||||
|
*/
|
||||||
|
|
||||||
|
int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout )
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
fd_set read_fds;
|
||||||
|
fd_set write_fds;
|
||||||
|
|
||||||
|
int fd = ctx->fd;
|
||||||
|
|
||||||
|
if( fd < 0 )
|
||||||
|
return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
|
||||||
|
|
||||||
|
/* Ensure that memory sanitizers consider
|
||||||
|
* read_fds and write_fds as initialized even
|
||||||
|
* if FD_ZERO is implemented in assembly. */
|
||||||
|
memset( &read_fds, 0, sizeof( read_fds ) );
|
||||||
|
memset( &write_fds, 0, sizeof( write_fds ) );
|
||||||
|
|
||||||
|
FD_ZERO( &read_fds );
|
||||||
|
if( rw & MBEDTLS_NET_POLL_READ )
|
||||||
|
{
|
||||||
|
rw &= ~MBEDTLS_NET_POLL_READ;
|
||||||
|
FD_SET( fd, &read_fds );
|
||||||
|
}
|
||||||
|
|
||||||
|
FD_ZERO( &write_fds );
|
||||||
|
if( rw & MBEDTLS_NET_POLL_WRITE )
|
||||||
|
{
|
||||||
|
rw &= ~MBEDTLS_NET_POLL_WRITE;
|
||||||
|
FD_SET( fd, &write_fds );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( rw != 0 )
|
||||||
|
return( MBEDTLS_ERR_NET_BAD_INPUT_DATA );
|
||||||
|
|
||||||
|
tv.tv_sec = timeout / 1000;
|
||||||
|
tv.tv_usec = ( timeout % 1000 ) * 1000;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ret = select( fd + 1, &read_fds, &write_fds, NULL,
|
||||||
|
timeout == (uint32_t) -1 ? NULL : &tv );
|
||||||
|
}
|
||||||
|
while( IS_EINTR( ret ) );
|
||||||
|
|
||||||
|
if( ret < 0 )
|
||||||
|
return( MBEDTLS_ERR_NET_POLL_FAILED );
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
if( FD_ISSET( fd, &read_fds ) )
|
||||||
|
ret |= MBEDTLS_NET_POLL_READ;
|
||||||
|
if( FD_ISSET( fd, &write_fds ) )
|
||||||
|
ret |= MBEDTLS_NET_POLL_WRITE;
|
||||||
|
|
||||||
|
return( ret );
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Portable usleep helper
|
* Portable usleep helper
|
||||||
*/
|
*/
|
||||||
@ -497,8 +563,8 @@ int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len )
|
|||||||
/*
|
/*
|
||||||
* Read at most 'len' characters, blocking for at most 'timeout' ms
|
* Read at most 'len' characters, blocking for at most 'timeout' ms
|
||||||
*/
|
*/
|
||||||
int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len,
|
int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf,
|
||||||
uint32_t timeout )
|
size_t len, uint32_t timeout )
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
@ -3750,7 +3750,10 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
|
|||||||
/* Read the message without adding it to the checksum */
|
/* Read the message without adding it to the checksum */
|
||||||
do {
|
do {
|
||||||
|
|
||||||
if( ( ret = mbedtls_ssl_read_record_layer( ssl ) ) != 0 )
|
do ret = mbedtls_ssl_read_record_layer( ssl );
|
||||||
|
while( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
|
||||||
|
|
||||||
|
if( ret != 0 )
|
||||||
{
|
{
|
||||||
MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret );
|
MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret );
|
||||||
return( ret );
|
return( ret );
|
||||||
@ -3758,7 +3761,8 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
|
|||||||
|
|
||||||
ret = mbedtls_ssl_handle_message_type( ssl );
|
ret = mbedtls_ssl_handle_message_type( ssl );
|
||||||
|
|
||||||
} while( MBEDTLS_ERR_SSL_NON_FATAL == ret );
|
} while( MBEDTLS_ERR_SSL_NON_FATAL == ret ||
|
||||||
|
MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret );
|
||||||
|
|
||||||
if( 0 != ret )
|
if( 0 != ret )
|
||||||
{
|
{
|
||||||
|
@ -2337,7 +2337,10 @@ int mbedtls_ssl_fetch_input( mbedtls_ssl_context *ssl, size_t nb_want )
|
|||||||
* that will end up being dropped.
|
* that will end up being dropped.
|
||||||
*/
|
*/
|
||||||
if( ssl_check_timer( ssl ) != 0 )
|
if( ssl_check_timer( ssl ) != 0 )
|
||||||
|
{
|
||||||
|
MBEDTLS_SSL_DEBUG_MSG( 2, ( "timer has expired" ) );
|
||||||
ret = MBEDTLS_ERR_SSL_TIMEOUT;
|
ret = MBEDTLS_ERR_SSL_TIMEOUT;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
len = MBEDTLS_SSL_BUFFER_LEN - ( ssl->in_hdr - ssl->in_buf );
|
len = MBEDTLS_SSL_BUFFER_LEN - ( ssl->in_hdr - ssl->in_buf );
|
||||||
@ -3085,7 +3088,7 @@ static int ssl_reassemble_dtls_handshake( mbedtls_ssl_context *ssl )
|
|||||||
if( ssl_bitmask_check( bitmask, msg_len ) != 0 )
|
if( ssl_bitmask_check( bitmask, msg_len ) != 0 )
|
||||||
{
|
{
|
||||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "message is not complete yet" ) );
|
MBEDTLS_SSL_DEBUG_MSG( 2, ( "message is not complete yet" ) );
|
||||||
return( MBEDTLS_ERR_SSL_WANT_READ );
|
return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
|
||||||
}
|
}
|
||||||
|
|
||||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake message completed" ) );
|
MBEDTLS_SSL_DEBUG_MSG( 2, ( "handshake message completed" ) );
|
||||||
@ -3162,9 +3165,11 @@ int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl )
|
|||||||
int ret;
|
int ret;
|
||||||
unsigned int recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5];
|
unsigned int recv_msg_seq = ( ssl->in_msg[4] << 8 ) | ssl->in_msg[5];
|
||||||
|
|
||||||
/* ssl->handshake is NULL when receiving ClientHello for renego */
|
|
||||||
if( ssl->handshake != NULL &&
|
if( ssl->handshake != NULL &&
|
||||||
recv_msg_seq != ssl->handshake->in_msg_seq )
|
( ( ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER &&
|
||||||
|
recv_msg_seq != ssl->handshake->in_msg_seq ) ||
|
||||||
|
( ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER &&
|
||||||
|
ssl->in_msg[0] != MBEDTLS_SSL_HS_CLIENT_HELLO ) ) )
|
||||||
{
|
{
|
||||||
/* Retransmit only on last message from previous flight, to avoid
|
/* Retransmit only on last message from previous flight, to avoid
|
||||||
* too many retransmissions.
|
* too many retransmissions.
|
||||||
@ -3191,7 +3196,7 @@ int mbedtls_ssl_prepare_handshake_record( mbedtls_ssl_context *ssl )
|
|||||||
ssl->handshake->in_msg_seq ) );
|
ssl->handshake->in_msg_seq ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
return( MBEDTLS_ERR_SSL_WANT_READ );
|
return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
|
||||||
}
|
}
|
||||||
/* Wait until message completion to increment in_msg_seq */
|
/* Wait until message completion to increment in_msg_seq */
|
||||||
|
|
||||||
@ -3594,81 +3599,23 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl )
|
|||||||
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check length against bounds of the current transform and version */
|
|
||||||
if( ssl->transform_in == NULL )
|
|
||||||
{
|
|
||||||
if( ssl->in_msglen < 1 ||
|
|
||||||
ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN )
|
|
||||||
{
|
|
||||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
|
|
||||||
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if( ssl->in_msglen < ssl->transform_in->minlen )
|
|
||||||
{
|
|
||||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
|
|
||||||
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SSL_PROTO_SSL3)
|
|
||||||
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 &&
|
|
||||||
ssl->in_msglen > ssl->transform_in->minlen + MBEDTLS_SSL_MAX_CONTENT_LEN )
|
|
||||||
{
|
|
||||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
|
|
||||||
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
|
|
||||||
defined(MBEDTLS_SSL_PROTO_TLS1_2)
|
|
||||||
/*
|
/*
|
||||||
* TLS encrypted messages can have up to 256 bytes of padding
|
* DTLS-related tests.
|
||||||
*/
|
* Check epoch before checking length constraint because
|
||||||
if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 &&
|
* the latter varies with the epoch. E.g., if a ChangeCipherSpec
|
||||||
ssl->in_msglen > ssl->transform_in->minlen +
|
* message gets duplicated before the corresponding Finished message,
|
||||||
MBEDTLS_SSL_MAX_CONTENT_LEN + 256 )
|
* the second ChangeCipherSpec should be discarded because it belongs
|
||||||
{
|
* to an old epoch, but not because its length is shorter than
|
||||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
|
* the minimum record length for packets using the new record transform.
|
||||||
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
* Note that these two kinds of failures are handled differently,
|
||||||
}
|
* as an unexpected record is silently skipped but an invalid
|
||||||
#endif
|
* record leads to the entire datagram being dropped.
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* DTLS-related tests done last, because most of them may result in
|
|
||||||
* silently dropping the record (but not the whole datagram), and we only
|
|
||||||
* want to consider that after ensuring that the "basic" fields (type,
|
|
||||||
* version, length) are sane.
|
|
||||||
*/
|
*/
|
||||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||||
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
|
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
|
||||||
{
|
{
|
||||||
unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1];
|
unsigned int rec_epoch = ( ssl->in_ctr[0] << 8 ) | ssl->in_ctr[1];
|
||||||
|
|
||||||
/* Drop unexpected ChangeCipherSpec messages */
|
|
||||||
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC &&
|
|
||||||
ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC &&
|
|
||||||
ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC )
|
|
||||||
{
|
|
||||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ChangeCipherSpec" ) );
|
|
||||||
return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Drop unexpected ApplicationData records,
|
|
||||||
* except at the beginning of renegotiations */
|
|
||||||
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA &&
|
|
||||||
ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER
|
|
||||||
#if defined(MBEDTLS_SSL_RENEGOTIATION)
|
|
||||||
&& ! ( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
|
|
||||||
ssl->state == MBEDTLS_SSL_SERVER_HELLO )
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
|
||||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ApplicationData" ) );
|
|
||||||
return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check epoch (and sequence number) with DTLS */
|
/* Check epoch (and sequence number) with DTLS */
|
||||||
if( rec_epoch != ssl->in_epoch )
|
if( rec_epoch != ssl->in_epoch )
|
||||||
{
|
{
|
||||||
@ -3708,9 +3655,74 @@ static int ssl_parse_record_header( mbedtls_ssl_context *ssl )
|
|||||||
return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
|
return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Drop unexpected ChangeCipherSpec messages */
|
||||||
|
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC &&
|
||||||
|
ssl->state != MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC &&
|
||||||
|
ssl->state != MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC )
|
||||||
|
{
|
||||||
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ChangeCipherSpec" ) );
|
||||||
|
return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Drop unexpected ApplicationData records,
|
||||||
|
* except at the beginning of renegotiations */
|
||||||
|
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA &&
|
||||||
|
ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER
|
||||||
|
#if defined(MBEDTLS_SSL_RENEGOTIATION)
|
||||||
|
&& ! ( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS &&
|
||||||
|
ssl->state == MBEDTLS_SSL_SERVER_HELLO )
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "dropping unexpected ApplicationData" ) );
|
||||||
|
return( MBEDTLS_ERR_SSL_UNEXPECTED_RECORD );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif /* MBEDTLS_SSL_PROTO_DTLS */
|
#endif /* MBEDTLS_SSL_PROTO_DTLS */
|
||||||
|
|
||||||
|
|
||||||
|
/* Check length against bounds of the current transform and version */
|
||||||
|
if( ssl->transform_in == NULL )
|
||||||
|
{
|
||||||
|
if( ssl->in_msglen < 1 ||
|
||||||
|
ssl->in_msglen > MBEDTLS_SSL_MAX_CONTENT_LEN )
|
||||||
|
{
|
||||||
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
|
||||||
|
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( ssl->in_msglen < ssl->transform_in->minlen )
|
||||||
|
{
|
||||||
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
|
||||||
|
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_SSL_PROTO_SSL3)
|
||||||
|
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 &&
|
||||||
|
ssl->in_msglen > ssl->transform_in->minlen + MBEDTLS_SSL_MAX_CONTENT_LEN )
|
||||||
|
{
|
||||||
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
|
||||||
|
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
|
||||||
|
defined(MBEDTLS_SSL_PROTO_TLS1_2)
|
||||||
|
/*
|
||||||
|
* TLS encrypted messages can have up to 256 bytes of padding
|
||||||
|
*/
|
||||||
|
if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_1 &&
|
||||||
|
ssl->in_msglen > ssl->transform_in->minlen +
|
||||||
|
MBEDTLS_SSL_MAX_CONTENT_LEN + 256 )
|
||||||
|
{
|
||||||
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad message length" ) );
|
||||||
|
return( MBEDTLS_ERR_SSL_INVALID_RECORD );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3799,7 +3811,10 @@ int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl )
|
|||||||
{
|
{
|
||||||
do {
|
do {
|
||||||
|
|
||||||
if( ( ret = mbedtls_ssl_read_record_layer( ssl ) ) != 0 )
|
do ret = mbedtls_ssl_read_record_layer( ssl );
|
||||||
|
while( ret == MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
|
||||||
|
|
||||||
|
if( ret != 0 )
|
||||||
{
|
{
|
||||||
MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret );
|
MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret );
|
||||||
return( ret );
|
return( ret );
|
||||||
@ -3807,11 +3822,12 @@ int mbedtls_ssl_read_record( mbedtls_ssl_context *ssl )
|
|||||||
|
|
||||||
ret = mbedtls_ssl_handle_message_type( ssl );
|
ret = mbedtls_ssl_handle_message_type( ssl );
|
||||||
|
|
||||||
} while( MBEDTLS_ERR_SSL_NON_FATAL == ret );
|
} while( MBEDTLS_ERR_SSL_NON_FATAL == ret ||
|
||||||
|
MBEDTLS_ERR_SSL_CONTINUE_PROCESSING == ret );
|
||||||
|
|
||||||
if( 0 != ret )
|
if( 0 != ret )
|
||||||
{
|
{
|
||||||
MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_read_record_layer" ), ret );
|
MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ssl_handle_message_type" ), ret );
|
||||||
return( ret );
|
return( ret );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3849,11 +3865,6 @@ int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl )
|
|||||||
* (2) Alert messages:
|
* (2) Alert messages:
|
||||||
* Consume whole record content, in_msglen = 0.
|
* Consume whole record content, in_msglen = 0.
|
||||||
*
|
*
|
||||||
* NOTE: This needs to be fixed, since like for
|
|
||||||
* handshake messages it is allowed to have
|
|
||||||
* multiple alerts witin a single record.
|
|
||||||
* Internal reference IOTSSL-1321.
|
|
||||||
*
|
|
||||||
* (3) Change cipher spec:
|
* (3) Change cipher spec:
|
||||||
* Consume whole record content, in_msglen = 0.
|
* Consume whole record content, in_msglen = 0.
|
||||||
*
|
*
|
||||||
@ -3881,12 +3892,12 @@ int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl )
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* Notes:
|
/* Notes:
|
||||||
* (1) in_hslen is *NOT* necessarily the size of the
|
* (1) in_hslen is not necessarily the size of the
|
||||||
* current handshake content: If DTLS handshake
|
* current handshake content: If DTLS handshake
|
||||||
* fragmentation is used, that's the fragment
|
* fragmentation is used, that's the fragment
|
||||||
* size instead. Using the total handshake message
|
* size instead. Using the total handshake message
|
||||||
* size here is FAULTY and should be changed at
|
* size here is faulty and should be changed at
|
||||||
* some point. Internal reference IOTSSL-1414.
|
* some point.
|
||||||
* (2) While it doesn't seem to cause problems, one
|
* (2) While it doesn't seem to cause problems, one
|
||||||
* has to be very careful not to assume that in_hslen
|
* has to be very careful not to assume that in_hslen
|
||||||
* is always <= in_msglen in a sensible communication.
|
* is always <= in_msglen in a sensible communication.
|
||||||
@ -3937,12 +3948,6 @@ int mbedtls_ssl_read_record_layer( mbedtls_ssl_context *ssl )
|
|||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Need to fetch a new record */
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
|
||||||
read_record_header:
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Current record either fully processed or to be discarded. */
|
/* Current record either fully processed or to be discarded. */
|
||||||
|
|
||||||
if( ( ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_hdr_len( ssl ) ) ) != 0 )
|
if( ( ret = mbedtls_ssl_fetch_input( ssl, mbedtls_ssl_hdr_len( ssl ) ) ) != 0 )
|
||||||
@ -3977,7 +3982,7 @@ read_record_header:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get next record */
|
/* Get next record */
|
||||||
goto read_record_header;
|
return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return( ret );
|
return( ret );
|
||||||
@ -3996,7 +4001,13 @@ read_record_header:
|
|||||||
/* Done reading this record, get ready for the next one */
|
/* Done reading this record, get ready for the next one */
|
||||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||||
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
|
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
|
||||||
|
{
|
||||||
ssl->next_record_offset = ssl->in_msglen + mbedtls_ssl_hdr_len( ssl );
|
ssl->next_record_offset = ssl->in_msglen + mbedtls_ssl_hdr_len( ssl );
|
||||||
|
if( ssl->next_record_offset < ssl->in_left )
|
||||||
|
{
|
||||||
|
MBEDTLS_SSL_DEBUG_MSG( 3, ( "more than one record within datagram" ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
ssl->in_left = 0;
|
ssl->in_left = 0;
|
||||||
@ -4043,7 +4054,7 @@ read_record_header:
|
|||||||
ssl->in_left = 0;
|
ssl->in_left = 0;
|
||||||
|
|
||||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record (mac)" ) );
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "discarding invalid record (mac)" ) );
|
||||||
goto read_record_header;
|
return( MBEDTLS_ERR_SSL_CONTINUE_PROCESSING );
|
||||||
}
|
}
|
||||||
|
|
||||||
return( ret );
|
return( ret );
|
||||||
@ -4064,46 +4075,6 @@ read_record_header:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* When we sent the last flight of the handshake, we MUST respond to a
|
|
||||||
* retransmit of the peer's previous flight with a retransmit. (In
|
|
||||||
* practice, only the Finished message will make it, other messages
|
|
||||||
* including CCS use the old transform so they're dropped as invalid.)
|
|
||||||
*
|
|
||||||
* If the record we received is not a handshake message, however, it
|
|
||||||
* means the peer received our last flight so we can clean up
|
|
||||||
* handshake info.
|
|
||||||
*
|
|
||||||
* This check needs to be done before prepare_handshake() due to an edge
|
|
||||||
* case: if the client immediately requests renegotiation, this
|
|
||||||
* finishes the current handshake first, avoiding the new ClientHello
|
|
||||||
* being mistaken for an ancient message in the current handshake.
|
|
||||||
*/
|
|
||||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
|
||||||
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
|
|
||||||
ssl->handshake != NULL &&
|
|
||||||
ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
|
|
||||||
{
|
|
||||||
if( ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
|
|
||||||
ssl->in_msg[0] == MBEDTLS_SSL_HS_FINISHED )
|
|
||||||
{
|
|
||||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "received retransmit of last flight" ) );
|
|
||||||
|
|
||||||
if( ( ret = mbedtls_ssl_resend( ssl ) ) != 0 )
|
|
||||||
{
|
|
||||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_resend", ret );
|
|
||||||
return( ret );
|
|
||||||
}
|
|
||||||
|
|
||||||
return( MBEDTLS_ERR_SSL_WANT_READ );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ssl_handshake_wrapup_free_hs_transform( ssl );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4148,7 +4119,7 @@ int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl )
|
|||||||
if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING &&
|
if( ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING &&
|
||||||
ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION )
|
ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION )
|
||||||
{
|
{
|
||||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no_cert" ) );
|
MBEDTLS_SSL_DEBUG_MSG( 2, ( "is a SSLv3 no renegotiation alert" ) );
|
||||||
/* Will be handled when trying to parse ServerHello */
|
/* Will be handled when trying to parse ServerHello */
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
@ -4170,6 +4141,15 @@ int mbedtls_ssl_handle_message_type( mbedtls_ssl_context *ssl )
|
|||||||
return MBEDTLS_ERR_SSL_NON_FATAL;
|
return MBEDTLS_ERR_SSL_NON_FATAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||||
|
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
|
||||||
|
ssl->handshake != NULL &&
|
||||||
|
ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER )
|
||||||
|
{
|
||||||
|
ssl_handshake_wrapup_free_hs_transform( ssl );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6506,6 +6486,61 @@ size_t mbedtls_ssl_get_bytes_avail( const mbedtls_ssl_context *ssl )
|
|||||||
return( ssl->in_offt == NULL ? 0 : ssl->in_msglen );
|
return( ssl->in_offt == NULL ? 0 : ssl->in_msglen );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mbedtls_ssl_check_pending( const mbedtls_ssl_context *ssl )
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Case A: We're currently holding back
|
||||||
|
* a message for further processing.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if( ssl->keep_current_message == 1 )
|
||||||
|
{
|
||||||
|
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: record held back for processing" ) );
|
||||||
|
return( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Case B: Further records are pending in the current datagram.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||||
|
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
|
||||||
|
ssl->in_left > ssl->next_record_offset )
|
||||||
|
{
|
||||||
|
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more records within current datagram" ) );
|
||||||
|
return( 1 );
|
||||||
|
}
|
||||||
|
#endif /* MBEDTLS_SSL_PROTO_DTLS */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Case C: A handshake message is being processed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if( ssl->in_hslen > 0 && ssl->in_hslen < ssl->in_msglen )
|
||||||
|
{
|
||||||
|
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: more handshake messages within current record" ) );
|
||||||
|
return( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Case D: An application data message is being processed
|
||||||
|
*/
|
||||||
|
if( ssl->in_offt != NULL )
|
||||||
|
{
|
||||||
|
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: application data record is being processed" ) );
|
||||||
|
return( 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In all other cases, the rest of the message can be dropped.
|
||||||
|
* As in ssl_read_record_layer, this needs to be adapted if
|
||||||
|
* we implement support for multiple alerts in single records.
|
||||||
|
*/
|
||||||
|
|
||||||
|
MBEDTLS_SSL_DEBUG_MSG( 3, ( "ssl_check_pending: nothing pending" ) );
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl )
|
uint32_t mbedtls_ssl_get_verify_result( const mbedtls_ssl_context *ssl )
|
||||||
{
|
{
|
||||||
if( ssl->session != NULL )
|
if( ssl->session != NULL )
|
||||||
@ -6914,25 +6949,16 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO
|
* The logic could be streamlined here. Instead of
|
||||||
*
|
|
||||||
* The logic should be streamlined here:
|
|
||||||
*
|
|
||||||
* Instead of
|
|
||||||
*
|
|
||||||
* - Manually checking whether ssl->in_offt is NULL
|
* - Manually checking whether ssl->in_offt is NULL
|
||||||
* - Fetching a new record if yes
|
* - Fetching a new record if yes
|
||||||
* - Setting ssl->in_offt if one finds an application record
|
* - Setting ssl->in_offt if one finds an application record
|
||||||
* - Resetting keep_current_message after handling the application data
|
* - Resetting keep_current_message after handling the application data
|
||||||
*
|
|
||||||
* one should
|
* one should
|
||||||
*
|
|
||||||
* - Adapt read_record to set ssl->in_offt automatically
|
* - Adapt read_record to set ssl->in_offt automatically
|
||||||
* when a new application data record is processed.
|
* when a new application data record is processed.
|
||||||
* - Always call mbedtls_ssl_read_record here.
|
* - Always call mbedtls_ssl_read_record here.
|
||||||
*
|
|
||||||
* This way, the logic of ssl_read would be much clearer:
|
* This way, the logic of ssl_read would be much clearer:
|
||||||
*
|
|
||||||
* (1) Always call record layer and see what kind of record is on
|
* (1) Always call record layer and see what kind of record is on
|
||||||
* and have it ready for consumption (in particular, in_offt
|
* and have it ready for consumption (in particular, in_offt
|
||||||
* properly set for application data records).
|
* properly set for application data records).
|
||||||
@ -6942,13 +6968,12 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
|
|||||||
* (3) If it's something different from application data,
|
* (3) If it's something different from application data,
|
||||||
* handle it accordingly, e.g. potentially start a
|
* handle it accordingly, e.g. potentially start a
|
||||||
* renegotiation.
|
* renegotiation.
|
||||||
*
|
|
||||||
* This will also remove the need to manually reset
|
* This will also remove the need to manually reset
|
||||||
* ssl->keep_current_message = 0 below.
|
* ssl->keep_current_message = 0 below.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if( ssl->in_offt == NULL )
|
/* Loop as long as no application data record is available */
|
||||||
|
while( ssl->in_offt == NULL )
|
||||||
{
|
{
|
||||||
/* Start timer if not already running */
|
/* Start timer if not already running */
|
||||||
if( ssl->f_get_timer != NULL &&
|
if( ssl->f_get_timer != NULL &&
|
||||||
@ -7002,7 +7027,9 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
|
|||||||
/* With DTLS, drop the packet (probably from last handshake) */
|
/* With DTLS, drop the packet (probably from last handshake) */
|
||||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||||
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
|
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
|
||||||
return( MBEDTLS_ERR_SSL_WANT_READ );
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
|
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
|
||||||
}
|
}
|
||||||
@ -7017,7 +7044,9 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
|
|||||||
/* With DTLS, drop the packet (probably from last handshake) */
|
/* With DTLS, drop the packet (probably from last handshake) */
|
||||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||||
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
|
if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
|
||||||
return( MBEDTLS_ERR_SSL_WANT_READ );
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
|
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
|
||||||
}
|
}
|
||||||
@ -7090,7 +7119,25 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return( MBEDTLS_ERR_SSL_WANT_READ );
|
/* At this point, we don't know whether the renegotiation has been
|
||||||
|
* completed or not. The cases to consider are the following:
|
||||||
|
* 1) The renegotiation is complete. In this case, no new record
|
||||||
|
* has been read yet.
|
||||||
|
* 2) The renegotiation is incomplete because the client received
|
||||||
|
* an application data record while awaiting the ServerHello.
|
||||||
|
* 3) The renegotiation is incomplete because the client received
|
||||||
|
* a non-handshake, non-application data message while awaiting
|
||||||
|
* the ServerHello.
|
||||||
|
* In each of these case, looping will be the proper action:
|
||||||
|
* - For 1), the next iteration will read a new record and check
|
||||||
|
* if it's application data.
|
||||||
|
* - For 2), the loop condition isn't satisfied as application data
|
||||||
|
* is present, hence continue is the same as break
|
||||||
|
* - For 3), the loop condition is satisfied and read_record
|
||||||
|
* will re-deliver the message that was held back by the client
|
||||||
|
* when expecting the ServerHello.
|
||||||
|
*/
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
#if defined(MBEDTLS_SSL_RENEGOTIATION)
|
#if defined(MBEDTLS_SSL_RENEGOTIATION)
|
||||||
else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING )
|
else if( ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING )
|
||||||
|
@ -73,6 +73,7 @@ int main( void )
|
|||||||
#define DFL_REQUEST_SIZE -1
|
#define DFL_REQUEST_SIZE -1
|
||||||
#define DFL_DEBUG_LEVEL 0
|
#define DFL_DEBUG_LEVEL 0
|
||||||
#define DFL_NBIO 0
|
#define DFL_NBIO 0
|
||||||
|
#define DFL_EVENT 0
|
||||||
#define DFL_READ_TIMEOUT 0
|
#define DFL_READ_TIMEOUT 0
|
||||||
#define DFL_MAX_RESEND 0
|
#define DFL_MAX_RESEND 0
|
||||||
#define DFL_CA_FILE ""
|
#define DFL_CA_FILE ""
|
||||||
@ -250,6 +251,8 @@ int main( void )
|
|||||||
" debug_level=%%d default: 0 (disabled)\n" \
|
" debug_level=%%d default: 0 (disabled)\n" \
|
||||||
" nbio=%%d default: 0 (blocking I/O)\n" \
|
" nbio=%%d default: 0 (blocking I/O)\n" \
|
||||||
" options: 1 (non-blocking), 2 (added delays)\n" \
|
" options: 1 (non-blocking), 2 (added delays)\n" \
|
||||||
|
" event=%%d default: 0 (loop)\n" \
|
||||||
|
" options: 1 (level-triggered, implies nbio=1),\n" \
|
||||||
" read_timeout=%%d default: 0 ms (no timeout)\n" \
|
" read_timeout=%%d default: 0 ms (no timeout)\n" \
|
||||||
" max_resend=%%d default: 0 (no resend on timeout)\n" \
|
" max_resend=%%d default: 0 (no resend on timeout)\n" \
|
||||||
"\n" \
|
"\n" \
|
||||||
@ -302,6 +305,7 @@ struct options
|
|||||||
const char *server_port; /* port on which the ssl service runs */
|
const char *server_port; /* port on which the ssl service runs */
|
||||||
int debug_level; /* level of debugging */
|
int debug_level; /* level of debugging */
|
||||||
int nbio; /* should I/O be blocking? */
|
int nbio; /* should I/O be blocking? */
|
||||||
|
int event; /* loop or event-driven IO? level or edge triggered? */
|
||||||
uint32_t read_timeout; /* timeout on mbedtls_ssl_read() in milliseconds */
|
uint32_t read_timeout; /* timeout on mbedtls_ssl_read() in milliseconds */
|
||||||
int max_resend; /* DTLS times to resend on read timeout */
|
int max_resend; /* DTLS times to resend on read timeout */
|
||||||
const char *request_page; /* page on server to request */
|
const char *request_page; /* page on server to request */
|
||||||
@ -353,7 +357,8 @@ static void my_debug( void *ctx, int level,
|
|||||||
if( *p == '/' || *p == '\\' )
|
if( *p == '/' || *p == '\\' )
|
||||||
basename = p + 1;
|
basename = p + 1;
|
||||||
|
|
||||||
mbedtls_fprintf( (FILE *) ctx, "%s:%04d: |%d| %s", basename, line, level, str );
|
mbedtls_fprintf( (FILE *) ctx, "%s:%04d: |%d| %s",
|
||||||
|
basename, line, level, str );
|
||||||
fflush( (FILE *) ctx );
|
fflush( (FILE *) ctx );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -399,7 +404,8 @@ static int my_send( void *ctx, const unsigned char *buf, size_t len )
|
|||||||
/*
|
/*
|
||||||
* Enabled if debug_level > 1 in code below
|
* Enabled if debug_level > 1 in code below
|
||||||
*/
|
*/
|
||||||
static int my_verify( void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags )
|
static int my_verify( void *data, mbedtls_x509_crt *crt,
|
||||||
|
int depth, uint32_t *flags )
|
||||||
{
|
{
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
((void) data);
|
((void) data);
|
||||||
@ -436,6 +442,57 @@ static int ssl_sig_hashes_for_test[] = {
|
|||||||
};
|
};
|
||||||
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wait for an event from the underlying transport or the timer
|
||||||
|
* (Used in event-driven IO mode).
|
||||||
|
*/
|
||||||
|
#if !defined(MBEDTLS_TIMING_C)
|
||||||
|
int idle( mbedtls_net_context *fd,
|
||||||
|
int idle_reason )
|
||||||
|
#else
|
||||||
|
int idle( mbedtls_net_context *fd,
|
||||||
|
mbedtls_timing_delay_context *timer,
|
||||||
|
int idle_reason )
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
int poll_type = 0;
|
||||||
|
|
||||||
|
if( idle_reason == MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||||
|
poll_type = MBEDTLS_NET_POLL_WRITE;
|
||||||
|
else if( idle_reason == MBEDTLS_ERR_SSL_WANT_READ )
|
||||||
|
poll_type = MBEDTLS_NET_POLL_READ;
|
||||||
|
#if !defined(MBEDTLS_TIMING_C)
|
||||||
|
else
|
||||||
|
return( 0 );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while( 1 )
|
||||||
|
{
|
||||||
|
/* Check if timer has expired */
|
||||||
|
#if defined(MBEDTLS_TIMING_C)
|
||||||
|
if( timer != NULL &&
|
||||||
|
mbedtls_timing_get_delay( timer ) == 2 )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif /* MBEDTLS_TIMING_C */
|
||||||
|
|
||||||
|
/* Check if underlying transport became available */
|
||||||
|
if( poll_type != 0 )
|
||||||
|
{
|
||||||
|
ret = mbedtls_net_poll( fd, poll_type, 0 );
|
||||||
|
if( ret < 0 )
|
||||||
|
return( ret );
|
||||||
|
if( ret == poll_type )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
int main( int argc, char *argv[] )
|
int main( int argc, char *argv[] )
|
||||||
{
|
{
|
||||||
int ret = 0, len, tail_len, i, written, frags, retry_left;
|
int ret = 0, len, tail_len, i, written, frags, retry_left;
|
||||||
@ -521,6 +578,7 @@ int main( int argc, char *argv[] )
|
|||||||
opt.server_port = DFL_SERVER_PORT;
|
opt.server_port = DFL_SERVER_PORT;
|
||||||
opt.debug_level = DFL_DEBUG_LEVEL;
|
opt.debug_level = DFL_DEBUG_LEVEL;
|
||||||
opt.nbio = DFL_NBIO;
|
opt.nbio = DFL_NBIO;
|
||||||
|
opt.event = DFL_EVENT;
|
||||||
opt.read_timeout = DFL_READ_TIMEOUT;
|
opt.read_timeout = DFL_READ_TIMEOUT;
|
||||||
opt.max_resend = DFL_MAX_RESEND;
|
opt.max_resend = DFL_MAX_RESEND;
|
||||||
opt.request_page = DFL_REQUEST_PAGE;
|
opt.request_page = DFL_REQUEST_PAGE;
|
||||||
@ -594,6 +652,12 @@ int main( int argc, char *argv[] )
|
|||||||
if( opt.nbio < 0 || opt.nbio > 2 )
|
if( opt.nbio < 0 || opt.nbio > 2 )
|
||||||
goto usage;
|
goto usage;
|
||||||
}
|
}
|
||||||
|
else if( strcmp( p, "event" ) == 0 )
|
||||||
|
{
|
||||||
|
opt.event = atoi( q );
|
||||||
|
if( opt.event < 0 || opt.event > 2 )
|
||||||
|
goto usage;
|
||||||
|
}
|
||||||
else if( strcmp( p, "read_timeout" ) == 0 )
|
else if( strcmp( p, "read_timeout" ) == 0 )
|
||||||
opt.read_timeout = atoi( q );
|
opt.read_timeout = atoi( q );
|
||||||
else if( strcmp( p, "max_resend" ) == 0 )
|
else if( strcmp( p, "max_resend" ) == 0 )
|
||||||
@ -638,16 +702,23 @@ int main( int argc, char *argv[] )
|
|||||||
}
|
}
|
||||||
else if( strcmp( p, "renegotiation" ) == 0 )
|
else if( strcmp( p, "renegotiation" ) == 0 )
|
||||||
{
|
{
|
||||||
opt.renegotiation = (atoi( q )) ? MBEDTLS_SSL_RENEGOTIATION_ENABLED :
|
opt.renegotiation = (atoi( q )) ?
|
||||||
|
MBEDTLS_SSL_RENEGOTIATION_ENABLED :
|
||||||
MBEDTLS_SSL_RENEGOTIATION_DISABLED;
|
MBEDTLS_SSL_RENEGOTIATION_DISABLED;
|
||||||
}
|
}
|
||||||
else if( strcmp( p, "allow_legacy" ) == 0 )
|
else if( strcmp( p, "allow_legacy" ) == 0 )
|
||||||
{
|
{
|
||||||
switch( atoi( q ) )
|
switch( atoi( q ) )
|
||||||
{
|
{
|
||||||
case -1: opt.allow_legacy = MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE; break;
|
case -1:
|
||||||
case 0: opt.allow_legacy = MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION; break;
|
opt.allow_legacy = MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE;
|
||||||
case 1: opt.allow_legacy = MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION; break;
|
break;
|
||||||
|
case 0:
|
||||||
|
opt.allow_legacy = MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
opt.allow_legacy = MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION;
|
||||||
|
break;
|
||||||
default: goto usage;
|
default: goto usage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -704,8 +775,12 @@ int main( int argc, char *argv[] )
|
|||||||
{
|
{
|
||||||
switch( atoi( q ) )
|
switch( atoi( q ) )
|
||||||
{
|
{
|
||||||
case 0: opt.extended_ms = MBEDTLS_SSL_EXTENDED_MS_DISABLED; break;
|
case 0:
|
||||||
case 1: opt.extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; break;
|
opt.extended_ms = MBEDTLS_SSL_EXTENDED_MS_DISABLED;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
opt.extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED;
|
||||||
|
break;
|
||||||
default: goto usage;
|
default: goto usage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -864,6 +939,15 @@ int main( int argc, char *argv[] )
|
|||||||
goto usage;
|
goto usage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Event-driven IO is incompatible with the above custom
|
||||||
|
* receive and send functions, as the polling builds on
|
||||||
|
* refers to the underlying net_context. */
|
||||||
|
if( opt.event == 1 && opt.nbio != 1 )
|
||||||
|
{
|
||||||
|
mbedtls_printf( "Warning: event-driven IO mandates nbio=1 - overwrite\n" );
|
||||||
|
opt.nbio = 1;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(MBEDTLS_DEBUG_C)
|
#if defined(MBEDTLS_DEBUG_C)
|
||||||
mbedtls_debug_set_threshold( opt.debug_level );
|
mbedtls_debug_set_threshold( opt.debug_level );
|
||||||
#endif
|
#endif
|
||||||
@ -871,7 +955,8 @@ int main( int argc, char *argv[] )
|
|||||||
if( opt.force_ciphersuite[0] > 0 )
|
if( opt.force_ciphersuite[0] > 0 )
|
||||||
{
|
{
|
||||||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
|
const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
|
||||||
ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( opt.force_ciphersuite[0] );
|
ciphersuite_info =
|
||||||
|
mbedtls_ssl_ciphersuite_from_id( opt.force_ciphersuite[0] );
|
||||||
|
|
||||||
if( opt.max_version != -1 &&
|
if( opt.max_version != -1 &&
|
||||||
ciphersuite_info->min_minor_ver > opt.max_version )
|
ciphersuite_info->min_minor_ver > opt.max_version )
|
||||||
@ -1051,11 +1136,12 @@ int main( int argc, char *argv[] )
|
|||||||
fflush( stdout );
|
fflush( stdout );
|
||||||
|
|
||||||
mbedtls_entropy_init( &entropy );
|
mbedtls_entropy_init( &entropy );
|
||||||
if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
|
if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func,
|
||||||
(const unsigned char *) pers,
|
&entropy, (const unsigned char *) pers,
|
||||||
strlen( pers ) ) ) != 0 )
|
strlen( pers ) ) ) != 0 )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned -0x%x\n", -ret );
|
mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned -0x%x\n",
|
||||||
|
-ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1098,7 +1184,8 @@ int main( int argc, char *argv[] )
|
|||||||
#endif
|
#endif
|
||||||
if( ret < 0 )
|
if( ret < 0 )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret );
|
mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n",
|
||||||
|
-ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1121,7 +1208,8 @@ int main( int argc, char *argv[] )
|
|||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
#if defined(MBEDTLS_CERTS_C)
|
#if defined(MBEDTLS_CERTS_C)
|
||||||
ret = mbedtls_x509_crt_parse( &clicert, (const unsigned char *) mbedtls_test_cli_crt,
|
ret = mbedtls_x509_crt_parse( &clicert,
|
||||||
|
(const unsigned char *) mbedtls_test_cli_crt,
|
||||||
mbedtls_test_cli_crt_len );
|
mbedtls_test_cli_crt_len );
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
@ -1131,7 +1219,8 @@ int main( int argc, char *argv[] )
|
|||||||
#endif
|
#endif
|
||||||
if( ret != 0 )
|
if( ret != 0 )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret );
|
mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n",
|
||||||
|
-ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1144,7 +1233,8 @@ int main( int argc, char *argv[] )
|
|||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
#if defined(MBEDTLS_CERTS_C)
|
#if defined(MBEDTLS_CERTS_C)
|
||||||
ret = mbedtls_pk_parse_key( &pkey, (const unsigned char *) mbedtls_test_cli_key,
|
ret = mbedtls_pk_parse_key( &pkey,
|
||||||
|
(const unsigned char *) mbedtls_test_cli_key,
|
||||||
mbedtls_test_cli_key_len, NULL, 0 );
|
mbedtls_test_cli_key_len, NULL, 0 );
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
@ -1154,7 +1244,8 @@ int main( int argc, char *argv[] )
|
|||||||
#endif
|
#endif
|
||||||
if( ret != 0 )
|
if( ret != 0 )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned -0x%x\n\n", -ret );
|
mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned -0x%x\n\n",
|
||||||
|
-ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1172,11 +1263,13 @@ int main( int argc, char *argv[] )
|
|||||||
opt.server_addr, opt.server_port );
|
opt.server_addr, opt.server_port );
|
||||||
fflush( stdout );
|
fflush( stdout );
|
||||||
|
|
||||||
if( ( ret = mbedtls_net_connect( &server_fd, opt.server_addr, opt.server_port,
|
if( ( ret = mbedtls_net_connect( &server_fd,
|
||||||
|
opt.server_addr, opt.server_port,
|
||||||
opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM ?
|
opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM ?
|
||||||
MBEDTLS_NET_PROTO_TCP : MBEDTLS_NET_PROTO_UDP ) ) != 0 )
|
MBEDTLS_NET_PROTO_TCP : MBEDTLS_NET_PROTO_UDP ) ) != 0 )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! mbedtls_net_connect returned -0x%x\n\n", -ret );
|
mbedtls_printf( " failed\n ! mbedtls_net_connect returned -0x%x\n\n",
|
||||||
|
-ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1186,7 +1279,8 @@ int main( int argc, char *argv[] )
|
|||||||
ret = mbedtls_net_set_block( &server_fd );
|
ret = mbedtls_net_set_block( &server_fd );
|
||||||
if( ret != 0 )
|
if( ret != 0 )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! net_set_(non)block() returned -0x%x\n\n", -ret );
|
mbedtls_printf( " failed\n ! net_set_(non)block() returned -0x%x\n\n",
|
||||||
|
-ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1203,7 +1297,8 @@ int main( int argc, char *argv[] )
|
|||||||
opt.transport,
|
opt.transport,
|
||||||
MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
|
MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned -0x%x\n\n", -ret );
|
mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned -0x%x\n\n",
|
||||||
|
-ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1226,13 +1321,15 @@ int main( int argc, char *argv[] )
|
|||||||
|
|
||||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||||
if( opt.hs_to_min != DFL_HS_TO_MIN || opt.hs_to_max != DFL_HS_TO_MAX )
|
if( opt.hs_to_min != DFL_HS_TO_MIN || opt.hs_to_max != DFL_HS_TO_MAX )
|
||||||
mbedtls_ssl_conf_handshake_timeout( &conf, opt.hs_to_min, opt.hs_to_max );
|
mbedtls_ssl_conf_handshake_timeout( &conf, opt.hs_to_min,
|
||||||
|
opt.hs_to_max );
|
||||||
#endif /* MBEDTLS_SSL_PROTO_DTLS */
|
#endif /* MBEDTLS_SSL_PROTO_DTLS */
|
||||||
|
|
||||||
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
|
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
|
||||||
if( ( ret = mbedtls_ssl_conf_max_frag_len( &conf, opt.mfl_code ) ) != 0 )
|
if( ( ret = mbedtls_ssl_conf_max_frag_len( &conf, opt.mfl_code ) ) != 0 )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! mbedtls_ssl_conf_max_frag_len returned %d\n\n", ret );
|
mbedtls_printf( " failed\n ! mbedtls_ssl_conf_max_frag_len returned %d\n\n",
|
||||||
|
ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1268,7 +1365,8 @@ int main( int argc, char *argv[] )
|
|||||||
if( opt.alpn_string != NULL )
|
if( opt.alpn_string != NULL )
|
||||||
if( ( ret = mbedtls_ssl_conf_alpn_protocols( &conf, alpn_list ) ) != 0 )
|
if( ( ret = mbedtls_ssl_conf_alpn_protocols( &conf, alpn_list ) ) != 0 )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! mbedtls_ssl_conf_alpn_protocols returned %d\n\n", ret );
|
mbedtls_printf( " failed\n ! mbedtls_ssl_conf_alpn_protocols returned %d\n\n",
|
||||||
|
ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1307,7 +1405,8 @@ int main( int argc, char *argv[] )
|
|||||||
{
|
{
|
||||||
if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &clicert, &pkey ) ) != 0 )
|
if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &clicert, &pkey ) ) != 0 )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret );
|
mbedtls_printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n",
|
||||||
|
ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1326,16 +1425,19 @@ int main( int argc, char *argv[] )
|
|||||||
(const unsigned char *) opt.psk_identity,
|
(const unsigned char *) opt.psk_identity,
|
||||||
strlen( opt.psk_identity ) ) ) != 0 )
|
strlen( opt.psk_identity ) ) ) != 0 )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! mbedtls_ssl_conf_psk returned %d\n\n", ret );
|
mbedtls_printf( " failed\n ! mbedtls_ssl_conf_psk returned %d\n\n",
|
||||||
|
ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if( opt.min_version != DFL_MIN_VERSION )
|
if( opt.min_version != DFL_MIN_VERSION )
|
||||||
mbedtls_ssl_conf_min_version( &conf, MBEDTLS_SSL_MAJOR_VERSION_3, opt.min_version );
|
mbedtls_ssl_conf_min_version( &conf, MBEDTLS_SSL_MAJOR_VERSION_3,
|
||||||
|
opt.min_version );
|
||||||
|
|
||||||
if( opt.max_version != DFL_MAX_VERSION )
|
if( opt.max_version != DFL_MAX_VERSION )
|
||||||
mbedtls_ssl_conf_max_version( &conf, MBEDTLS_SSL_MAJOR_VERSION_3, opt.max_version );
|
mbedtls_ssl_conf_max_version( &conf, MBEDTLS_SSL_MAJOR_VERSION_3,
|
||||||
|
opt.max_version );
|
||||||
|
|
||||||
#if defined(MBEDTLS_SSL_FALLBACK_SCSV)
|
#if defined(MBEDTLS_SSL_FALLBACK_SCSV)
|
||||||
if( opt.fallback != DFL_FALLBACK )
|
if( opt.fallback != DFL_FALLBACK )
|
||||||
@ -1344,14 +1446,16 @@ int main( int argc, char *argv[] )
|
|||||||
|
|
||||||
if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 )
|
if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned -0x%x\n\n", -ret );
|
mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned -0x%x\n\n",
|
||||||
|
-ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||||
if( ( ret = mbedtls_ssl_set_hostname( &ssl, opt.server_name ) ) != 0 )
|
if( ( ret = mbedtls_ssl_set_hostname( &ssl, opt.server_name ) ) != 0 )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret );
|
mbedtls_printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n",
|
||||||
|
ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1363,7 +1467,8 @@ int main( int argc, char *argv[] )
|
|||||||
(const unsigned char *) opt.ecjpake_pw,
|
(const unsigned char *) opt.ecjpake_pw,
|
||||||
strlen( opt.ecjpake_pw ) ) ) != 0 )
|
strlen( opt.ecjpake_pw ) ) ) != 0 )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! mbedtls_ssl_set_hs_ecjpake_password returned %d\n\n", ret );
|
mbedtls_printf( " failed\n ! mbedtls_ssl_set_hs_ecjpake_password returned %d\n\n",
|
||||||
|
ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1372,7 +1477,8 @@ int main( int argc, char *argv[] )
|
|||||||
if( opt.nbio == 2 )
|
if( opt.nbio == 2 )
|
||||||
mbedtls_ssl_set_bio( &ssl, &server_fd, my_send, my_recv, NULL );
|
mbedtls_ssl_set_bio( &ssl, &server_fd, my_send, my_recv, NULL );
|
||||||
else
|
else
|
||||||
mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv,
|
mbedtls_ssl_set_bio( &ssl, &server_fd,
|
||||||
|
mbedtls_net_send, mbedtls_net_recv,
|
||||||
opt.nbio == 0 ? mbedtls_net_recv_timeout : NULL );
|
opt.nbio == 0 ? mbedtls_net_recv_timeout : NULL );
|
||||||
|
|
||||||
#if defined(MBEDTLS_TIMING_C)
|
#if defined(MBEDTLS_TIMING_C)
|
||||||
@ -1390,9 +1496,11 @@ int main( int argc, char *argv[] )
|
|||||||
|
|
||||||
while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 )
|
while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 )
|
||||||
{
|
{
|
||||||
if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||||
|
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n", -ret );
|
mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n",
|
||||||
|
-ret );
|
||||||
if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED )
|
if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED )
|
||||||
mbedtls_printf(
|
mbedtls_printf(
|
||||||
" Unable to verify the server's certificate. "
|
" Unable to verify the server's certificate. "
|
||||||
@ -1404,10 +1512,23 @@ int main( int argc, char *argv[] )
|
|||||||
mbedtls_printf( "\n" );
|
mbedtls_printf( "\n" );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* For event-driven IO, wait for socket to become available */
|
||||||
|
if( opt.event == 1 /* level triggered IO */ )
|
||||||
|
{
|
||||||
|
#if defined(MBEDTLS_TIMING_C)
|
||||||
|
ret = idle( &server_fd, &timer, ret );
|
||||||
|
#else
|
||||||
|
ret = idle( &server_fd, ret );
|
||||||
|
#endif
|
||||||
|
if( ret != 0 )
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mbedtls_printf( " ok\n [ Protocol is %s ]\n [ Ciphersuite is %s ]\n",
|
mbedtls_printf( " ok\n [ Protocol is %s ]\n [ Ciphersuite is %s ]\n",
|
||||||
mbedtls_ssl_get_version( &ssl ), mbedtls_ssl_get_ciphersuite( &ssl ) );
|
mbedtls_ssl_get_version( &ssl ),
|
||||||
|
mbedtls_ssl_get_ciphersuite( &ssl ) );
|
||||||
|
|
||||||
if( ( ret = mbedtls_ssl_get_record_expansion( &ssl ) ) >= 0 )
|
if( ( ret = mbedtls_ssl_get_record_expansion( &ssl ) ) >= 0 )
|
||||||
mbedtls_printf( " [ Record expansion is %d ]\n", ret );
|
mbedtls_printf( " [ Record expansion is %d ]\n", ret );
|
||||||
@ -1435,7 +1556,8 @@ int main( int argc, char *argv[] )
|
|||||||
|
|
||||||
if( ( ret = mbedtls_ssl_get_session( &ssl, &saved_session ) ) != 0 )
|
if( ( ret = mbedtls_ssl_get_session( &ssl, &saved_session ) ) != 0 )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! mbedtls_ssl_get_session returned -0x%x\n\n", -ret );
|
mbedtls_printf( " failed\n ! mbedtls_ssl_get_session returned -0x%x\n\n",
|
||||||
|
-ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1454,7 +1576,8 @@ int main( int argc, char *argv[] )
|
|||||||
|
|
||||||
mbedtls_printf( " failed\n" );
|
mbedtls_printf( " failed\n" );
|
||||||
|
|
||||||
mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags );
|
mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ),
|
||||||
|
" ! ", flags );
|
||||||
|
|
||||||
mbedtls_printf( "%s\n", vrfy_buf );
|
mbedtls_printf( "%s\n", vrfy_buf );
|
||||||
}
|
}
|
||||||
@ -1484,9 +1607,21 @@ int main( int argc, char *argv[] )
|
|||||||
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||||
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! mbedtls_ssl_renegotiate returned %d\n\n", ret );
|
mbedtls_printf( " failed\n ! mbedtls_ssl_renegotiate returned %d\n\n",
|
||||||
|
ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* For event-driven IO, wait for socket to become available */
|
||||||
|
if( opt.event == 1 /* level triggered IO */ )
|
||||||
|
{
|
||||||
|
#if defined(MBEDTLS_TIMING_C)
|
||||||
|
idle( &server_fd, &timer, ret );
|
||||||
|
#else
|
||||||
|
idle( &server_fd, ret );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
mbedtls_printf( " ok\n" );
|
mbedtls_printf( " ok\n" );
|
||||||
}
|
}
|
||||||
@ -1530,27 +1665,54 @@ send_request:
|
|||||||
{
|
{
|
||||||
for( written = 0, frags = 0; written < len; written += ret, frags++ )
|
for( written = 0, frags = 0; written < len; written += ret, frags++ )
|
||||||
{
|
{
|
||||||
while( ( ret = mbedtls_ssl_write( &ssl, buf + written, len - written ) )
|
while( ( ret = mbedtls_ssl_write( &ssl, buf + written,
|
||||||
<= 0 )
|
len - written ) ) <= 0 )
|
||||||
{
|
{
|
||||||
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||||
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! mbedtls_ssl_write returned -0x%x\n\n", -ret );
|
mbedtls_printf( " failed\n ! mbedtls_ssl_write returned -0x%x\n\n",
|
||||||
|
-ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* For event-driven IO, wait for socket to become available */
|
||||||
|
if( opt.event == 1 /* level triggered IO */ )
|
||||||
|
{
|
||||||
|
#if defined(MBEDTLS_TIMING_C)
|
||||||
|
idle( &server_fd, &timer, ret );
|
||||||
|
#else
|
||||||
|
idle( &server_fd, ret );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else /* Not stream, so datagram */
|
else /* Not stream, so datagram */
|
||||||
{
|
{
|
||||||
do ret = mbedtls_ssl_write( &ssl, buf, len );
|
while( 1 )
|
||||||
while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
|
{
|
||||||
ret == MBEDTLS_ERR_SSL_WANT_WRITE );
|
ret = mbedtls_ssl_write( &ssl, buf, len );
|
||||||
|
|
||||||
|
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||||
|
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* For event-driven IO, wait for socket to become available */
|
||||||
|
if( opt.event == 1 /* level triggered IO */ )
|
||||||
|
{
|
||||||
|
#if defined(MBEDTLS_TIMING_C)
|
||||||
|
idle( &server_fd, &timer, ret );
|
||||||
|
#else
|
||||||
|
idle( &server_fd, ret );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if( ret < 0 )
|
if( ret < 0 )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret );
|
mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n",
|
||||||
|
ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1565,7 +1727,8 @@ send_request:
|
|||||||
}
|
}
|
||||||
|
|
||||||
buf[written] = '\0';
|
buf[written] = '\0';
|
||||||
mbedtls_printf( " %d bytes written in %d fragments\n\n%s\n", written, frags, (char *) buf );
|
mbedtls_printf( " %d bytes written in %d fragments\n\n%s\n",
|
||||||
|
written, frags, (char *) buf );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 7. Read the HTTP response
|
* 7. Read the HTTP response
|
||||||
@ -1586,7 +1749,18 @@ send_request:
|
|||||||
|
|
||||||
if( ret == MBEDTLS_ERR_SSL_WANT_READ ||
|
if( ret == MBEDTLS_ERR_SSL_WANT_READ ||
|
||||||
ret == MBEDTLS_ERR_SSL_WANT_WRITE )
|
ret == MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||||
|
{
|
||||||
|
/* For event-driven IO, wait for socket to become available */
|
||||||
|
if( opt.event == 1 /* level triggered IO */ )
|
||||||
|
{
|
||||||
|
#if defined(MBEDTLS_TIMING_C)
|
||||||
|
idle( &server_fd, &timer, ret );
|
||||||
|
#else
|
||||||
|
idle( &server_fd, ret );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if( ret <= 0 )
|
if( ret <= 0 )
|
||||||
{
|
{
|
||||||
@ -1604,7 +1778,8 @@ send_request:
|
|||||||
goto reconnect;
|
goto reconnect;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
mbedtls_printf( " mbedtls_ssl_read returned -0x%x\n", -ret );
|
mbedtls_printf( " mbedtls_ssl_read returned -0x%x\n",
|
||||||
|
-ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1628,9 +1803,24 @@ send_request:
|
|||||||
len = sizeof( buf ) - 1;
|
len = sizeof( buf ) - 1;
|
||||||
memset( buf, 0, sizeof( buf ) );
|
memset( buf, 0, sizeof( buf ) );
|
||||||
|
|
||||||
do ret = mbedtls_ssl_read( &ssl, buf, len );
|
while( 1 )
|
||||||
while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
|
{
|
||||||
ret == MBEDTLS_ERR_SSL_WANT_WRITE );
|
ret = mbedtls_ssl_read( &ssl, buf, len );
|
||||||
|
|
||||||
|
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||||
|
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* For event-driven IO, wait for socket to become available */
|
||||||
|
if( opt.event == 1 /* level triggered IO */ )
|
||||||
|
{
|
||||||
|
#if defined(MBEDTLS_TIMING_C)
|
||||||
|
idle( &server_fd, &timer, ret );
|
||||||
|
#else
|
||||||
|
idle( &server_fd, ret );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if( ret <= 0 )
|
if( ret <= 0 )
|
||||||
{
|
{
|
||||||
@ -1671,7 +1861,8 @@ send_request:
|
|||||||
|
|
||||||
if( ( ret = mbedtls_ssl_session_reset( &ssl ) ) != 0 )
|
if( ( ret = mbedtls_ssl_session_reset( &ssl ) ) != 0 )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! mbedtls_ssl_session_reset returned -0x%x\n\n", -ret );
|
mbedtls_printf( " failed\n ! mbedtls_ssl_session_reset returned -0x%x\n\n",
|
||||||
|
-ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1680,9 +1871,20 @@ send_request:
|
|||||||
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||||
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret );
|
mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n",
|
||||||
|
-ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* For event-driven IO, wait for socket to become available */
|
||||||
|
if( opt.event == 1 /* level triggered IO */ )
|
||||||
|
{
|
||||||
|
#if defined(MBEDTLS_TIMING_C)
|
||||||
|
idle( &server_fd, &timer, ret );
|
||||||
|
#else
|
||||||
|
idle( &server_fd, ret );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mbedtls_printf( " ok\n" );
|
mbedtls_printf( " ok\n" );
|
||||||
@ -1729,21 +1931,25 @@ reconnect:
|
|||||||
|
|
||||||
if( ( ret = mbedtls_ssl_session_reset( &ssl ) ) != 0 )
|
if( ( ret = mbedtls_ssl_session_reset( &ssl ) ) != 0 )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! mbedtls_ssl_session_reset returned -0x%x\n\n", -ret );
|
mbedtls_printf( " failed\n ! mbedtls_ssl_session_reset returned -0x%x\n\n",
|
||||||
|
-ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ( ret = mbedtls_ssl_set_session( &ssl, &saved_session ) ) != 0 )
|
if( ( ret = mbedtls_ssl_set_session( &ssl, &saved_session ) ) != 0 )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! mbedtls_ssl_conf_session returned %d\n\n", ret );
|
mbedtls_printf( " failed\n ! mbedtls_ssl_conf_session returned %d\n\n",
|
||||||
|
ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ( ret = mbedtls_net_connect( &server_fd, opt.server_addr, opt.server_port,
|
if( ( ret = mbedtls_net_connect( &server_fd,
|
||||||
|
opt.server_addr, opt.server_port,
|
||||||
opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM ?
|
opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM ?
|
||||||
MBEDTLS_NET_PROTO_TCP : MBEDTLS_NET_PROTO_UDP ) ) != 0 )
|
MBEDTLS_NET_PROTO_TCP : MBEDTLS_NET_PROTO_UDP ) ) != 0 )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! mbedtls_net_connect returned -0x%x\n\n", -ret );
|
mbedtls_printf( " failed\n ! mbedtls_net_connect returned -0x%x\n\n",
|
||||||
|
-ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1763,7 +1969,8 @@ reconnect:
|
|||||||
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||||
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret );
|
mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n",
|
||||||
|
-ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,6 +101,7 @@ int main( void )
|
|||||||
#define DFL_SERVER_PORT "4433"
|
#define DFL_SERVER_PORT "4433"
|
||||||
#define DFL_DEBUG_LEVEL 0
|
#define DFL_DEBUG_LEVEL 0
|
||||||
#define DFL_NBIO 0
|
#define DFL_NBIO 0
|
||||||
|
#define DFL_EVENT 0
|
||||||
#define DFL_READ_TIMEOUT 0
|
#define DFL_READ_TIMEOUT 0
|
||||||
#define DFL_CA_FILE ""
|
#define DFL_CA_FILE ""
|
||||||
#define DFL_CA_PATH ""
|
#define DFL_CA_PATH ""
|
||||||
@ -331,6 +332,8 @@ int main( void )
|
|||||||
" debug_level=%%d default: 0 (disabled)\n" \
|
" debug_level=%%d default: 0 (disabled)\n" \
|
||||||
" nbio=%%d default: 0 (blocking I/O)\n" \
|
" nbio=%%d default: 0 (blocking I/O)\n" \
|
||||||
" options: 1 (non-blocking), 2 (added delays)\n" \
|
" options: 1 (non-blocking), 2 (added delays)\n" \
|
||||||
|
" event=%%d default: 0 (loop)\n" \
|
||||||
|
" options: 1 (level-triggered, implies nbio=1),\n" \
|
||||||
" read_timeout=%%d default: 0 ms (no timeout)\n" \
|
" read_timeout=%%d default: 0 ms (no timeout)\n" \
|
||||||
"\n" \
|
"\n" \
|
||||||
USAGE_DTLS \
|
USAGE_DTLS \
|
||||||
@ -399,6 +402,7 @@ struct options
|
|||||||
const char *server_port; /* port on which the ssl service runs */
|
const char *server_port; /* port on which the ssl service runs */
|
||||||
int debug_level; /* level of debugging */
|
int debug_level; /* level of debugging */
|
||||||
int nbio; /* should I/O be blocking? */
|
int nbio; /* should I/O be blocking? */
|
||||||
|
int event; /* loop or event-driven IO? level or edge triggered? */
|
||||||
uint32_t read_timeout; /* timeout on mbedtls_ssl_read() in milliseconds */
|
uint32_t read_timeout; /* timeout on mbedtls_ssl_read() in milliseconds */
|
||||||
const char *ca_file; /* the file with the CA certificate(s) */
|
const char *ca_file; /* the file with the CA certificate(s) */
|
||||||
const char *ca_path; /* the path with the CA certificate(s) reside */
|
const char *ca_path; /* the path with the CA certificate(s) reside */
|
||||||
@ -837,6 +841,56 @@ static int ssl_sig_hashes_for_test[] = {
|
|||||||
};
|
};
|
||||||
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wait for an event from the underlying transport or the timer
|
||||||
|
* (Used in event-driven IO mode).
|
||||||
|
*/
|
||||||
|
#if !defined(MBEDTLS_TIMING_C)
|
||||||
|
int idle( mbedtls_net_context *fd,
|
||||||
|
int idle_reason )
|
||||||
|
#else
|
||||||
|
int idle( mbedtls_net_context *fd,
|
||||||
|
mbedtls_timing_delay_context *timer,
|
||||||
|
int idle_reason )
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
int poll_type = 0;
|
||||||
|
|
||||||
|
if( idle_reason == MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||||
|
poll_type = MBEDTLS_NET_POLL_WRITE;
|
||||||
|
else if( idle_reason == MBEDTLS_ERR_SSL_WANT_READ )
|
||||||
|
poll_type = MBEDTLS_NET_POLL_READ;
|
||||||
|
#if !defined(MBEDTLS_TIMING_C)
|
||||||
|
else
|
||||||
|
return( 0 );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while( 1 )
|
||||||
|
{
|
||||||
|
/* Check if timer has expired */
|
||||||
|
#if defined(MBEDTLS_TIMING_C)
|
||||||
|
if( timer != NULL &&
|
||||||
|
mbedtls_timing_get_delay( timer ) == 2 )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif /* MBEDTLS_TIMING_C */
|
||||||
|
|
||||||
|
/* Check if underlying transport became available */
|
||||||
|
if( poll_type != 0 )
|
||||||
|
{
|
||||||
|
ret = mbedtls_net_poll( fd, poll_type, 0 );
|
||||||
|
if( ret < 0 )
|
||||||
|
return( ret );
|
||||||
|
if( ret == poll_type )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
int main( int argc, char *argv[] )
|
int main( int argc, char *argv[] )
|
||||||
{
|
{
|
||||||
int ret = 0, len, written, frags, exchanges_left;
|
int ret = 0, len, written, frags, exchanges_left;
|
||||||
@ -969,6 +1023,7 @@ int main( int argc, char *argv[] )
|
|||||||
opt.server_addr = DFL_SERVER_ADDR;
|
opt.server_addr = DFL_SERVER_ADDR;
|
||||||
opt.server_port = DFL_SERVER_PORT;
|
opt.server_port = DFL_SERVER_PORT;
|
||||||
opt.debug_level = DFL_DEBUG_LEVEL;
|
opt.debug_level = DFL_DEBUG_LEVEL;
|
||||||
|
opt.event = DFL_EVENT;
|
||||||
opt.nbio = DFL_NBIO;
|
opt.nbio = DFL_NBIO;
|
||||||
opt.read_timeout = DFL_READ_TIMEOUT;
|
opt.read_timeout = DFL_READ_TIMEOUT;
|
||||||
opt.ca_file = DFL_CA_FILE;
|
opt.ca_file = DFL_CA_FILE;
|
||||||
@ -1047,6 +1102,12 @@ int main( int argc, char *argv[] )
|
|||||||
if( opt.nbio < 0 || opt.nbio > 2 )
|
if( opt.nbio < 0 || opt.nbio > 2 )
|
||||||
goto usage;
|
goto usage;
|
||||||
}
|
}
|
||||||
|
else if( strcmp( p, "event" ) == 0 )
|
||||||
|
{
|
||||||
|
opt.event = atoi( q );
|
||||||
|
if( opt.event < 0 || opt.event > 2 )
|
||||||
|
goto usage;
|
||||||
|
}
|
||||||
else if( strcmp( p, "read_timeout" ) == 0 )
|
else if( strcmp( p, "read_timeout" ) == 0 )
|
||||||
opt.read_timeout = atoi( q );
|
opt.read_timeout = atoi( q );
|
||||||
else if( strcmp( p, "ca_file" ) == 0 )
|
else if( strcmp( p, "ca_file" ) == 0 )
|
||||||
@ -1088,16 +1149,23 @@ int main( int argc, char *argv[] )
|
|||||||
opt.version_suites = q;
|
opt.version_suites = q;
|
||||||
else if( strcmp( p, "renegotiation" ) == 0 )
|
else if( strcmp( p, "renegotiation" ) == 0 )
|
||||||
{
|
{
|
||||||
opt.renegotiation = (atoi( q )) ? MBEDTLS_SSL_RENEGOTIATION_ENABLED :
|
opt.renegotiation = (atoi( q )) ?
|
||||||
|
MBEDTLS_SSL_RENEGOTIATION_ENABLED :
|
||||||
MBEDTLS_SSL_RENEGOTIATION_DISABLED;
|
MBEDTLS_SSL_RENEGOTIATION_DISABLED;
|
||||||
}
|
}
|
||||||
else if( strcmp( p, "allow_legacy" ) == 0 )
|
else if( strcmp( p, "allow_legacy" ) == 0 )
|
||||||
{
|
{
|
||||||
switch( atoi( q ) )
|
switch( atoi( q ) )
|
||||||
{
|
{
|
||||||
case -1: opt.allow_legacy = MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE; break;
|
case -1:
|
||||||
case 0: opt.allow_legacy = MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION; break;
|
opt.allow_legacy = MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE;
|
||||||
case 1: opt.allow_legacy = MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION; break;
|
break;
|
||||||
|
case 0:
|
||||||
|
opt.allow_legacy = MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
opt.allow_legacy = MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION;
|
||||||
|
break;
|
||||||
default: goto usage;
|
default: goto usage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1254,8 +1322,12 @@ int main( int argc, char *argv[] )
|
|||||||
{
|
{
|
||||||
switch( atoi( q ) )
|
switch( atoi( q ) )
|
||||||
{
|
{
|
||||||
case 0: opt.extended_ms = MBEDTLS_SSL_EXTENDED_MS_DISABLED; break;
|
case 0:
|
||||||
case 1: opt.extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; break;
|
opt.extended_ms = MBEDTLS_SSL_EXTENDED_MS_DISABLED;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
opt.extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED;
|
||||||
|
break;
|
||||||
default: goto usage;
|
default: goto usage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1328,6 +1400,15 @@ int main( int argc, char *argv[] )
|
|||||||
goto usage;
|
goto usage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Event-driven IO is incompatible with the above custom
|
||||||
|
* receive and send functions, as the polling builds on
|
||||||
|
* refers to the underlying net_context. */
|
||||||
|
if( opt.event == 1 && opt.nbio != 1 )
|
||||||
|
{
|
||||||
|
mbedtls_printf( "Warning: event-driven IO mandates nbio=1 - overwrite\n" );
|
||||||
|
opt.nbio = 1;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(MBEDTLS_DEBUG_C)
|
#if defined(MBEDTLS_DEBUG_C)
|
||||||
mbedtls_debug_set_threshold( opt.debug_level );
|
mbedtls_debug_set_threshold( opt.debug_level );
|
||||||
#endif
|
#endif
|
||||||
@ -1335,7 +1416,8 @@ int main( int argc, char *argv[] )
|
|||||||
if( opt.force_ciphersuite[0] > 0 )
|
if( opt.force_ciphersuite[0] > 0 )
|
||||||
{
|
{
|
||||||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
|
const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
|
||||||
ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( opt.force_ciphersuite[0] );
|
ciphersuite_info =
|
||||||
|
mbedtls_ssl_ciphersuite_from_id( opt.force_ciphersuite[0] );
|
||||||
|
|
||||||
if( opt.max_version != -1 &&
|
if( opt.max_version != -1 &&
|
||||||
ciphersuite_info->min_minor_ver > opt.max_version )
|
ciphersuite_info->min_minor_ver > opt.max_version )
|
||||||
@ -1526,11 +1608,12 @@ int main( int argc, char *argv[] )
|
|||||||
fflush( stdout );
|
fflush( stdout );
|
||||||
|
|
||||||
mbedtls_entropy_init( &entropy );
|
mbedtls_entropy_init( &entropy );
|
||||||
if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
|
if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func,
|
||||||
(const unsigned char *) pers,
|
&entropy, (const unsigned char *) pers,
|
||||||
strlen( pers ) ) ) != 0 )
|
strlen( pers ) ) ) != 0 )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned -0x%x\n", -ret );
|
mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned -0x%x\n",
|
||||||
|
-ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1645,8 +1728,7 @@ int main( int argc, char *argv[] )
|
|||||||
strcmp( opt.key_file2, "none" ) != 0 )
|
strcmp( opt.key_file2, "none" ) != 0 )
|
||||||
{
|
{
|
||||||
#if !defined(MBEDTLS_CERTS_C)
|
#if !defined(MBEDTLS_CERTS_C)
|
||||||
mbedtls_printf( "Not certificated or key provided, and \n"
|
mbedtls_printf( "Not certificated or key provided, and \nMBEDTLS_CERTS_C not defined!\n" );
|
||||||
"MBEDTLS_CERTS_C not defined!\n" );
|
|
||||||
goto exit;
|
goto exit;
|
||||||
#else
|
#else
|
||||||
#if defined(MBEDTLS_RSA_C)
|
#if defined(MBEDTLS_RSA_C)
|
||||||
@ -1654,14 +1736,16 @@ int main( int argc, char *argv[] )
|
|||||||
(const unsigned char *) mbedtls_test_srv_crt_rsa,
|
(const unsigned char *) mbedtls_test_srv_crt_rsa,
|
||||||
mbedtls_test_srv_crt_rsa_len ) ) != 0 )
|
mbedtls_test_srv_crt_rsa_len ) ) != 0 )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret );
|
mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n",
|
||||||
|
-ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if( ( ret = mbedtls_pk_parse_key( &pkey,
|
if( ( ret = mbedtls_pk_parse_key( &pkey,
|
||||||
(const unsigned char *) mbedtls_test_srv_key_rsa,
|
(const unsigned char *) mbedtls_test_srv_key_rsa,
|
||||||
mbedtls_test_srv_key_rsa_len, NULL, 0 ) ) != 0 )
|
mbedtls_test_srv_key_rsa_len, NULL, 0 ) ) != 0 )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned -0x%x\n\n", -ret );
|
mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned -0x%x\n\n",
|
||||||
|
-ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
key_cert_init = 2;
|
key_cert_init = 2;
|
||||||
@ -1671,14 +1755,16 @@ int main( int argc, char *argv[] )
|
|||||||
(const unsigned char *) mbedtls_test_srv_crt_ec,
|
(const unsigned char *) mbedtls_test_srv_crt_ec,
|
||||||
mbedtls_test_srv_crt_ec_len ) ) != 0 )
|
mbedtls_test_srv_crt_ec_len ) ) != 0 )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! x509_crt_parse2 returned -0x%x\n\n", -ret );
|
mbedtls_printf( " failed\n ! x509_crt_parse2 returned -0x%x\n\n",
|
||||||
|
-ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
if( ( ret = mbedtls_pk_parse_key( &pkey2,
|
if( ( ret = mbedtls_pk_parse_key( &pkey2,
|
||||||
(const unsigned char *) mbedtls_test_srv_key_ec,
|
(const unsigned char *) mbedtls_test_srv_key_ec,
|
||||||
mbedtls_test_srv_key_ec_len, NULL, 0 ) ) != 0 )
|
mbedtls_test_srv_key_ec_len, NULL, 0 ) ) != 0 )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! pk_parse_key2 returned -0x%x\n\n", -ret );
|
mbedtls_printf( " failed\n ! pk_parse_key2 returned -0x%x\n\n",
|
||||||
|
-ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
key_cert_init2 = 2;
|
key_cert_init2 = 2;
|
||||||
@ -2088,8 +2174,8 @@ reset:
|
|||||||
if( ( ret = mbedtls_ssl_set_client_transport_id( &ssl,
|
if( ( ret = mbedtls_ssl_set_client_transport_id( &ssl,
|
||||||
client_ip, cliip_len ) ) != 0 )
|
client_ip, cliip_len ) ) != 0 )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " failed\n ! "
|
mbedtls_printf( " failed\n ! mbedtls_ssl_set_client_transport_id() returned -0x%x\n\n",
|
||||||
"mbedtls_ssl_set_client_transport_id() returned -0x%x\n\n", -ret );
|
-ret );
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2117,9 +2203,24 @@ handshake:
|
|||||||
mbedtls_printf( " . Performing the SSL/TLS handshake..." );
|
mbedtls_printf( " . Performing the SSL/TLS handshake..." );
|
||||||
fflush( stdout );
|
fflush( stdout );
|
||||||
|
|
||||||
do ret = mbedtls_ssl_handshake( &ssl );
|
while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 )
|
||||||
while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
|
{
|
||||||
ret == MBEDTLS_ERR_SSL_WANT_WRITE );
|
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||||
|
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* For event-driven IO, wait for socket to become available */
|
||||||
|
if( opt.event == 1 /* level triggered IO */ )
|
||||||
|
{
|
||||||
|
#if defined(MBEDTLS_TIMING_C)
|
||||||
|
ret = idle( &client_fd, &timer, ret );
|
||||||
|
#else
|
||||||
|
ret = idle( &client_fd, ret );
|
||||||
|
#endif
|
||||||
|
if( ret != 0 )
|
||||||
|
goto reset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED )
|
if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED )
|
||||||
{
|
{
|
||||||
@ -2225,7 +2326,18 @@ data_exchange:
|
|||||||
|
|
||||||
if( ret == MBEDTLS_ERR_SSL_WANT_READ ||
|
if( ret == MBEDTLS_ERR_SSL_WANT_READ ||
|
||||||
ret == MBEDTLS_ERR_SSL_WANT_WRITE )
|
ret == MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||||
|
{
|
||||||
|
if( opt.event == 1 /* level triggered IO */ )
|
||||||
|
{
|
||||||
|
#if defined(MBEDTLS_TIMING_C)
|
||||||
|
idle( &client_fd, &timer, ret );
|
||||||
|
#else
|
||||||
|
idle( &client_fd, ret );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if( ret <= 0 )
|
if( ret <= 0 )
|
||||||
{
|
{
|
||||||
@ -2313,9 +2425,40 @@ data_exchange:
|
|||||||
len = sizeof( buf ) - 1;
|
len = sizeof( buf ) - 1;
|
||||||
memset( buf, 0, sizeof( buf ) );
|
memset( buf, 0, sizeof( buf ) );
|
||||||
|
|
||||||
do ret = mbedtls_ssl_read( &ssl, buf, len );
|
while( 1 )
|
||||||
while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
|
{
|
||||||
ret == MBEDTLS_ERR_SSL_WANT_WRITE );
|
/* Without the call to `mbedtls_ssl_check_pending`, it might
|
||||||
|
* happen that the client sends application data in the same
|
||||||
|
* datagram as the Finished message concluding the handshake.
|
||||||
|
* In this case, the application data would be ready to be
|
||||||
|
* processed while the underlying transport wouldn't signal
|
||||||
|
* any further incoming data.
|
||||||
|
*
|
||||||
|
* See the test 'Event-driven I/O: session-id resume, UDP packing'
|
||||||
|
* in tests/ssl-opt.sh.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* For event-driven IO, wait for socket to become available */
|
||||||
|
if( mbedtls_ssl_check_pending( &ssl ) == 0 &&
|
||||||
|
opt.event == 1 /* level triggered IO */ )
|
||||||
|
{
|
||||||
|
#if defined(MBEDTLS_TIMING_C)
|
||||||
|
idle( &client_fd, &timer, MBEDTLS_ERR_SSL_WANT_READ );
|
||||||
|
#else
|
||||||
|
idle( &client_fd, MBEDTLS_ERR_SSL_WANT_READ );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mbedtls_ssl_read( &ssl, buf, len );
|
||||||
|
|
||||||
|
/* Note that even if `mbedtls_ssl_check_pending` returns true,
|
||||||
|
* it can happen that the subsequent call to `mbedtls_ssl_read`
|
||||||
|
* returns `MBEDTLS_ERR_SSL_WANT_READ`, because the pending messages
|
||||||
|
* might be discarded (e.g. because they are retransmissions). */
|
||||||
|
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||||
|
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if( ret <= 0 )
|
if( ret <= 0 )
|
||||||
{
|
{
|
||||||
@ -2356,6 +2499,16 @@ data_exchange:
|
|||||||
mbedtls_printf( " failed\n ! mbedtls_ssl_renegotiate returned %d\n\n", ret );
|
mbedtls_printf( " failed\n ! mbedtls_ssl_renegotiate returned %d\n\n", ret );
|
||||||
goto reset;
|
goto reset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* For event-driven IO, wait for socket to become available */
|
||||||
|
if( opt.event == 1 /* level triggered IO */ )
|
||||||
|
{
|
||||||
|
#if defined(MBEDTLS_TIMING_C)
|
||||||
|
idle( &client_fd, &timer, ret );
|
||||||
|
#else
|
||||||
|
idle( &client_fd, ret );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mbedtls_printf( " ok\n" );
|
mbedtls_printf( " ok\n" );
|
||||||
@ -2390,14 +2543,39 @@ data_exchange:
|
|||||||
mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret );
|
mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret );
|
||||||
goto reset;
|
goto reset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* For event-driven IO, wait for socket to become available */
|
||||||
|
if( opt.event == 1 /* level triggered IO */ )
|
||||||
|
{
|
||||||
|
#if defined(MBEDTLS_TIMING_C)
|
||||||
|
idle( &client_fd, &timer, ret );
|
||||||
|
#else
|
||||||
|
idle( &client_fd, ret );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else /* Not stream, so datagram */
|
else /* Not stream, so datagram */
|
||||||
{
|
{
|
||||||
do ret = mbedtls_ssl_write( &ssl, buf, len );
|
while( 1 )
|
||||||
while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
|
{
|
||||||
ret == MBEDTLS_ERR_SSL_WANT_WRITE );
|
ret = mbedtls_ssl_write( &ssl, buf, len );
|
||||||
|
|
||||||
|
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||||
|
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* For event-driven IO, wait for socket to become available */
|
||||||
|
if( opt.event == 1 /* level triggered IO */ )
|
||||||
|
{
|
||||||
|
#if defined(MBEDTLS_TIMING_C)
|
||||||
|
idle( &client_fd, &timer, ret );
|
||||||
|
#else
|
||||||
|
idle( &client_fd, ret );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if( ret < 0 )
|
if( ret < 0 )
|
||||||
{
|
{
|
||||||
|
@ -53,6 +53,7 @@ int main( void )
|
|||||||
#include "mbedtls/net_sockets.h"
|
#include "mbedtls/net_sockets.h"
|
||||||
#include "mbedtls/error.h"
|
#include "mbedtls/error.h"
|
||||||
#include "mbedtls/ssl.h"
|
#include "mbedtls/ssl.h"
|
||||||
|
#include "mbedtls/timing.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@ -74,17 +75,21 @@ int main( void )
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
|
#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
|
||||||
|
|
||||||
/* For gettimeofday() */
|
|
||||||
#if !defined(_WIN32)
|
|
||||||
#include <sys/time.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define MAX_MSG_SIZE 16384 + 2048 /* max record/datagram size */
|
#define MAX_MSG_SIZE 16384 + 2048 /* max record/datagram size */
|
||||||
|
|
||||||
#define DFL_SERVER_ADDR "localhost"
|
#define DFL_SERVER_ADDR "localhost"
|
||||||
#define DFL_SERVER_PORT "4433"
|
#define DFL_SERVER_PORT "4433"
|
||||||
#define DFL_LISTEN_ADDR "localhost"
|
#define DFL_LISTEN_ADDR "localhost"
|
||||||
#define DFL_LISTEN_PORT "5556"
|
#define DFL_LISTEN_PORT "5556"
|
||||||
|
#define DFL_PACK 0
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_TIMING_C)
|
||||||
|
#define USAGE_PACK \
|
||||||
|
" pack=%%d default: 0 (don't pack)\n" \
|
||||||
|
" options: t > 0 (pack for t milliseconds)\n"
|
||||||
|
#else
|
||||||
|
#define USAGE_PACK
|
||||||
|
#endif
|
||||||
|
|
||||||
#define USAGE \
|
#define USAGE \
|
||||||
"\n usage: udp_proxy param=<>...\n" \
|
"\n usage: udp_proxy param=<>...\n" \
|
||||||
@ -108,6 +113,7 @@ int main( void )
|
|||||||
" protect_len=%%d default: (don't protect packets of this size)\n" \
|
" protect_len=%%d default: (don't protect packets of this size)\n" \
|
||||||
"\n" \
|
"\n" \
|
||||||
" seed=%%d default: (use current time)\n" \
|
" seed=%%d default: (use current time)\n" \
|
||||||
|
USAGE_PACK \
|
||||||
"\n"
|
"\n"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -128,7 +134,8 @@ static struct options
|
|||||||
int bad_ad; /* inject corrupted ApplicationData record */
|
int bad_ad; /* inject corrupted ApplicationData record */
|
||||||
int protect_hvr; /* never drop or delay HelloVerifyRequest */
|
int protect_hvr; /* never drop or delay HelloVerifyRequest */
|
||||||
int protect_len; /* never drop/delay packet of the given size*/
|
int protect_len; /* never drop/delay packet of the given size*/
|
||||||
|
unsigned pack; /* merge packets into single datagram for
|
||||||
|
* at most \c merge milliseconds if > 0 */
|
||||||
unsigned int seed; /* seed for "random" events */
|
unsigned int seed; /* seed for "random" events */
|
||||||
} opt;
|
} opt;
|
||||||
|
|
||||||
@ -152,6 +159,7 @@ static void get_options( int argc, char *argv[] )
|
|||||||
opt.server_port = DFL_SERVER_PORT;
|
opt.server_port = DFL_SERVER_PORT;
|
||||||
opt.listen_addr = DFL_LISTEN_ADDR;
|
opt.listen_addr = DFL_LISTEN_ADDR;
|
||||||
opt.listen_port = DFL_LISTEN_PORT;
|
opt.listen_port = DFL_LISTEN_PORT;
|
||||||
|
opt.pack = DFL_PACK;
|
||||||
/* Other members default to 0 */
|
/* Other members default to 0 */
|
||||||
|
|
||||||
for( i = 1; i < argc; i++ )
|
for( i = 1; i < argc; i++ )
|
||||||
@ -193,6 +201,15 @@ static void get_options( int argc, char *argv[] )
|
|||||||
if( opt.drop < 0 || opt.drop > 20 || opt.drop == 1 )
|
if( opt.drop < 0 || opt.drop > 20 || opt.drop == 1 )
|
||||||
exit_usage( p, q );
|
exit_usage( p, q );
|
||||||
}
|
}
|
||||||
|
else if( strcmp( p, "pack" ) == 0 )
|
||||||
|
{
|
||||||
|
#if defined(MBEDTLS_TIMING_C)
|
||||||
|
opt.pack = (unsigned) atoi( q );
|
||||||
|
#else
|
||||||
|
mbedtls_printf( " option pack only defined if MBEDTLS_TIMING_C is enabled\n" );
|
||||||
|
exit( 1 );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
else if( strcmp( p, "mtu" ) == 0 )
|
else if( strcmp( p, "mtu" ) == 0 )
|
||||||
{
|
{
|
||||||
opt.mtu = atoi( q );
|
opt.mtu = atoi( q );
|
||||||
@ -267,25 +284,122 @@ static const char *msg_type( unsigned char *msg, size_t len )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_TIMING_C)
|
||||||
/* Return elapsed time in milliseconds since the first call */
|
/* Return elapsed time in milliseconds since the first call */
|
||||||
static unsigned long ellapsed_time( void )
|
static unsigned ellapsed_time( void )
|
||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
static int initialized = 0;
|
||||||
return( 0 );
|
static struct mbedtls_timing_hr_time hires;
|
||||||
#else
|
|
||||||
static struct timeval ref = { 0, 0 };
|
|
||||||
struct timeval now;
|
|
||||||
|
|
||||||
if( ref.tv_sec == 0 && ref.tv_usec == 0 )
|
if( initialized == 0 )
|
||||||
{
|
{
|
||||||
gettimeofday( &ref, NULL );
|
(void) mbedtls_timing_get_timer( &hires, 1 );
|
||||||
|
initialized = 1;
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
gettimeofday( &now, NULL );
|
return( mbedtls_timing_get_timer( &hires, 0 ) );
|
||||||
return( 1000 * ( now.tv_sec - ref.tv_sec )
|
}
|
||||||
+ ( now.tv_usec - ref.tv_usec ) / 1000 );
|
|
||||||
#endif
|
typedef struct
|
||||||
|
{
|
||||||
|
mbedtls_net_context *ctx;
|
||||||
|
|
||||||
|
const char *description;
|
||||||
|
|
||||||
|
unsigned packet_lifetime;
|
||||||
|
unsigned num_datagrams;
|
||||||
|
|
||||||
|
unsigned char data[MAX_MSG_SIZE];
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
} ctx_buffer;
|
||||||
|
|
||||||
|
static ctx_buffer outbuf[2];
|
||||||
|
|
||||||
|
static int ctx_buffer_flush( ctx_buffer *buf )
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
mbedtls_printf( " %05u flush %s: %u bytes, %u datagrams, last %u ms\n",
|
||||||
|
ellapsed_time(), buf->description,
|
||||||
|
(unsigned) buf->len, buf->num_datagrams,
|
||||||
|
ellapsed_time() - buf->packet_lifetime );
|
||||||
|
|
||||||
|
ret = mbedtls_net_send( buf->ctx, buf->data, buf->len );
|
||||||
|
|
||||||
|
buf->len = 0;
|
||||||
|
buf->num_datagrams = 0;
|
||||||
|
|
||||||
|
return( ret );
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned ctx_buffer_time_remaining( ctx_buffer *buf )
|
||||||
|
{
|
||||||
|
unsigned const cur_time = ellapsed_time();
|
||||||
|
|
||||||
|
if( buf->num_datagrams == 0 )
|
||||||
|
return( (unsigned) -1 );
|
||||||
|
|
||||||
|
if( cur_time - buf->packet_lifetime >= opt.pack )
|
||||||
|
return( 0 );
|
||||||
|
|
||||||
|
return( opt.pack - ( cur_time - buf->packet_lifetime ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ctx_buffer_append( ctx_buffer *buf,
|
||||||
|
const unsigned char * data,
|
||||||
|
size_t len )
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if( len > (size_t) INT_MAX )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
if( len > sizeof( buf->data ) )
|
||||||
|
{
|
||||||
|
mbedtls_printf( " ! buffer size %u too large (max %u)\n",
|
||||||
|
(unsigned) len, (unsigned) sizeof( buf->data ) );
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( sizeof( buf->data ) - buf->len < len )
|
||||||
|
{
|
||||||
|
if( ( ret = ctx_buffer_flush( buf ) ) <= 0 )
|
||||||
|
return( ret );
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy( buf->data + buf->len, data, len );
|
||||||
|
|
||||||
|
buf->len += len;
|
||||||
|
if( ++buf->num_datagrams == 1 )
|
||||||
|
buf->packet_lifetime = ellapsed_time();
|
||||||
|
|
||||||
|
return( (int) len );
|
||||||
|
}
|
||||||
|
#endif /* MBEDTLS_TIMING_C */
|
||||||
|
|
||||||
|
static int dispatch_data( mbedtls_net_context *ctx,
|
||||||
|
const unsigned char * data,
|
||||||
|
size_t len )
|
||||||
|
{
|
||||||
|
#if defined(MBEDTLS_TIMING_C)
|
||||||
|
ctx_buffer *buf = NULL;
|
||||||
|
if( opt.pack > 0 )
|
||||||
|
{
|
||||||
|
if( outbuf[0].ctx == ctx )
|
||||||
|
buf = &outbuf[0];
|
||||||
|
else if( outbuf[1].ctx == ctx )
|
||||||
|
buf = &outbuf[1];
|
||||||
|
|
||||||
|
if( buf == NULL )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
return( ctx_buffer_append( buf, data, len ) );
|
||||||
|
}
|
||||||
|
#endif /* MBEDTLS_TIMING_C */
|
||||||
|
|
||||||
|
return( mbedtls_net_send( ctx, data, len ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@ -300,12 +414,22 @@ typedef struct
|
|||||||
/* Print packet. Outgoing packets come with a reason (forward, dupl, etc.) */
|
/* Print packet. Outgoing packets come with a reason (forward, dupl, etc.) */
|
||||||
void print_packet( const packet *p, const char *why )
|
void print_packet( const packet *p, const char *why )
|
||||||
{
|
{
|
||||||
|
#if defined(MBEDTLS_TIMING_C)
|
||||||
if( why == NULL )
|
if( why == NULL )
|
||||||
mbedtls_printf( " %05lu %s %s (%u bytes)\n",
|
mbedtls_printf( " %05u dispatch %s %s (%u bytes)\n",
|
||||||
ellapsed_time(), p->way, p->type, p->len );
|
ellapsed_time(), p->way, p->type, p->len );
|
||||||
else
|
else
|
||||||
mbedtls_printf( " %s %s (%u bytes): %s\n",
|
mbedtls_printf( " %05u dispatch %s %s (%u bytes): %s\n",
|
||||||
|
ellapsed_time(), p->way, p->type, p->len, why );
|
||||||
|
#else
|
||||||
|
if( why == NULL )
|
||||||
|
mbedtls_printf( " dispatch %s %s (%u bytes)\n",
|
||||||
|
p->way, p->type, p->len );
|
||||||
|
else
|
||||||
|
mbedtls_printf( " dispatch %s %s (%u bytes): %s\n",
|
||||||
p->way, p->type, p->len, why );
|
p->way, p->type, p->len, why );
|
||||||
|
#endif
|
||||||
|
|
||||||
fflush( stdout );
|
fflush( stdout );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -320,20 +444,28 @@ int send_packet( const packet *p, const char *why )
|
|||||||
{
|
{
|
||||||
unsigned char buf[MAX_MSG_SIZE];
|
unsigned char buf[MAX_MSG_SIZE];
|
||||||
memcpy( buf, p->buf, p->len );
|
memcpy( buf, p->buf, p->len );
|
||||||
++buf[p->len - 1];
|
|
||||||
|
|
||||||
print_packet( p, "corrupted" );
|
if( p->len <= 13 )
|
||||||
if( ( ret = mbedtls_net_send( dst, buf, p->len ) ) <= 0 )
|
|
||||||
{
|
{
|
||||||
mbedtls_printf( " ! mbedtls_net_send returned %d\n", ret );
|
mbedtls_printf( " ! can't corrupt empty AD record" );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++buf[13];
|
||||||
|
print_packet( p, "corrupted" );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ( ret = dispatch_data( dst, buf, p->len ) ) <= 0 )
|
||||||
|
{
|
||||||
|
mbedtls_printf( " ! dispatch returned %d\n", ret );
|
||||||
return( ret );
|
return( ret );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
print_packet( p, why );
|
print_packet( p, why );
|
||||||
if( ( ret = mbedtls_net_send( dst, p->buf, p->len ) ) <= 0 )
|
if( ( ret = dispatch_data( dst, p->buf, p->len ) ) <= 0 )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " ! mbedtls_net_send returned %d\n", ret );
|
mbedtls_printf( " ! dispatch returned %d\n", ret );
|
||||||
return( ret );
|
return( ret );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,9 +476,9 @@ int send_packet( const packet *p, const char *why )
|
|||||||
{
|
{
|
||||||
print_packet( p, "duplicated" );
|
print_packet( p, "duplicated" );
|
||||||
|
|
||||||
if( ( ret = mbedtls_net_send( dst, p->buf, p->len ) ) <= 0 )
|
if( ( ret = dispatch_data( dst, p->buf, p->len ) ) <= 0 )
|
||||||
{
|
{
|
||||||
mbedtls_printf( " ! mbedtls_net_send returned %d\n", ret );
|
mbedtls_printf( " ! dispatch returned %d\n", ret );
|
||||||
return( ret );
|
return( ret );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -472,6 +604,12 @@ int main( int argc, char *argv[] )
|
|||||||
|
|
||||||
mbedtls_net_context listen_fd, client_fd, server_fd;
|
mbedtls_net_context listen_fd, client_fd, server_fd;
|
||||||
|
|
||||||
|
#if defined( MBEDTLS_TIMING_C )
|
||||||
|
struct timeval tm;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct timeval *tm_ptr = NULL;
|
||||||
|
|
||||||
int nb_fds;
|
int nb_fds;
|
||||||
fd_set read_fds;
|
fd_set read_fds;
|
||||||
|
|
||||||
@ -560,14 +698,65 @@ accept:
|
|||||||
nb_fds = listen_fd.fd;
|
nb_fds = listen_fd.fd;
|
||||||
++nb_fds;
|
++nb_fds;
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_TIMING_C)
|
||||||
|
if( opt.pack > 0 )
|
||||||
|
{
|
||||||
|
outbuf[0].ctx = &server_fd;
|
||||||
|
outbuf[0].description = "S <- C";
|
||||||
|
outbuf[0].num_datagrams = 0;
|
||||||
|
outbuf[0].len = 0;
|
||||||
|
|
||||||
|
outbuf[1].ctx = &client_fd;
|
||||||
|
outbuf[1].description = "S -> C";
|
||||||
|
outbuf[1].num_datagrams = 0;
|
||||||
|
outbuf[1].len = 0;
|
||||||
|
}
|
||||||
|
#endif /* MBEDTLS_TIMING_C */
|
||||||
|
|
||||||
while( 1 )
|
while( 1 )
|
||||||
{
|
{
|
||||||
|
#if defined(MBEDTLS_TIMING_C)
|
||||||
|
if( opt.pack > 0 )
|
||||||
|
{
|
||||||
|
unsigned max_wait_server, max_wait_client, max_wait;
|
||||||
|
max_wait_server = ctx_buffer_time_remaining( &outbuf[0] );
|
||||||
|
max_wait_client = ctx_buffer_time_remaining( &outbuf[1] );
|
||||||
|
|
||||||
|
max_wait = (unsigned) -1;
|
||||||
|
|
||||||
|
if( max_wait_server == 0 )
|
||||||
|
ctx_buffer_flush( &outbuf[0] );
|
||||||
|
else
|
||||||
|
max_wait = max_wait_server;
|
||||||
|
|
||||||
|
if( max_wait_client == 0 )
|
||||||
|
ctx_buffer_flush( &outbuf[1] );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( max_wait_client < max_wait )
|
||||||
|
max_wait = max_wait_client;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( max_wait != (unsigned) -1 )
|
||||||
|
{
|
||||||
|
tm.tv_sec = max_wait / 1000;
|
||||||
|
tm.tv_usec = ( max_wait % 1000 ) * 1000;
|
||||||
|
|
||||||
|
tm_ptr = &tm;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tm_ptr = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* MBEDTLS_TIMING_C */
|
||||||
|
|
||||||
FD_ZERO( &read_fds );
|
FD_ZERO( &read_fds );
|
||||||
FD_SET( server_fd.fd, &read_fds );
|
FD_SET( server_fd.fd, &read_fds );
|
||||||
FD_SET( client_fd.fd, &read_fds );
|
FD_SET( client_fd.fd, &read_fds );
|
||||||
FD_SET( listen_fd.fd, &read_fds );
|
FD_SET( listen_fd.fd, &read_fds );
|
||||||
|
|
||||||
if( ( ret = select( nb_fds, &read_fds, NULL, NULL, NULL ) ) <= 0 )
|
if( ( ret = select( nb_fds, &read_fds, NULL, NULL, tm_ptr ) ) < 0 )
|
||||||
{
|
{
|
||||||
perror( "select" );
|
perror( "select" );
|
||||||
goto exit;
|
goto exit;
|
||||||
@ -589,6 +778,7 @@ accept:
|
|||||||
&client_fd, &server_fd ) ) != 0 )
|
&client_fd, &server_fd ) ) != 0 )
|
||||||
goto accept;
|
goto accept;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
|
117
programs/test/udp_proxy_wrapper.sh
Executable file
117
programs/test/udp_proxy_wrapper.sh
Executable file
@ -0,0 +1,117 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# -*-sh-basic-offset: 4-*-
|
||||||
|
# Usage: udp_proxy_wrapper.sh [PROXY_PARAM...] -- [SERVER_PARAM...]
|
||||||
|
|
||||||
|
set -u
|
||||||
|
|
||||||
|
MBEDTLS_BASE="$(dirname -- "$0")/../.."
|
||||||
|
TPXY_BIN="$MBEDTLS_BASE/programs/test/udp_proxy"
|
||||||
|
SRV_BIN="$MBEDTLS_BASE/programs/ssl/ssl_server2"
|
||||||
|
|
||||||
|
: ${VERBOSE:=0}
|
||||||
|
|
||||||
|
stop_proxy() {
|
||||||
|
if [ -n "${tpxy_pid:-}" ]; then
|
||||||
|
echo
|
||||||
|
echo " * Killing proxy (pid $tpxy_pid) ..."
|
||||||
|
kill $tpxy_pid
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
stop_server() {
|
||||||
|
if [ -n "${srv_pid:-}" ]; then
|
||||||
|
echo
|
||||||
|
echo " * Killing server (pid $srv_pid) ..."
|
||||||
|
kill $srv_pid >/dev/null 2>/dev/null
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
stop_server
|
||||||
|
stop_proxy
|
||||||
|
exit 129
|
||||||
|
}
|
||||||
|
|
||||||
|
trap cleanup INT TERM HUP
|
||||||
|
|
||||||
|
# Extract the proxy parameters
|
||||||
|
tpxy_cmd_snippet='"$TPXY_BIN"'
|
||||||
|
while [ $# -ne 0 ] && [ "$1" != "--" ]; do
|
||||||
|
tail="$1" quoted=""
|
||||||
|
while [ -n "$tail" ]; do
|
||||||
|
case "$tail" in
|
||||||
|
*\'*) quoted="${quoted}${tail%%\'*}'\\''" tail="${tail#*\'}";;
|
||||||
|
*) quoted="${quoted}${tail}"; tail=; false;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
tpxy_cmd_snippet="$tpxy_cmd_snippet '$quoted'"
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
unset tail quoted
|
||||||
|
if [ $# -eq 0 ]; then
|
||||||
|
echo " * No server arguments (must be preceded by \" -- \") - exit"
|
||||||
|
exit 3
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
|
||||||
|
dtls_enabled=
|
||||||
|
ipv6_in_use=
|
||||||
|
server_port_orig=
|
||||||
|
server_addr_orig=
|
||||||
|
for param; do
|
||||||
|
case "$param" in
|
||||||
|
server_port=*) server_port_orig="${param#*=}";;
|
||||||
|
server_addr=*:*) server_addr_orig="${param#*=}"; ipv6_in_use=1;;
|
||||||
|
server_addr=*) server_addr_orig="${param#*=}";;
|
||||||
|
dtls=[!0]*) dtls_enabled=1;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z "$dtls_enabled" ] || [ -n "$ipv6_in_use" ]; then
|
||||||
|
echo >&2 "$0: Couldn't find DTLS enabling, or IPv6 is in use - immediate fallback to server application..."
|
||||||
|
if [ $VERBOSE -gt 0 ]; then
|
||||||
|
echo "[ $SRV_BIN $* ]"
|
||||||
|
fi
|
||||||
|
exec "$SRV_BIN" "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$server_port_orig" ]; then
|
||||||
|
server_port_orig=4433
|
||||||
|
fi
|
||||||
|
echo " * Server port: $server_port_orig"
|
||||||
|
tpxy_cmd_snippet="$tpxy_cmd_snippet \"listen_port=\$server_port_orig\""
|
||||||
|
tpxy_cmd_snippet="$tpxy_cmd_snippet \"server_port=\$server_port\""
|
||||||
|
|
||||||
|
if [ -n "$server_addr_orig" ]; then
|
||||||
|
echo " * Server address: $server_addr_orig"
|
||||||
|
tpxy_cmd_snippet="$tpxy_cmd_snippet \"server_addr=\$server_addr_orig\""
|
||||||
|
tpxy_cmd_snippet="$tpxy_cmd_snippet \"listen_addr=\$server_addr_orig\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
server_port=$(( server_port_orig + 1 ))
|
||||||
|
set -- "$@" "server_port=$server_port"
|
||||||
|
echo " * Intermediate port: $server_port"
|
||||||
|
|
||||||
|
echo " * Start proxy in background ..."
|
||||||
|
if [ $VERBOSE -gt 0 ]; then
|
||||||
|
echo "[ $tpxy_cmd_snippet ]"
|
||||||
|
fi
|
||||||
|
eval exec "$tpxy_cmd_snippet" >/dev/null 2>&1 &
|
||||||
|
tpxy_pid=$!
|
||||||
|
|
||||||
|
if [ $VERBOSE -gt 0 ]; then
|
||||||
|
echo " * Proxy ID: $TPXY_PID"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo " * Starting server ..."
|
||||||
|
if [ $VERBOSE -gt 0 ]; then
|
||||||
|
echo "[ $SRV_BIN $* ]"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$SRV_BIN" "$@" >&2 &
|
||||||
|
srv_pid=$!
|
||||||
|
|
||||||
|
wait $srv_pid
|
||||||
|
|
||||||
|
stop_proxy
|
||||||
|
return 0
|
156
tests/ssl-opt.sh
156
tests/ssl-opt.sh
@ -465,9 +465,12 @@ run_test() {
|
|||||||
eval "$CLI_CMD" >> $CLI_OUT 2>&1 &
|
eval "$CLI_CMD" >> $CLI_OUT 2>&1 &
|
||||||
wait_client_done
|
wait_client_done
|
||||||
|
|
||||||
|
sleep 0.05
|
||||||
|
|
||||||
# terminate the server (and the proxy)
|
# terminate the server (and the proxy)
|
||||||
kill $SRV_PID
|
kill $SRV_PID
|
||||||
wait $SRV_PID
|
wait $SRV_PID
|
||||||
|
|
||||||
if [ -n "$PXY_CMD" ]; then
|
if [ -n "$PXY_CMD" ]; then
|
||||||
kill $PXY_PID >/dev/null 2>&1
|
kill $PXY_PID >/dev/null 2>&1
|
||||||
wait $PXY_PID
|
wait $PXY_PID
|
||||||
@ -631,16 +634,19 @@ fi
|
|||||||
get_options "$@"
|
get_options "$@"
|
||||||
|
|
||||||
# sanity checks, avoid an avalanche of errors
|
# sanity checks, avoid an avalanche of errors
|
||||||
if [ ! -x "$P_SRV" ]; then
|
P_SRV_BIN="${P_SRV%%[ ]*}"
|
||||||
echo "Command '$P_SRV' is not an executable file"
|
P_CLI_BIN="${P_CLI%%[ ]*}"
|
||||||
|
P_PXY_BIN="${P_PXY%%[ ]*}"
|
||||||
|
if [ ! -x "$P_SRV_BIN" ]; then
|
||||||
|
echo "Command '$P_SRV_BIN' is not an executable file"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
if [ ! -x "$P_CLI" ]; then
|
if [ ! -x "$P_CLI_BIN" ]; then
|
||||||
echo "Command '$P_CLI' is not an executable file"
|
echo "Command '$P_CLI_BIN' is not an executable file"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
if [ ! -x "$P_PXY" ]; then
|
if [ ! -x "$P_PXY_BIN" ]; then
|
||||||
echo "Command '$P_PXY' is not an executable file"
|
echo "Command '$P_PXY_BIN' is not an executable file"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
if [ "$MEMCHECK" -gt 0 ]; then
|
if [ "$MEMCHECK" -gt 0 ]; then
|
||||||
@ -2704,6 +2710,118 @@ run_test "Non-blocking I/O: session-id resume" \
|
|||||||
-C "mbedtls_ssl_handshake returned" \
|
-C "mbedtls_ssl_handshake returned" \
|
||||||
-c "Read from server: .* bytes read"
|
-c "Read from server: .* bytes read"
|
||||||
|
|
||||||
|
# Tests for event-driven I/O: exercise a variety of handshake flows
|
||||||
|
|
||||||
|
run_test "Event-driven I/O: basic handshake" \
|
||||||
|
"$P_SRV event=1 tickets=0 auth_mode=none" \
|
||||||
|
"$P_CLI event=1 tickets=0" \
|
||||||
|
0 \
|
||||||
|
-S "mbedtls_ssl_handshake returned" \
|
||||||
|
-C "mbedtls_ssl_handshake returned" \
|
||||||
|
-c "Read from server: .* bytes read"
|
||||||
|
|
||||||
|
run_test "Event-driven I/O: client auth" \
|
||||||
|
"$P_SRV event=1 tickets=0 auth_mode=required" \
|
||||||
|
"$P_CLI event=1 tickets=0" \
|
||||||
|
0 \
|
||||||
|
-S "mbedtls_ssl_handshake returned" \
|
||||||
|
-C "mbedtls_ssl_handshake returned" \
|
||||||
|
-c "Read from server: .* bytes read"
|
||||||
|
|
||||||
|
run_test "Event-driven I/O: ticket" \
|
||||||
|
"$P_SRV event=1 tickets=1 auth_mode=none" \
|
||||||
|
"$P_CLI event=1 tickets=1" \
|
||||||
|
0 \
|
||||||
|
-S "mbedtls_ssl_handshake returned" \
|
||||||
|
-C "mbedtls_ssl_handshake returned" \
|
||||||
|
-c "Read from server: .* bytes read"
|
||||||
|
|
||||||
|
run_test "Event-driven I/O: ticket + client auth" \
|
||||||
|
"$P_SRV event=1 tickets=1 auth_mode=required" \
|
||||||
|
"$P_CLI event=1 tickets=1" \
|
||||||
|
0 \
|
||||||
|
-S "mbedtls_ssl_handshake returned" \
|
||||||
|
-C "mbedtls_ssl_handshake returned" \
|
||||||
|
-c "Read from server: .* bytes read"
|
||||||
|
|
||||||
|
run_test "Event-driven I/O: ticket + client auth + resume" \
|
||||||
|
"$P_SRV event=1 tickets=1 auth_mode=required" \
|
||||||
|
"$P_CLI event=1 tickets=1 reconnect=1" \
|
||||||
|
0 \
|
||||||
|
-S "mbedtls_ssl_handshake returned" \
|
||||||
|
-C "mbedtls_ssl_handshake returned" \
|
||||||
|
-c "Read from server: .* bytes read"
|
||||||
|
|
||||||
|
run_test "Event-driven I/O: ticket + resume" \
|
||||||
|
"$P_SRV event=1 tickets=1 auth_mode=none" \
|
||||||
|
"$P_CLI event=1 tickets=1 reconnect=1" \
|
||||||
|
0 \
|
||||||
|
-S "mbedtls_ssl_handshake returned" \
|
||||||
|
-C "mbedtls_ssl_handshake returned" \
|
||||||
|
-c "Read from server: .* bytes read"
|
||||||
|
|
||||||
|
run_test "Event-driven I/O: session-id resume" \
|
||||||
|
"$P_SRV event=1 tickets=0 auth_mode=none" \
|
||||||
|
"$P_CLI event=1 tickets=0 reconnect=1" \
|
||||||
|
0 \
|
||||||
|
-S "mbedtls_ssl_handshake returned" \
|
||||||
|
-C "mbedtls_ssl_handshake returned" \
|
||||||
|
-c "Read from server: .* bytes read"
|
||||||
|
|
||||||
|
run_test "Event-driven I/O, DTLS: basic handshake" \
|
||||||
|
"$P_SRV dtls=1 event=1 tickets=0 auth_mode=none" \
|
||||||
|
"$P_CLI dtls=1 event=1 tickets=0" \
|
||||||
|
0 \
|
||||||
|
-c "Read from server: .* bytes read"
|
||||||
|
|
||||||
|
run_test "Event-driven I/O, DTLS: client auth" \
|
||||||
|
"$P_SRV dtls=1 event=1 tickets=0 auth_mode=required" \
|
||||||
|
"$P_CLI dtls=1 event=1 tickets=0" \
|
||||||
|
0 \
|
||||||
|
-c "Read from server: .* bytes read"
|
||||||
|
|
||||||
|
run_test "Event-driven I/O, DTLS: ticket" \
|
||||||
|
"$P_SRV dtls=1 event=1 tickets=1 auth_mode=none" \
|
||||||
|
"$P_CLI dtls=1 event=1 tickets=1" \
|
||||||
|
0 \
|
||||||
|
-c "Read from server: .* bytes read"
|
||||||
|
|
||||||
|
run_test "Event-driven I/O, DTLS: ticket + client auth" \
|
||||||
|
"$P_SRV dtls=1 event=1 tickets=1 auth_mode=required" \
|
||||||
|
"$P_CLI dtls=1 event=1 tickets=1" \
|
||||||
|
0 \
|
||||||
|
-c "Read from server: .* bytes read"
|
||||||
|
|
||||||
|
run_test "Event-driven I/O, DTLS: ticket + client auth + resume" \
|
||||||
|
"$P_SRV dtls=1 event=1 tickets=1 auth_mode=required" \
|
||||||
|
"$P_CLI dtls=1 event=1 tickets=1 reconnect=1" \
|
||||||
|
0 \
|
||||||
|
-c "Read from server: .* bytes read"
|
||||||
|
|
||||||
|
run_test "Event-driven I/O, DTLS: ticket + resume" \
|
||||||
|
"$P_SRV dtls=1 event=1 tickets=1 auth_mode=none" \
|
||||||
|
"$P_CLI dtls=1 event=1 tickets=1 reconnect=1" \
|
||||||
|
0 \
|
||||||
|
-c "Read from server: .* bytes read"
|
||||||
|
|
||||||
|
run_test "Event-driven I/O, DTLS: session-id resume" \
|
||||||
|
"$P_SRV dtls=1 event=1 tickets=0 auth_mode=none" \
|
||||||
|
"$P_CLI dtls=1 event=1 tickets=0 reconnect=1" \
|
||||||
|
0 \
|
||||||
|
-c "Read from server: .* bytes read"
|
||||||
|
|
||||||
|
# This test demonstrates the need for the mbedtls_ssl_check_pending function.
|
||||||
|
# During session resumption, the client will send its ApplicationData record
|
||||||
|
# within the same datagram as the Finished messages. In this situation, the
|
||||||
|
# server MUST NOT idle on the underlying transport after handshake completion,
|
||||||
|
# because the ApplicationData request has already been queued internally.
|
||||||
|
run_test "Event-driven I/O, DTLS: session-id resume, UDP packing" \
|
||||||
|
-p "$P_PXY pack=50" \
|
||||||
|
"$P_SRV dtls=1 event=1 tickets=0 auth_mode=required" \
|
||||||
|
"$P_CLI dtls=1 event=1 tickets=0 reconnect=1" \
|
||||||
|
0 \
|
||||||
|
-c "Read from server: .* bytes read"
|
||||||
|
|
||||||
# Tests for version negotiation
|
# Tests for version negotiation
|
||||||
|
|
||||||
run_test "Version check: all -> 1.2" \
|
run_test "Version check: all -> 1.2" \
|
||||||
@ -4195,8 +4313,8 @@ run_test "DTLS proxy: duplicate every packet" \
|
|||||||
0 \
|
0 \
|
||||||
-c "replayed record" \
|
-c "replayed record" \
|
||||||
-s "replayed record" \
|
-s "replayed record" \
|
||||||
-c "discarding invalid record" \
|
-c "record from another epoch" \
|
||||||
-s "discarding invalid record" \
|
-s "record from another epoch" \
|
||||||
-S "resend" \
|
-S "resend" \
|
||||||
-s "Extra-header:" \
|
-s "Extra-header:" \
|
||||||
-c "HTTP/1.0 200 OK"
|
-c "HTTP/1.0 200 OK"
|
||||||
@ -4208,13 +4326,29 @@ run_test "DTLS proxy: duplicate every packet, server anti-replay off" \
|
|||||||
0 \
|
0 \
|
||||||
-c "replayed record" \
|
-c "replayed record" \
|
||||||
-S "replayed record" \
|
-S "replayed record" \
|
||||||
-c "discarding invalid record" \
|
-c "record from another epoch" \
|
||||||
-s "discarding invalid record" \
|
-s "record from another epoch" \
|
||||||
-c "resend" \
|
-c "resend" \
|
||||||
-s "resend" \
|
-s "resend" \
|
||||||
-s "Extra-header:" \
|
-s "Extra-header:" \
|
||||||
-c "HTTP/1.0 200 OK"
|
-c "HTTP/1.0 200 OK"
|
||||||
|
|
||||||
|
run_test "DTLS proxy: multiple records in same datagram" \
|
||||||
|
-p "$P_PXY pack=50" \
|
||||||
|
"$P_SRV dtls=1 debug_level=2" \
|
||||||
|
"$P_CLI dtls=1 debug_level=2" \
|
||||||
|
0 \
|
||||||
|
-c "next record in same datagram" \
|
||||||
|
-s "next record in same datagram"
|
||||||
|
|
||||||
|
run_test "DTLS proxy: multiple records in same datagram, duplicate every packet" \
|
||||||
|
-p "$P_PXY pack=50 duplicate=1" \
|
||||||
|
"$P_SRV dtls=1 debug_level=2" \
|
||||||
|
"$P_CLI dtls=1 debug_level=2" \
|
||||||
|
0 \
|
||||||
|
-c "next record in same datagram" \
|
||||||
|
-s "next record in same datagram"
|
||||||
|
|
||||||
run_test "DTLS proxy: inject invalid AD record, default badmac_limit" \
|
run_test "DTLS proxy: inject invalid AD record, default badmac_limit" \
|
||||||
-p "$P_PXY bad_ad=1" \
|
-p "$P_PXY bad_ad=1" \
|
||||||
"$P_SRV dtls=1 debug_level=1" \
|
"$P_SRV dtls=1 debug_level=1" \
|
||||||
@ -4270,8 +4404,6 @@ run_test "DTLS proxy: delay ChangeCipherSpec" \
|
|||||||
0 \
|
0 \
|
||||||
-c "record from another epoch" \
|
-c "record from another epoch" \
|
||||||
-s "record from another epoch" \
|
-s "record from another epoch" \
|
||||||
-c "discarding invalid record" \
|
|
||||||
-s "discarding invalid record" \
|
|
||||||
-s "Extra-header:" \
|
-s "Extra-header:" \
|
||||||
-c "HTTP/1.0 200 OK"
|
-c "HTTP/1.0 200 OK"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user