|
@@ -8864,7 +8864,7 @@ static int SendHandshakeMsg(WOLFSSL* ssl, byte* input, word32 inputSz,
|
|
|
WOLFSSL_MSG("Can't use output buffer for input in SendHandshakeMsg");
|
|
|
return BAD_FUNC_ARG;
|
|
|
}
|
|
|
- if (ssl->fragOffset == 0) {
|
|
|
+ if (!ssl->options.buildingMsg) {
|
|
|
/* Hash it before the loop as we modify the input with
|
|
|
* encryption on */
|
|
|
ret = HashOutput(ssl, input, headerSz + (int)inputSz, 0);
|
|
@@ -8882,6 +8882,9 @@ static int SendHandshakeMsg(WOLFSSL* ssl, byte* input, word32 inputSz,
|
|
|
int outputSz;
|
|
|
byte* data = input + ssl->fragOffset + headerSz;
|
|
|
word32 fragSz = (word32)maxFrag;
|
|
|
+
|
|
|
+ ssl->options.buildingMsg = 1;
|
|
|
+
|
|
|
if (inputSz - ssl->fragOffset < fragSz)
|
|
|
fragSz = inputSz - ssl->fragOffset;
|
|
|
|
|
@@ -8967,6 +8970,7 @@ static int SendHandshakeMsg(WOLFSSL* ssl, byte* input, word32 inputSz,
|
|
|
ssl->keys.dtls_handshake_number++;
|
|
|
#endif
|
|
|
ssl->fragOffset = 0;
|
|
|
+ ssl->options.buildingMsg = 0;
|
|
|
return ret;
|
|
|
}
|
|
|
#endif /* !NO_WOLFSSL_SERVER || (!NO_WOLFSSL_CLIENT && !NO_CERTS &&
|
|
@@ -18188,6 +18192,10 @@ int SendChangeCipher(WOLFSSL* ssl)
|
|
|
sendSz += MAX_MSG_EXTRA;
|
|
|
}
|
|
|
|
|
|
+ /* Set this in case CheckAvailableSize returns a WANT_WRITE so that state
|
|
|
+ * is not advanced yet */
|
|
|
+ ssl->options.buildingMsg = 1;
|
|
|
+
|
|
|
/* check for available size */
|
|
|
if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
|
|
|
return ret;
|
|
@@ -18247,6 +18255,8 @@ int SendChangeCipher(WOLFSSL* ssl)
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
+ ssl->options.buildingMsg = 0;
|
|
|
+
|
|
|
if (ssl->options.groupMessages)
|
|
|
return 0;
|
|
|
#if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_DEBUG_DTLS)
|
|
@@ -19043,6 +19053,11 @@ int SendFinished(WOLFSSL* ssl)
|
|
|
|
|
|
/* check for available size */
|
|
|
outputSz = sizeof(input) + MAX_MSG_EXTRA;
|
|
|
+
|
|
|
+ /* Set this in case CheckAvailableSize returns a WANT_WRITE so that state
|
|
|
+ * is not advanced yet */
|
|
|
+ ssl->options.buildingMsg = 1;
|
|
|
+
|
|
|
if ((ret = CheckAvailableSize(ssl, outputSz)) != 0)
|
|
|
return ret;
|
|
|
|
|
@@ -19145,6 +19160,8 @@ int SendFinished(WOLFSSL* ssl)
|
|
|
|
|
|
ret = SendBuffered(ssl);
|
|
|
|
|
|
+ ssl->options.buildingMsg = 0;
|
|
|
+
|
|
|
#ifdef WOLFSSL_DTLS
|
|
|
if ((!ssl->options.resuming &&
|
|
|
ssl->options.side == WOLFSSL_SERVER_END) ||
|
|
@@ -19394,6 +19411,8 @@ int SendCertificate(WOLFSSL* ssl)
|
|
|
word32 i = RECORD_HEADER_SZ;
|
|
|
int sendSz = RECORD_HEADER_SZ;
|
|
|
|
|
|
+ ssl->options.buildingMsg = 1;
|
|
|
+
|
|
|
if (!ssl->options.dtls) {
|
|
|
if (ssl->fragOffset == 0) {
|
|
|
if (headerSz + certSz + certChainSz <=
|
|
@@ -19434,6 +19453,9 @@ int SendCertificate(WOLFSSL* ssl)
|
|
|
output = ssl->buffers.outputBuffer.buffer +
|
|
|
ssl->buffers.outputBuffer.length;
|
|
|
|
|
|
+ /* Safe to use ssl->fragOffset since it will be incremented immediately
|
|
|
+ * after this block. This block needs to be entered only once to not
|
|
|
+ * hash the cert msg twice. */
|
|
|
if (ssl->fragOffset == 0) {
|
|
|
if (!ssl->options.dtls) {
|
|
|
AddFragHeaders(output, fragSz, 0, payloadSz, certificate, ssl);
|
|
@@ -19583,6 +19605,7 @@ int SendCertificate(WOLFSSL* ssl)
|
|
|
|
|
|
if (ret != WANT_WRITE) {
|
|
|
/* Clean up the fragment offset. */
|
|
|
+ ssl->options.buildingMsg = 0;
|
|
|
ssl->fragOffset = 0;
|
|
|
#ifdef WOLFSSL_DTLS
|
|
|
if (ssl->options.dtls)
|
|
@@ -19657,6 +19680,10 @@ int SendCertificateRequest(WOLFSSL* ssl)
|
|
|
if (IsEncryptionOn(ssl, 1))
|
|
|
sendSz += cipherExtraData(ssl);
|
|
|
|
|
|
+ /* Set this in case CheckAvailableSize returns a WANT_WRITE so that state
|
|
|
+ * is not advanced yet */
|
|
|
+ ssl->options.buildingMsg = 1;
|
|
|
+
|
|
|
/* check for available size */
|
|
|
if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
|
|
|
return ret;
|
|
@@ -19772,6 +19799,8 @@ int SendCertificateRequest(WOLFSSL* ssl)
|
|
|
else
|
|
|
ret = SendBuffered(ssl);
|
|
|
|
|
|
+ ssl->options.buildingMsg = 0;
|
|
|
+
|
|
|
WOLFSSL_LEAVE("SendCertificateRequest", ret);
|
|
|
WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_SEND);
|
|
|
|
|
@@ -19812,6 +19841,10 @@ static int BuildCertificateStatus(WOLFSSL* ssl, byte type, buffer* status,
|
|
|
if (ssl->keys.encryptionOn)
|
|
|
sendSz += MAX_MSG_EXTRA;
|
|
|
|
|
|
+ /* Set this in case CheckAvailableSize returns a WANT_WRITE so that state
|
|
|
+ * is not advanced yet */
|
|
|
+ ssl->options.buildingMsg = 1;
|
|
|
+
|
|
|
if ((ret = CheckAvailableSize(ssl, sendSz)) == 0) {
|
|
|
output = ssl->buffers.outputBuffer.buffer +
|
|
|
ssl->buffers.outputBuffer.length;
|
|
@@ -19876,6 +19909,7 @@ static int BuildCertificateStatus(WOLFSSL* ssl, byte type, buffer* status,
|
|
|
#endif
|
|
|
|
|
|
if (ret == 0) {
|
|
|
+ ssl->options.buildingMsg = 0;
|
|
|
ssl->buffers.outputBuffer.length += sendSz;
|
|
|
if (!ssl->options.groupMessages)
|
|
|
ret = SendBuffered(ssl);
|
|
@@ -20574,8 +20608,16 @@ int SendAlert(WOLFSSL* ssl, int severity, int type)
|
|
|
|
|
|
/* check for available size */
|
|
|
outputSz = ALERT_SIZE + MAX_MSG_EXTRA + dtlsExtra;
|
|
|
- if ((ret = CheckAvailableSize(ssl, outputSz)) != 0)
|
|
|
- return ret;
|
|
|
+ if ((ret = CheckAvailableSize(ssl, outputSz)) != 0) {
|
|
|
+ /* If CheckAvailableSize returned WANT_WRITE due to a blocking write
|
|
|
+ * then discard pending output and just send the alert. */
|
|
|
+ if (ret != WANT_WRITE || severity != alert_fatal)
|
|
|
+ return ret;
|
|
|
+ ShrinkOutputBuffer(ssl);
|
|
|
+ if ((ret = CheckAvailableSize(ssl, outputSz)) != 0) {
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
/* Check output buffer */
|
|
|
if (ssl->buffers.outputBuffer.buffer == NULL)
|
|
@@ -23310,6 +23352,10 @@ exit_dpk:
|
|
|
if (IsEncryptionOn(ssl, 1))
|
|
|
sendSz += MAX_MSG_EXTRA;
|
|
|
|
|
|
+ /* Set this in case CheckAvailableSize returns a WANT_WRITE so that state
|
|
|
+ * is not advanced yet */
|
|
|
+ ssl->options.buildingMsg = 1;
|
|
|
+
|
|
|
/* check for available size */
|
|
|
if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
|
|
|
return ret;
|
|
@@ -23470,6 +23516,8 @@ exit_dpk:
|
|
|
WRITE_PROTO, ssl->heap);
|
|
|
#endif
|
|
|
|
|
|
+ ssl->options.buildingMsg = 0;
|
|
|
+
|
|
|
ssl->buffers.outputBuffer.length += sendSz;
|
|
|
|
|
|
ret = SendBuffered(ssl);
|
|
@@ -25631,7 +25679,7 @@ static void FreeSckeArgs(WOLFSSL* ssl, void* pArgs)
|
|
|
int SendClientKeyExchange(WOLFSSL* ssl)
|
|
|
{
|
|
|
int ret = 0;
|
|
|
-#ifdef WOLFSSL_ASYNC_CRYPT
|
|
|
+#ifdef WOLFSSL_ASYNC_IO
|
|
|
SckeArgs* args = NULL;
|
|
|
WOLFSSL_ASSERT_SIZEOF_GE(ssl->async->args, *args);
|
|
|
#else
|
|
@@ -25648,7 +25696,7 @@ int SendClientKeyExchange(WOLFSSL* ssl)
|
|
|
ssl->CBIS(ssl, SSL_CB_CONNECT_LOOP, SSL_SUCCESS);
|
|
|
#endif
|
|
|
|
|
|
-#ifdef WOLFSSL_ASYNC_CRYPT
|
|
|
+#ifdef WOLFSSL_ASYNC_IO
|
|
|
if (ssl->async == NULL) {
|
|
|
ssl->async = (struct WOLFSSL_ASYNC*)
|
|
|
XMALLOC(sizeof(struct WOLFSSL_ASYNC), ssl->heap,
|
|
@@ -25658,6 +25706,7 @@ int SendClientKeyExchange(WOLFSSL* ssl)
|
|
|
}
|
|
|
args = (SckeArgs*)ssl->async->args;
|
|
|
|
|
|
+#ifdef WOLFSSL_ASYNC_CRYPT
|
|
|
ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState);
|
|
|
if (ret != WC_NOT_PENDING_E) {
|
|
|
/* Check for error */
|
|
@@ -25665,13 +25714,21 @@ int SendClientKeyExchange(WOLFSSL* ssl)
|
|
|
goto exit_scke;
|
|
|
}
|
|
|
else
|
|
|
+#endif
|
|
|
+ if (ssl->options.buildingMsg) {
|
|
|
+ /* Continue building the message */
|
|
|
+ }
|
|
|
+ else
|
|
|
#endif
|
|
|
{
|
|
|
/* Reset state */
|
|
|
ret = 0;
|
|
|
ssl->options.asyncState = TLS_ASYNC_BEGIN;
|
|
|
XMEMSET(args, 0, sizeof(SckeArgs));
|
|
|
- #ifdef WOLFSSL_ASYNC_CRYPT
|
|
|
+ /* Set this in case CheckAvailableSize returns a WANT_WRITE so that state
|
|
|
+ * is not advanced yet */
|
|
|
+ ssl->options.buildingMsg = 1;
|
|
|
+ #ifdef WOLFSSL_ASYNC_IO
|
|
|
ssl->async->freeArgs = FreeSckeArgs;
|
|
|
#endif
|
|
|
}
|
|
@@ -26680,9 +26737,8 @@ int SendClientKeyExchange(WOLFSSL* ssl)
|
|
|
}
|
|
|
|
|
|
/* check for available size */
|
|
|
- if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) {
|
|
|
+ if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0)
|
|
|
goto exit_scke;
|
|
|
- }
|
|
|
|
|
|
/* get output buffer */
|
|
|
args->output = ssl->buffers.outputBuffer.buffer +
|
|
@@ -26773,6 +26829,7 @@ int SendClientKeyExchange(WOLFSSL* ssl)
|
|
|
ret = tmpRet; /* save WANT_WRITE unless more serious */
|
|
|
}
|
|
|
ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE;
|
|
|
+ ssl->options.buildingMsg = 0;
|
|
|
}
|
|
|
#if defined(OPENSSL_EXTRA) && defined(HAVE_SECRET_CALLBACK)
|
|
|
if (ssl->keyLogCb != NULL) {
|
|
@@ -26794,10 +26851,14 @@ exit_scke:
|
|
|
WOLFSSL_LEAVE("SendClientKeyExchange", ret);
|
|
|
WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND);
|
|
|
|
|
|
-#ifdef WOLFSSL_ASYNC_CRYPT
|
|
|
+#ifdef WOLFSSL_ASYNC_IO
|
|
|
/* Handle async operation */
|
|
|
- if (ret == WC_PENDING_E)
|
|
|
- return ret;
|
|
|
+ if (ret == WC_PENDING_E || ret == WANT_WRITE) {
|
|
|
+ if (ssl->options.buildingMsg)
|
|
|
+ return ret;
|
|
|
+ /* If we have completed all states then we will not enter this function
|
|
|
+ * again. We need to do clean up now. */
|
|
|
+ }
|
|
|
#endif
|
|
|
|
|
|
/* No further need for PMS */
|
|
@@ -26807,7 +26868,7 @@ exit_scke:
|
|
|
ssl->arrays->preMasterSz = 0;
|
|
|
|
|
|
/* Final cleanup */
|
|
|
-#ifdef WOLFSSL_ASYNC_CRYPT
|
|
|
+#ifdef WOLFSSL_ASYNC_IO
|
|
|
/* Cleanup async */
|
|
|
FreeAsyncCtx(ssl, 0);
|
|
|
#else
|
|
@@ -26894,7 +26955,7 @@ int SendCertificateVerify(WOLFSSL* ssl)
|
|
|
}
|
|
|
else
|
|
|
#endif
|
|
|
- if (ssl->fragOffset != 0) {
|
|
|
+ if (ssl->options.buildingMsg) {
|
|
|
/* We should be in the sending state. */
|
|
|
if (ssl->options.asyncState != TLS_ASYNC_END) {
|
|
|
ret = BAD_STATE_E;
|
|
@@ -27225,12 +27286,6 @@ int SendCertificateVerify(WOLFSSL* ssl)
|
|
|
if (args->output == NULL) {
|
|
|
ERROR_OUT(BUFFER_ERROR, exit_scv);
|
|
|
}
|
|
|
- #ifdef WOLFSSL_DTLS
|
|
|
- /* We have re-entered this funtion after a WANT_WRITE. Make sure
|
|
|
- * the handshake number stays the same. */
|
|
|
- if (ssl->options.dtls && ssl->fragOffset != 0)
|
|
|
- ssl->keys.dtls_handshake_number--;
|
|
|
- #endif
|
|
|
AddHeaders(args->output, (word32)args->length + args->extraSz +
|
|
|
VERIFY_HEADER, certificate_verify, ssl);
|
|
|
|
|
@@ -27615,6 +27670,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
|
|
if (IsEncryptionOn(ssl, 1))
|
|
|
sendSz += MAX_MSG_EXTRA;
|
|
|
|
|
|
+ /* Set this in case CheckAvailableSize returns a WANT_WRITE so that state
|
|
|
+ * is not advanced yet */
|
|
|
+ ssl->options.buildingMsg = 1;
|
|
|
+
|
|
|
/* check for available size */
|
|
|
if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
|
|
|
return ret;
|
|
@@ -27769,6 +27828,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
|
|
#endif
|
|
|
|
|
|
ssl->options.serverState = SERVER_HELLO_COMPLETE;
|
|
|
+ ssl->options.buildingMsg = 0;
|
|
|
ssl->buffers.outputBuffer.length += sendSz;
|
|
|
|
|
|
if (ssl->options.groupMessages)
|
|
@@ -27885,7 +27945,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
|
|
}
|
|
|
else
|
|
|
#endif
|
|
|
- if (ssl->fragOffset != 0) {
|
|
|
+ if (ssl->options.buildingMsg) {
|
|
|
/* We should be in the sending state. */
|
|
|
if (ssl->options.asyncState != TLS_ASYNC_END) {
|
|
|
ret = BAD_STATE_E;
|
|
@@ -29344,12 +29404,6 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
|
|
|
|
|
case TLS_ASYNC_FINALIZE:
|
|
|
{
|
|
|
- #ifdef WOLFSSL_DTLS
|
|
|
- /* We have re-entered this funtion after a WANT_WRITE. Make sure
|
|
|
- * the handshake number stays the same. */
|
|
|
- if (ssl->options.dtls && ssl->fragOffset != 0)
|
|
|
- ssl->keys.dtls_handshake_number--;
|
|
|
- #endif
|
|
|
#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \
|
|
|
defined(HAVE_CURVE448)
|
|
|
if (ssl->specs.kea == ecdhe_psk_kea ||
|
|
@@ -31060,6 +31114,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
|
|
if (IsEncryptionOn(ssl, 1))
|
|
|
sendSz += MAX_MSG_EXTRA;
|
|
|
|
|
|
+ /* Set this in case CheckAvailableSize returns a WANT_WRITE so that state
|
|
|
+ * is not advanced yet */
|
|
|
+ ssl->options.buildingMsg = 1;
|
|
|
+
|
|
|
/* check for available size */
|
|
|
if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
|
|
|
return ret;
|
|
@@ -31120,6 +31178,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
|
|
WRITE_PROTO, ssl->heap);
|
|
|
#endif
|
|
|
ssl->options.serverState = SERVER_HELLODONE_COMPLETE;
|
|
|
+ ssl->options.buildingMsg = 0;
|
|
|
|
|
|
ssl->buffers.outputBuffer.length += sendSz;
|
|
|
|
|
@@ -31544,6 +31603,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
|
|
if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone)
|
|
|
sendSz += cipherExtraData(ssl);
|
|
|
|
|
|
+ /* Set this in case CheckAvailableSize returns a WANT_WRITE so that state
|
|
|
+ * is not advanced yet */
|
|
|
+ ssl->options.buildingMsg = 1;
|
|
|
+
|
|
|
/* check for available size */
|
|
|
if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
|
|
|
return ret;
|
|
@@ -31601,6 +31664,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
|
|
}
|
|
|
|
|
|
ssl->buffers.outputBuffer.length += sendSz;
|
|
|
+ ssl->options.buildingMsg = 0;
|
|
|
|
|
|
if (!ssl->options.groupMessages)
|
|
|
ret = SendBuffered(ssl);
|
|
@@ -32065,6 +32129,10 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
|
|
|
if (ssl->options.dtls)
|
|
|
sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA;
|
|
|
|
|
|
+ /* Set this in case CheckAvailableSize returns a WANT_WRITE so that state
|
|
|
+ * is not advanced yet */
|
|
|
+ ssl->options.buildingMsg = 1;
|
|
|
+
|
|
|
/* check for available size */
|
|
|
if ((ret = CheckAvailableSize(ssl, sendSz)) != 0)
|
|
|
return ret;
|
|
@@ -32106,6 +32174,7 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ],
|
|
|
}
|
|
|
|
|
|
ssl->buffers.outputBuffer.length += sendSz;
|
|
|
+ ssl->options.buildingMsg = 0;
|
|
|
|
|
|
ret = SendBuffered(ssl);
|
|
|
|