mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-07-30 02:37:28 +02:00
Merge pull request #5284 from julek-wolfssl/dtls-good-ch-cb
DTLS 1.3: additions for event driven server in wolfssl-examples
This commit is contained in:
@ -1595,7 +1595,87 @@ WOLFSSL* wolfSSL_new(WOLFSSL_CTX*);
|
||||
\sa wolfSSL_SetIOReadCtx
|
||||
\sa wolfSSL_SetIOWriteCtx
|
||||
*/
|
||||
int wolfSSL_set_fd (WOLFSSL* ssl, int fd);
|
||||
int wolfSSL_set_fd(WOLFSSL* ssl, int fd);
|
||||
|
||||
/*!
|
||||
\ingroup Setup
|
||||
|
||||
\brief This function assigns a file descriptor (fd) as the
|
||||
input/output facility for the SSL connection. Typically this will be
|
||||
a socket file descriptor. This is a DTLS specific API because it marks that
|
||||
the socket is connected. recvfrom and sendto calls on this fd will have the
|
||||
addr and addr_len parameters set to NULL.
|
||||
|
||||
\return SSL_SUCCESS upon success.
|
||||
\return Bad_FUNC_ARG upon failure.
|
||||
|
||||
\param ssl pointer to the SSL session, created with wolfSSL_new().
|
||||
\param fd file descriptor to use with SSL/TLS connection.
|
||||
|
||||
_Example_
|
||||
\code
|
||||
int sockfd;
|
||||
WOLFSSL* ssl = 0;
|
||||
...
|
||||
if (connect(sockfd, peer_addr, peer_addr_len) != 0) {
|
||||
// handle connect error
|
||||
}
|
||||
...
|
||||
ret = wolfSSL_set_dtls_fd_connected(ssl, sockfd);
|
||||
if (ret != SSL_SUCCESS) {
|
||||
// failed to set SSL file descriptor
|
||||
}
|
||||
\endcode
|
||||
|
||||
\sa wolfSSL_CTX_SetIOSend
|
||||
\sa wolfSSL_CTX_SetIORecv
|
||||
\sa wolfSSL_SetIOReadCtx
|
||||
\sa wolfSSL_SetIOWriteCtx
|
||||
\sa wolfDTLS_SetChGoodCb
|
||||
*/
|
||||
int wolfSSL_set_dtls_fd_connected(WOLFSSL* ssl, int fd)
|
||||
|
||||
/*!
|
||||
\ingroup Setup
|
||||
|
||||
\brief Allows setting a callback for a correctly processed and verified DTLS
|
||||
client hello. When using a cookie exchange mechanism (either the
|
||||
HelloVerifyRequest in DTLS 1.2 or the HelloRetryRequest with a cookie
|
||||
extension in DTLS 1.3) this callback is called after the cookie
|
||||
exchange has succeeded. This is useful to use one WOLFSSL object as
|
||||
the listener for new connections and being able to isolate the
|
||||
WOLFSSL object once the ClientHello is verified (either through a
|
||||
cookie exchange or just checking if the ClientHello had the correct
|
||||
format).
|
||||
DTLS 1.2:
|
||||
https://datatracker.ietf.org/doc/html/rfc6347#section-4.2.1
|
||||
DTLS 1.3:
|
||||
https://www.rfc-editor.org/rfc/rfc8446#section-4.2.2
|
||||
|
||||
\return SSL_SUCCESS upon success.
|
||||
\return BAD_FUNC_ARG upon failure.
|
||||
|
||||
\param ssl pointer to the SSL session, created with wolfSSL_new().
|
||||
\param fd file descriptor to use with SSL/TLS connection.
|
||||
|
||||
_Example_
|
||||
\code
|
||||
|
||||
// Called when we have verified a connection
|
||||
static int chGoodCb(WOLFSSL* ssl, void* arg)
|
||||
{
|
||||
// setup peer and file descriptors
|
||||
|
||||
}
|
||||
|
||||
if (wolfDTLS_SetChGoodCb(ssl, chGoodCb, NULL) != WOLFSSL_SUCCESS) {
|
||||
// error setting callback
|
||||
}
|
||||
\endcode
|
||||
|
||||
\sa wolfSSL_set_dtls_fd_connected
|
||||
*/
|
||||
int wolfDTLS_SetChGoodCb(WOLFSSL* ssl, ClientHelloGoodCb cb, void* user_ctx);
|
||||
|
||||
/*!
|
||||
\ingroup IO
|
||||
@ -3521,9 +3601,11 @@ int wolfSSL_dtls(WOLFSSL* ssl);
|
||||
\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 peer’s sockaddr_in structure.
|
||||
\param peerSz size of the sockaddr_in structure pointed to by peer.
|
||||
\param ssl a pointer to a WOLFSSL structure, created using wolfSSL_new().
|
||||
\param peer pointer to peer’s 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
|
||||
|
14
src/dtls13.c
14
src/dtls13.c
@ -331,6 +331,8 @@ static byte Dtls13RtxMsgNeedsAck(WOLFSSL* ssl, enum HandShakeType hs)
|
||||
message */
|
||||
if (ssl->options.side == WOLFSSL_SERVER_END && (hs == finished))
|
||||
return 1;
|
||||
#else
|
||||
(void)ssl;
|
||||
#endif /* NO_WOLFSSL_SERVER */
|
||||
|
||||
if (hs == session_ticket || hs == key_update)
|
||||
@ -1388,6 +1390,18 @@ static int _Dtls13HandshakeRecv(WOLFSSL* ssl, byte* input, word32 size,
|
||||
if (frag_off + frag_length > message_length)
|
||||
return BUFFER_ERROR;
|
||||
|
||||
if (handshake_type == client_hello &&
|
||||
/* Only when receiving an unverified ClientHello */
|
||||
ssl->options.serverState < SERVER_HELLO_COMPLETE) {
|
||||
/* To be able to operate in stateless mode, we assume the ClientHello
|
||||
* is in order and we use its Handshake Message number and Sequence
|
||||
* Number for our Tx. */
|
||||
ssl->keys.dtls_expected_peer_handshake_number =
|
||||
ssl->keys.dtls_handshake_number =
|
||||
ssl->keys.dtls_peer_handshake_number;
|
||||
ssl->dtls13Epochs[0].nextSeqNumber = ssl->keys.curSeq;
|
||||
}
|
||||
|
||||
ret = Dtls13RtxMsgRecvd(ssl, (enum HandShakeType)handshake_type, frag_off);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
@ -554,7 +554,7 @@ int IsDtlsNotSctpMode(WOLFSSL* ssl)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef WOLFSSL_NO_TLS12
|
||||
#if !defined(WOLFSSL_NO_TLS12) && !defined(NO_WOLFSSL_SERVER)
|
||||
/* Secure Real-time Transport Protocol */
|
||||
/* If SRTP is not enabled returns the state of the dtls option.
|
||||
* If SRTP is enabled returns dtls && !dtlsSrtpProfiles. */
|
||||
@ -566,7 +566,7 @@ static WC_INLINE int IsDtlsNotSrtpMode(WOLFSSL* ssl)
|
||||
return ssl->options.dtls;
|
||||
#endif
|
||||
}
|
||||
#endif /* !WOLFSSL_NO_TLS12 */
|
||||
#endif /* !WOLFSSL_NO_TLS12 && !NO_WOLFSSL_SERVER */
|
||||
#endif /* WOLFSSL_DTLS */
|
||||
|
||||
|
||||
@ -8788,6 +8788,14 @@ static int EdDSA_Update(WOLFSSL* ssl, const byte* data, int sz)
|
||||
int HashRaw(WOLFSSL* ssl, const byte* data, int sz)
|
||||
{
|
||||
int ret = 0;
|
||||
#ifdef WOLFSSL_DEBUG_TLS
|
||||
byte digest[WC_MAX_DIGEST_SIZE];
|
||||
|
||||
WOLFSSL_MSG("HashRaw:");
|
||||
WOLFSSL_MSG("Data:");
|
||||
WOLFSSL_BUFFER(data, sz);
|
||||
WOLFSSL_MSG("Hashes:");
|
||||
#endif
|
||||
|
||||
(void)data;
|
||||
(void)sz;
|
||||
@ -8817,16 +8825,31 @@ int HashRaw(WOLFSSL* ssl, const byte* data, int sz)
|
||||
ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, data, sz);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
#ifdef WOLFSSL_DEBUG_TLS
|
||||
WOLFSSL_MSG("Sha256");
|
||||
wc_Sha256GetHash(&ssl->hsHashes->hashSha256, digest);
|
||||
WOLFSSL_BUFFER(digest, WC_SHA224_DIGEST_SIZE);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef WOLFSSL_SHA384
|
||||
ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, data, sz);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
#ifdef WOLFSSL_DEBUG_TLS
|
||||
WOLFSSL_MSG("Sha384");
|
||||
wc_Sha384GetHash(&ssl->hsHashes->hashSha384, digest);
|
||||
WOLFSSL_BUFFER(digest, WC_SHA384_DIGEST_SIZE);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef WOLFSSL_SHA512
|
||||
ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, data, sz);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
#ifdef WOLFSSL_DEBUG_TLS
|
||||
WOLFSSL_MSG("Sha512");
|
||||
wc_Sha512GetHash(&ssl->hsHashes->hashSha512, digest);
|
||||
WOLFSSL_BUFFER(digest, WC_SHA512_DIGEST_SIZE);
|
||||
#endif
|
||||
#endif
|
||||
#if !defined(WOLFSSL_NO_CLIENT_AUTH) && \
|
||||
((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \
|
||||
|
59
src/ssl.c
59
src/ssl.c
@ -890,6 +890,25 @@ int wolfSSL_set_fd(WOLFSSL* ssl, int fd)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef WOLFSSL_DTLS
|
||||
int wolfSSL_set_dtls_fd_connected(WOLFSSL* ssl, int fd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
WOLFSSL_ENTER("SSL_set_dtls_fd_connected");
|
||||
|
||||
if (ssl == NULL) {
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
ret = wolfSSL_set_fd(ssl, fd);
|
||||
if (ret == WOLFSSL_SUCCESS)
|
||||
ssl->buffers.dtlsCtx.connected = 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
int wolfSSL_set_read_fd(WOLFSSL* ssl, int fd)
|
||||
{
|
||||
@ -903,6 +922,7 @@ int wolfSSL_set_read_fd(WOLFSSL* ssl, int fd)
|
||||
ssl->IOCB_ReadCtx = &ssl->rfd;
|
||||
|
||||
#ifdef WOLFSSL_DTLS
|
||||
ssl->buffers.dtlsCtx.connected = 0;
|
||||
if (ssl->options.dtls) {
|
||||
ssl->IOCB_ReadCtx = &ssl->buffers.dtlsCtx;
|
||||
ssl->buffers.dtlsCtx.rfd = fd;
|
||||
@ -926,6 +946,7 @@ int wolfSSL_set_write_fd(WOLFSSL* ssl, int fd)
|
||||
ssl->IOCB_WriteCtx = &ssl->wfd;
|
||||
|
||||
#ifdef WOLFSSL_DTLS
|
||||
ssl->buffers.dtlsCtx.connected = 0;
|
||||
if (ssl->options.dtls) {
|
||||
ssl->IOCB_WriteCtx = &ssl->buffers.dtlsCtx;
|
||||
ssl->buffers.dtlsCtx.wfd = fd;
|
||||
@ -1183,6 +1204,16 @@ int wolfSSL_dtls_set_peer(WOLFSSL* ssl, void* peer, unsigned int peerSz)
|
||||
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) {
|
||||
@ -1192,6 +1223,8 @@ int wolfSSL_dtls_set_peer(WOLFSSL* ssl, void* peer, unsigned int peerSz)
|
||||
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;
|
||||
}
|
||||
return WOLFSSL_FAILURE;
|
||||
@ -12527,6 +12560,18 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
|
||||
return wolfSSL_accept_TLSv13(ssl);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_DTLS
|
||||
if (ssl->chGoodCb != NULL && !IsSCR(ssl)) {
|
||||
int cbret = ssl->chGoodCb(ssl, ssl->chGoodCtx);
|
||||
if (cbret < 0) {
|
||||
ssl->error = cbret;
|
||||
WOLFSSL_MSG("ClientHello Good Cb don't continue error");
|
||||
return WOLFSSL_FATAL_ERROR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ssl->options.acceptState = ACCEPT_FIRST_REPLY_DONE;
|
||||
WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE");
|
||||
FALL_THROUGH;
|
||||
@ -12748,6 +12793,20 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
|
||||
|
||||
#endif /* NO_WOLFSSL_SERVER */
|
||||
|
||||
#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
|
||||
int wolfDTLS_SetChGoodCb(WOLFSSL* ssl, ClientHelloGoodCb cb, void* user_ctx)
|
||||
{
|
||||
WOLFSSL_ENTER("wolfDTLS_SetChGoodCb");
|
||||
|
||||
if (ssl == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
|
||||
ssl->chGoodCb = cb;
|
||||
ssl->chGoodCtx = user_ctx;
|
||||
|
||||
return WOLFSSL_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef NO_HANDSHAKE_DONE_CB
|
||||
|
||||
|
13
src/tls.c
13
src/tls.c
@ -6167,8 +6167,17 @@ static int TLSX_Cookie_Parse(WOLFSSL* ssl, const byte* input, word16 length,
|
||||
|
||||
/* client_hello */
|
||||
extension = TLSX_Find(ssl->extensions, TLSX_COOKIE);
|
||||
if (extension == NULL)
|
||||
return HRR_COOKIE_ERROR;
|
||||
if (extension == NULL) {
|
||||
#ifdef WOLFSSL_DTLS13
|
||||
if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version))
|
||||
/* Allow a cookie extension with DTLS 1.3 because it is possible
|
||||
* that a different SSL instance sent the cookie but we are now
|
||||
* receiving it. */
|
||||
return TLSX_Cookie_Use(ssl, input + idx, len, NULL, 0, 0);
|
||||
else
|
||||
#endif
|
||||
return HRR_COOKIE_ERROR;
|
||||
}
|
||||
|
||||
cookie = (Cookie*)extension->data;
|
||||
if (cookie->len != len || XMEMCMP(&cookie->data, input + idx, len) != 0)
|
||||
|
184
src/tls13.c
184
src/tls13.c
@ -2823,17 +2823,30 @@ static int CreateCookie(WOLFSSL* ssl, byte* hash, byte hashSz)
|
||||
cookieType = WC_SHA256;
|
||||
macSz = WC_SHA256_DIGEST_SIZE;
|
||||
#endif /* NO_SHA256 */
|
||||
XMEMSET(&cookieHmac, 0, sizeof(Hmac));
|
||||
|
||||
ret = wc_HmacSetKey(&cookieHmac, cookieType,
|
||||
ssl->buffers.tls13CookieSecret.buffer,
|
||||
ssl->buffers.tls13CookieSecret.length);
|
||||
ret = wc_HmacInit(&cookieHmac, ssl->heap, INVALID_DEVID);
|
||||
if (ret == 0) {
|
||||
ret = wc_HmacSetKey(&cookieHmac, cookieType,
|
||||
ssl->buffers.tls13CookieSecret.buffer,
|
||||
ssl->buffers.tls13CookieSecret.length);
|
||||
}
|
||||
if (ret == 0)
|
||||
ret = wc_HmacUpdate(&cookieHmac, hash, hashSz);
|
||||
#ifdef WOLFSSL_DTLS13
|
||||
/* Tie cookie to peer address */
|
||||
if (ret == 0) {
|
||||
if (ssl->options.dtls && ssl->buffers.dtlsCtx.peer.sz > 0) {
|
||||
ret = wc_HmacUpdate(&cookieHmac, ssl->buffers.dtlsCtx.peer.sa,
|
||||
ssl->buffers.dtlsCtx.peer.sz);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (ret == 0)
|
||||
ret = wc_HmacFinal(&cookieHmac, mac);
|
||||
|
||||
wc_HmacFree(&cookieHmac);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
if ((ret = wc_HmacUpdate(&cookieHmac, hash, hashSz)) != 0)
|
||||
return ret;
|
||||
if ((ret = wc_HmacFinal(&cookieHmac, mac)) != 0)
|
||||
return ret;
|
||||
|
||||
/* The cookie data is the hash and the integrity check. */
|
||||
return TLSX_Cookie_Use(ssl, hash, hashSz, mac, macSz, 1);
|
||||
@ -2889,7 +2902,7 @@ int RestartHandshakeHash(WOLFSSL* ssl)
|
||||
#endif
|
||||
|
||||
#if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER)
|
||||
if (ssl->options.sendCookie) {
|
||||
if (ssl->options.sendCookie && ssl->options.side == WOLFSSL_SERVER_END) {
|
||||
byte cookie[OPAQUE8_LEN + WC_MAX_DIGEST_SIZE + OPAQUE16_LEN * 2];
|
||||
TLSX* ext;
|
||||
word32 idx = 0;
|
||||
@ -4766,17 +4779,30 @@ static int CheckCookie(WOLFSSL* ssl, byte* cookie, byte cookieSz)
|
||||
if (cookieSz < ssl->specs.hash_size + macSz)
|
||||
return HRR_COOKIE_ERROR;
|
||||
cookieSz -= macSz;
|
||||
XMEMSET(&cookieHmac, 0, sizeof(Hmac));
|
||||
|
||||
ret = wc_HmacSetKey(&cookieHmac, cookieType,
|
||||
ssl->buffers.tls13CookieSecret.buffer,
|
||||
ssl->buffers.tls13CookieSecret.length);
|
||||
ret = wc_HmacInit(&cookieHmac, ssl->heap, INVALID_DEVID);
|
||||
if (ret == 0) {
|
||||
ret = wc_HmacSetKey(&cookieHmac, cookieType,
|
||||
ssl->buffers.tls13CookieSecret.buffer,
|
||||
ssl->buffers.tls13CookieSecret.length);
|
||||
}
|
||||
if (ret == 0)
|
||||
ret = wc_HmacUpdate(&cookieHmac, cookie, cookieSz);
|
||||
#ifdef WOLFSSL_DTLS13
|
||||
/* Tie cookie to peer address */
|
||||
if (ret == 0) {
|
||||
if (ssl->options.dtls && ssl->buffers.dtlsCtx.peer.sz > 0) {
|
||||
ret = wc_HmacUpdate(&cookieHmac, ssl->buffers.dtlsCtx.peer.sa,
|
||||
ssl->buffers.dtlsCtx.peer.sz);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (ret == 0)
|
||||
ret = wc_HmacFinal(&cookieHmac, mac);
|
||||
|
||||
wc_HmacFree(&cookieHmac);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
if ((ret = wc_HmacUpdate(&cookieHmac, cookie, cookieSz)) != 0)
|
||||
return ret;
|
||||
if ((ret = wc_HmacFinal(&cookieHmac, mac)) != 0)
|
||||
return ret;
|
||||
|
||||
if (ConstantCompare(cookie + cookieSz, mac, macSz) != 0)
|
||||
return HRR_COOKIE_ERROR;
|
||||
@ -4833,6 +4859,10 @@ static int RestartHandshakeHashWithCookie(WOLFSSL* ssl, Cookie* cookie)
|
||||
return ret;
|
||||
if ((ret = HashRaw(ssl, header, sizeof(header))) != 0)
|
||||
return ret;
|
||||
#ifdef WOLFSSL_DEBUG_TLS
|
||||
WOLFSSL_MSG("Restart Hash from Cookie");
|
||||
WOLFSSL_BUFFER(cookieData + idx, hashSz);
|
||||
#endif
|
||||
if ((ret = HashRaw(ssl, cookieData + idx, hashSz)) != 0)
|
||||
return ret;
|
||||
|
||||
@ -5282,20 +5312,45 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
||||
|
||||
#if defined(WOLFSSL_SEND_HRR_COOKIE)
|
||||
if (ssl->options.sendCookie &&
|
||||
ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
|
||||
TLSX* ext;
|
||||
(ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE
|
||||
#ifdef WOLFSSL_DTLS13
|
||||
/* Always check for a valid cookie since we may have already
|
||||
* sent a HRR but we reset the state. */
|
||||
|| ssl->options.dtls
|
||||
#endif
|
||||
)) {
|
||||
TLSX* ext = TLSX_Find(ssl->extensions, TLSX_COOKIE);
|
||||
|
||||
if ((ext = TLSX_Find(ssl->extensions, TLSX_COOKIE)) == NULL)
|
||||
ERROR_OUT(HRR_COOKIE_ERROR, exit_dch);
|
||||
|
||||
/* Ensure the cookie came from client and isn't the one in the
|
||||
* response - HelloRetryRequest.
|
||||
*/
|
||||
if (ext->resp == 1)
|
||||
ERROR_OUT(HRR_COOKIE_ERROR, exit_dch);
|
||||
ret = RestartHandshakeHashWithCookie(ssl, (Cookie*)ext->data);
|
||||
if (ret != 0)
|
||||
goto exit_dch;
|
||||
if (ext != NULL) {
|
||||
/* Ensure the cookie came from client and isn't the one in the
|
||||
* response - HelloRetryRequest.
|
||||
*/
|
||||
if (ext->resp == 0) {
|
||||
ret = RestartHandshakeHashWithCookie(ssl, (Cookie*)ext->data);
|
||||
#ifdef WOLFSSL_DTLS13
|
||||
/* Send a new cookie request */
|
||||
if (ret == HRR_COOKIE_ERROR && ssl->options.dtls)
|
||||
ssl->options.serverState = NULL_STATE;
|
||||
else
|
||||
#endif
|
||||
if (ret != 0)
|
||||
goto exit_dch;
|
||||
ssl->options.serverState = SERVER_HELLO_COMPLETE;
|
||||
}
|
||||
else {
|
||||
#ifdef WOLFSSL_DTLS13
|
||||
if (ssl->options.dtls)
|
||||
ssl->options.serverState = NULL_STATE;
|
||||
else
|
||||
#endif
|
||||
ERROR_OUT(HRR_COOKIE_ERROR, exit_dch);
|
||||
}
|
||||
}
|
||||
else
|
||||
#ifdef WOLFSSL_DTLS13
|
||||
if (!ssl->options.dtls)
|
||||
#endif
|
||||
ERROR_OUT(HRR_COOKIE_ERROR, exit_dch);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -5424,9 +5479,9 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
||||
/* We are using DTLSv13 and set the HRR cookie secret, use the cookie to
|
||||
perform a return-routability check. */
|
||||
if (ret == 0 && ssl->options.dtls && ssl->options.sendCookie &&
|
||||
ssl->options.serverState != SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
|
||||
ssl->options.serverState < SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
|
||||
|
||||
/* ssl->options.serverState != SERVER_HELLO_RETRY_REQUEST_COMPLETE
|
||||
/* ssl->options.serverState < SERVER_HELLO_RETRY_REQUEST_COMPLETE
|
||||
so the client already provided a good KeyShareEntry. In this case
|
||||
we don't add the KEY_SHARE extension to the HelloRetryRequest or
|
||||
in the Cookie. The RFC8446 forbids to select a supported group
|
||||
@ -5556,18 +5611,27 @@ int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType)
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
|
||||
#ifdef WOLFSSL_DTLS13
|
||||
if (ssl->options.dtls) {
|
||||
ret = Dtls13HashHandshake(ssl,
|
||||
output + Dtls13GetRlHeaderLength(0) ,
|
||||
sendSz - Dtls13GetRlHeaderLength(0));
|
||||
#ifdef WOLFSSL_SEND_HRR_COOKIE
|
||||
if (ssl->options.sendCookie && extMsgType == hello_retry_request) {
|
||||
/* Reset the hashes from here. We will be able to restart the hashes
|
||||
* from the cookie in RestartHandshakeHashWithCookie */
|
||||
ret = InitHandshakeHashes(ssl);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#ifdef WOLFSSL_DTLS13
|
||||
if (ssl->options.dtls) {
|
||||
ret = Dtls13HashHandshake(ssl,
|
||||
output + Dtls13GetRlHeaderLength(0) ,
|
||||
sendSz - Dtls13GetRlHeaderLength(0));
|
||||
}
|
||||
else
|
||||
#endif /* WOLFSSL_DTLS13 */
|
||||
{
|
||||
ret = HashOutput(ssl, output, sendSz, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
@ -5598,7 +5662,6 @@ int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType)
|
||||
ssl->buffers.outputBuffer.length += sendSz;
|
||||
|
||||
if (!ssl->options.groupMessages || extMsgType != server_hello)
|
||||
|
||||
ret = SendBuffered(ssl);
|
||||
|
||||
WOLFSSL_LEAVE("SendTls13ServerHello", ret);
|
||||
@ -10754,6 +10817,38 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl)
|
||||
WOLFSSL_ERROR(ssl->error);
|
||||
return WOLFSSL_FATAL_ERROR;
|
||||
}
|
||||
#ifdef WOLFSSL_DTLS13
|
||||
if (ssl->options.dtls && wolfSSL_dtls_get_using_nonblock(ssl)) {
|
||||
/* Reset the state so that we can statelessly await the
|
||||
* ClientHello that contains the cookie. Return a WANT_READ
|
||||
* to the user so that we don't drop UDP messages in the
|
||||
* network callbacks. */
|
||||
|
||||
/* Reset DTLS window */
|
||||
w64Zero(&ssl->dtls13Epochs[0].nextSeqNumber);
|
||||
w64Zero(&ssl->dtls13Epochs[0].nextPeerSeqNumber);
|
||||
XMEMSET(ssl->dtls13Epochs[0].window, 0,
|
||||
sizeof(ssl->dtls13Epochs[0].window));
|
||||
|
||||
ssl->keys.dtls_expected_peer_handshake_number = 0;
|
||||
ssl->keys.dtls_handshake_number = 0;
|
||||
|
||||
ssl->msgsReceived.got_client_hello = 0;
|
||||
/* Remove cookie so that it will get computed again */
|
||||
TLSX_Remove(&ssl->extensions, TLSX_COOKIE, ssl->heap);
|
||||
|
||||
/* Reset states */
|
||||
ssl->options.serverState = NULL_STATE;
|
||||
ssl->options.clientState = NULL_STATE;
|
||||
ssl->options.connectState = CONNECT_BEGIN;
|
||||
ssl->options.acceptState = ACCEPT_BEGIN;
|
||||
ssl->options.handShakeState = NULL_STATE;
|
||||
|
||||
ssl->error = WANT_READ;
|
||||
WOLFSSL_ERROR(ssl->error);
|
||||
return WOLFSSL_FATAL_ERROR;
|
||||
}
|
||||
#endif /* WOLFSSL_DTLS13 */
|
||||
}
|
||||
|
||||
ssl->options.acceptState = TLS13_ACCEPT_HELLO_RETRY_REQUEST_DONE;
|
||||
@ -10798,6 +10893,17 @@ int wolfSSL_accept_TLSv13(WOLFSSL* ssl)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WOLFSSL_DTLS
|
||||
if (ssl->chGoodCb != NULL) {
|
||||
int cbret = ssl->chGoodCb(ssl, ssl->chGoodCtx);
|
||||
if (cbret < 0) {
|
||||
ssl->error = cbret;
|
||||
WOLFSSL_MSG("ClientHello Good Cb don't continue error");
|
||||
return WOLFSSL_FATAL_ERROR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ssl->options.acceptState = TLS13_ACCEPT_SECOND_REPLY_DONE;
|
||||
WOLFSSL_MSG("accept state ACCEPT_SECOND_REPLY_DONE");
|
||||
FALL_THROUGH;
|
||||
|
48
src/wolfio.c
48
src/wolfio.c
@ -382,11 +382,35 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
|
||||
int sd = dtlsCtx->rfd;
|
||||
int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl);
|
||||
byte doDtlsTimeout;
|
||||
SOCKADDR_S peer;
|
||||
XSOCKLENT peerSz = sizeof(peer);
|
||||
SOCKADDR_S lclPeer;
|
||||
SOCKADDR_S* peer;
|
||||
XSOCKLENT peerSz;
|
||||
|
||||
WOLFSSL_ENTER("EmbedReceiveFrom()");
|
||||
|
||||
if (dtlsCtx->connected) {
|
||||
peer = NULL;
|
||||
}
|
||||
else if (dtlsCtx->userSet) {
|
||||
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;
|
||||
}
|
||||
peer = (SOCKADDR_S*)dtlsCtx->peer.sa;
|
||||
peerSz = dtlsCtx->peer.bufSz;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
@ -443,10 +467,8 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
|
||||
}
|
||||
#endif /* !NO_ASN_TIME */
|
||||
|
||||
XMEMSET(&peer, 0, sizeof(peer));
|
||||
|
||||
recvd = (int)DTLS_RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags,
|
||||
(SOCKADDR*)&peer, &peerSz);
|
||||
(SOCKADDR*)peer, peer != NULL ? &peerSz : NULL);
|
||||
|
||||
recvd = TranslateReturnCode(recvd, sd);
|
||||
|
||||
@ -459,15 +481,23 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx)
|
||||
}
|
||||
return recvd;
|
||||
}
|
||||
else {
|
||||
else if (dtlsCtx->connected) {
|
||||
/* Nothing to do */
|
||||
}
|
||||
else if (dtlsCtx->userSet) {
|
||||
/* Check we received the packet from the correct peer */
|
||||
if (dtlsCtx->peer.sz > 0 &&
|
||||
(peerSz != (XSOCKLENT)dtlsCtx->peer.sz ||
|
||||
!sockAddrEqual(&peer, peerSz, (SOCKADDR_S*)dtlsCtx->peer.sa,
|
||||
!sockAddrEqual(peer, peerSz, (SOCKADDR_S*)dtlsCtx->peer.sa,
|
||||
dtlsCtx->peer.sz))) {
|
||||
WOLFSSL_MSG(" Ignored packet from invalid peer");
|
||||
return WOLFSSL_CBIO_ERR_WANT_READ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Store size of saved address */
|
||||
dtlsCtx->peer.sz = peerSz;
|
||||
}
|
||||
#ifndef NO_ASN_TIME
|
||||
ssl->dtls_start_timeout = 0;
|
||||
#endif /* !NO_ASN_TIME */
|
||||
@ -488,8 +518,8 @@ int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx)
|
||||
WOLFSSL_ENTER("EmbedSendTo()");
|
||||
|
||||
sent = (int)DTLS_SENDTO_FUNCTION(sd, buf, sz, ssl->wflags,
|
||||
(const SOCKADDR*)dtlsCtx->peer.sa,
|
||||
dtlsCtx->peer.sz);
|
||||
!dtlsCtx->connected ? (const SOCKADDR*)dtlsCtx->peer.sa : NULL,
|
||||
!dtlsCtx->connected ? dtlsCtx->peer.sz : 0);
|
||||
|
||||
sent = TranslateReturnCode(sent, sd);
|
||||
|
||||
|
@ -463,6 +463,7 @@ int wc_PRF_TLS(byte* digest, word32 digLen, const byte* secret, word32 secLen,
|
||||
WOLFSSL_BUFFER(prk, prkLen);
|
||||
WOLFSSL_MSG(" Info");
|
||||
WOLFSSL_BUFFER(data, idx);
|
||||
WOLFSSL_MSG_EX(" Digest %d", digest);
|
||||
#endif
|
||||
|
||||
ret = wc_HKDF_Expand(digest, prk, prkLen, data, idx, okm, okmLen);
|
||||
|
@ -2219,6 +2219,7 @@ WOLFSSL_LOCAL int DoVerifyCallback(WOLFSSL_CERT_MANAGER* cm, WOLFSSL* ssl,
|
||||
/* wolfSSL Sock Addr */
|
||||
struct WOLFSSL_SOCKADDR {
|
||||
unsigned int sz; /* sockaddr size */
|
||||
unsigned int bufSz; /* size of allocated buffer */
|
||||
void* sa; /* pointer to the sockaddr_in or sockaddr_in6 */
|
||||
};
|
||||
|
||||
@ -2226,6 +2227,11 @@ typedef struct WOLFSSL_DTLS_CTX {
|
||||
WOLFSSL_SOCKADDR peer;
|
||||
int rfd;
|
||||
int wfd;
|
||||
byte userSet:1;
|
||||
byte connected:1; /* When set indicates rfd and wfd sockets are
|
||||
* connected (connect() and bind() both called).
|
||||
* This means that sendto and recvfrom do not need to
|
||||
* specify and store the peer address. */
|
||||
} WOLFSSL_DTLS_CTX;
|
||||
|
||||
|
||||
@ -4478,6 +4484,11 @@ struct WOLFSSL {
|
||||
#ifdef WOLFSSL_STATIC_MEMORY
|
||||
WOLFSSL_HEAP_HINT heap_hint;
|
||||
#endif
|
||||
#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
|
||||
ClientHelloGoodCb chGoodCb; /* notify user we parsed a verified
|
||||
* ClientHello */
|
||||
void* chGoodCtx; /* user ClientHello cb context */
|
||||
#endif
|
||||
#ifndef NO_HANDSHAKE_DONE_CB
|
||||
HandShakeDoneCb hsDoneCb; /* notify user handshake done */
|
||||
void* hsDoneCtx; /* user handshake cb context */
|
||||
|
@ -1045,6 +1045,9 @@ WOLFSSL_API int wolfSSL_CTX_set1_param(WOLFSSL_CTX* ctx, WOLFSSL_X509_VERIFY_PAR
|
||||
WOLFSSL_API int wolfSSL_is_server(WOLFSSL* ssl);
|
||||
WOLFSSL_API WOLFSSL* wolfSSL_write_dup(WOLFSSL* ssl);
|
||||
WOLFSSL_ABI WOLFSSL_API int wolfSSL_set_fd(WOLFSSL* ssl, int fd);
|
||||
#ifdef WOLFSSL_DTLS
|
||||
WOLFSSL_API int wolfSSL_set_dtls_fd_connected(WOLFSSL* ssl, int fd);
|
||||
#endif
|
||||
WOLFSSL_API int wolfSSL_set_write_fd (WOLFSSL* ssl, int fd);
|
||||
WOLFSSL_API int wolfSSL_set_read_fd (WOLFSSL* ssl, int fd);
|
||||
WOLFSSL_API char* wolfSSL_get_cipher_list(int priority);
|
||||
@ -3940,6 +3943,13 @@ WOLFSSL_API int wolfSSL_CTX_DisableExtendedMasterSecret(WOLFSSL_CTX* ctx);
|
||||
#define WOLFSSL_CRL_START_MON 0x02 /* start monitoring flag */
|
||||
|
||||
|
||||
#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER)
|
||||
/* notify user we parsed a verified ClientHello is done. This only has an effect
|
||||
* on the server end. */
|
||||
typedef int (*ClientHelloGoodCb)(WOLFSSL* ssl, void*);
|
||||
WOLFSSL_API int wolfDTLS_SetChGoodCb(WOLFSSL* ssl, ClientHelloGoodCb cb, void* user_ctx);
|
||||
#endif
|
||||
|
||||
/* notify user the handshake is done */
|
||||
typedef int (*HandShakeDoneCb)(WOLFSSL* ssl, void*);
|
||||
WOLFSSL_API int wolfSSL_SetHsDoneCb(WOLFSSL* ssl, HandShakeDoneCb cb, void* user_ctx);
|
||||
|
Reference in New Issue
Block a user