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:
John Safranek
2022-07-05 10:14:59 -07:00
committed by GitHub
10 changed files with 401 additions and 56 deletions

View File

@ -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
@ -3522,8 +3602,10 @@ int wolfSSL_dtls(WOLFSSL* ssl);
with DTLS support.
\param ssl a pointer to a WOLFSSL structure, created using wolfSSL_new().
\param peer pointer to peers sockaddr_in structure.
\param peerSz size of the sockaddr_in structure pointed to by peer.
\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

View File

@ -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;

View File

@ -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)) || \

View File

@ -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

View File

@ -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)
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)

View File

@ -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_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_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;
if ((ext = TLSX_Find(ssl->extensions, TLSX_COOKIE)) == NULL)
ERROR_OUT(HRR_COOKIE_ERROR, exit_dch);
(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 != NULL) {
/* 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);
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,7 +5611,15 @@ int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType)
if (ret != 0)
return ret;
#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,
@ -5568,6 +5631,7 @@ int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType)
{
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;

View File

@ -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);

View File

@ -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);

View File

@ -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 */

View File

@ -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);