mirror of https://github.com/wolfSSL/wolfssl
ASYNC: Fix issues with TLS and DTLS
This commit is contained in:
parent
eb7a49a1d7
commit
f2d2dadc89
|
@ -3079,14 +3079,29 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
|
|||
}
|
||||
else {
|
||||
printf("Beginning secure resumption.\n");
|
||||
if (wolfSSL_SecureResume(ssl) != WOLFSSL_SUCCESS) {
|
||||
if ((ret = wolfSSL_SecureResume(ssl)) != WOLFSSL_SUCCESS) {
|
||||
err = wolfSSL_get_error(ssl, 0);
|
||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||
while (err == WC_PENDING_E) {
|
||||
err = 0;
|
||||
ret = wolfSSL_negotiate(ssl);
|
||||
if (ret != WOLFSSL_SUCCESS) {
|
||||
err = wolfSSL_get_error(ssl, 0);
|
||||
if (err == WC_PENDING_E) {
|
||||
ret = wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW);
|
||||
if (ret < 0) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (ret != WOLFSSL_SUCCESS) {
|
||||
printf("err = %d, %s\n", err,
|
||||
wolfSSL_ERR_error_string(err, buffer));
|
||||
wolfSSL_free(ssl); ssl = NULL;
|
||||
wolfSSL_CTX_free(ctx); ctx = NULL;
|
||||
err_sys("wolfSSL_SecureResume failed");
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf("SECURE RESUMPTION SUCCESSFUL\n");
|
||||
}
|
||||
|
|
132
src/internal.c
132
src/internal.c
|
@ -7042,7 +7042,7 @@ int DtlsMsgSet(DtlsMsg* msg, word32 seq, word16 epoch, const byte* data, byte ty
|
|||
|
||||
DtlsMsg* DtlsMsgFind(DtlsMsg* head, word32 epoch, word32 seq)
|
||||
{
|
||||
while (head != NULL && head->epoch == epoch && head->seq != seq) {
|
||||
while (head != NULL && !(head->epoch == epoch && head->seq == seq)) {
|
||||
head = head->next;
|
||||
}
|
||||
return head;
|
||||
|
@ -7111,7 +7111,8 @@ void DtlsMsgStore(WOLFSSL* ssl, word32 epoch, word32 seq, const byte* data,
|
|||
/* DtlsMsgInsert() is an in-order insert. */
|
||||
DtlsMsg* DtlsMsgInsert(DtlsMsg* head, DtlsMsg* item)
|
||||
{
|
||||
if (head == NULL || item->seq < head->seq) {
|
||||
if (head == NULL || (item->epoch <= head->epoch &&
|
||||
item->seq < head->seq)) {
|
||||
item->next = head;
|
||||
head = item;
|
||||
}
|
||||
|
@ -7122,7 +7123,8 @@ DtlsMsg* DtlsMsgInsert(DtlsMsg* head, DtlsMsg* item)
|
|||
DtlsMsg* cur = head->next;
|
||||
DtlsMsg* prev = head;
|
||||
while (cur) {
|
||||
if (item->seq < cur->seq) {
|
||||
if (item->epoch <= head->epoch &&
|
||||
item->seq < head->seq) {
|
||||
item->next = cur;
|
||||
prev->next = item;
|
||||
break;
|
||||
|
@ -11910,10 +11912,13 @@ static int DoHelloRequest(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
|||
return BUFFER_ERROR;
|
||||
|
||||
if (IsEncryptionOn(ssl, 0)) {
|
||||
/* If size == totalSz then we are in DtlsMsgDrain so no need to worry
|
||||
* about padding */
|
||||
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
|
||||
if (ssl->options.startedETMRead) {
|
||||
word32 digestSz = MacSize(ssl);
|
||||
if (*inOutIdx + ssl->keys.padSz + digestSz > totalSz)
|
||||
if (size != totalSz &&
|
||||
*inOutIdx + ssl->keys.padSz + digestSz > totalSz)
|
||||
return BUFFER_E;
|
||||
*inOutIdx += ssl->keys.padSz + digestSz;
|
||||
}
|
||||
|
@ -11921,7 +11926,8 @@ static int DoHelloRequest(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
|||
#endif
|
||||
{
|
||||
/* access beyond input + size should be checked against totalSz */
|
||||
if (*inOutIdx + ssl->keys.padSz > totalSz)
|
||||
if (size != totalSz &&
|
||||
*inOutIdx + ssl->keys.padSz > totalSz)
|
||||
return BUFFER_E;
|
||||
|
||||
*inOutIdx += ssl->keys.padSz;
|
||||
|
@ -11957,7 +11963,10 @@ int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size,
|
|||
if (finishedSz != size)
|
||||
return BUFFER_ERROR;
|
||||
|
||||
/* check against totalSz */
|
||||
/* check against totalSz
|
||||
* If size == totalSz then we are in DtlsMsgDrain so no need to worry about
|
||||
* padding */
|
||||
if (size != totalSz) {
|
||||
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
|
||||
if (ssl->options.startedETMRead) {
|
||||
if (*inOutIdx + size + ssl->keys.padSz + MacSize(ssl) > totalSz)
|
||||
|
@ -11969,6 +11978,7 @@ int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size,
|
|||
if (*inOutIdx + size + ssl->keys.padSz > totalSz)
|
||||
return BUFFER_E;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WOLFSSL_CALLBACKS
|
||||
if (ssl->hsInfoOn) AddPacketName(ssl, "Finished");
|
||||
|
@ -12304,9 +12314,6 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type)
|
|||
case change_cipher_hs:
|
||||
if (ssl->msgsReceived.got_change_cipher) {
|
||||
WOLFSSL_MSG("Duplicate ChangeCipher received");
|
||||
#ifdef WOLFSSL_EXTRA_ALERTS
|
||||
SendAlert(ssl, alert_fatal, unexpected_message);
|
||||
#endif
|
||||
return DUPLICATE_MSG_E;
|
||||
}
|
||||
/* DTLS is going to ignore the CCS message if the client key
|
||||
|
@ -12641,11 +12648,14 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
|||
}
|
||||
}
|
||||
#endif
|
||||
/* If size == totalSz then we are in DtlsMsgDrain so no need to worry
|
||||
* about padding */
|
||||
if (IsEncryptionOn(ssl, 0)) {
|
||||
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
|
||||
if (ssl->options.startedETMRead) {
|
||||
word32 digestSz = MacSize(ssl);
|
||||
if (*inOutIdx + ssl->keys.padSz + digestSz > totalSz)
|
||||
if (size != totalSz &&
|
||||
*inOutIdx + ssl->keys.padSz + digestSz > totalSz)
|
||||
return BUFFER_E;
|
||||
*inOutIdx += ssl->keys.padSz + digestSz;
|
||||
}
|
||||
|
@ -12654,9 +12664,9 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
|||
{
|
||||
/* access beyond input + size should be checked against totalSz
|
||||
*/
|
||||
if (*inOutIdx + ssl->keys.padSz > totalSz)
|
||||
if (size != totalSz &&
|
||||
*inOutIdx + ssl->keys.padSz > totalSz)
|
||||
return BUFFER_E;
|
||||
|
||||
*inOutIdx += ssl->keys.padSz;
|
||||
}
|
||||
}
|
||||
|
@ -13073,10 +13083,9 @@ static int DtlsMsgDrain(WOLFSSL* ssl)
|
|||
item->fragSz == item->sz &&
|
||||
ret == 0) {
|
||||
word32 idx = 0;
|
||||
/* If item is from the wrong epoch then just ignore it */
|
||||
if (ssl->keys.dtls_epoch == item->epoch &&
|
||||
(ret = DoHandShakeMsgType(ssl, item->msg, &idx, item->type,
|
||||
if ((ret = DoHandShakeMsgType(ssl, item->msg, &idx, item->type,
|
||||
item->sz, item->sz)) == 0) {
|
||||
if (item->type != finished)
|
||||
ssl->keys.dtls_expected_peer_handshake_number++;
|
||||
DtlsTxMsgListClean(ssl);
|
||||
}
|
||||
|
@ -13107,17 +13116,6 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
|||
|
||||
WOLFSSL_ENTER("DoDtlsHandShakeMsg()");
|
||||
|
||||
/* process any pending DTLS messages - this flow can happen with async */
|
||||
if (ssl->dtls_rx_msg_list != NULL) {
|
||||
ret = DtlsMsgDrain(ssl);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
/* if done processing fragment exit with success */
|
||||
if (totalSz == *inOutIdx)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* parse header */
|
||||
if (GetDtlsHandShakeHeader(ssl, input, inOutIdx, &type,
|
||||
&size, &fragOffset, &fragSz, totalSz) != 0) {
|
||||
|
@ -13274,7 +13272,33 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
|||
else {
|
||||
/* This branch is in order next, and a complete message. On success
|
||||
* clean the tx list. */
|
||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||
word32 idx = *inOutIdx;
|
||||
#endif
|
||||
WOLFSSL_MSG("Branch is in order and a complete message");
|
||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||
/* In async mode always store the message and process it with
|
||||
* DtlsMsgDrain because in case of a WC_PENDING_E it will be
|
||||
* easier this way. */
|
||||
if (ssl->dtls_rx_msg_list_sz < DTLS_POOL_SZ) {
|
||||
DtlsMsgStore(ssl, ssl->keys.curEpoch,
|
||||
ssl->keys.dtls_peer_handshake_number,
|
||||
input + idx, size, type,
|
||||
fragOffset, fragSz, ssl->heap);
|
||||
}
|
||||
if (idx + fragSz + ssl->keys.padSz > totalSz)
|
||||
return BUFFER_E;
|
||||
*inOutIdx = idx + fragSz + ssl->keys.padSz;
|
||||
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
|
||||
if (ssl->options.startedETMRead && ssl->keys.curEpoch != 0) {
|
||||
word32 digestSz = MacSize(ssl);
|
||||
if (*inOutIdx + digestSz > totalSz)
|
||||
return BUFFER_E;
|
||||
*inOutIdx += digestSz;
|
||||
}
|
||||
#endif
|
||||
ret = DtlsMsgDrain(ssl);
|
||||
#else
|
||||
ret = DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz);
|
||||
if (ret == 0) {
|
||||
DtlsTxMsgListClean(ssl);
|
||||
|
@ -13284,6 +13308,7 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
|||
ret = DtlsMsgDrain(ssl);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
WOLFSSL_LEAVE("DoDtlsHandShakeMsg()", ret);
|
||||
|
@ -14876,6 +14901,17 @@ int ProcessReply(WOLFSSL* ssl)
|
|||
return ssl->error;
|
||||
}
|
||||
|
||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||
/* process any pending DTLS messages - this flow can happen with async */
|
||||
if (ssl->dtls_rx_msg_list != NULL) {
|
||||
ret = DtlsMsgDrain(ssl);
|
||||
if (ret != 0) {
|
||||
WOLFSSL_ERROR(ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for (;;) {
|
||||
switch (ssl->options.processReply) {
|
||||
|
||||
|
@ -15319,9 +15355,15 @@ int ProcessReply(WOLFSSL* ssl)
|
|||
|
||||
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
|
||||
if (IsEncryptionOn(ssl, 0) && ssl->options.startedETMRead) {
|
||||
if (ssl->buffers.inputBuffer.length - ssl->keys.padSz -
|
||||
ssl->buffers.inputBuffer.idx -
|
||||
MacSize(ssl) > MAX_PLAINTEXT_SZ) {
|
||||
if ((ssl->buffers.inputBuffer.length -
|
||||
ssl->keys.padSz -
|
||||
MacSize(ssl) -
|
||||
ssl->buffers.inputBuffer.idx > MAX_PLAINTEXT_SZ)
|
||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||
&& ssl->buffers.inputBuffer.length !=
|
||||
ssl->buffers.inputBuffer.idx
|
||||
#endif
|
||||
) {
|
||||
WOLFSSL_MSG("Plaintext too long - Encrypt-Then-MAC");
|
||||
#if defined(WOLFSSL_EXTRA_ALERTS)
|
||||
SendAlert(ssl, alert_fatal, record_overflow);
|
||||
|
@ -15332,7 +15374,13 @@ int ProcessReply(WOLFSSL* ssl)
|
|||
else
|
||||
#endif
|
||||
if (ssl->buffers.inputBuffer.length -
|
||||
ssl->buffers.inputBuffer.idx > MAX_PLAINTEXT_SZ) {
|
||||
ssl->keys.padSz -
|
||||
ssl->buffers.inputBuffer.idx > MAX_PLAINTEXT_SZ
|
||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||
&& ssl->buffers.inputBuffer.length !=
|
||||
ssl->buffers.inputBuffer.idx
|
||||
#endif
|
||||
) {
|
||||
WOLFSSL_MSG("Plaintext too long");
|
||||
#if defined(WOLFSSL_TLS13) || defined(WOLFSSL_EXTRA_ALERTS)
|
||||
SendAlert(ssl, alert_fatal, record_overflow);
|
||||
|
@ -15392,7 +15440,15 @@ int ProcessReply(WOLFSSL* ssl)
|
|||
ret = BUFFER_ERROR;
|
||||
#endif
|
||||
}
|
||||
if (ret != 0) {
|
||||
if (ret != 0
|
||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||
/* In async case, on pending, move onto next message.
|
||||
* Current message should have been DtlsMsgStore'ed and
|
||||
* should be processed with DtlsMsgDrain */
|
||||
&& (!ssl->options.dtls
|
||||
|| ret != WC_PENDING_E)
|
||||
#endif
|
||||
) {
|
||||
WOLFSSL_ERROR(ret);
|
||||
return ret;
|
||||
}
|
||||
|
@ -15597,7 +15653,7 @@ int ProcessReply(WOLFSSL* ssl)
|
|||
|
||||
/* input exhausted? */
|
||||
if (ssl->buffers.inputBuffer.idx >= ssl->buffers.inputBuffer.length)
|
||||
return 0;
|
||||
return ret;
|
||||
|
||||
/* more messages per record */
|
||||
else if ((ssl->buffers.inputBuffer.idx - startIdx) < ssl->curSize) {
|
||||
|
@ -15632,15 +15688,19 @@ int ProcessReply(WOLFSSL* ssl)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
/* more records */
|
||||
else {
|
||||
WOLFSSL_MSG("More records in input");
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||
/* We are setup to read next message/record but we had an error
|
||||
* (probably WC_PENDING_E) so return that so it can be handled
|
||||
* by higher layers. */
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
#endif
|
||||
continue;
|
||||
default:
|
||||
WOLFSSL_MSG("Bad process input state, programming error");
|
||||
return INPUT_CASE_ERROR;
|
||||
|
|
|
@ -11783,6 +11783,14 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
|
|||
}
|
||||
#endif /* WOLFSSL_DTLS */
|
||||
|
||||
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_SECURE_RENEGOTIATION)
|
||||
/* This may be necessary in async so that we don't try to
|
||||
* renegotiate again */
|
||||
if (ssl->secure_renegotiation && ssl->secure_renegotiation->startScr) {
|
||||
ssl->secure_renegotiation->startScr = 0;
|
||||
}
|
||||
#endif /* WOLFSSL_ASYNC_CRYPT && HAVE_SECURE_RENEGOTIATION */
|
||||
|
||||
WOLFSSL_LEAVE("SSL_connect()", WOLFSSL_SUCCESS);
|
||||
return WOLFSSL_SUCCESS;
|
||||
|
||||
|
|
Loading…
Reference in New Issue