mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2025-04-01 04:20:45 +00:00
tls13: Add definition of mbedtls_ssl_{write,read}_early_data
Signed-off-by: Ronald Cron <ronald.cron@arm.com>
This commit is contained in:
parent
ef25a99f20
commit
4a8c9e2cff
@ -478,3 +478,175 @@ outbound message on server side as well.
|
|||||||
|
|
||||||
* state change: the state change is done in the main state handler to ease
|
* state change: the state change is done in the main state handler to ease
|
||||||
the navigation of the state machine transitions.
|
the navigation of the state machine transitions.
|
||||||
|
|
||||||
|
|
||||||
|
Writing and reading early or 0-RTT data
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
An application function to write and send a buffer of data to a server through
|
||||||
|
TLS may plausibly look like:
|
||||||
|
|
||||||
|
```
|
||||||
|
int write_data( mbedtls_ssl_context *ssl,
|
||||||
|
const unsigned char *data_to_write,
|
||||||
|
size_t data_to_write_len,
|
||||||
|
size_t *data_written )
|
||||||
|
{
|
||||||
|
*data_written = 0;
|
||||||
|
|
||||||
|
while( *data_written < data_to_write_len )
|
||||||
|
{
|
||||||
|
ret = mbedtls_ssl_write( ssl, data_to_write + *data_written,
|
||||||
|
data_to_write_len - *data_written );
|
||||||
|
|
||||||
|
if( ret < 0 &&
|
||||||
|
ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||||
|
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||||
|
{
|
||||||
|
return( ret );
|
||||||
|
}
|
||||||
|
|
||||||
|
*data_written += ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
```
|
||||||
|
where ssl is the SSL context to use, data_to_write the address of the data
|
||||||
|
buffer and data_to_write_len the number of data bytes. The handshake may
|
||||||
|
not be completed, not even started for the SSL context ssl when the function is
|
||||||
|
called and in that case the mbedtls_ssl_write() API takes care transparently of
|
||||||
|
completing the handshake before to write and send data to the server. The
|
||||||
|
mbedtls_ssl_write() may not been able to write and send all data in one go thus
|
||||||
|
the need for a loop calling it as long as there are still data to write and
|
||||||
|
send.
|
||||||
|
|
||||||
|
An application function to write and send early data and only early data,
|
||||||
|
data sent during the first flight of client messages while the handshake is in
|
||||||
|
its initial phase, would look completely similar but the call to
|
||||||
|
mbedtls_ssl_write_early_data() instead of mbedtls_ssl_write().
|
||||||
|
```
|
||||||
|
int write_early_data( mbedtls_ssl_context *ssl,
|
||||||
|
const unsigned char *data_to_write,
|
||||||
|
size_t data_to_write_len,
|
||||||
|
size_t *data_written )
|
||||||
|
{
|
||||||
|
*data_written = 0;
|
||||||
|
|
||||||
|
while( *data_written < data_to_write_len )
|
||||||
|
{
|
||||||
|
ret = mbedtls_ssl_write_early_data( ssl, data_to_write + *data_written,
|
||||||
|
data_to_write_len - *data_written );
|
||||||
|
|
||||||
|
if( ret < 0 &&
|
||||||
|
ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||||
|
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||||
|
{
|
||||||
|
return( ret );
|
||||||
|
}
|
||||||
|
|
||||||
|
*data_written += ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Note that compared to write_data(), write_early_data() can also return
|
||||||
|
MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA and that should be handled
|
||||||
|
specifically by the user of write_early_data(). A fresh SSL context (typically
|
||||||
|
just after a call to mbedtls_ssl_setup() or mbedtls_ssl_session_reset()) would
|
||||||
|
be expected when calling `write_early_data`.
|
||||||
|
|
||||||
|
All together, code to write and send a buffer of data as long as possible as
|
||||||
|
early data and then as standard post-handshake application data could
|
||||||
|
plausibly look like:
|
||||||
|
|
||||||
|
```
|
||||||
|
ret = write_early_data( ssl, data_to_write, data_to_write_len,
|
||||||
|
&early_data_written );
|
||||||
|
if( ret < 0 &&
|
||||||
|
ret != MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA )
|
||||||
|
{
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = write_data( ssl, data_to_write + early_data_written,
|
||||||
|
data_to_write_len - early_data_written, &data_written );
|
||||||
|
if( ret < 0 )
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
data_written += early_data_written;
|
||||||
|
```
|
||||||
|
|
||||||
|
Finally, taking into account that the server may reject early data, application
|
||||||
|
code to write and send a buffer of data could plausibly look like:
|
||||||
|
```
|
||||||
|
ret = write_early_data( ssl, data_to_write, data_to_write_len,
|
||||||
|
&early_data_written );
|
||||||
|
if( ret < 0 &&
|
||||||
|
ret != MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA )
|
||||||
|
{
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure the handshake is completed as it is a requisite to
|
||||||
|
* mbedtls_ssl_get_early_data_status().
|
||||||
|
*/
|
||||||
|
while( !mbedtls_ssl_is_handshake_over( ssl ) )
|
||||||
|
{
|
||||||
|
ret = mbedtls_ssl_handshake( ssl );
|
||||||
|
if( ret < 0 &&
|
||||||
|
ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||||
|
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||||
|
{
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = mbedtls_ssl_get_early_data_status( ssl );
|
||||||
|
if( ret < 0 )
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if( ret == MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED )
|
||||||
|
early_data_written = 0;
|
||||||
|
|
||||||
|
ret = write_data( ssl, data_to_write + early_data_written,
|
||||||
|
data_to_write_len - early_data_written, &data_written );
|
||||||
|
if( ret < 0 )
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
data_written += early_data_written;
|
||||||
|
```
|
||||||
|
|
||||||
|
Basically, the same holds for reading early data on the server side without the
|
||||||
|
complication of possible rejection. An application function to read early data
|
||||||
|
into a given buffer could plausibly look like:
|
||||||
|
```
|
||||||
|
int read_early_data( mbedtls_ssl_context *ssl,
|
||||||
|
unsigned char *buffer,
|
||||||
|
size_t buffer_size,
|
||||||
|
size_t *data_len )
|
||||||
|
{
|
||||||
|
*data_len = 0;
|
||||||
|
|
||||||
|
while( *data_len < buffer_size )
|
||||||
|
{
|
||||||
|
ret = mbedtls_ssl_read_early_data( ssl, buffer + *data_len,
|
||||||
|
buffer_size - *data_len );
|
||||||
|
|
||||||
|
if( ret < 0 &&
|
||||||
|
ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||||
|
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
|
||||||
|
{
|
||||||
|
return( ret );
|
||||||
|
}
|
||||||
|
|
||||||
|
*data_len += ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
```
|
||||||
|
with again calls to read_early_data() expected to be done with a fresh SSL
|
||||||
|
context.
|
||||||
|
@ -96,15 +96,16 @@
|
|||||||
/* Error space gap */
|
/* Error space gap */
|
||||||
/** Processing of the Certificate handshake message failed. */
|
/** Processing of the Certificate handshake message failed. */
|
||||||
#define MBEDTLS_ERR_SSL_BAD_CERTIFICATE -0x7A00
|
#define MBEDTLS_ERR_SSL_BAD_CERTIFICATE -0x7A00
|
||||||
|
/* Error space gap */
|
||||||
/**
|
/**
|
||||||
* Received NewSessionTicket Post Handshake Message.
|
* Received NewSessionTicket Post Handshake Message.
|
||||||
* This error code is experimental and may be changed or removed without notice.
|
* This error code is experimental and may be changed or removed without notice.
|
||||||
*/
|
*/
|
||||||
#define MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET -0x7B00
|
#define MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET -0x7B00
|
||||||
/* Error space gap */
|
/** Not possible to read early data */
|
||||||
/* Error space gap */
|
#define MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA -0x7B80
|
||||||
/* Error space gap */
|
/** Not possible to write early data */
|
||||||
/* Error space gap */
|
#define MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA -0x7C00
|
||||||
/* Error space gap */
|
/* Error space gap */
|
||||||
/* Error space gap */
|
/* Error space gap */
|
||||||
/* Error space gap */
|
/* Error space gap */
|
||||||
@ -806,14 +807,6 @@ typedef struct mbedtls_ssl_key_cert mbedtls_ssl_key_cert;
|
|||||||
typedef struct mbedtls_ssl_flight_item mbedtls_ssl_flight_item;
|
typedef struct mbedtls_ssl_flight_item mbedtls_ssl_flight_item;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C)
|
|
||||||
#define MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN 0
|
|
||||||
#define MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT 1
|
|
||||||
#define MBEDTLS_SSL_EARLY_DATA_STATUS_INDICATION_SENT 2
|
|
||||||
#define MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED 3
|
|
||||||
#define MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED 4
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS)
|
#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS)
|
||||||
typedef uint8_t mbedtls_ssl_tls13_ticket_flags;
|
typedef uint8_t mbedtls_ssl_tls13_ticket_flags;
|
||||||
|
|
||||||
@ -4897,6 +4890,151 @@ int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl,
|
|||||||
*/
|
*/
|
||||||
int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl );
|
int mbedtls_ssl_close_notify( mbedtls_ssl_context *ssl );
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_SSL_EARLY_DATA)
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_SSL_SRV_C)
|
||||||
|
/**
|
||||||
|
* \brief Read at most 'len' application data bytes while performing
|
||||||
|
* the handshake (early data).
|
||||||
|
*
|
||||||
|
* \note This function behaves mainly as mbedtls_ssl_read(). The
|
||||||
|
* specification of mbedtls_ssl_read() relevant to TLS 1.3
|
||||||
|
* (thus not the parts specific to (D)TLS 1.2) applies to this
|
||||||
|
* function and the present documentation is restricted to the
|
||||||
|
* differences with mbedtls_ssl_read().
|
||||||
|
*
|
||||||
|
* \param ssl SSL context
|
||||||
|
* \param buf buffer that will hold the data
|
||||||
|
* \param len maximum number of bytes to read
|
||||||
|
*
|
||||||
|
* \return One additional specific return value:
|
||||||
|
* #MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA.
|
||||||
|
*
|
||||||
|
* #MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA is returned when it
|
||||||
|
* is not possible to read early data for the SSL context
|
||||||
|
* \p ssl.
|
||||||
|
*
|
||||||
|
* It may have been possible and it is not possible
|
||||||
|
* anymore because the server received the End of Early Data
|
||||||
|
* message or the maximum number of allowed early data for the
|
||||||
|
* PSK in use has been reached.
|
||||||
|
*
|
||||||
|
* It may never have been possible and will never be possible
|
||||||
|
* for the SSL context \p ssl because the use of early data
|
||||||
|
* is disabled for that context or more generally the context
|
||||||
|
* is not suitably configured to enable early data or the
|
||||||
|
* client does not use early data or the first call to the
|
||||||
|
* function was done while the handshake was already too
|
||||||
|
* advanced to gather and accept early data.
|
||||||
|
*
|
||||||
|
* It is not possible to read early data for the SSL context
|
||||||
|
* \p ssl but this does not preclude for using it with
|
||||||
|
* mbedtls_ssl_write(), mbedtls_ssl_read() or
|
||||||
|
* mbedtls_ssl_handshake().
|
||||||
|
*
|
||||||
|
* \note When a server wants to retrieve early data, it is expected
|
||||||
|
* that this function starts the handshake for the SSL context
|
||||||
|
* \p ssl. But this is not mandatory.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int mbedtls_ssl_read_early_data( mbedtls_ssl_context *ssl,
|
||||||
|
unsigned char *buf, size_t len );
|
||||||
|
#endif /* MBEDTLS_SSL_SRV_C */
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_SSL_CLI_C)
|
||||||
|
/**
|
||||||
|
* \brief Try to write exactly 'len' application data bytes while
|
||||||
|
* performing the handshake (early data).
|
||||||
|
*
|
||||||
|
* \note This function behaves mainly as mbedtls_ssl_write(). The
|
||||||
|
* specification of mbedtls_ssl_write() relevant to TLS 1.3
|
||||||
|
* (thus not the parts specific to (D)TLS1.2) applies to this
|
||||||
|
* function and the present documentation is restricted to the
|
||||||
|
* differences with mbedtls_ssl_write().
|
||||||
|
*
|
||||||
|
* \param ssl SSL context
|
||||||
|
* \param buf buffer holding the data
|
||||||
|
* \param len how many bytes must be written
|
||||||
|
*
|
||||||
|
* \return One additional specific return value:
|
||||||
|
* #MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA.
|
||||||
|
*
|
||||||
|
* #MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA is returned when it
|
||||||
|
* is not possible to write early data for the SSL context
|
||||||
|
* \p ssl.
|
||||||
|
*
|
||||||
|
* It may have been possible and it is not possible
|
||||||
|
* anymore because the client received the server Finished
|
||||||
|
* message, the server rejected early data or the maximum
|
||||||
|
* number of allowed early data for the PSK in use has been
|
||||||
|
* reached.
|
||||||
|
*
|
||||||
|
* It may never have been possible and will never be possible
|
||||||
|
* for the SSL context \p ssl because the use of early data
|
||||||
|
* is disabled for that context or more generally the context
|
||||||
|
* is not suitably configured to enable early data or the first
|
||||||
|
* call to the function was done while the handshake was
|
||||||
|
* already completed.
|
||||||
|
*
|
||||||
|
* It is not possible to write early data for the SSL context
|
||||||
|
* \p ssl but this does not preclude for using it with
|
||||||
|
* mbedtls_ssl_write(), mbedtls_ssl_read() or
|
||||||
|
* mbedtls_ssl_handshake().
|
||||||
|
*
|
||||||
|
* \note This function may write early data only if the SSL context
|
||||||
|
* has been configured for the handshake with a PSK for which
|
||||||
|
* early data is allowed.
|
||||||
|
*
|
||||||
|
* \note To maximize the number of early data that can be written in
|
||||||
|
* the course of the handshake, it is expected that this
|
||||||
|
* function starts the handshake for the SSL context \p ssl.
|
||||||
|
* But this is not mandatory.
|
||||||
|
*
|
||||||
|
* \note This function does not provide any information on whether
|
||||||
|
* the server has accepted or will accept early data or not.
|
||||||
|
* When it returns a positive value, it just means that it
|
||||||
|
* has written early data to the server. To know whether the
|
||||||
|
* server has accepted early data or not, you should call
|
||||||
|
* mbedtls_ssl_get_early_data_status() with the handshake
|
||||||
|
* completed.
|
||||||
|
*/
|
||||||
|
int mbedtls_ssl_write_early_data( mbedtls_ssl_context *ssl,
|
||||||
|
const unsigned char *buf, size_t len );
|
||||||
|
|
||||||
|
#define MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT 0
|
||||||
|
#define MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED 1
|
||||||
|
#define MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED 2
|
||||||
|
/**
|
||||||
|
* \brief Get the status of the negotiation of the use of early data.
|
||||||
|
*
|
||||||
|
* \param ssl The SSL context to query
|
||||||
|
*
|
||||||
|
* \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if this function is called
|
||||||
|
* from the server-side.
|
||||||
|
*
|
||||||
|
* \return #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if this function is called
|
||||||
|
* prior to completion of the handshake.
|
||||||
|
*
|
||||||
|
* \return #MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT if the client has
|
||||||
|
* not indicated the use of early data to the server.
|
||||||
|
*
|
||||||
|
* \return #MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED if the client has
|
||||||
|
* indicated the use of early data and the server has accepted
|
||||||
|
* it.
|
||||||
|
*
|
||||||
|
* \return #MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED if the client has
|
||||||
|
* indicated the use of early data but the server has rejected
|
||||||
|
* it. In this situation, the client may want to re-send the
|
||||||
|
* early data it may have tried to send by calling
|
||||||
|
* mbedtls_ssl_write_early_data() as ordinary post-handshake
|
||||||
|
* application data by calling mbedtls_ssl_write().
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int mbedtls_ssl_get_early_data_status( mbedtls_ssl_context *ssl );
|
||||||
|
#endif /* MBEDTLS_SSL_CLI_C */
|
||||||
|
|
||||||
|
#endif /* MBEDTLS_SSL_EARLY_DATA */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Free referenced items in an SSL context and clear memory
|
* \brief Free referenced items in an SSL context and clear memory
|
||||||
*
|
*
|
||||||
|
@ -1183,11 +1183,11 @@ int mbedtls_ssl_tls13_write_client_hello_exts( mbedtls_ssl_context *ssl,
|
|||||||
return( ret );
|
return( ret );
|
||||||
p += ext_len;
|
p += ext_len;
|
||||||
|
|
||||||
/* Initializes the status to `indication sent`. It will be updated to
|
/* Initializes the status to `rejected`. It will be updated to
|
||||||
* `accepted` or `rejected` depending on whether the EncryptedExtension
|
* `accepted` if the EncryptedExtension message contain an early data
|
||||||
* message will contain an early data indication extension or not.
|
* indication extension.
|
||||||
*/
|
*/
|
||||||
ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_INDICATION_SENT;
|
ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user