Merge pull request #8224 from julek-wolfssl/dtls-server-demux

DTLS: Add server side stateless and CID QoL API
pull/8312/head
JacobBarthelmeh 2024-12-23 10:01:01 -07:00 committed by GitHub
commit 2409971b14
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 1097 additions and 133 deletions

View File

@ -78,4 +78,4 @@ jobs:
run: |
export LD_LIBRARY_PATH=$GITHUB_WORKSPACE/build-dir/lib:$LD_LIBRARY_PATH
export SHELL=/bin/bash
SOCAT=$GITHUB_WORKSPACE/socat-1.8.0.0/socat ./test.sh -t 0.5 --expect-fail 36,64,146,214,216,217,309,310,386,399,402,403,459,460,467,468,478,492,528,530
SOCAT=$GITHUB_WORKSPACE/socat-1.8.0.0/socat ./test.sh -t 0.5 --expect-fail 36,64,146,214,216,217,309,310,386,399,402,403,459,460,467,468,475,478,492,528,530

View File

@ -1997,8 +1997,8 @@ const char* wolfSSL_get_cipher_name(WOLFSSL* ssl);
/*!
\ingroup IO
\brief This function returns the file descriptor (fd) used as the
input/output facility for the SSL connection. Typically this
\brief This function returns the read file descriptor (fd) used as the
input facility for the SSL connection. Typically this
will be a socket file descriptor.
\return fd If successful the call will return the SSL session file
@ -2016,9 +2016,38 @@ const char* wolfSSL_get_cipher_name(WOLFSSL* ssl);
\endcode
\sa wolfSSL_set_fd
\sa wolfSSL_set_read_fd
\sa wolfSSL_set_write_fd
*/
int wolfSSL_get_fd(const WOLFSSL*);
/*!
\ingroup IO
\brief This function returns the write file descriptor (fd) used as the
output facility for the SSL connection. Typically this
will be a socket file descriptor.
\return fd If successful the call will return the SSL session file
descriptor.
\param ssl pointer to the SSL session, created with wolfSSL_new().
_Example_
\code
int sockfd;
WOLFSSL* ssl = 0;
...
sockfd = wolfSSL_get_wfd(ssl);
...
\endcode
\sa wolfSSL_set_fd
\sa wolfSSL_set_read_fd
\sa wolfSSL_set_write_fd
*/
int wolfSSL_get_wfd(const WOLFSSL*);
/*!
\ingroup Setup
@ -2289,6 +2318,48 @@ int wolfSSL_peek(WOLFSSL* ssl, void* data, int sz);
*/
int wolfSSL_accept(WOLFSSL*);
/*!
\ingroup IO
\brief This function is called on the server side and statelessly listens
for an SSL client to initiate the DTLS handshake.
\return WOLFSSL_SUCCESS ClientHello containing a valid cookie was received.
The connection can be continued with wolfSSL_accept().
\return WOLFSSL_FAILURE The I/O layer returned WANT_READ. This is either
because there is no data to read and we are using non-blocking sockets or
we sent a cookie request and we are waiting for a reply. The user should
call wolfDTLS_accept_stateless again after data becomes available in
the I/O layer.
\return WOLFSSL_FATAL_ERROR A fatal error occurred. The ssl object should be
free'd and allocated again to continue.
\param ssl a pointer to a WOLFSSL structure, created using wolfSSL_new().
_Example_
\code
int ret = 0;
int err = 0;
WOLFSSL* ssl;
...
do {
ret = wolfDTLS_accept_stateless(ssl);
if (ret == WOLFSSL_FATAL_ERROR)
// re-allocate the ssl object with wolfSSL_free() and wolfSSL_new()
} while (ret != WOLFSSL_SUCCESS);
ret = wolfSSL_accept(ssl);
if (ret != SSL_SUCCESS) {
err = wolfSSL_get_error(ssl, ret);
printf(error = %d, %s\n, err, wolfSSL_ERR_error_string(err, buffer));
}
\endcode
\sa wolfSSL_accept
\sa wolfSSL_get_error
\sa wolfSSL_connect
*/
int wolfDTLS_accept_stateless(WOLFSSL* ssl);
/*!
\ingroup Setup
@ -3856,12 +3927,53 @@ int wolfSSL_dtls(WOLFSSL* ssl);
\endcode
\sa wolfSSL_dtls_get_current_timeout
\sa wolfSSL_dtls_set_pending_peer
\sa wolfSSL_dtls_get_peer
\sa wolfSSL_dtls_got_timeout
\sa wolfSSL_dtls
*/
int wolfSSL_dtls_set_peer(WOLFSSL* ssl, void* peer, unsigned int peerSz);
/*!
\brief This function sets the pending DTLS peer, peer (sockaddr_in) with
size of peerSz. This sets the pending peer that will be upgraded to a
regular peer when we successfully de-protect the next record. This is useful
in scenarios where the peer's address can change to avoid off-path attackers
from changing the peer address. This should be used with Connection ID's to
allow seamless and safe transition to a new peer address.
\return SSL_SUCCESS will be returned upon success.
\return SSL_FAILURE will be returned upon failure.
\return SSL_NOT_IMPLEMENTED will be returned if wolfSSL was not compiled
with DTLS support.
\param ssl a pointer to a WOLFSSL structure, created using wolfSSL_new().
\param peer pointer to peers sockaddr_in structure. If NULL then the peer
information in ssl is cleared.
\param peerSz size of the sockaddr_in structure pointed to by peer. If 0
then the peer information in ssl is cleared.
_Example_
\code
int ret = 0;
WOLFSSL* ssl;
sockaddr_in addr;
...
ret = wolfSSL_dtls_set_pending_peer(ssl, &addr, sizeof(addr));
if (ret != SSL_SUCCESS) {
// failed to set DTLS peer
}
\endcode
\sa wolfSSL_dtls_get_current_timeout
\sa wolfSSL_dtls_set_peer
\sa wolfSSL_dtls_get_peer
\sa wolfSSL_dtls_got_timeout
\sa wolfSSL_dtls
*/
int wolfSSL_dtls_set_pending_peer(WOLFSSL* ssl, void* peer,
unsigned int peerSz);
/*!
\brief This function gets the sockaddr_in (of size peerSz) of the current
DTLS peer. The function will compare peerSz to the actual DTLS peer size
@ -3899,6 +4011,41 @@ int wolfSSL_dtls_set_peer(WOLFSSL* ssl, void* peer, unsigned int peerSz);
*/
int wolfSSL_dtls_get_peer(WOLFSSL* ssl, void* peer, unsigned int* peerSz);
/*!
\brief This function gets the sockaddr_in (of size peerSz) of the current
DTLS peer. This is a zero-copy alternative to wolfSSL_dtls_get_peer().
\return SSL_SUCCESS will be returned upon success.
\return SSL_FAILURE will be returned upon failure.
\return SSL_NOT_IMPLEMENTED will be returned if wolfSSL was not compiled
with DTLS support.
\param ssl a pointer to a WOLFSSL structure, created using wolfSSL_new().
\param peer pointer to return the internal buffer holding the peer address
\param peerSz output the size of the actual sockaddr_in structure
pointed to by peer.
_Example_
\code
int ret = 0;
WOLFSSL* ssl;
sockaddr_in* addr;
unsigned int addrSz;
...
ret = wolfSSL_dtls_get_peer(ssl, &addr, &addrSz);
if (ret != SSL_SUCCESS) {
// failed to get DTLS peer
}
\endcode
\sa wolfSSL_dtls_get_current_timeout
\sa wolfSSL_dtls_got_timeout
\sa wolfSSL_dtls_set_peer
\sa wolfSSL_dtls
*/
int wolfSSL_dtls_get0_peer(WOLFSSL* ssl, const void** peer,
unsigned int* peerSz);
/*!
\ingroup Debug
@ -14138,6 +14285,39 @@ int wolfSSL_write_early_data(WOLFSSL* ssl, const void* data,
int wolfSSL_read_early_data(WOLFSSL* ssl, void* data, int sz,
int* outSz);
/*!
\ingroup IO
\brief This function is called to inject data into the WOLFSSL object. This
is useful when data needs to be read from a single place and demultiplexed
into multiple connections. The caller should then call wolfSSL_read() to
extract the plaintext data from the WOLFSSL object.
\param [in] ssl a pointer to a WOLFSSL structure, created using
wolfSSL_new().
\param [in] data data to inject into the ssl object.
\param [in] sz number of bytes of data to inject.
\return BAD_FUNC_ARG if any pointer parameter is NULL or sz <= 0
\return APP_DATA_READY if there is application data left to read
\return MEMORY_E if allocation fails
\return WOLFSSL_SUCCESS on success
_Example_
\code
byte buf[2000]
sz = recv(fd, buf, sizeof(buf), 0);
if (sz <= 0)
// error
if (wolfSSL_inject(ssl, buf, sz) != WOLFSSL_SUCCESS)
// error
sz = wolfSSL_read(ssl, buf, sizeof(buf);
\endcode
\sa wolfSSL_read
*/
int wolfSSL_inject(WOLFSSL* ssl, const void* data, int sz);
/*!
\ingroup Setup
@ -14955,6 +15135,7 @@ connection into the buffer pointed by the parameter buffer. See RFC 9146 and RFC
\param buffer A buffer where the ConnectionID will be copied
\param bufferSz available space in buffer
\sa wolfSSL_dtls_cid_get0_rx
\sa wolfSSL_dtls_cid_use
\sa wolfSSL_dtls_cid_is_enabled
\sa wolfSSL_dtls_cid_set
@ -14967,6 +15148,26 @@ int wolfSSL_dtls_cid_get_rx(WOLFSSL* ssl, unsigned char* buffer,
/*!
\brief Get the ConnectionID used by the other peer. See RFC 9146 and RFC
9147.
\return WOLFSSL_SUCCESS if ConnectionID was correctly set in cid.
\param ssl A WOLFSSL object pointern
\param cid Pointer that will be set to the internal memory that holds the CID
\sa wolfSSL_dtls_cid_get_rx
\sa wolfSSL_dtls_cid_use
\sa wolfSSL_dtls_cid_is_enabled
\sa wolfSSL_dtls_cid_set
\sa wolfSSL_dtls_cid_get_rx_size
\sa wolfSSL_dtls_cid_get_tx_size
\sa wolfSSL_dtls_cid_get_tx
*/
int wolfSSL_dtls_cid_get0_rx(WOLFSSL* ssl, unsigned char** cid);
/*!
\brief Get the size of the ConnectionID used to send records in this
connection. See RFC 9146 and RFC 9147. The size is stored in the parameter size.
@ -14998,6 +15199,7 @@ available size need to be provided in bufferSz.
\param buffer A buffer where the ConnectionID will be copied
\param bufferSz available space in buffer
\sa wolfSSL_dtls_cid_get0_tx
\sa wolfSSL_dtls_cid_use
\sa wolfSSL_dtls_cid_is_enabled
\sa wolfSSL_dtls_cid_set
@ -15008,6 +15210,50 @@ available size need to be provided in bufferSz.
int wolfSSL_dtls_cid_get_tx(WOLFSSL* ssl, unsigned char* buffer,
unsigned int bufferSz);
/*!
\brief Get the ConnectionID used when sending records in this connection. See
RFC 9146 and RFC 9147.
\return WOLFSSL_SUCCESS if ConnectionID was correctly retrieved, error code
otherwise
\param ssl A WOLFSSL object pointern
\param cid Pointer that will be set to the internal memory that holds the CID
\sa wolfSSL_dtls_cid_get_tx
\sa wolfSSL_dtls_cid_use
\sa wolfSSL_dtls_cid_is_enabled
\sa wolfSSL_dtls_cid_set
\sa wolfSSL_dtls_cid_get_rx_size
\sa wolfSSL_dtls_cid_get_rx
\sa wolfSSL_dtls_cid_get_tx_size
*/
int wolfSSL_dtls_cid_get0_tx(WOLFSSL* ssl, unsigned char** cid);
/*!
\brief Extract the ConnectionID from a record datagram/message. See
RFC 9146 and RFC 9147.
\param msg buffer holding the datagram read from the network
\param msgSz size of msg in bytes
\param cid pointer to the start of the CID inside the msg buffer
\param cidSz the expected size of the CID. The record layer does not have a CID
size field so we have to know beforehand the size of the CID. It is recommended
to use a constant CID for all connections.
\sa wolfSSL_dtls_cid_get_tx
\sa wolfSSL_dtls_cid_use
\sa wolfSSL_dtls_cid_is_enabled
\sa wolfSSL_dtls_cid_set
\sa wolfSSL_dtls_cid_get_rx_size
\sa wolfSSL_dtls_cid_get_rx
\sa wolfSSL_dtls_cid_get_tx_size
*/
void wolfSSL_dtls_cid_parse(const unsigned char* msg, unsigned int msgSz,
const unsigned char** cid, unsigned int cidSz);
/*!
\ingroup TLS

View File

@ -575,3 +575,46 @@ int wolfSSL_SetIO_ISOTP(WOLFSSL *ssl, isotp_wolfssl_ctx *ctx,
can_recv_fn recv_fn, can_send_fn send_fn, can_delay_fn delay_fn,
word32 receive_delay, char *receive_buffer, int receive_buffer_size,
void *arg);
/*!
\ingroup Setup
\brief This function disables reading from the IO layer.
\param ssl the wolfSSL context
_Example_
\code
WOLFSSL_CTX* ctx = wolfSSL_CTX_new(method);
WOLFSSL* ssl = wolfSSL_new(ctx);
wolfSSL_SSLDisableRead(ssl);
\endcode
\sa wolfSSL_CTX_SetIORecv
\sa wolfSSL_SSLSetIORecv
\sa wolfSSL_SSLEnableRead
*/
void wolfSSL_SSLDisableRead(WOLFSSL *ssl);
/*!
\ingroup Setup
\brief This function enables reading from the IO layer. Reading is enabled
by default and should be used to undo wolfSSL_SSLDisableRead();
\param ssl the wolfSSL context
_Example_
\code
WOLFSSL_CTX* ctx = wolfSSL_CTX_new(method);
WOLFSSL* ssl = wolfSSL_new(ctx);
wolfSSL_SSLDisableRead(ssl);
...
wolfSSL_SSLEnableRead(ssl);
\endcode
\sa wolfSSL_CTX_SetIORecv
\sa wolfSSL_SSLSetIORecv
\sa wolfSSL_SSLEnableRead
*/
void wolfSSL_SSLEnableRead(WOLFSSL *ssl);

View File

@ -2404,7 +2404,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
err_sys("provided connection ID is too big");
}
else {
strcpy(dtlsCID, myoptarg);
XSTRLCPY(dtlsCID, myoptarg, DTLS_CID_BUFFER_SIZE);
}
}
break;

View File

@ -2423,7 +2423,7 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
err_sys("provided connection ID is too big");
}
else {
strcpy(dtlsCID, myoptarg);
XSTRLCPY(dtlsCID, myoptarg, DTLS_CID_BUFFER_SIZE);
}
}
break;

View File

@ -101,6 +101,15 @@ void DtlsResetState(WOLFSSL* ssl)
ssl->options.tls = 0;
ssl->options.tls1_1 = 0;
ssl->options.tls1_3 = 0;
#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_DTLS_CID)
ssl->buffers.dtlsCtx.processingPendingRecord = 0;
/* Clear the pending peer in case user set */
XFREE(ssl->buffers.dtlsCtx.pendingPeer.sa, ssl->heap,
DYNAMIC_TYPE_SOCKADDR);
ssl->buffers.dtlsCtx.pendingPeer.sa = NULL;
ssl->buffers.dtlsCtx.pendingPeer.sz = 0;
ssl->buffers.dtlsCtx.pendingPeer.bufSz = 0;
#endif
}
int DtlsIgnoreError(int err)
@ -221,6 +230,7 @@ static int CreateDtls12Cookie(const WOLFSSL* ssl, const WolfSSL_CH* ch,
ssl->buffers.dtlsCookieSecret.buffer,
ssl->buffers.dtlsCookieSecret.length);
if (ret == 0) {
/* peerLock not necessary. Still in handshake phase. */
ret = wc_HmacUpdate(&cookieHmac,
(const byte*)ssl->buffers.dtlsCtx.peer.sa,
ssl->buffers.dtlsCtx.peer.sz);
@ -1108,6 +1118,26 @@ static int DtlsCidGet(WOLFSSL* ssl, unsigned char* buf, int bufferSz, int rx)
return WOLFSSL_SUCCESS;
}
static int DtlsCidGet0(WOLFSSL* ssl, unsigned char** cid, int rx)
{
ConnectionID* id;
CIDInfo* info;
if (ssl == NULL || cid == NULL)
return BAD_FUNC_ARG;
info = DtlsCidGetInfo(ssl);
if (info == NULL)
return WOLFSSL_FAILURE;
id = rx ? info->rx : info->tx;
if (id == NULL || id->length == 0)
return WOLFSSL_SUCCESS;
*cid = id->id;
return WOLFSSL_SUCCESS;
}
static CIDInfo* DtlsCidGetInfoFromExt(byte* ext)
{
WOLFSSL** sslPtr;
@ -1366,6 +1396,11 @@ int wolfSSL_dtls_cid_get_rx(WOLFSSL* ssl, unsigned char* buf,
return DtlsCidGet(ssl, buf, bufferSz, 1);
}
int wolfSSL_dtls_cid_get0_rx(WOLFSSL* ssl, unsigned char** cid)
{
return DtlsCidGet0(ssl, cid, 1);
}
int wolfSSL_dtls_cid_get_tx_size(WOLFSSL* ssl, unsigned int* size)
{
return DtlsCidGetSize(ssl, size, 0);
@ -1377,10 +1412,40 @@ int wolfSSL_dtls_cid_get_tx(WOLFSSL* ssl, unsigned char* buf,
return DtlsCidGet(ssl, buf, bufferSz, 0);
}
int wolfSSL_dtls_cid_get0_tx(WOLFSSL* ssl, unsigned char** cid)
{
return DtlsCidGet0(ssl, cid, 0);
}
int wolfSSL_dtls_cid_max_size(void)
{
return DTLS_CID_MAX_SIZE;
}
const unsigned char* wolfSSL_dtls_cid_parse(const unsigned char* msg,
unsigned int msgSz, unsigned int cidSz)
{
/* we need at least the first byte to check version */
if (msg == NULL || cidSz == 0 || msgSz < OPAQUE8_LEN + cidSz)
return NULL;
if (msg[0] == dtls12_cid) {
/* DTLS 1.2 CID packet */
if (msgSz < DTLS_RECORD_HEADER_SZ + cidSz)
return NULL;
/* content type(1) + version(2) + epoch(2) + sequence(6) */
return msg + ENUM_LEN + VERSION_SZ + OPAQUE16_LEN + OPAQUE16_LEN +
OPAQUE32_LEN;
}
#ifdef WOLFSSL_DTLS13
else if (Dtls13UnifiedHeaderCIDPresent(msg[0])) {
/* DTLS 1.3 CID packet */
if (msgSz < OPAQUE8_LEN + cidSz)
return NULL;
return msg + OPAQUE8_LEN;
}
#endif
return NULL;
}
#endif /* WOLFSSL_DTLS_CID */
byte DtlsGetCidTxSize(WOLFSSL* ssl)
@ -1413,6 +1478,11 @@ byte DtlsGetCidRxSize(WOLFSSL* ssl)
#endif
}
byte wolfSSL_is_stateful(WOLFSSL* ssl)
{
return (byte)(ssl != NULL ? ssl->options.dtlsStateful : 0);
}
#endif /* WOLFSSL_DTLS */
#endif /* WOLFCRYPT_ONLY */

View File

@ -1151,6 +1151,11 @@ static int Dtls13UnifiedHeaderParseCID(WOLFSSL* ssl, byte flags,
return 0;
}
int Dtls13UnifiedHeaderCIDPresent(byte flags)
{
return Dtls13IsUnifiedHeader(flags) && (flags & DTLS13_CID_BIT);
}
#else
#define Dtls13AddCID(a, b, c, d) 0
#define Dtls13UnifiedHeaderParseCID(a, b, c, d, e) 0

View File

@ -7621,6 +7621,11 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
ssl->buffers.dtlsCtx.rfd = -1;
ssl->buffers.dtlsCtx.wfd = -1;
#ifdef WOLFSSL_RW_THREADED
if (wc_InitRwLock(&ssl->buffers.dtlsCtx.peerLock) != 0)
return BAD_MUTEX_E;
#endif
ssl->IOCB_ReadCtx = &ssl->buffers.dtlsCtx; /* prevent invalid pointer access if not */
ssl->IOCB_WriteCtx = &ssl->buffers.dtlsCtx; /* correctly set */
#else
@ -8493,6 +8498,14 @@ void wolfSSL_ResourceFree(WOLFSSL* ssl)
}
XFREE(ssl->buffers.dtlsCtx.peer.sa, ssl->heap, DYNAMIC_TYPE_SOCKADDR);
ssl->buffers.dtlsCtx.peer.sa = NULL;
#ifdef WOLFSSL_RW_THREADED
wc_FreeRwLock(&ssl->buffers.dtlsCtx.peerLock);
#endif
#ifdef WOLFSSL_DTLS_CID
XFREE(ssl->buffers.dtlsCtx.pendingPeer.sa, ssl->heap,
DYNAMIC_TYPE_SOCKADDR);
ssl->buffers.dtlsCtx.pendingPeer.sa = NULL;
#endif
#ifndef NO_WOLFSSL_SERVER
if (ssl->buffers.dtlsCookieSecret.buffer != NULL) {
ForceZero(ssl->buffers.dtlsCookieSecret.buffer,
@ -10813,7 +10826,7 @@ retry:
}
}
#endif
goto retry;
return WOLFSSL_FATAL_ERROR;
case WC_NO_ERR_TRACE(WOLFSSL_CBIO_ERR_CONN_CLOSE):
ssl->options.isClosed = 1;
@ -11754,15 +11767,14 @@ static int GetDtlsRecordHeader(WOLFSSL* ssl, word32* inOutIdx,
#ifdef WOLFSSL_DTLS_CID
if (rh->type == dtls12_cid) {
byte cid[DTLS_CID_MAX_SIZE];
byte* ourCid = NULL;
if (ssl->buffers.inputBuffer.length - *inOutIdx <
(word32)cidSz + LENGTH_SZ)
return LENGTH_ERROR;
if (cidSz > DTLS_CID_MAX_SIZE ||
wolfSSL_dtls_cid_get_rx(ssl, cid, cidSz) != WOLFSSL_SUCCESS)
if (wolfSSL_dtls_cid_get0_rx(ssl, &ourCid) != WOLFSSL_SUCCESS)
return DTLS_CID_ERROR;
if (XMEMCMP(ssl->buffers.inputBuffer.buffer + *inOutIdx,
cid, cidSz) != 0)
if (XMEMCMP(ssl->buffers.inputBuffer.buffer + *inOutIdx, ourCid, cidSz)
!= 0)
return DTLS_CID_ERROR;
*inOutIdx += cidSz;
}
@ -11972,7 +11984,7 @@ int GetDtlsHandShakeHeader(WOLFSSL* ssl, const byte* input,
{
word32 idx = *inOutIdx;
*inOutIdx += HANDSHAKE_HEADER_SZ + DTLS_HANDSHAKE_EXTRA;
*inOutIdx += DTLS_HANDSHAKE_HEADER_SZ;
if (*inOutIdx > totalSz) {
WOLFSSL_ERROR(BUFFER_E);
return BUFFER_E;
@ -21277,11 +21289,14 @@ static int GetInputData(WOLFSSL *ssl, word32 size)
int usedLength;
int dtlsExtra = 0;
if (ssl->options.disableRead)
return WC_NO_ERR_TRACE(WANT_READ);
/* check max input length */
usedLength = (int)(ssl->buffers.inputBuffer.length - ssl->buffers.inputBuffer.idx);
maxLength = (int)(ssl->buffers.inputBuffer.bufferSize - (word32)usedLength);
inSz = (int)(size - (word32)usedLength); /* from last partial read */
usedLength = (int)(ssl->buffers.inputBuffer.length -
ssl->buffers.inputBuffer.idx);
maxLength = (int)(ssl->buffers.inputBuffer.bufferSize -
(word32)usedLength);
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls && IsDtlsNotSctpMode(ssl)) {
@ -21295,13 +21310,22 @@ static int GetInputData(WOLFSSL *ssl, word32 size)
if (size < (word32)inSz)
dtlsExtra = (int)(inSz - size);
}
else
#endif
{
/* check that no lengths or size values are negative */
if (usedLength < 0 || maxLength < 0 || inSz <= 0) {
if (usedLength < 0 || maxLength < 0) {
return BUFFER_ERROR;
}
/* Return if we have enough data already in the buffer */
if (size <= (word32)usedLength) {
return 0;
}
inSz = (int)(size - (word32)usedLength); /* from last partial read */
}
if (inSz > maxLength) {
if (GrowInputBuffer(ssl, (int)(size + (word32)dtlsExtra), usedLength) < 0)
return MEMORY_E;
@ -21533,7 +21557,8 @@ static int DtlsShouldDrop(WOLFSSL* ssl, int retcode)
}
#endif /* WOLFSSL_DTLS */
#if defined(WOLFSSL_TLS13) || defined(WOLFSSL_DTLS) && defined(WOLFSSL_DTLS_CID)
#if defined(WOLFSSL_TLS13) || \
(defined(WOLFSSL_DTLS) && defined(WOLFSSL_DTLS_CID))
static int removeMsgInnerPadding(WOLFSSL* ssl)
{
word32 i = ssl->buffers.inputBuffer.idx +
@ -21565,16 +21590,58 @@ static int removeMsgInnerPadding(WOLFSSL* ssl)
}
#endif
int ProcessReply(WOLFSSL* ssl)
#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_DTLS_CID)
static void dtlsClearPeer(WOLFSSL_SOCKADDR* peer)
{
return ProcessReplyEx(ssl, 0);
XFREE(peer->sa, NULL, DYNAMIC_TYPE_SOCKADDR);
peer->sa = NULL;
peer->sz = 0;
peer->bufSz = 0;
}
/**
* @brief Handle pending peer during record processing.
* @param ssl WOLFSSL object.
* @param deprotected 0 when we have not decrypted the record yet
* 1 when we have decrypted and verified the record
*/
static void dtlsProcessPendingPeer(WOLFSSL* ssl, int deprotected)
{
if (ssl->buffers.dtlsCtx.pendingPeer.sa != NULL) {
if (!deprotected) {
/* Here we have just read an entire record from the network. It is
* still encrypted. If processingPendingRecord is set then that
* means that an error occurred when processing the previous record.
* In that case we should clear the pendingPeer because we only
* want to allow it to be valid for one record. */
if (ssl->buffers.dtlsCtx.processingPendingRecord) {
/* Clear the pending peer. */
dtlsClearPeer(&ssl->buffers.dtlsCtx.pendingPeer);
}
ssl->buffers.dtlsCtx.processingPendingRecord =
!ssl->buffers.dtlsCtx.processingPendingRecord;
}
else {
/* Pending peer present and record deprotected. Update the peer. */
(void)wolfSSL_dtls_set_peer(ssl,
&ssl->buffers.dtlsCtx.pendingPeer.sa,
ssl->buffers.dtlsCtx.pendingPeer.sz);
ssl->buffers.dtlsCtx.processingPendingRecord = 0;
dtlsClearPeer(&ssl->buffers.dtlsCtx.pendingPeer);
}
}
else {
ssl->buffers.dtlsCtx.processingPendingRecord = 0;
}
}
#endif
/* Process input requests. Return 0 is done, 1 is call again to complete, and
negative number is error. If allowSocketErr is set, SOCKET_ERROR_E in
ssl->error will be whitelisted. This is useful when the connection has been
closed and the endpoint wants to check for an alert sent by the other end. */
int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
static int DoProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
{
int ret = 0, type = internal_error, readSz;
int atomicUser = 0;
@ -21773,6 +21840,10 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
&ssl->curRL, &ssl->curSize);
#ifdef WOLFSSL_DTLS
#ifdef WOLFSSL_DTLS_CID
if (ssl->options.dtls)
dtlsProcessPendingPeer(ssl, 0);
#endif
if (ssl->options.dtls && DtlsShouldDrop(ssl, ret)) {
ssl->options.processReply = doProcessInit;
ssl->buffers.inputBuffer.length = 0;
@ -22152,7 +22223,8 @@ default:
}
if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 1) {
#if defined(WOLFSSL_TLS13) || defined(WOLFSSL_DTLS) && defined(WOLFSSL_DTLS_CID)
#if defined(WOLFSSL_TLS13) || \
(defined(WOLFSSL_DTLS) && defined(WOLFSSL_DTLS_CID))
int removePadding = 0;
if (ssl->options.tls1_3)
removePadding = 1;
@ -22197,8 +22269,9 @@ default:
/* the record layer is here */
case runProcessingOneRecord:
#ifdef WOLFSSL_DTLS13
#ifdef WOLFSSL_DTLS
if (ssl->options.dtls) {
#ifdef WOLFSSL_DTLS13
if (IsAtLeastTLSv1_3(ssl->version)) {
if (!Dtls13CheckWindow(ssl)) {
/* drop packet */
@ -22222,11 +22295,18 @@ default:
}
}
}
else if (IsDtlsNotSctpMode(ssl)) {
else
#endif /* WOLFSSL_DTLS13 */
if (IsDtlsNotSctpMode(ssl)) {
DtlsUpdateWindow(ssl);
}
#ifdef WOLFSSL_DTLS_CID
/* Update the peer if we were able to de-protect the message */
if (IsEncryptionOn(ssl, 0))
dtlsProcessPendingPeer(ssl, 1);
#endif
}
#endif /* WOLFSSL_DTLS13 */
#endif /* WOLFSSL_DTLS */
ssl->options.processReply = runProcessingOneMessage;
FALL_THROUGH;
@ -22694,6 +22774,35 @@ default:
}
}
int ProcessReply(WOLFSSL* ssl)
{
return ProcessReplyEx(ssl, 0);
}
int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
{
int ret;
ret = DoProcessReplyEx(ssl, allowSocketErr);
#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_DTLS_CID)
if (ssl->options.dtls) {
/* Don't clear pending peer if we are going to re-enter
* DoProcessReplyEx */
if (ret != WC_NO_ERR_TRACE(WANT_READ)
#ifdef WOLFSSL_ASYNC_CRYPT
&& ret != WC_NO_ERR_TRACE(WC_PENDING_E)
#endif
) {
dtlsClearPeer(&ssl->buffers.dtlsCtx.pendingPeer);
ssl->buffers.dtlsCtx.processingPendingRecord = 0;
}
}
#endif
return ret;
}
#if !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS) || \
(defined(WOLFSSL_TLS13) && defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT))
int SendChangeCipher(WOLFSSL* ssl)

281
src/ssl.c
View File

@ -1767,6 +1767,17 @@ int wolfSSL_get_fd(const WOLFSSL* ssl)
return fd;
}
int wolfSSL_get_wfd(const WOLFSSL* ssl)
{
int fd = -1;
WOLFSSL_ENTER("wolfSSL_get_fd");
if (ssl) {
fd = ssl->wfd;
}
WOLFSSL_LEAVE("wolfSSL_get_fd", fd);
return fd;
}
int wolfSSL_dtls(WOLFSSL* ssl)
{
@ -1899,38 +1910,58 @@ int wolfSSL_dtls_free_peer(void* addr)
}
#endif
#ifdef WOLFSSL_DTLS
static int SockAddrSet(WOLFSSL_SOCKADDR* sockAddr, void* peer,
unsigned int peerSz, void* heap)
{
if (peer == NULL || peerSz == 0) {
if (sockAddr->sa != NULL)
XFREE(sockAddr->sa, heap, DYNAMIC_TYPE_SOCKADDR);
sockAddr->sa = NULL;
sockAddr->sz = 0;
sockAddr->bufSz = 0;
return WOLFSSL_SUCCESS;
}
if (peerSz > sockAddr->bufSz) {
if (sockAddr->sa != NULL)
XFREE(sockAddr->sa, heap, DYNAMIC_TYPE_SOCKADDR);
sockAddr->sa =
(void*)XMALLOC(peerSz, heap, DYNAMIC_TYPE_SOCKADDR);
if (sockAddr->sa == NULL) {
sockAddr->sz = 0;
sockAddr->bufSz = 0;
return WOLFSSL_FAILURE;
}
sockAddr->bufSz = peerSz;
}
XMEMCPY(sockAddr->sa, peer, peerSz);
sockAddr->sz = peerSz;
return WOLFSSL_SUCCESS;
}
#endif
int wolfSSL_dtls_set_peer(WOLFSSL* ssl, void* peer, unsigned int peerSz)
{
#ifdef WOLFSSL_DTLS
void* sa;
int ret;
if (ssl == NULL)
return WOLFSSL_FAILURE;
if (peer == NULL || peerSz == 0) {
if (ssl->buffers.dtlsCtx.peer.sa != NULL)
XFREE(ssl->buffers.dtlsCtx.peer.sa,ssl->heap,DYNAMIC_TYPE_SOCKADDR);
ssl->buffers.dtlsCtx.peer.sa = NULL;
ssl->buffers.dtlsCtx.peer.sz = 0;
ssl->buffers.dtlsCtx.peer.bufSz = 0;
ssl->buffers.dtlsCtx.userSet = 0;
return WOLFSSL_SUCCESS;
}
sa = (void*)XMALLOC(peerSz, ssl->heap, DYNAMIC_TYPE_SOCKADDR);
if (sa != NULL) {
if (ssl->buffers.dtlsCtx.peer.sa != NULL) {
XFREE(ssl->buffers.dtlsCtx.peer.sa,ssl->heap,DYNAMIC_TYPE_SOCKADDR);
ssl->buffers.dtlsCtx.peer.sa = NULL;
}
XMEMCPY(sa, peer, peerSz);
ssl->buffers.dtlsCtx.peer.sa = sa;
ssl->buffers.dtlsCtx.peer.sz = peerSz;
ssl->buffers.dtlsCtx.peer.bufSz = peerSz;
ssl->buffers.dtlsCtx.userSet = 1;
return WOLFSSL_SUCCESS;
}
#ifdef WOLFSSL_RW_THREADED
if (wc_LockRwLock_Wr(&ssl->buffers.dtlsCtx.peerLock) != 0)
return WOLFSSL_FAILURE;
#endif
ret = SockAddrSet(&ssl->buffers.dtlsCtx.peer, peer, peerSz, ssl->heap);
if (ret == WOLFSSL_SUCCESS && !(peer == NULL || peerSz == 0))
ssl->buffers.dtlsCtx.userSet = 1;
else
ssl->buffers.dtlsCtx.userSet = 0;
#ifdef WOLFSSL_RW_THREADED
if (wc_UnLockRwLock(&ssl->buffers.dtlsCtx.peerLock) != 0)
ret = WOLFSSL_FAILURE;
#endif
return ret;
#else
(void)ssl;
(void)peer;
@ -1939,21 +1970,97 @@ int wolfSSL_dtls_set_peer(WOLFSSL* ssl, void* peer, unsigned int peerSz)
#endif
}
#if defined(WOLFSSL_DTLS_CID) && !defined(WOLFSSL_NO_SOCK)
int wolfSSL_dtls_set_pending_peer(WOLFSSL* ssl, void* peer, unsigned int peerSz)
{
#ifdef WOLFSSL_DTLS
int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
if (ssl == NULL)
return WOLFSSL_FAILURE;
#ifdef WOLFSSL_RW_THREADED
if (wc_LockRwLock_Rd(&ssl->buffers.dtlsCtx.peerLock) != 0)
return WOLFSSL_FAILURE;
#endif
if (ssl->buffers.dtlsCtx.peer.sa != NULL &&
ssl->buffers.dtlsCtx.peer.sz == peerSz &&
sockAddrEqual((SOCKADDR_S*)ssl->buffers.dtlsCtx.peer.sa,
(XSOCKLENT)ssl->buffers.dtlsCtx.peer.sz, (SOCKADDR_S*)peer,
(XSOCKLENT)peerSz)) {
/* Already the current peer. */
if (ssl->buffers.dtlsCtx.pendingPeer.sa != NULL) {
/* Clear any other pendingPeer */
XFREE(ssl->buffers.dtlsCtx.pendingPeer.sa, ssl->heap,
DYNAMIC_TYPE_SOCKADDR);
ssl->buffers.dtlsCtx.pendingPeer.sa = NULL;
ssl->buffers.dtlsCtx.pendingPeer.sz = 0;
ssl->buffers.dtlsCtx.pendingPeer.bufSz = 0;
}
ret = WOLFSSL_SUCCESS;
}
else {
ret = SockAddrSet(&ssl->buffers.dtlsCtx.pendingPeer, peer, peerSz,
ssl->heap);
}
if (ret == WOLFSSL_SUCCESS)
ssl->buffers.dtlsCtx.processingPendingRecord = 0;
#ifdef WOLFSSL_RW_THREADED
if (wc_UnLockRwLock(&ssl->buffers.dtlsCtx.peerLock) != 0)
ret = WOLFSSL_FAILURE;
#endif
return ret;
#else
(void)ssl;
(void)peer;
(void)peerSz;
return WOLFSSL_NOT_IMPLEMENTED;
#endif
}
#endif /* WOLFSSL_DTLS_CID && !WOLFSSL_NO_SOCK */
int wolfSSL_dtls_get_peer(WOLFSSL* ssl, void* peer, unsigned int* peerSz)
{
#ifdef WOLFSSL_DTLS
if (ssl == NULL) {
int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
if (ssl == NULL)
return WOLFSSL_FAILURE;
}
#ifdef WOLFSSL_RW_THREADED
if (wc_LockRwLock_Rd(&ssl->buffers.dtlsCtx.peerLock) != 0)
return WOLFSSL_FAILURE;
#endif
if (peer != NULL && peerSz != NULL
&& *peerSz >= ssl->buffers.dtlsCtx.peer.sz
&& ssl->buffers.dtlsCtx.peer.sa != NULL) {
*peerSz = ssl->buffers.dtlsCtx.peer.sz;
XMEMCPY(peer, ssl->buffers.dtlsCtx.peer.sa, *peerSz);
return WOLFSSL_SUCCESS;
ret = WOLFSSL_SUCCESS;
}
#ifdef WOLFSSL_RW_THREADED
if (wc_UnLockRwLock(&ssl->buffers.dtlsCtx.peerLock) != 0)
ret = WOLFSSL_FAILURE;
#endif
return ret;
#else
(void)ssl;
(void)peer;
(void)peerSz;
return WOLFSSL_NOT_IMPLEMENTED;
#endif
}
int wolfSSL_dtls_get0_peer(WOLFSSL* ssl, const void** peer,
unsigned int* peerSz)
{
#if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_RW_THREADED)
if (ssl == NULL)
return WOLFSSL_FAILURE;
if (peer == NULL || peerSz == NULL)
return WOLFSSL_FAILURE;
*peer = ssl->buffers.dtlsCtx.peer.sa;
*peerSz = ssl->buffers.dtlsCtx.peer.sz;
return WOLFSSL_SUCCESS;
#else
(void)ssl;
(void)peer;
@ -2996,6 +3103,42 @@ int wolfSSL_write(WOLFSSL* ssl, const void* data, int sz)
return ret;
}
int wolfSSL_inject(WOLFSSL* ssl, const void* data, int sz)
{
int maxLength;
int usedLength;
WOLFSSL_ENTER("wolfSSL_inject");
if (ssl == NULL || data == NULL || sz <= 0)
return BAD_FUNC_ARG;
usedLength = (int)(ssl->buffers.inputBuffer.length -
ssl->buffers.inputBuffer.idx);
maxLength = (int)(ssl->buffers.inputBuffer.bufferSize -
(word32)usedLength);
if (sz > maxLength) {
/* Need to make space */
int ret;
if (ssl->buffers.clearOutputBuffer.length > 0) {
/* clearOutputBuffer points into so reallocating inputBuffer will
* invalidate clearOutputBuffer and lose app data */
WOLFSSL_MSG("Can't inject while there is application data to read");
return APP_DATA_READY;
}
ret = GrowInputBuffer(ssl, sz, usedLength);
if (ret < 0)
return ret;
}
XMEMCPY(ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx,
data, sz);
ssl->buffers.inputBuffer.length += sz;
return WOLFSSL_SUCCESS;
}
static int wolfSSL_read_internal(WOLFSSL* ssl, void* data, int sz, int peek)
{
int ret;
@ -9617,7 +9760,13 @@ int wolfSSL_dtls_retransmit(WOLFSSL* ssl)
return WOLFSSL_FATAL_ERROR;
if (!ssl->options.handShakeDone) {
int result = DtlsMsgPoolSend(ssl, 0);
int result;
#ifdef WOLFSSL_DTLS13
if (IsAtLeastTLSv1_3(ssl->version))
result = Dtls13DoScheduledWork(ssl);
else
#endif
result = DtlsMsgPoolSend(ssl, 0);
if (result < 0) {
ssl->error = result;
WOLFSSL_ERROR(result);
@ -9625,7 +9774,7 @@ int wolfSSL_dtls_retransmit(WOLFSSL* ssl)
}
}
return 0;
return WOLFSSL_SUCCESS;
}
#endif /* DTLS */
@ -10794,6 +10943,76 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
struct chGoodDisableReadCbCtx {
ClientHelloGoodCb userCb;
void* userCtx;
};
static int chGoodDisableReadCB(WOLFSSL* ssl, void* ctx)
{
struct chGoodDisableReadCbCtx* cb = (struct chGoodDisableReadCbCtx*)ctx;
int ret = 0;
if (cb->userCb != NULL)
ret = cb->userCb(ssl, cb->userCtx);
if (ret >= 0)
wolfSSL_SSLDisableRead(ssl);
return ret;
}
/**
* Statelessly listen for a connection
* @param ssl The ssl object to use for listening to connections
* @return WOLFSSL_SUCCESS - ClientHello containing a valid cookie was received
* The connection can be continued with wolfSSL_accept
* WOLFSSL_FAILURE - The I/O layer returned WANT_READ. This is either
* because there is no data to read and we are using
* non-blocking sockets or we sent a cookie request
* and we are waiting for a reply. The user should
* call wolfDTLS_accept_stateless again after data
* becomes available in the I/O layer.
* WOLFSSL_FATAL_ERROR - A fatal error occurred. The ssl object should
* be free'd and allocated again to continue.
*/
int wolfDTLS_accept_stateless(WOLFSSL* ssl)
{
byte disableRead;
int ret = WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR);
struct chGoodDisableReadCbCtx cb;
WOLFSSL_ENTER("wolfDTLS_SetChGoodCb");
if (ssl == NULL)
return WOLFSSL_FATAL_ERROR;
/* Save this to restore it later */
disableRead = (byte)ssl->options.disableRead;
cb.userCb = ssl->chGoodCb;
cb.userCtx = ssl->chGoodCtx;
/* Register our own callback so that we can disable reading */
if (wolfDTLS_SetChGoodCb(ssl, chGoodDisableReadCB, &cb) != WOLFSSL_SUCCESS)
return WOLFSSL_FATAL_ERROR;
ret = wolfSSL_accept(ssl);
/* restore user options */
ssl->options.disableRead = disableRead;
(void)wolfDTLS_SetChGoodCb(ssl, cb.userCb, cb.userCtx);
if (ret == WOLFSSL_SUCCESS) {
WOLFSSL_MSG("should not happen. maybe the user called "
"wolfDTLS_accept_stateless instead of wolfSSL_accept");
}
else if (ssl->error == WC_NO_ERR_TRACE(WANT_READ)) {
if (ssl->options.dtlsStateful)
ret = WOLFSSL_SUCCESS;
else
ret = WOLFSSL_FAILURE;
}
else {
ret = WOLFSSL_FATAL_ERROR;
}
return ret;
}
int wolfDTLS_SetChGoodCb(WOLFSSL* ssl, ClientHelloGoodCb cb, void* user_ctx)
{
WOLFSSL_ENTER("wolfDTLS_SetChGoodCb");

View File

@ -2413,6 +2413,9 @@ static WC_INLINE void WriteSEQTls13(WOLFSSL* ssl, int verifyOrder, byte* out)
if (seq[1] > ssl->keys.sequence_number_lo)
ssl->keys.sequence_number_hi++;
}
#ifdef WOLFSSL_DEBUG_TLS
WOLFSSL_MSG_EX("TLS 1.3 Write Sequence %d %d", seq[0], seq[1]);
#endif
c32toa(seq[0], out);
c32toa(seq[1], out + OPAQUE32_LEN);
@ -2428,14 +2431,11 @@ static WC_INLINE void WriteSEQTls13(WOLFSSL* ssl, int verifyOrder, byte* out)
static WC_INLINE void BuildTls13Nonce(WOLFSSL* ssl, byte* nonce, const byte* iv,
int order)
{
int i;
int seq_offset = AEAD_NONCE_SZ - SEQ_SZ;
/* The nonce is the IV with the sequence XORed into the last bytes. */
WriteSEQTls13(ssl, order, nonce + AEAD_NONCE_SZ - SEQ_SZ);
for (i = 0; i < AEAD_NONCE_SZ - SEQ_SZ; i++)
nonce[i] = iv[i];
for (; i < AEAD_NONCE_SZ; i++)
nonce[i] ^= iv[i];
WriteSEQTls13(ssl, order, nonce + seq_offset);
XMEMCPY(nonce, iv, seq_offset);
xorbuf(nonce + seq_offset, iv + seq_offset, SEQ_SZ);
}
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
@ -3621,6 +3621,7 @@ int CreateCookieExt(const WOLFSSL* ssl, byte* hash, word16 hashSz,
#ifdef WOLFSSL_DTLS13
/* Tie cookie to peer address */
if (ret == 0) {
/* peerLock not necessary. Still in handshake phase. */
if (ssl->options.dtls && ssl->buffers.dtlsCtx.peer.sz > 0) {
ret = wc_HmacUpdate(&cookieHmac,
(byte*)ssl->buffers.dtlsCtx.peer.sa,
@ -6409,6 +6410,7 @@ int TlsCheckCookie(const WOLFSSL* ssl, const byte* cookie, word16 cookieSz)
#ifdef WOLFSSL_DTLS13
/* Tie cookie to peer address */
if (ret == 0) {
/* peerLock not necessary. Still in handshake phase. */
if (ssl->options.dtls && ssl->buffers.dtlsCtx.peer.sz > 0) {
ret = wc_HmacUpdate(&cookieHmac,
(byte*)ssl->buffers.dtlsCtx.peer.sa,
@ -10905,6 +10907,7 @@ int DoTls13Finished(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
/* Force input exhaustion at ProcessReply by consuming padSz. */
*inOutIdx += size + ssl->keys.padSz;
#ifndef NO_WOLFSSL_SERVER
if (ssl->options.side == WOLFSSL_SERVER_END &&
!ssl->options.handShakeDone) {
#ifdef WOLFSSL_EARLY_DATA
@ -10917,6 +10920,7 @@ int DoTls13Finished(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0)
return ret;
}
#endif
#ifndef NO_WOLFSSL_CLIENT
if (ssl->options.side == WOLFSSL_CLIENT_END)
@ -11149,14 +11153,14 @@ static int SendTls13Finished(WOLFSSL* ssl)
!ssl->options.handShakeDone) {
#ifdef WOLFSSL_EARLY_DATA
if (ssl->earlyData != no_early_data) {
if ((ret = DeriveTls13Keys(ssl, no_key, ENCRYPT_AND_DECRYPT_SIDE,
if ((ret = DeriveTls13Keys(ssl, no_key, ENCRYPT_SIDE_ONLY,
1)) != 0) {
return ret;
}
}
#endif
/* Setup keys for application data messages. */
if ((ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE)) != 0)
if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0)
return ret;
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
@ -12831,12 +12835,21 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
ssl->earlyData == no_early_data)) != 0) {
return ret;
}
if (ssl->earlyData != no_early_data) {
if ((ret = DeriveTls13Keys(ssl, no_key, DECRYPT_SIDE_ONLY,
1)) != 0) {
return ret;
}
}
#else
if ((ret = DeriveTls13Keys(ssl, traffic_key,
ENCRYPT_AND_DECRYPT_SIDE, 1)) != 0) {
return ret;
}
#endif
/* Setup keys for application data messages. */
if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0)
return ret;
}
#ifdef WOLFSSL_POST_HANDSHAKE_AUTH
if (type == certificate_request &&

View File

@ -569,7 +569,7 @@ STATIC int nucyassl_sendto(INT sd, CHAR *buf, UINT16 sz, INT16 flags,
#define DTLS_RECVFROM_FUNCTION recvfrom
#endif
static int sockAddrEqual(
int sockAddrEqual(
SOCKADDR_S *a, XSOCKLENT aLen, SOCKADDR_S *b, XSOCKLENT bLen)
{
if (aLen != bLen)
@ -660,8 +660,17 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
word32 invalidPeerPackets = 0;
#endif
int newPeer = 0;
int ret = 0;
WOLFSSL_ENTER("EmbedReceiveFrom");
(void)ret; /* possibly unused */
XMEMSET(&lclPeer, 0, sizeof(lclPeer));
#ifdef WOLFSSL_RW_THREADED
if (wc_LockRwLock_Rd(&ssl->buffers.dtlsCtx.peerLock) != 0)
return WOLFSSL_CBIO_ERR_GENERAL;
#endif
if (dtlsCtx->connected) {
peer = NULL;
@ -670,33 +679,32 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
#ifndef WOLFSSL_IPV6
if (PeerIsIpv6((SOCKADDR_S*)dtlsCtx->peer.sa, dtlsCtx->peer.sz)) {
WOLFSSL_MSG("ipv6 dtls peer set but no ipv6 support compiled");
return NOT_COMPILED_IN;
ret = WOLFSSL_CBIO_ERR_GENERAL;
}
#endif
peer = &lclPeer;
XMEMSET(&lclPeer, 0, sizeof(lclPeer));
peerSz = sizeof(lclPeer);
}
else {
/* Store the peer address. It is used to calculate the DTLS cookie. */
if (dtlsCtx->peer.sa == NULL) {
dtlsCtx->peer.sa = (void*)XMALLOC(sizeof(SOCKADDR_S),
ssl->heap, DYNAMIC_TYPE_SOCKADDR);
dtlsCtx->peer.sz = 0;
if (dtlsCtx->peer.sa != NULL)
dtlsCtx->peer.bufSz = sizeof(SOCKADDR_S);
else
dtlsCtx->peer.bufSz = 0;
newPeer = 1;
peer = (SOCKADDR_S*)dtlsCtx->peer.sa;
}
else {
newPeer = dtlsCtx->peer.sa == NULL || !ssl->options.dtlsStateful;
peer = &lclPeer;
XMEMCPY(peer, (SOCKADDR_S*)dtlsCtx->peer.sa, sizeof(lclPeer));
if (dtlsCtx->peer.sa != NULL) {
XMEMCPY(peer, (SOCKADDR_S*)dtlsCtx->peer.sa, MIN(sizeof(lclPeer),
dtlsCtx->peer.sz));
}
peerSz = dtlsCtx->peer.bufSz;
peerSz = sizeof(lclPeer);
}
#ifdef WOLFSSL_RW_THREADED
/* We make a copy above to avoid holding the lock for the entire function */
if (wc_UnLockRwLock(&ssl->buffers.dtlsCtx.peerLock) != 0)
return WOLFSSL_CBIO_ERR_GENERAL;
#endif
if (ret != 0)
return ret;
/* Don't use ssl->options.handShakeDone since it is true even if
* we are in the process of renegotiation */
doDtlsTimeout = ssl->options.handShakeState != HANDSHAKE_DONE;
@ -705,12 +713,9 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version)) {
doDtlsTimeout = doDtlsTimeout || ssl->dtls13Rtx.rtxRecords != NULL;
#ifdef WOLFSSL_RW_THREADED
{
int ret = wc_LockMutex(&ssl->dtls13Rtx.mutex);
if (ret < 0) {
ret = wc_LockMutex(&ssl->dtls13Rtx.mutex);
if (ret != 0)
return ret;
}
}
#endif
doDtlsTimeout = doDtlsTimeout ||
(ssl->dtls13FastTimeout && ssl->dtls13Rtx.seenRecords != NULL);
@ -781,26 +786,16 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
}
#endif /* !NO_ASN_TIME */
recvd = (int)DTLS_RECVFROM_FUNCTION(sd, buf, (size_t)sz, ssl->rflags,
(SOCKADDR*)peer, peer != NULL ? &peerSz : NULL);
/* From the RECV(2) man page
{
XSOCKLENT inPeerSz = peerSz;
recvd = (int)DTLS_RECVFROM_FUNCTION(sd, buf, (size_t)sz,
ssl->rflags, (SOCKADDR*)peer, peer != NULL ? &inPeerSz : NULL);
/* Truncate peerSz. From the RECV(2) man page
* The returned address is truncated if the buffer provided is too
* small; in this case, addrlen will return a value greater than was
* supplied to the call.
*/
if (dtlsCtx->connected) {
/* No need to sanitize the value of peerSz */
}
else if (dtlsCtx->userSet) {
/* Truncate peer size */
if (peerSz > (XSOCKLENT)sizeof(lclPeer))
peerSz = (XSOCKLENT)sizeof(lclPeer);
}
else {
/* Truncate peer size */
if (peerSz > (XSOCKLENT)dtlsCtx->peer.bufSz)
peerSz = (XSOCKLENT)dtlsCtx->peer.bufSz;
peerSz = MIN(peerSz, inPeerSz);
}
recvd = TranslateIoReturnCode(recvd, sd, SOCKET_RECEIVING);
@ -829,11 +824,23 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
}
else if (dtlsCtx->userSet) {
/* Check we received the packet from the correct peer */
int ignore = 0;
#ifdef WOLFSSL_RW_THREADED
if (wc_LockRwLock_Rd(&ssl->buffers.dtlsCtx.peerLock) != 0)
return WOLFSSL_CBIO_ERR_GENERAL;
#endif
if (dtlsCtx->peer.sz > 0 &&
(peerSz != (XSOCKLENT)dtlsCtx->peer.sz ||
!sockAddrEqual(peer, peerSz, (SOCKADDR_S*)dtlsCtx->peer.sa,
dtlsCtx->peer.sz))) {
WOLFSSL_MSG(" Ignored packet from invalid peer");
ignore = 1;
}
#ifdef WOLFSSL_RW_THREADED
if (wc_UnLockRwLock(&ssl->buffers.dtlsCtx.peerLock) != 0)
return WOLFSSL_CBIO_ERR_GENERAL;
#endif
if (ignore) {
#if defined(NO_ASN_TIME) && \
!defined(DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER)
if (doDtlsTimeout) {
@ -849,13 +856,27 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
}
else {
if (newPeer) {
/* Store size of saved address */
dtlsCtx->peer.sz = peerSz;
/* Store size of saved address. Locking handled internally. */
if (wolfSSL_dtls_set_peer(ssl, peer, peerSz) != WOLFSSL_SUCCESS)
return WOLFSSL_CBIO_ERR_GENERAL;
}
#ifndef WOLFSSL_PEER_ADDRESS_CHANGES
else if ((dtlsCtx->peer.sz != (unsigned int)peerSz) ||
(XMEMCMP(peer, dtlsCtx->peer.sa, peerSz) != 0)) {
else {
ret = 0;
#ifdef WOLFSSL_RW_THREADED
if (wc_LockRwLock_Rd(&ssl->buffers.dtlsCtx.peerLock) != 0)
return WOLFSSL_CBIO_ERR_GENERAL;
#endif
if (!sockAddrEqual(peer, peerSz, (SOCKADDR_S*)dtlsCtx->peer.sa,
dtlsCtx->peer.sz)) {
ret = WOLFSSL_CBIO_ERR_GENERAL;
}
#ifdef WOLFSSL_RW_THREADED
if (wc_UnLockRwLock(&ssl->buffers.dtlsCtx.peerLock) != 0)
return WOLFSSL_CBIO_ERR_GENERAL;
#endif
if (ret != 0)
return ret;
}
#endif
}
@ -2351,6 +2372,20 @@ void wolfSSL_SSLSetIOSend(WOLFSSL *ssl, CallbackIOSend CBIOSend)
}
}
void wolfSSL_SSLDisableRead(WOLFSSL *ssl)
{
if (ssl) {
ssl->options.disableRead = 1;
}
}
void wolfSSL_SSLEnableRead(WOLFSSL *ssl)
{
if (ssl) {
ssl->options.disableRead = 0;
}
}
void wolfSSL_SetIOReadCtx(WOLFSSL* ssl, void *rctx)
{

View File

@ -90317,7 +90317,7 @@ static void test_wolfSSL_dtls_plaintext_server(WOLFSSL* ssl)
static void test_wolfSSL_dtls_plaintext_client(WOLFSSL* ssl)
{
byte ch[50];
int fd = wolfSSL_get_fd(ssl);
int fd = wolfSSL_get_wfd(ssl);
byte msg[] = "This is a msg for the server";
byte reply[40];
@ -90387,7 +90387,7 @@ static void test_wolfSSL_dtls12_fragments_spammer(WOLFSSL* ssl)
size_t seq_offset = 0;
size_t msg_offset = 0;
int i;
int fd = wolfSSL_get_fd(ssl);
int fd = wolfSSL_get_wfd(ssl);
int ret = wolfSSL_connect_cert(ssl); /* This gets us past the cookie */
word32 seq_number = 100; /* start high so server definitely reads this */
word16 msg_number = 50; /* start high so server has to buffer this */
@ -90449,7 +90449,7 @@ static void test_wolfSSL_dtls13_fragments_spammer(WOLFSSL* ssl)
byte b[150]; /* buffer for the messages to send */
size_t idx = 0;
size_t msg_offset = 0;
int fd = wolfSSL_get_fd(ssl);
int fd = wolfSSL_get_wfd(ssl);
word16 msg_number = 10; /* start high so server has to buffer this */
int ret = wolfSSL_connect_cert(ssl); /* This gets us past the cookie */
AssertIntEQ(ret, 1);
@ -90554,7 +90554,7 @@ static void test_wolfSSL_dtls_send_alert(WOLFSSL* ssl)
0x46 /* protocol version */
};
fd = wolfSSL_get_fd(ssl);
fd = wolfSSL_get_wfd(ssl);
ret = (int)send(fd, alert_msg, sizeof(alert_msg), 0);
AssertIntGT(ret, 0);
}
@ -90624,7 +90624,7 @@ static void test_wolfSSL_send_bad_record(WOLFSSL* ssl)
0x03, 0x18, 0x72
};
fd = wolfSSL_get_fd(ssl);
fd = wolfSSL_get_wfd(ssl);
AssertIntGE(fd, 0);
ret = (int)send(fd, bad_msg, sizeof(bad_msg), 0);
AssertIntEQ(ret, sizeof(bad_msg));
@ -90951,7 +90951,7 @@ static void test_wolfSSL_dtls_send_ch(WOLFSSL* ssl)
0x31, 0x68, 0x4c
};
fd = wolfSSL_get_fd(ssl);
fd = wolfSSL_get_wfd(ssl);
ret = (int)send(fd, ch_msg, sizeof(ch_msg), 0);
AssertIntGT(ret, 0);
/* consume the HRR otherwise handshake will fail */
@ -91022,7 +91022,7 @@ static void test_wolfSSL_dtls_send_ch_with_invalid_cookie(WOLFSSL* ssl)
0x02, 0x02, 0x2f
};
fd = wolfSSL_get_fd(ssl);
fd = wolfSSL_get_wfd(ssl);
ret = (int)send(fd, ch_msh_invalid_cookie, sizeof(ch_msh_invalid_cookie), 0);
AssertIntGT(ret, 0);
/* should reply with an illegal_parameter reply */
@ -94637,18 +94637,31 @@ static int test_wolfSSL_dtls_stateless2(void)
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method), 0);
ExpectNotNull(ssl_c2 = wolfSSL_new(ctx_c));
wolfSSL_SetIOWriteCtx(ssl_c2, &test_ctx);
wolfSSL_SetIOReadCtx(ssl_c2, &test_ctx);
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, NULL, &ssl_c2, NULL,
wolfDTLSv1_2_client_method, NULL), 0);
ExpectFalse(wolfSSL_is_stateful(ssl_s));
/* send CH */
ExpectTrue((wolfSSL_connect(ssl_c2) == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)) &&
(ssl_c2->error == WC_NO_ERR_TRACE(WANT_READ)));
ExpectTrue((wolfSSL_accept(ssl_s) == WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)) &&
(ssl_s->error == WC_NO_ERR_TRACE(WANT_READ)));
ExpectIntEQ(wolfDTLS_accept_stateless(ssl_s), WOLFSSL_FAILURE);
ExpectFalse(wolfSSL_is_stateful(ssl_s));
ExpectIntNE(test_ctx.c_len, 0);
/* consume HRR */
test_ctx.c_len = 0;
/* send CH1 */
ExpectIntEQ(wolfSSL_connect(ssl_c), WOLFSSL_FATAL_ERROR);
ExpectIntEQ(wolfSSL_get_error(ssl_c, WOLFSSL_FATAL_ERROR),
WOLFSSL_ERROR_WANT_READ);
/* send HRR */
ExpectIntEQ(wolfDTLS_accept_stateless(ssl_s), WOLFSSL_FAILURE);
/* send CH2 */
ExpectIntEQ(wolfSSL_connect(ssl_c), WOLFSSL_FATAL_ERROR);
ExpectIntEQ(wolfSSL_get_error(ssl_c, WOLFSSL_FATAL_ERROR),
WOLFSSL_ERROR_WANT_READ);
/* send HRR */
ExpectIntEQ(wolfDTLS_accept_stateless(ssl_s), WOLFSSL_SUCCESS);
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
ExpectTrue(wolfSSL_is_stateful(ssl_s));
wolfSSL_free(ssl_c2);
wolfSSL_free(ssl_c);
@ -99223,7 +99236,7 @@ static int test_dtls12_basic_connection_id(void)
#endif /* WOLFSSL_AES_128 && WOLFSSL_STATIC_RSA */
#endif /* NO_SHA256 */
#endif /* NO_RSA */
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305)
#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && !defined(HAVE_FIPS)
"DHE-RSA-CHACHA20-POLY1305",
"DHE-RSA-CHACHA20-POLY1305-OLD",
"ECDHE-RSA-CHACHA20-POLY1305",
@ -99232,7 +99245,7 @@ static int test_dtls12_basic_connection_id(void)
#ifndef NO_PSK
"DHE-PSK-AES128-CBC-SHA256",
"DHE-PSK-AES256-GCM-SHA384",
#ifndef HAVE_NULL_CIPHER
#ifdef HAVE_NULL_CIPHER
"DHE-PSK-NULL-SHA256",
#endif
"DHE-PSK-AES128-CCM",
@ -99550,7 +99563,7 @@ static int test_dtls13_basic_connection_id(void)
&& defined(WOLFSSL_DTLS_CID)
unsigned char client_cid[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
unsigned char server_cid[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
unsigned char readBuf[30];
unsigned char readBuf[50];
const char* params[] = {
#ifndef NO_SHA256
#ifdef WOLFSSL_AES_128
@ -99969,9 +99982,11 @@ static int test_tls13_early_data(void)
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
params[i].client_meth, params[i].server_meth), 0);
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_set_session(ssl_c, sess), WOLFSSL_SUCCESS);
#ifdef WOLFSSL_DTLS13
if (params[i].isUdp) {
wolfSSL_SetLoggingPrefix("server");
#ifdef WOLFSSL_DTLS13_NO_HRR_ON_RESUME
ExpectIntEQ(wolfSSL_dtls13_no_hrr_on_resume(ssl_s, 1), WOLFSSL_SUCCESS);
#else
@ -99983,6 +99998,7 @@ static int test_tls13_early_data(void)
#endif
/* Test 0-RTT data */
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_write_early_data(ssl_c, msg, sizeof(msg),
&written), sizeof(msg));
ExpectIntEQ(written, sizeof(msg));
@ -99994,6 +100010,7 @@ static int test_tls13_early_data(void)
}
/* Read first 0-RTT data (if split otherwise entire data) */
wolfSSL_SetLoggingPrefix("server");
ExpectIntEQ(wolfSSL_read_early_data(ssl_s, msgBuf, sizeof(msgBuf),
&read), sizeof(msg));
ExpectIntEQ(read, sizeof(msg));
@ -100011,6 +100028,7 @@ static int test_tls13_early_data(void)
}
if (params[i].isUdp) {
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WC_NO_ERR_TRACE(APP_DATA_READY));
@ -100027,17 +100045,21 @@ static int test_tls13_early_data(void)
* handshake status to us with non-blocking IO and we can't use
* wolfSSL_accept as TLS layer may return ZERO_RETURN due to early data
* parsing logic. */
wolfSSL_SetLoggingPrefix("server");
ExpectFalse(wolfSSL_is_init_finished(ssl_s));
ExpectIntEQ(wolfSSL_read_early_data(ssl_s, msgBuf, sizeof(msgBuf),
&read), 0);
ExpectIntEQ(read, 0);
ExpectTrue(wolfSSL_is_init_finished(ssl_s));
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS);
}
else {
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS);
wolfSSL_SetLoggingPrefix("server");
ExpectFalse(wolfSSL_is_init_finished(ssl_s));
ExpectIntEQ(wolfSSL_read_early_data(ssl_s, msgBuf, sizeof(msgBuf),
&read), 0);
@ -100045,18 +100067,23 @@ static int test_tls13_early_data(void)
ExpectTrue(wolfSSL_is_init_finished(ssl_s));
/* Read server 0.5-RTT data */
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_read(ssl_c, msgBuf, sizeof(msgBuf)), sizeof(msg4));
ExpectStrEQ(msg4, msgBuf);
}
/* Test bi-directional write */
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_write(ssl_c, msg2, sizeof(msg2)), sizeof(msg2));
wolfSSL_SetLoggingPrefix("server");
ExpectIntEQ(wolfSSL_read(ssl_s, msgBuf, sizeof(msgBuf)), sizeof(msg2));
ExpectStrEQ(msg2, msgBuf);
ExpectIntEQ(wolfSSL_write(ssl_s, msg3, sizeof(msg3)), sizeof(msg3));
wolfSSL_SetLoggingPrefix("client");
ExpectIntEQ(wolfSSL_read(ssl_c, msgBuf, sizeof(msgBuf)), sizeof(msg3));
ExpectStrEQ(msg3, msgBuf);
wolfSSL_SetLoggingPrefix(NULL);
ExpectTrue(wolfSSL_session_reused(ssl_c));
ExpectTrue(wolfSSL_session_reused(ssl_s));
@ -100909,6 +100936,165 @@ static int test_ocsp_callback_fails(void)
defined(HAVE_OCSP) && \
defined(HAVE_CERTIFICATE_STATUS_REQUEST) */
#ifdef HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES
static int test_wolfSSL_SSLDisableRead_recv(WOLFSSL *ssl, char *buf, int sz,
void *ctx)
{
(void)ssl;
(void)buf;
(void)sz;
(void)ctx;
return WOLFSSL_CBIO_ERR_GENERAL;
}
static int test_wolfSSL_SSLDisableRead(void)
{
EXPECT_DECLS;
WOLFSSL_CTX *ctx_c = NULL;
WOLFSSL *ssl_c = NULL;
struct test_memio_ctx test_ctx;
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, NULL, &ssl_c, NULL,
wolfTLS_client_method, NULL), 0);
wolfSSL_SSLSetIORecv(ssl_c, test_wolfSSL_SSLDisableRead_recv);
wolfSSL_SSLDisableRead(ssl_c);
/* Disabling reading should not even go into the IO layer */
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
wolfSSL_SSLEnableRead(ssl_c);
/* By enabling reading we should reach the IO that will return an error */
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), SOCKET_ERROR_E);
wolfSSL_free(ssl_c);
wolfSSL_CTX_free(ctx_c);
return EXPECT_RESULT();
}
#else
static int test_wolfSSL_SSLDisableRead(void)
{
EXPECT_DECLS;
return EXPECT_RESULT();
}
#endif
static int test_wolfSSL_inject(void)
{
EXPECT_DECLS;
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES)
size_t i;
struct {
method_provider client_meth;
method_provider server_meth;
const char* tls_version;
} params[] = {
#if defined(WOLFSSL_TLS13)
/* With WOLFSSL_TLS13_MIDDLEBOX_COMPAT a short ID will result in an error */
{ wolfTLSv1_3_client_method, wolfTLSv1_3_server_method, "TLSv1_3" },
#ifdef WOLFSSL_DTLS13
{ wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method, "DTLSv1_3" },
#endif
#endif
#ifndef WOLFSSL_NO_TLS12
{ wolfTLSv1_2_client_method, wolfTLSv1_2_server_method, "TLSv1_2" },
#ifdef WOLFSSL_DTLS
{ wolfDTLSv1_2_client_method, wolfDTLSv1_2_server_method, "DTLSv1_2" },
#endif
#endif
#if !defined(NO_OLD_TLS)
{ wolfTLSv1_1_client_method, wolfTLSv1_1_server_method, "TLSv1_1" },
#ifdef WOLFSSL_DTLS
{ wolfDTLSv1_client_method, wolfDTLSv1_server_method, "DTLSv1_0" },
#endif
#endif
};
for (i = 0; i < XELEM_CNT(params) && !EXPECT_FAIL(); i++) {
WOLFSSL_CTX *ctx_c = NULL;
WOLFSSL_CTX *ctx_s = NULL;
WOLFSSL *ssl_c = NULL;
WOLFSSL *ssl_s = NULL;
struct test_memio_ctx test_ctx;
WOLFSSL_ALERT_HISTORY h;
int rounds;
printf("Testing %s\n", params[i].tls_version);
XMEMSET(&h, 0, sizeof(h));
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
params[i].client_meth, params[i].server_meth), 0);
for (rounds = 0; rounds < 10 && EXPECT_SUCCESS(); rounds++) {
wolfSSL_SetLoggingPrefix("client");
if (wolfSSL_negotiate(ssl_c) != 1) {
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1),
WOLFSSL_ERROR_WANT_READ);
}
wolfSSL_SetLoggingPrefix("server");
if (test_ctx.s_len > 0) {
ExpectIntEQ(wolfSSL_inject(ssl_s, test_ctx.s_buff,
test_ctx.s_len), 1);
test_ctx.s_len = 0;
}
if (wolfSSL_negotiate(ssl_s) != 1) {
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1),
WOLFSSL_ERROR_WANT_READ);
}
wolfSSL_SetLoggingPrefix("client");
if (test_ctx.c_len > 0) {
ExpectIntEQ(wolfSSL_inject(ssl_c, test_ctx.c_buff,
test_ctx.c_len), 1);
test_ctx.c_len = 0;
}
wolfSSL_SetLoggingPrefix(NULL);
}
ExpectIntEQ(wolfSSL_negotiate(ssl_c), 1);
ExpectIntEQ(wolfSSL_negotiate(ssl_s), 1);
wolfSSL_free(ssl_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_c);
wolfSSL_CTX_free(ctx_s);
}
#endif
return EXPECT_RESULT();
}
static int test_wolfSSL_dtls_cid_parse(void)
{
EXPECT_DECLS;
#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_DTLS_CID)
/* Taken from Wireshark. Right-click -> copy -> ... as escaped string */
/* Plaintext ServerHelloDone. No CID. */
byte noCid[] =
"\x16\xfe\xfd\x00\x00\x00\x00\x00\x00\x00\x04\x00\x0c\x0e\x00\x00" \
"\x00\x00\x04\x00\x00\x00\x00\x00\x00";
/* 1.2 app data containing CID */
byte cid12[] =
"\x19\xfe\xfd\x00\x01\x00\x00\x00\x00\x00\x01\x77\xa3\x79\x34\xb3" \
"\xf1\x1f\x34\x00\x1f\xdb\x8c\x28\x25\x9f\xe1\x02\x26\x77\x1c\x3a" \
"\x50\x1b\x50\x99\xd0\xb5\x20\xd8\x2c\x2e\xaa\x36\x36\xe0\xb7\xb7" \
"\xf7\x7d\xff\xb0";
#ifdef WOLFSSL_DTLS13
/* 1.3 app data containing CID */
byte cid13[] =
"\x3f\x70\x64\x04\xc6\xfb\x97\x21\xd9\x28\x27\x00\x17\xc1\x01\x86" \
"\xe7\x23\x2c\xad\x65\x83\xa8\xf4\xbf\xbf\x7b\x25\x16\x80\x19\xc3" \
"\x81\xda\xf5\x3f";
#endif
ExpectPtrEq(wolfSSL_dtls_cid_parse(noCid, sizeof(noCid), 8), NULL);
ExpectPtrEq(wolfSSL_dtls_cid_parse(cid12, sizeof(cid12), 8), cid12 + 11);
#ifdef WOLFSSL_DTLS13
ExpectPtrEq(wolfSSL_dtls_cid_parse(cid13, sizeof(cid13), 8), cid13 + 1);
#endif
#endif
return EXPECT_RESULT();
}
/*----------------------------------------------------------------------------*
| Main
@ -102316,6 +102502,9 @@ TEST_CASE testCases[] = {
TEST_DECL(test_get_signature_nid),
TEST_DECL(test_tls_cert_store_unchanged),
TEST_DECL(test_wolfSSL_SendUserCanceled),
TEST_DECL(test_wolfSSL_SSLDisableRead),
TEST_DECL(test_wolfSSL_inject),
TEST_DECL(test_wolfSSL_dtls_cid_parse),
/* This test needs to stay at the end to clean up any caches allocated. */
TEST_DECL(test_wolfSSL_Cleanup)
};

View File

@ -2764,7 +2764,16 @@ struct WOLFSSL_SOCKADDR {
};
typedef struct WOLFSSL_DTLS_CTX {
#ifdef WOLFSSL_RW_THREADED
/* Protect peer access after the handshake */
wolfSSL_RwLock peerLock;
#endif
WOLFSSL_SOCKADDR peer;
#ifdef WOLFSSL_DTLS_CID
WOLFSSL_SOCKADDR pendingPeer; /* When using CID's, we don't want to update
* the peer's address until we successfully
* de-protect the record. */
#endif
int rfd;
int wfd;
byte userSet:1;
@ -2772,6 +2781,9 @@ typedef struct WOLFSSL_DTLS_CTX {
* connected (connect() and bind() both called).
* This means that sendto and recvfrom do not need to
* specify and store the peer address. */
#ifdef WOLFSSL_DTLS_CID
byte processingPendingRecord:1;
#endif
} WOLFSSL_DTLS_CTX;
@ -3718,6 +3730,7 @@ WOLFSSL_LOCAL int TLSX_ConnectionID_Parse(WOLFSSL* ssl, const byte* input,
WOLFSSL_LOCAL void DtlsCIDOnExtensionsParsed(WOLFSSL* ssl);
WOLFSSL_LOCAL byte DtlsCIDCheck(WOLFSSL* ssl, const byte* input,
word16 inputSize);
WOLFSSL_LOCAL int Dtls13UnifiedHeaderCIDPresent(byte flags);
#endif /* WOLFSSL_DTLS_CID */
WOLFSSL_LOCAL byte DtlsGetCidTxSize(WOLFSSL* ssl);
WOLFSSL_LOCAL byte DtlsGetCidRxSize(WOLFSSL* ssl);
@ -5061,6 +5074,7 @@ struct Options {
#if defined(HAVE_DANE)
word16 useDANE:1;
#endif /* HAVE_DANE */
word16 disableRead:1;
#ifdef WOLFSSL_DTLS
byte haveMcast; /* using multicast ? */
#endif
@ -6729,6 +6743,10 @@ WOLFSSL_LOCAL word32 MacSize(const WOLFSSL* ssl);
WOLFSSL_LOCAL int DoClientHelloStateless(WOLFSSL* ssl,
const byte* input, word32 helloSz, byte isFirstCHFrag, byte* tls13);
#endif /* !defined(NO_WOLFSSL_SERVER) */
#if !defined(WOLFCRYPT_ONLY) && defined(USE_WOLFSSL_IO)
WOLFSSL_LOCAL int sockAddrEqual(SOCKADDR_S *a, XSOCKLENT aLen,
SOCKADDR_S *b, XSOCKLENT bLen);
#endif
#endif /* WOLFSSL_DTLS */
#if defined(HAVE_SECURE_RENEGOTIATION) && defined(WOLFSSL_DTLS)

View File

@ -1359,6 +1359,7 @@ WOLFSSL_API const char* wolfSSL_get_shared_ciphers(WOLFSSL* ssl, char* buf,
int len);
WOLFSSL_API const char* wolfSSL_get_curve_name(WOLFSSL* ssl);
WOLFSSL_API int wolfSSL_get_fd(const WOLFSSL* ssl);
WOLFSSL_API int wolfSSL_get_wfd(const WOLFSSL* ssl);
/* please see note at top of README if you get an error from connect */
WOLFSSL_ABI WOLFSSL_API int wolfSSL_connect(WOLFSSL* ssl);
WOLFSSL_ABI WOLFSSL_API int wolfSSL_write(
@ -1366,6 +1367,7 @@ WOLFSSL_ABI WOLFSSL_API int wolfSSL_write(
WOLFSSL_ABI WOLFSSL_API int wolfSSL_read(WOLFSSL* ssl, void* data, int sz);
WOLFSSL_API int wolfSSL_peek(WOLFSSL* ssl, void* data, int sz);
WOLFSSL_ABI WOLFSSL_API int wolfSSL_accept(WOLFSSL* ssl);
WOLFSSL_API int wolfSSL_inject(WOLFSSL* ssl, const void* data, int sz);
WOLFSSL_API int wolfSSL_CTX_mutual_auth(WOLFSSL_CTX* ctx, int req);
WOLFSSL_API int wolfSSL_mutual_auth(WOLFSSL* ssl, int req);
@ -1733,8 +1735,16 @@ WOLFSSL_API int wolfSSL_dtls(WOLFSSL* ssl);
WOLFSSL_API void* wolfSSL_dtls_create_peer(int port, char* ip);
WOLFSSL_API int wolfSSL_dtls_free_peer(void* addr);
WOLFSSL_API int wolfSSL_dtls_set_peer(WOLFSSL* ssl, void* peer, unsigned int peerSz);
WOLFSSL_API int wolfSSL_dtls_get_peer(WOLFSSL* ssl, void* peer, unsigned int* peerSz);
WOLFSSL_API int wolfSSL_dtls_set_peer(WOLFSSL* ssl, void* peer,
unsigned int peerSz);
WOLFSSL_API int wolfSSL_dtls_set_pending_peer(WOLFSSL* ssl, void* peer,
unsigned int peerSz);
WOLFSSL_API int wolfSSL_dtls_get_peer(WOLFSSL* ssl, void* peer,
unsigned int* peerSz);
WOLFSSL_API int wolfSSL_dtls_get0_peer(WOLFSSL* ssl, const void** peer,
unsigned int* peerSz);
WOLFSSL_API byte wolfSSL_is_stateful(WOLFSSL* ssl);
#if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS)
WOLFSSL_API int wolfSSL_CTX_dtls_set_sctp(WOLFSSL_CTX* ctx);
@ -4727,6 +4737,7 @@ WOLFSSL_API int wolfSSL_CTX_DisableExtendedMasterSecret(WOLFSSL_CTX* ctx);
#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
WOLFSSL_API int wolfDTLS_accept_stateless(WOLFSSL* ssl);
/* notify user we parsed a verified ClientHello is done. This only has an effect
* on the server end. */
typedef int (*ClientHelloGoodCb)(WOLFSSL* ssl, void*);
@ -5861,11 +5872,15 @@ WOLFSSL_API int wolfSSL_dtls_cid_get_rx_size(WOLFSSL* ssl,
unsigned int* size);
WOLFSSL_API int wolfSSL_dtls_cid_get_rx(WOLFSSL* ssl, unsigned char* buffer,
unsigned int bufferSz);
WOLFSSL_API int wolfSSL_dtls_cid_get0_rx(WOLFSSL* ssl, unsigned char** cid);
WOLFSSL_API int wolfSSL_dtls_cid_get_tx_size(WOLFSSL* ssl,
unsigned int* size);
WOLFSSL_API int wolfSSL_dtls_cid_get_tx(WOLFSSL* ssl, unsigned char* buffer,
unsigned int bufferSz);
WOLFSSL_API int wolfSSL_dtls_cid_get0_tx(WOLFSSL* ssl, unsigned char** cid);
WOLFSSL_API int wolfSSL_dtls_cid_max_size(void);
WOLFSSL_API const unsigned char* wolfSSL_dtls_cid_parse(const unsigned char* msg,
unsigned int msgSz, unsigned int cidSz);
#endif /* defined(WOLFSSL_DTLS_CID) */
#ifdef WOLFSSL_DTLS_CH_FRAG

View File

@ -611,6 +611,8 @@ WOLFSSL_API void wolfSSL_CTX_SetIORecv(WOLFSSL_CTX *ctx, CallbackIORecv CBIORecv
WOLFSSL_API void wolfSSL_CTX_SetIOSend(WOLFSSL_CTX *ctx, CallbackIOSend CBIOSend);
WOLFSSL_API void wolfSSL_SSLSetIORecv(WOLFSSL *ssl, CallbackIORecv CBIORecv);
WOLFSSL_API void wolfSSL_SSLSetIOSend(WOLFSSL *ssl, CallbackIOSend CBIOSend);
WOLFSSL_API void wolfSSL_SSLDisableRead(WOLFSSL *ssl);
WOLFSSL_API void wolfSSL_SSLEnableRead(WOLFSSL *ssl);
/* deprecated old name */
#define wolfSSL_SetIORecv wolfSSL_CTX_SetIORecv
#define wolfSSL_SetIOSend wolfSSL_CTX_SetIOSend