From 1addc4dafbdc9b76af04f38af8c713369c6923cf Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Fri, 26 Jul 2024 14:14:30 +1000 Subject: [PATCH] SSL asynchronous read/write and encrypt Add support for being able to read and write in different threads with same SSL object. Add support for encrypt in threads. --- src/dtls13.c | 120 +++++++++--- src/internal.c | 463 ++++++++++++++++++++++++++++++++++++--------- src/keys.c | 2 +- src/ssl.c | 81 +++++++- src/tls13.c | 7 +- src/wolfio.c | 35 +++- wolfssl/internal.h | 69 +++++-- wolfssl/ssl.h | 15 ++ 8 files changed, 654 insertions(+), 138 deletions(-) diff --git a/src/dtls13.c b/src/dtls13.c index 955b4198f1..117447a20c 100644 --- a/src/dtls13.c +++ b/src/dtls13.c @@ -339,9 +339,17 @@ static void Dtls13MsgWasProcessed(WOLFSSL* ssl, enum HandShakeType hs) if (ssl->options.dtlsStateful) ssl->keys.dtls_expected_peer_handshake_number++; - /* we need to send ACKs on the last message of a flight that needs explicit - acknowledgment */ - ssl->dtls13Rtx.sendAcks = Dtls13RtxMsgNeedsAck(ssl, hs); +#ifdef WOLFSSL_RW_THREADED + if (wc_LockMutex(&ssl->dtls13Rtx.mutex) == 0) +#endif + { + /* we need to send ACKs on the last message of a flight that needs + * explicit acknowledgment */ + ssl->dtls13Rtx.sendAcks = Dtls13RtxMsgNeedsAck(ssl, hs); + #ifdef WOLFSSL_RW_THREADED + wc_UnLockMutex(&ssl->dtls13Rtx.mutex); + #endif + } } int Dtls13ProcessBufferedMessages(WOLFSSL* ssl) @@ -652,8 +660,17 @@ static void Dtls13RtxRecordUnlink(WOLFSSL* ssl, Dtls13RtxRecord** prevNext, Dtls13RtxRecord* r) { /* if r was at the tail of the list, update the tail pointer */ - if (r->next == NULL) - ssl->dtls13Rtx.rtxRecordTailPtr = prevNext; + if (r->next == NULL) { + #ifdef WOLFSSL_RW_THREADED + if (wc_LockMutex(&ssl->dtls13Rtx.mutex) == 0) + #endif + { + ssl->dtls13Rtx.rtxRecordTailPtr = prevNext; + #ifdef WOLFSSL_RW_THREADED + wc_UnLockMutex(&ssl->dtls13Rtx.mutex); + #endif + } + } /* unlink */ *prevNext = r->next; @@ -710,12 +727,20 @@ static int Dtls13RtxAddAck(WOLFSSL* ssl, w64wrapper epoch, w64wrapper seq) WOLFSSL_ENTER("Dtls13RtxAddAck"); - rn = Dtls13NewRecordNumber(epoch, seq, ssl->heap); - if (rn == NULL) - return MEMORY_E; +#ifdef WOLFSSL_RW_THREADED + if (wc_LockMutex(&ssl->dtls13Rtx.mutex) == 0) +#endif + { + rn = Dtls13NewRecordNumber(epoch, seq, ssl->heap); + if (rn == NULL) + return MEMORY_E; - rn->next = ssl->dtls13Rtx.seenRecords; - ssl->dtls13Rtx.seenRecords = rn; + rn->next = ssl->dtls13Rtx.seenRecords; + ssl->dtls13Rtx.seenRecords = rn; + #ifdef WOLFSSL_RW_THREADED + wc_UnLockMutex(&ssl->dtls13Rtx.mutex); + #endif + } return 0; } @@ -728,15 +753,23 @@ static void Dtls13RtxFlushAcks(WOLFSSL* ssl) WOLFSSL_ENTER("Dtls13RtxFlushAcks"); - list = ssl->dtls13Rtx.seenRecords; +#ifdef WOLFSSL_RW_THREADED + if (wc_LockMutex(&ssl->dtls13Rtx.mutex) == 0) +#endif + { + list = ssl->dtls13Rtx.seenRecords; - while (list != NULL) { - rn = list; - list = rn->next; - XFREE(rn, ssl->heap, DYNAMIC_TYPE_DTLS_MSG); - } + while (list != NULL) { + rn = list; + list = rn->next; + XFREE(rn, ssl->heap, DYNAMIC_TYPE_DTLS_MSG); + } - ssl->dtls13Rtx.seenRecords = NULL; + ssl->dtls13Rtx.seenRecords = NULL; + #ifdef WOLFSSL_RW_THREADED + wc_UnLockMutex(&ssl->dtls13Rtx.mutex); + #endif + } } static int Dtls13DetectDisruption(WOLFSSL* ssl, word32 fragOffset) @@ -2522,13 +2555,25 @@ static void Dtls13RtxRemoveRecord(WOLFSSL* ssl, w64wrapper epoch, int Dtls13DoScheduledWork(WOLFSSL* ssl) { int ret; + int sendAcks; WOLFSSL_ENTER("Dtls13DoScheduledWork"); ssl->dtls13SendingAckOrRtx = 1; - if (ssl->dtls13Rtx.sendAcks) { +#ifdef WOLFSSL_RW_THREADED + ret = wc_LockMutex(&ssl->dtls13Rtx.mutex); + if (ret < 0) + return ret; +#endif + sendAcks = ssl->dtls13Rtx.sendAcks; + if (sendAcks) { ssl->dtls13Rtx.sendAcks = 0; + } +#ifdef WOLFSSL_RW_THREADED + ret = wc_UnLockMutex(&ssl->dtls13Rtx.mutex); +#endif + if (sendAcks) { ret = SendDtls13Ack(ssl); if (ret != 0) return ret; @@ -2604,13 +2649,28 @@ static int Dtls13RtxHasKeyUpdateBuffered(WOLFSSL* ssl) return 0; } +int DoDtls13KeyUpdateAck(WOLFSSL* ssl) +{ + int ret = 0; + + if (!Dtls13RtxHasKeyUpdateBuffered(ssl)) { + /* we removed the KeyUpdate message because it was ACKed */ + ssl->dtls13WaitKeyUpdateAck = 0; + ret = Dtls13KeyUpdateAckReceived(ssl); + } + + return ret; +} + int DoDtls13Ack(WOLFSSL* ssl, const byte* input, word32 inputSize, word32* processedSize) { const byte* ackMessage; w64wrapper epoch, seq; word16 length; +#ifndef WOLFSSL_RW_THREADED int ret; +#endif int i; if (inputSize < OPAQUE16_LEN) @@ -2642,15 +2702,13 @@ int DoDtls13Ack(WOLFSSL* ssl, const byte* input, word32 inputSize, ssl->options.serverState = SERVER_FINISHED_ACKED; } +#ifndef WOLFSSL_RW_THREADED if (ssl->dtls13WaitKeyUpdateAck) { - if (!Dtls13RtxHasKeyUpdateBuffered(ssl)) { - /* we removed the KeyUpdate message because it was ACKed */ - ssl->dtls13WaitKeyUpdateAck = 0; - ret = Dtls13KeyUpdateAckReceived(ssl); - if (ret != 0) - return ret; - } + ret = DoDtls13KeyUpdateAck(ssl); + if (ret != 0) + return ret; } +#endif *processedSize = length + OPAQUE16_LEN; @@ -2701,9 +2759,17 @@ int SendDtls13Ack(WOLFSSL* ssl) if (ret != 0) return ret; - ret = Dtls13WriteAckMessage(ssl, ssl->dtls13Rtx.seenRecords, &length); - if (ret != 0) +#ifdef WOLFSSL_RW_THREADED + ret = wc_LockMutex(&ssl->dtls13Rtx.mutex); + if (ret < 0) return ret; +#endif + ret = Dtls13WriteAckMessage(ssl, ssl->dtls13Rtx.seenRecords, &length); +#ifdef WOLFSSL_RW_THREADED + wc_UnLockMutex(&ssl->dtls13Rtx.mutex); +#endif + if (ret != 0) + return ret; output = GetOutputBuffer(ssl); diff --git a/src/internal.c b/src/internal.c index 8cc28ac53f..33aa7fb4f2 100644 --- a/src/internal.c +++ b/src/internal.c @@ -2883,74 +2883,62 @@ void InitCiphers(WOLFSSL* ssl) } - -/* Free ciphers */ -void FreeCiphers(WOLFSSL* ssl) +static void FreeCiphersSide(Ciphers *cipher, void* heap) { - (void)ssl; #ifdef BUILD_ARC4 - wc_Arc4Free(ssl->encrypt.arc4); - wc_Arc4Free(ssl->decrypt.arc4); - XFREE(ssl->encrypt.arc4, ssl->heap, DYNAMIC_TYPE_CIPHER); - XFREE(ssl->decrypt.arc4, ssl->heap, DYNAMIC_TYPE_CIPHER); + wc_Arc4Free(cipher->arc4); + XFREE(cipher->arc4, heap, DYNAMIC_TYPE_CIPHER); #endif #ifdef BUILD_DES3 - wc_Des3Free(ssl->encrypt.des3); - wc_Des3Free(ssl->decrypt.des3); - XFREE(ssl->encrypt.des3, ssl->heap, DYNAMIC_TYPE_CIPHER); - XFREE(ssl->decrypt.des3, ssl->heap, DYNAMIC_TYPE_CIPHER); + wc_Des3Free(cipher->des3); + XFREE(cipher->des3, heap, DYNAMIC_TYPE_CIPHER); #endif #if defined(BUILD_AES) || defined(BUILD_AESGCM) || defined(HAVE_ARIA) - /* See: InitKeys() in keys.c on addition of BUILD_AESGCM check (enc->aes, dec->aes) */ - wc_AesFree(ssl->encrypt.aes); - wc_AesFree(ssl->decrypt.aes); - XFREE(ssl->encrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER); - XFREE(ssl->decrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER); + /* See: InitKeys() in keys.c on addition of BUILD_AESGCM check (enc->aes, + * dec->aes) */ + wc_AesFree(cipher->aes); + XFREE(cipher->aes, heap, DYNAMIC_TYPE_CIPHER); #endif #if defined(WOLFSSL_SM4_GCM) || defined(WOLFSSL_SM4_CCM) - wc_Sm4Free(ssl->encrypt.sm4); - wc_Sm4Free(ssl->decrypt.sm4); - XFREE(ssl->encrypt.sm4, ssl->heap, DYNAMIC_TYPE_CIPHER); - XFREE(ssl->decrypt.sm4, ssl->heap, DYNAMIC_TYPE_CIPHER); + wc_Sm4Free(cipher->sm4); + XFREE(cipher->sm4, heap, DYNAMIC_TYPE_CIPHER); #endif #if (defined(BUILD_AESGCM) || defined(BUILD_AESCCM) || defined(HAVE_ARIA)) && \ !defined(WOLFSSL_NO_TLS12) - XFREE(ssl->decrypt.additional, ssl->heap, DYNAMIC_TYPE_CIPHER); - XFREE(ssl->encrypt.additional, ssl->heap, DYNAMIC_TYPE_CIPHER); + XFREE(cipher->additional, heap, DYNAMIC_TYPE_CIPHER); #endif #ifdef CIPHER_NONCE - XFREE(ssl->decrypt.nonce, ssl->heap, DYNAMIC_TYPE_CIPHER); - XFREE(ssl->encrypt.nonce, ssl->heap, DYNAMIC_TYPE_CIPHER); + XFREE(cipher->nonce, heap, DYNAMIC_TYPE_CIPHER); #endif #ifdef HAVE_ARIA - wc_AriaFreeCrypt(ssl->encrypt.aria); - wc_AriaFreeCrypt(ssl->decrypt.aria); - XFREE(ssl->encrypt.aria, ssl->heap, DYNAMIC_TYPE_CIPHER); - XFREE(ssl->decrypt.aria, ssl->heap, DYNAMIC_TYPE_CIPHER); + wc_AriaFreeCrypt(cipher->aria); + XFREE(cipher->aria, heap, DYNAMIC_TYPE_CIPHER); #endif #ifdef HAVE_CAMELLIA - XFREE(ssl->encrypt.cam, ssl->heap, DYNAMIC_TYPE_CIPHER); - XFREE(ssl->decrypt.cam, ssl->heap, DYNAMIC_TYPE_CIPHER); + XFREE(cipher->cam, heap, DYNAMIC_TYPE_CIPHER); #endif #ifdef HAVE_CHACHA - if (ssl->encrypt.chacha) - ForceZero(ssl->encrypt.chacha, sizeof(ChaCha)); - if (ssl->decrypt.chacha) - ForceZero(ssl->decrypt.chacha, sizeof(ChaCha)); - XFREE(ssl->encrypt.chacha, ssl->heap, DYNAMIC_TYPE_CIPHER); - XFREE(ssl->decrypt.chacha, ssl->heap, DYNAMIC_TYPE_CIPHER); + if (cipher->chacha) + ForceZero(cipher->chacha, sizeof(ChaCha)); + XFREE(cipher->chacha, heap, DYNAMIC_TYPE_CIPHER); +#endif +#if defined(WOLFSSL_TLS13) && defined(HAVE_NULL_CIPHER) + wc_HmacFree(cipher->hmac); + XFREE(cipher->hmac, heap, DYNAMIC_TYPE_CIPHER); #endif +} + +/* Free ciphers */ +void FreeCiphers(WOLFSSL* ssl) +{ + FreeCiphersSide(&ssl->encrypt, ssl->heap); + FreeCiphersSide(&ssl->decrypt, ssl->heap); + #if defined(HAVE_POLY1305) && defined(HAVE_ONE_TIME_AUTH) if (ssl->auth.poly1305) ForceZero(ssl->auth.poly1305, sizeof(Poly1305)); XFREE(ssl->auth.poly1305, ssl->heap, DYNAMIC_TYPE_CIPHER); #endif -#if defined(WOLFSSL_TLS13) && defined(HAVE_NULL_CIPHER) - wc_HmacFree(ssl->encrypt.hmac); - wc_HmacFree(ssl->decrypt.hmac); - XFREE(ssl->encrypt.hmac, ssl->heap, DYNAMIC_TYPE_CIPHER); - XFREE(ssl->decrypt.hmac, ssl->heap, DYNAMIC_TYPE_CIPHER); -#endif #ifdef WOLFSSL_DTLS13 #ifdef BUILD_AES @@ -2976,7 +2964,6 @@ void FreeCiphers(WOLFSSL* ssl) #endif /* WOLFSSL_DTLS13 */ } - void InitCipherSpecs(CipherSpecs* cs) { XMEMSET(cs, 0, sizeof(CipherSpecs)); @@ -7358,6 +7345,15 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) ssl->buffers.outputBuffer.buffer = ssl->buffers.outputBuffer.staticBuffer; ssl->buffers.outputBuffer.bufferSize = STATIC_BUFFER_LEN; +#ifdef WOLFSSL_THREADED_CRYPT + { + int i; + for (i = 0; i < WOLFSSL_THREADED_CRYPT_CNT; i++) { + ssl->buffers.encrypt[i].avail = 1; + } + } +#endif + #ifdef KEEP_PEER_CERT InitX509(&ssl->peerCert, 0, ssl->heap); #endif @@ -7692,6 +7688,13 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) ssl->dtls13DecryptEpoch = &ssl->dtls13Epochs[0]; ssl->options.dtls13SendMoreAcks = WOLFSSL_DTLS13_SEND_MOREACK_DEFAULT; ssl->dtls13Rtx.rtxRecordTailPtr = &ssl->dtls13Rtx.rtxRecords; + +#ifdef WOLFSSL_RW_THREADED + ret = wc_InitMutex(&ssl->dtls13Rtx.mutex); + if (ret < 0) { + return ret; + } +#endif #endif /* WOLFSSL_DTLS13 */ #ifdef WOLFSSL_QUIC @@ -8217,6 +8220,25 @@ void SSL_ResourceFree(WOLFSSL* ssl) ShrinkInputBuffer(ssl, FORCED_FREE); if (ssl->buffers.outputBuffer.dynamicFlag) ShrinkOutputBuffer(ssl); +#ifdef WOLFSSL_THREADED_CRYPT + { + int i; + for (i = 0; i < WOLFSSL_THREADED_CRYPT_CNT; i++) { + bufferStatic* buff = &ssl->buffers.encrypt[i].buffer; + + ssl->buffers.encrypt[i].stop = 1; + FreeCiphersSide(&ssl->buffers.encrypt[i].encrypt, ssl->heap); + if (buff->dynamicFlag) { + XFREE(buff->buffer - buff->offset, ssl->heap, + DYNAMIC_TYPE_OUT_BUFFER); + buff->buffer = buff->staticBuffer; + buff->bufferSize = STATIC_BUFFER_LEN; + buff->offset = 0; + buff->dynamicFlag = 0; + } + } + } +#endif #if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER) if (ssl->buffers.tls13CookieSecret.buffer != NULL) { ForceZero(ssl->buffers.tls13CookieSecret.buffer, @@ -8469,6 +8491,10 @@ void SSL_ResourceFree(WOLFSSL* ssl) #endif #ifdef WOLFSSL_DTLS13 Dtls13FreeFsmResources(ssl); + +#ifdef WOLFSSL_RW_THREADED + wc_FreeMutex(&ssl->dtls13Rtx.mutex); +#endif #endif /* WOLFSSL_DTLS13 */ #ifdef WOLFSSL_QUIC wolfSSL_quic_free(ssl); @@ -10709,6 +10735,69 @@ int SendBuffered(WOLFSSL* ssl) return 0; } +#ifdef WOLFSSL_THREADED_CRYPT +static WC_INLINE int GrowAnOutputBuffer(WOLFSSL* ssl, + bufferStatic* outputBuffer, int size) +{ + byte* tmp; +#if WOLFSSL_GENERAL_ALIGNMENT > 0 + byte hdrSz = ssl->options.dtls ? DTLS_RECORD_HEADER_SZ : + RECORD_HEADER_SZ; + byte align = WOLFSSL_GENERAL_ALIGNMENT; +#else + const byte align = WOLFSSL_GENERAL_ALIGNMENT; +#endif + +#if WOLFSSL_GENERAL_ALIGNMENT > 0 + /* the encrypted data will be offset from the front of the buffer by + the header, if the user wants encrypted alignment they need + to define their alignment requirement */ + + while (align < hdrSz) + align *= 2; +#endif + + tmp = (byte*)XMALLOC(size + outputBuffer->length + align, + ssl->heap, DYNAMIC_TYPE_OUT_BUFFER); + WOLFSSL_MSG("growing output buffer"); + + if (tmp == NULL) + return MEMORY_E; + +#if WOLFSSL_GENERAL_ALIGNMENT > 0 + if (align) + tmp += align - hdrSz; +#endif + +#ifdef WOLFSSL_STATIC_MEMORY + /* can be from IO memory pool which does not need copy if same buffer */ + if (outputBuffer->length && tmp == outputBuffer->buffer) { + outputBuffer->bufferSize = size + outputBuffer->length; + return 0; + } +#endif + + if (outputBuffer->length) + XMEMCPY(tmp, outputBuffer->buffer, outputBuffer->length); + + if (outputBuffer->dynamicFlag) { + XFREE(outputBuffer->buffer - outputBuffer->offset, ssl->heap, + DYNAMIC_TYPE_OUT_BUFFER); + } + +#if WOLFSSL_GENERAL_ALIGNMENT > 0 + if (align) + outputBuffer->offset = align - hdrSz; + else +#endif + outputBuffer->offset = 0; + + outputBuffer->buffer = tmp; + outputBuffer->dynamicFlag = 1; + outputBuffer->bufferSize = size + outputBuffer->length; + return 0; +} +#endif /* returns the current location in the output buffer to start writing to */ byte* GetOutputBuffer(WOLFSSL* ssl) @@ -22044,6 +22133,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) #endif } #endif + #ifndef WOLFSSL_RW_THREADED #ifdef WOLFSSL_TLS13 if (ssl->keys.keyUpdateRespond) { WOLFSSL_MSG("No KeyUpdate from peer seen"); @@ -22051,6 +22141,7 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) return SANITY_MSG_E; } #endif + #endif if ((ret = DoApplicationData(ssl, ssl->buffers.inputBuffer.buffer, &ssl->buffers.inputBuffer.idx, @@ -23006,6 +23097,29 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, ssl->keys.dtls_prev_sequence_number_lo; } #endif + +#ifdef WOLFSSL_THREADED_CRYPT + if (asyncOkay) { + WOLFSSL_MSG("Not encrypting\n"); + /* make sure build message state is reset */ + ssl->options.buildMsgState = BUILD_MSG_BEGIN; + + /* return sz on success */ + if (ret == 0) { + ret = args->sz; + } + else { + WOLFSSL_ERROR_VERBOSE(ret); + } + + /* Final cleanup */ + FreeBuildMsgArgs(ssl, args); + + return ret; + } + else +#endif + { #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) if (ssl->options.startedETMWrite) { ret = Encrypt(ssl, output + args->headerSz, @@ -23027,6 +23141,7 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, ssl->keys.dtls_sequence_number_lo = dtls_sequence_number_lo; } #endif + } } if (ret != 0) { @@ -24435,6 +24550,50 @@ static int CheckTLS13AEADSendLimit(WOLFSSL* ssl) } #endif /* WOLFSSL_TLS13 && !WOLFSSL_TLS13_IGNORE_AEAD_LIMITS */ +#ifdef WOLFSSL_THREADED_CRYPT +int SendAsyncData(WOLFSSL* ssl) +{ + int i; + + for (i = 0; i < WOLFSSL_THREADED_CRYPT_CNT; i++) { + ThreadCrypt* encrypt = &ssl->buffers.encrypt[i]; + + if (encrypt->done) { + int error; + + GrowOutputBuffer(ssl, encrypt->buffer.length); + XMEMCPY(ssl->buffers.outputBuffer.buffer, encrypt->buffer.buffer, + encrypt->buffer.length); + ssl->buffers.outputBuffer.length = encrypt->buffer.length; + ssl->buffers.outputBuffer.idx = 0; + encrypt->done = 0; + encrypt->avail = 1; + if ((error = SendBuffered(ssl)) < 0) { + ssl->error = error; + WOLFSSL_ERROR(ssl->error); + /* store for next call if WANT_WRITE or user embedSend() that + doesn't present like WANT_WRITE */ + ssl->buffers.plainSz = encrypt->buffer.length; + ssl->buffers.prevSent = encrypt->buffer.length; + if (ssl->error == SOCKET_ERROR_E && (ssl->options.connReset || + ssl->options.isClosed)) { + return SOCKET_PEER_CLOSED_E; /* peer reset or closed */ + } + return ssl->error; + } + + /* only one message per attempt */ + if (ssl->options.partialWrite == 1) { + WOLFSSL_MSG("Partial Write on, only sending one record"); + break; + } + } + } + + return 0; +} +#endif + /** * ssl_in_handshake(): * Invoked in wolfSSL_read/wolfSSL_write to check if wolfSSL_negotiate() is @@ -24489,18 +24648,20 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) #if defined(WOLFSSL_EARLY_DATA) && defined(WOLFSSL_EARLY_DATA_GROUP) int groupMsgs = 0; #endif + int error = ssl->error; - if (ssl->error == WC_NO_ERR_TRACE(WANT_WRITE) + if (error == WC_NO_ERR_TRACE(WANT_WRITE) #ifdef WOLFSSL_ASYNC_CRYPT - || ssl->error == WC_NO_ERR_TRACE(WC_PENDING_E) + || error == WC_NO_ERR_TRACE(WC_PENDING_E) #endif ) { + error = 0; ssl->error = 0; } /* don't allow write after decrypt or mac error */ - if (ssl->error == WC_NO_ERR_TRACE(VERIFY_MAC_ERROR) || - ssl->error == WC_NO_ERR_TRACE(DECRYPT_ERROR)) { + if (error == WC_NO_ERR_TRACE(VERIFY_MAC_ERROR) || + error == WC_NO_ERR_TRACE(DECRYPT_ERROR)) { /* For DTLS allow these possible errors and allow the session to continue despite them */ if (ssl->options.dtls) { @@ -24543,10 +24704,33 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) return WOLFSSL_CBIO_ERR_WANT_WRITE; } #endif - return err; + return err; } } +#ifdef WOLFSSL_RW_THREADED +#ifdef WOLFSSL_DTLS13 + if (ssl->options.dtls) { + /* Dtls13DoScheduledWork(ssl) may return WANT_WRITE */ + if ((error = Dtls13DoScheduledWork(ssl)) < 0) { + ssl->error = error; + WOLFSSL_ERROR(error); + return error; + } + } +#endif /* WOLFSSL_DTLS13 */ +#ifdef WOLFSSL_TLS13 + if (ssl->options.sendKeyUpdate) { + ssl->options.sendKeyUpdate = 0; + ret = SendTls13KeyUpdate(ssl); + if (ret != 0) { + ssl->error = BUILD_MSG_ERROR; + return WOLFSSL_FATAL_ERROR; + } + } +#endif +#endif + /* last time system socket output buffer was full, try again to send */ if (ssl->buffers.outputBuffer.length > 0 #if defined(WOLFSSL_EARLY_DATA) && defined(WOLFSSL_EARLY_DATA_GROUP) @@ -24554,15 +24738,16 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) #endif ) { WOLFSSL_MSG("output buffer was full, trying to send again"); - if ( (ssl->error = SendBuffered(ssl)) < 0) { - WOLFSSL_ERROR(ssl->error); - if (ssl->error == WC_NO_ERR_TRACE(SOCKET_ERROR_E) && - (ssl->options.connReset || ssl->options.isClosed)) { - ssl->error = SOCKET_PEER_CLOSED_E; - WOLFSSL_ERROR(ssl->error); + if ( (error = SendBuffered(ssl)) < 0) { + WOLFSSL_ERROR(error); + if (error == WC_NO_ERR_TRACE(SOCKET_ERROR_E) && + (ssl->options.connReset || ssl->options.isClosed)) { + error = SOCKET_PEER_CLOSED_E; + ssl->error = error; + WOLFSSL_ERROR(error); return 0; /* peer reset or closed */ } - return ssl->error; + return (ssl->error = error); } else { /* advance sent to previous sent + plain size just sent */ @@ -24571,7 +24756,7 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) if (sent > sz) { WOLFSSL_MSG("error: write() after WANT_WRITE with short size"); - return ssl->error = BAD_FUNC_ARG; + return (ssl->error = BAD_FUNC_ARG); } } } @@ -24582,6 +24767,19 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) return WOLFSSL_FATAL_ERROR; } +#ifdef WOLFSSL_THREADED_CRYPT + ret = SendAsyncData(ssl); + if (ret != 0) { + ssl->error = ret; + return WOLFSSL_FATAL_ERROR; + } + if (ssl->dtls13WaitKeyUpdateAck) { + ret = DoDtls13KeyUpdateAck(ssl); + if (ret != 0) + return ret; + } +#endif + for (;;) { byte* out; byte* sendBuffer = (byte*)data + sent; /* may switch on comp */ @@ -24590,6 +24788,10 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) #ifdef HAVE_LIBZ byte comp[MAX_RECORD_SIZE + MAX_COMP_EXTRA]; #endif +#ifdef WOLFSSL_THREADED_CRYPT + int i; + ThreadCrypt* encrypt = NULL; +#endif #if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_TLS13_IGNORE_AEAD_LIMITS) if (IsAtLeastTLSv1_3(ssl->version)) { @@ -24654,9 +24856,10 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) #if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_NO_DTLS_SIZE_CHECK) if (ssl->options.dtls && (buffSz < sz - sent)) { - ssl->error = DTLS_SIZE_ERROR; - WOLFSSL_ERROR(ssl->error); - return ssl->error; + error = DTLS_SIZE_ERROR; + ssl->error = error; + WOLFSSL_ERROR(error); + return error; } #endif outputSz = buffSz + COMP_EXTRA + DTLS_RECORD_HEADER_SZ; @@ -24665,10 +24868,33 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) /* check for available size */ if ((ret = CheckAvailableSize(ssl, outputSz)) != 0) - return ssl->error = ret; + return (ssl->error = ret); /* get output buffer */ +#ifndef WOLFSSL_THREADED_CRYPT out = GetOutputBuffer(ssl); +#else + do { + for (i = 0; i < WOLFSSL_THREADED_CRYPT_CNT; i++) { + if (ssl->buffers.encrypt[i].avail) { + encrypt = &ssl->buffers.encrypt[i]; + break; + } + } + if (encrypt == NULL) { + ret = SendAsyncData(ssl); + if (ret != 0) { + ssl->error = ret; + return WOLFSSL_FATAL_ERROR; + } + } + } + while (encrypt == NULL); + encrypt->done = 0; + encrypt->avail = 0; + GrowAnOutputBuffer(ssl, &encrypt->buffer, outputSz); + out = encrypt->buffer.buffer; +#endif #ifdef HAVE_LIBZ if (ssl->options.usingCompression) { @@ -24712,21 +24938,70 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) #ifdef WOLFSSL_ASYNC_CRYPT FreeAsyncCtx(ssl, 0); #endif +#ifdef WOLFSSL_THREADED_CRYPT + if (!encrypt->init) { + SetKeys(&encrypt->encrypt, NULL, &ssl->keys, &ssl->specs, + ssl->options.side, ssl->heap, ssl->devId, ssl->rng, + ssl->options.tls1_3); + encrypt->init = 1; + } + encrypt->buffer.length = sendSz; + encrypt->offset = RECORD_HEADER_SZ; + if (ssl->options.dtls) { + encrypt->offset += DTLS_RECORD_EXTRA; + } + encrypt->cryptLen = outputSz - encrypt->offset; + #ifdef HAVE_TRUNCATED_HMAC + if (ssl->truncated_hmac) { + encrypt->cryptLen -= min(TRUNCATED_HMAC_SZ, ssl->specs.hash_size); + } + else + #endif + { + encrypt->cryptLen -= ssl->specs.hash_size; + } + +#if !defined(NO_PUBLIC_GCM_SET_IV) && \ + ((defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))) + XMEMCPY(encrypt->nonce, ssl->keys.aead_enc_imp_IV, AESGCM_IMP_IV_SZ); + XMEMCPY(encrypt->nonce + AESGCM_IMP_IV_SZ, ssl->keys.aead_exp_IV, + AESGCM_EXP_IV_SZ); +#endif + XMEMSET(encrypt->additional, 0, AEAD_AUTH_DATA_SZ); + WriteSEQ(ssl, CUR_ORDER, encrypt->additional); + XMEMCPY(encrypt->additional + AEAD_TYPE_OFFSET, encrypt->buffer.buffer, + 3); + c16toa(sendSz - encrypt->offset - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, + encrypt->additional + AEAD_LEN_OFFSET); + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif + + if (encrypt->signal != NULL) { + encrypt->signal(encrypt->signalCtx, ssl); + } + return sendSz; +#else ssl->buffers.outputBuffer.length += sendSz; - if ( (ssl->error = SendBuffered(ssl)) < 0) { - WOLFSSL_ERROR(ssl->error); + if ( (error = SendBuffered(ssl)) < 0) { + ssl->error = error; + WOLFSSL_ERROR(error); /* store for next call if WANT_WRITE or user embedSend() that doesn't present like WANT_WRITE */ ssl->buffers.plainSz = buffSz; ssl->buffers.prevSent = sent; - if (ssl->error == WC_NO_ERR_TRACE(SOCKET_ERROR_E) && - (ssl->options.connReset || ssl->options.isClosed)) { + if (error == WC_NO_ERR_TRACE(SOCKET_ERROR_E) && + (ssl->options.connReset || ssl->options.isClosed)) { + error = SOCKET_PEER_CLOSED_E; ssl->error = SOCKET_PEER_CLOSED_E; - WOLFSSL_ERROR(ssl->error); + WOLFSSL_ERROR(error); return 0; /* peer reset or closed */ } - return ssl->error; + return error; } sent += buffSz; @@ -24736,6 +25011,7 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) WOLFSSL_MSG("Partial Write on, only sending one record"); break; } +#endif } return sent; @@ -24745,13 +25021,14 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek) { int size; + int error = ssl->error; WOLFSSL_ENTER("ReceiveData"); /* reset error state */ - if (ssl->error == WC_NO_ERR_TRACE(WANT_READ) || - ssl->error == WOLFSSL_ERROR_WANT_READ) - { + if (error == WC_NO_ERR_TRACE(WANT_READ) || + error == WOLFSSL_ERROR_WANT_READ) { + error = 0; ssl->error = 0; } @@ -24759,25 +25036,26 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek) if (ssl->options.dtls) { /* In DTLS mode, we forgive some errors and allow the session * to continue despite them. */ - if (ssl->error == WC_NO_ERR_TRACE(VERIFY_MAC_ERROR) || - ssl->error == WC_NO_ERR_TRACE(DECRYPT_ERROR) || - ssl->error == WC_NO_ERR_TRACE(DTLS_SIZE_ERROR)) { + if (error == WC_NO_ERR_TRACE(VERIFY_MAC_ERROR) || + error == WC_NO_ERR_TRACE(DECRYPT_ERROR) || + error == WC_NO_ERR_TRACE(DTLS_SIZE_ERROR)) { + error = 0; ssl->error = 0; } } #endif /* WOLFSSL_DTLS */ - if (ssl->error != 0 && ssl->error != WC_NO_ERR_TRACE(WANT_WRITE) + if (error != 0 && error != WC_NO_ERR_TRACE(WANT_WRITE) #ifdef WOLFSSL_ASYNC_CRYPT - && ssl->error != WC_NO_ERR_TRACE(WC_PENDING_E) + && error != WC_NO_ERR_TRACE(WC_PENDING_E) #endif #if defined(HAVE_SECURE_RENEGOTIATION) || defined(WOLFSSL_DTLS13) - && ssl->error != WC_NO_ERR_TRACE(APP_DATA_READY) + && error != WC_NO_ERR_TRACE(APP_DATA_READY) #endif ) { WOLFSSL_MSG("User calling wolfSSL_read in error state, not allowed"); - return ssl->error; + return error; } #ifdef WOLFSSL_EARLY_DATA @@ -24815,32 +25093,39 @@ int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek) #endif while (ssl->buffers.clearOutputBuffer.length == 0) { - if ( (ssl->error = ProcessReply(ssl)) < 0) { - if (ssl->error == WC_NO_ERR_TRACE(ZERO_RETURN)) { + if ( (error = ProcessReply(ssl)) < 0) { + if (error == WC_NO_ERR_TRACE(ZERO_RETURN)) { + ssl->error = error; WOLFSSL_MSG("Zero return, no more data coming"); return 0; /* no more data coming */ } - if (ssl->error == WC_NO_ERR_TRACE(SOCKET_ERROR_E)) { + if (error == WC_NO_ERR_TRACE(SOCKET_ERROR_E)) { if (ssl->options.connReset || ssl->options.isClosed) { WOLFSSL_MSG("Peer reset or closed, connection done"); - ssl->error = SOCKET_PEER_CLOSED_E; - WOLFSSL_ERROR(ssl->error); + error = SOCKET_PEER_CLOSED_E; + ssl->error = error; + WOLFSSL_ERROR(error); return 0; /* peer reset or closed */ } } - WOLFSSL_ERROR(ssl->error); - return ssl->error; + ssl->error = error; + WOLFSSL_ERROR(error); + return error; } -#ifdef WOLFSSL_DTLS13 +#ifndef WOLFSSL_RW_THREADED + #ifdef WOLFSSL_DTLS13 if (ssl->options.dtls) { /* Dtls13DoScheduledWork(ssl) may return WANT_WRITE */ - if ((ssl->error = Dtls13DoScheduledWork(ssl)) < 0) { - WOLFSSL_ERROR(ssl->error); - return ssl->error; + if ((error = Dtls13DoScheduledWork(ssl)) < 0) { + ssl->error = error; + WOLFSSL_ERROR(error); + return error; } } -#endif /* WOLFSSL_DTLS13 */ + #endif /* WOLFSSL_DTLS13 */ +#endif + #ifdef HAVE_SECURE_RENEGOTIATION if (ssl->secure_renegotiation && ssl->secure_renegotiation->startScr) { diff --git a/src/keys.c b/src/keys.c index 3123a610e0..b13fbdf5b8 100644 --- a/src/keys.c +++ b/src/keys.c @@ -2371,7 +2371,7 @@ static int SetPrefix(byte* sha_input, int idx) #endif -static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, +int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, int side, void* heap, int devId, WC_RNG* rng, int tls13) { (void)rng; diff --git a/src/ssl.c b/src/ssl.c index b4bf407446..4c66ae2bde 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -23529,7 +23529,86 @@ wolfSSL_CTX_keylog_cb_func wolfSSL_CTX_get_keylog_callback( #endif /* OPENSSL_EXTRA */ -#ifndef NO_CERTS +#ifdef WOLFSSL_THREADED_CRYPT +int wolfSSL_AsyncEncryptReady(WOLFSSL* ssl, int idx) +{ + ThreadCrypt* encrypt; + + if (ssl == NULL) { + return 0; + } + + encrypt = &ssl->buffers.encrypt[idx]; + return (encrypt->avail == 0) && (encrypt->done == 0); +} + +int wolfSSL_AsyncEncryptStop(WOLFSSL* ssl, int idx) +{ + ThreadCrypt* encrypt; + + if (ssl == NULL) { + return 1; + } + + encrypt = &ssl->buffers.encrypt[idx]; + return encrypt->stop; +} + +int wolfSSL_AsyncEncrypt(WOLFSSL* ssl, int idx) +{ + int ret = NOT_COMPILED_IN; + ThreadCrypt* encrypt = &ssl->buffers.encrypt[idx]; + + if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) { + unsigned char* out = encrypt->buffer.buffer + encrypt->offset; + unsigned char* input = encrypt->buffer.buffer + encrypt->offset; + word32 encSz = encrypt->buffer.length - encrypt->offset; + + ret = +#if !defined(NO_GCM_ENCRYPT_EXTRA) && \ + ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))) + wc_AesGcmEncrypt_ex +#else + wc_AesGcmEncrypt +#endif + (encrypt->encrypt.aes, + out + AESGCM_EXP_IV_SZ, input + AESGCM_EXP_IV_SZ, + encSz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, + encrypt->nonce, AESGCM_NONCE_SZ, + out + encSz - ssl->specs.aead_mac_size, + ssl->specs.aead_mac_size, + encrypt->additional, AEAD_AUTH_DATA_SZ); +#if !defined(NO_PUBLIC_GCM_SET_IV) && \ + ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))) + XMEMCPY(out, encrypt->nonce + AESGCM_IMP_IV_SZ, AESGCM_EXP_IV_SZ); +#endif + encrypt->done = 1; + } + + return ret; +} + +int wolfSSL_AsyncEncryptSetSignal(WOLFSSL* ssl, int idx, + WOLFSSL_THREAD_SIGNAL signal, void* ctx) +{ + int ret = 0; + + if (ssl == NULL) { + ret = BAD_FUNC_ARG; + } + else { + ssl->buffers.encrypt[idx].signal = signal; + ssl->buffers.encrypt[idx].signalCtx = ctx; + } + + return ret; +} +#endif + + +#ifndef NO_CERT #define WOLFSSL_X509_INCLUDED #include "src/x509.c" #endif diff --git a/src/tls13.c b/src/tls13.c index bbca4fac57..4910b33455 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -11071,7 +11071,7 @@ static int SendTls13Finished(WOLFSSL* ssl) * ssl The SSL/TLS object. * returns 0 on success, otherwise failure. */ -static int SendTls13KeyUpdate(WOLFSSL* ssl) +int SendTls13KeyUpdate(WOLFSSL* ssl) { byte* input; byte* output; @@ -11248,7 +11248,12 @@ static int DoTls13KeyUpdate(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } #endif /* WOLFSSL_DTLS13 */ +#ifndef WOLFSSL_RW_THREADED return SendTls13KeyUpdate(ssl); +#else + ssl->options.sendKeyUpdate = 1; + return 0; +#endif } WOLFSSL_LEAVE("DoTls13KeyUpdate", ret); diff --git a/src/wolfio.c b/src/wolfio.c index 658dfe9339..d3d9ebdaf6 100644 --- a/src/wolfio.c +++ b/src/wolfio.c @@ -650,6 +650,7 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx) #elif !defined(DTLS_RECEIVEFROM_NO_TIMEOUT_ON_INVALID_PEER) word32 invalidPeerPackets = 0; #endif + int newPeer = 0; WOLFSSL_ENTER("EmbedReceiveFrom"); @@ -677,8 +678,13 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx) dtlsCtx->peer.bufSz = sizeof(SOCKADDR_S); else dtlsCtx->peer.bufSz = 0; + newPeer = 1; + peer = (SOCKADDR_S*)dtlsCtx->peer.sa; + } + else { + peer = &lclPeer; + XMEMCPY(peer, (SOCKADDR_S*)dtlsCtx->peer.sa, sizeof(lclPeer)); } - peer = (SOCKADDR_S*)dtlsCtx->peer.sa; peerSz = dtlsCtx->peer.bufSz; } @@ -688,9 +694,20 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx) #ifdef WOLFSSL_DTLS13 if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version)) { - doDtlsTimeout = - doDtlsTimeout || ssl->dtls13Rtx.rtxRecords != NULL || + doDtlsTimeout = doDtlsTimeout || ssl->dtls13Rtx.rtxRecords != NULL; +#ifdef WOLFSSL_RW_THREADED + { + int ret = wc_LockMutex(&ssl->dtls13Rtx.mutex); + if (ret < 0) { + return ret; + } + } +#endif + doDtlsTimeout = doDtlsTimeout || (ssl->dtls13FastTimeout && ssl->dtls13Rtx.seenRecords != NULL); +#ifdef WOLFSSL_RW_THREADED + wc_UnLockMutex(&ssl->dtls13Rtx.mutex); +#endif } #endif /* WOLFSSL_DTLS13 */ @@ -822,8 +839,16 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx) } } else { - /* Store size of saved address */ - dtlsCtx->peer.sz = peerSz; + if (newPeer) { + /* Store size of saved address */ + dtlsCtx->peer.sz = peerSz; + } +#ifndef WOLFSSL_PEER_ADDRESS_CHANGES + else if ((dtlsCtx->peer.sz != (unsigned int)peerSz) || + (XMEMCMP(peer, dtlsCtx->peer.sa, peerSz) != 0)) { + return WOLFSSL_CBIO_ERR_GENERAL; + } +#endif } #ifndef NO_ASN_TIME ssl->dtls_start_timeout = 0; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 9e57ab0c46..c928233050 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -2870,8 +2870,8 @@ typedef struct Keys { byte encryptionOn; /* true after change cipher spec */ byte decryptedCur; /* only decrypt current record once */ #ifdef WOLFSSL_TLS13 - byte updateResponseReq:1; /* KeyUpdate response from peer required. */ - byte keyUpdateRespond:1; /* KeyUpdate is to be responded to. */ + byte updateResponseReq; /* KeyUpdate response from peer required. */ + byte keyUpdateRespond; /* KeyUpdate is to be responded to. */ #endif #ifdef WOLFSSL_RENESAS_TSIP_TLS @@ -4671,10 +4671,34 @@ enum AcceptStateTls13 { TLS13_TICKET_SENT }; +#ifdef WOLFSSL_THREADED_CRYPT + +#include + +typedef struct ThreadCrypt { + Ciphers encrypt; + bufferStatic buffer; + unsigned char nonce[AESGCM_NONCE_SZ]; + unsigned char additional[AEAD_AUTH_DATA_SZ]; + int init; + int offset; + int cryptLen; + int done; + int avail; + int stop; + WOLFSSL_THREAD_SIGNAL signal; + void* signalCtx; +} ThreadCrypt; + +#endif + /* buffers for struct WOLFSSL */ typedef struct Buffers { bufferStatic inputBuffer; bufferStatic outputBuffer; +#ifdef WOLFSSL_THREADED_CRYPT + ThreadCrypt encrypt[WOLFSSL_THREADED_CRYPT_CNT]; +#endif buffer domainName; /* for client check */ buffer clearOutputBuffer; buffer sig; /* signature data */ @@ -4828,7 +4852,6 @@ struct Options { word16 tls:1; /* using TLS ? */ word16 tls1_1:1; /* using TLSv1.1+ ? */ word16 tls1_3:1; /* using TLSv1.3+ ? */ - word16 seenUnifiedHdr:1; /* received msg with unified header */ word16 dtls:1; /* using datagrams ? */ #ifdef WOLFSSL_DTLS word16 dtlsStateful:1; /* allow stateful processing ? */ @@ -4837,7 +4860,6 @@ struct Options { word16 isClosed:1; /* if we consider conn closed */ word16 closeNotify:1; /* we've received a close notify */ word16 sentNotify:1; /* we've sent a close notify */ - word16 shutdownDone:1; /* we've completed a shutdown */ word16 usingCompression:1; /* are we using compression */ word16 haveRSA:1; /* RSA available */ word16 haveECC:1; /* ECC available */ @@ -4885,7 +4907,6 @@ struct Options { #endif word16 dtlsUseNonblock:1; /* are we using nonblocking socket */ word16 dtlsHsRetain:1; /* DTLS retaining HS data */ - word16 haveMcast:1; /* using multicast ? */ #ifdef WOLFSSL_SCTP word16 dtlsSctp:1; /* DTLS-over-SCTP mode */ #endif @@ -4938,8 +4959,6 @@ struct Options { word16 buildArgsSet:1; /* buildArgs are set and need to * be free'd */ #endif - word16 buildingMsg:1; /* If set then we need to re-enter the - * handshake logic. */ #ifdef WOLFSSL_DTLS13 word16 dtls13SendMoreAcks:1; /* Send more acks during the * handshake process */ @@ -4965,6 +4984,14 @@ struct Options { #if defined(HAVE_DANE) word16 useDANE:1; #endif /* HAVE_DANE */ +#ifdef WOLFSSL_DTLS + byte haveMcast; /* using multicast ? */ +#endif + byte buildingMsg; /* If set then we need to re-enter the + * handshake logic. */ + byte seenUnifiedHdr; /* received msg with unified header */ + byte shutdownDone; /* we've completed a shutdown */ + byte sendKeyUpdate; /* Key Update to write */ #if defined(HAVE_RPK) RpkConfig rpkConfig; RpkState rpkState; @@ -5579,14 +5606,17 @@ typedef struct Dtls13RecordNumber { } Dtls13RecordNumber; typedef struct Dtls13Rtx { - enum Dtls13RtxFsmState state; +#ifdef WOLFSSL_RW_THREADED + wolfSSL_Mutex mutex; +#endif + enum Dtls13RtxFsmState state; /* Unused? */ Dtls13RtxRecord *rtxRecords; Dtls13RtxRecord **rtxRecordTailPtr; Dtls13RecordNumber *seenRecords; word32 lastRtx; - byte triggeredRtxs; - byte sendAcks:1; - byte retransmit:1; + byte triggeredRtxs; /* Unused? */ + byte sendAcks; + byte retransmit; } Dtls13Rtx; #endif /* WOLFSSL_DTLS13 */ @@ -5850,10 +5880,10 @@ struct WOLFSSL { /* used to store the message if it needs to be fragmented */ buffer dtls13FragmentsBuffer; byte dtls13SendingFragments:1; - byte dtls13SendingAckOrRtx:1; + byte dtls13SendingAckOrRtx; byte dtls13FastTimeout:1; - byte dtls13WaitKeyUpdateAck:1; - byte dtls13DoKeyUpdate:1; + byte dtls13WaitKeyUpdateAck; + byte dtls13DoKeyUpdate; word32 dtls13MessageLength; word32 dtls13FragOffset; byte dtls13FragHandshakeType; @@ -6304,6 +6334,9 @@ WOLFSSL_LOCAL int DoClientTicket_ex(const WOLFSSL* ssl, PreSharedKey* psk, WOLFSSL_LOCAL int DoClientTicket(WOLFSSL* ssl, const byte* input, word32 len); #endif /* HAVE_SESSION_TICKET */ WOLFSSL_LOCAL int SendData(WOLFSSL* ssl, const void* data, int sz); +#ifdef WOLFSSL_THREADED_CRYPT +WOLFSSL_LOCAL int SendAsyncData(WOLFSSL* ssl); +#endif #ifdef WOLFSSL_TLS13 WOLFSSL_LOCAL int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType); #endif @@ -6504,6 +6537,10 @@ WOLFSSL_LOCAL int cipherExtraData(WOLFSSL* ssl); WOLFSSL_LOCAL int SendServerHelloDone(WOLFSSL* ssl); #endif /* NO_WOLFSSL_SERVER */ +#ifdef WOLFSSL_TLS13 + WOLFSSL_LOCAL int SendTls13KeyUpdate(WOLFSSL* ssl); +#endif + #ifdef WOLFSSL_DTLS WOLFSSL_LOCAL DtlsMsg* DtlsMsgNew(word32 sz, byte tx, void* heap); WOLFSSL_LOCAL void DtlsMsgDelete(DtlsMsg* item, void* heap); @@ -6642,6 +6679,9 @@ enum encrypt_side { ENCRYPT_AND_DECRYPT_SIDE }; +WOLFSSL_LOCAL int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, + CipherSpecs* specs, int side, void* heap, int devId, WC_RNG* rng, + int tls13); WOLFSSL_LOCAL int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side); /* Set*Internal and Set*External functions */ @@ -6801,6 +6841,7 @@ WOLFSSL_LOCAL int Dtls13HandshakeAddHeader(WOLFSSL* ssl, byte* output, enum HandShakeType msg_type, word32 length); #define EE_MASK (0x3) WOLFSSL_LOCAL int Dtls13FragmentsContinue(WOLFSSL* ssl); +WOLFSSL_LOCAL int DoDtls13KeyUpdateAck(WOLFSSL* ssl); WOLFSSL_LOCAL int DoDtls13Ack(WOLFSSL* ssl, const byte* input, word32 inputSize, word32* processedSize); WOLFSSL_LOCAL int Dtls13ReconstructEpochNumber(WOLFSSL* ssl, byte epochBits, diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 9adc0be00c..488bd784b3 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -3304,6 +3304,21 @@ WOLFSSL_API void wolfSSL_CTX_SetEncryptMacCb(WOLFSSL_CTX* ctx, CallbackEncryptM WOLFSSL_API void wolfSSL_SetEncryptMacCtx(WOLFSSL* ssl, void *ctx); WOLFSSL_API void* wolfSSL_GetEncryptMacCtx(WOLFSSL* ssl); +#ifdef WOLFSSL_THREADED_CRYPT + #ifndef WOLFSSL_THREADED_CRYPT_CNT + #define WOLFSSL_THREADED_CRYPT_CNT 16 + #endif + +typedef void (*WOLFSSL_THREAD_SIGNAL)(void* ctx, WOLFSSL* ssl); + +WOLFSSL_API int wolfSSL_AsyncEncryptReady(WOLFSSL* ssl, int idx); +WOLFSSL_API int wolfSSL_AsyncEncryptStop(WOLFSSL* ssl, int idx); +WOLFSSL_API int wolfSSL_AsyncEncrypt(WOLFSSL* ssl, int idx); +WOLFSSL_API int wolfSSL_AsyncEncryptSetSignal(WOLFSSL* ssl, int idx, + WOLFSSL_THREAD_SIGNAL signal, void* ctx); +#endif + + typedef int (*CallbackVerifyDecrypt)(WOLFSSL* ssl, unsigned char* decOut, const unsigned char* decIn, unsigned int decSz, int content, int verify, unsigned int* padSz,