From 651a7a97b90462e998f565c7bcd3e431618e04d1 Mon Sep 17 00:00:00 2001 From: Juliusz Sosinowicz Date: Tue, 19 May 2020 14:11:05 +0200 Subject: [PATCH] Add secure renegotiation to DTLS 1.2 - Hash of fragmented certificate was not calculated as a single message and instead we were hashing individual fragments which produced the wrong digest, shared secret, etc... - Reset handshake number after server Finished packet is sent or received (depending on side) - Reserve space in buffer for cipher stuff - Take `DTLS_RECORD_EXTRA` and `DTLS_HANDSHAKE_EXTRA` into size and offset calculations for DTLS path - Fix renegotiation in DTLS with AES128-SHA - Fix renegotiation in DTLS with AES-GCM - Support HelloVerify request during secure renegotiation - Save renegotiation handshake messages for retransmission in timeout - Handle cipher parameters from different epochs. DTLS may need to resend and receive messages from previous epochs so handling different sets of encryption and decryption parameters is crucial. --- src/internal.c | 910 ++++++++++++++++++++++++++++++++++----------- src/keys.c | 102 ++++- src/ssl.c | 68 +++- src/tls.c | 25 +- src/wolfio.c | 4 +- wolfssl/internal.h | 31 +- wolfssl/ssl.h | 1 + 7 files changed, 898 insertions(+), 243 deletions(-) diff --git a/src/internal.c b/src/internal.c index 96e0d8f46..53d1c688e 100644 --- a/src/internal.c +++ b/src/internal.c @@ -161,7 +161,7 @@ static const byte tls13Downgrade[7] = { #if !defined(NO_OLD_TLS) && !defined(WOLFSSL_AEAD_ONLY) static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, - int padSz, int content, int verify); + int padSz, int content, int verify, int epochOrder); #endif @@ -221,15 +221,25 @@ static WC_INLINE int IsEncryptionOn(WOLFSSL* ssl, int isSend) * If SCTP is enabled returns dtls && !sctp. */ static WC_INLINE int IsDtlsNotSctpMode(WOLFSSL* ssl) { - int result = ssl->options.dtls; - - if (result) { #ifdef WOLFSSL_SCTP - result = !ssl->options.dtlsSctp; + return ssl->options.dtls && !ssl->options.dtlsSctp; +#else + return ssl->options.dtls; #endif - } +} - return result; +int IsInitialRenegotiationState(WOLFSSL* ssl) +{ + if (ssl->options.acceptState == ACCEPT_FIRST_REPLY_DONE + #ifdef HAVE_SECURE_RENEGOTIATION + || ssl->options.acceptState == ACCEPT_BEGIN_RENEG + #endif + ) { + return 1; + } + else { + return 0; + } } #endif /* DTLS || !WOLFSSL_NO_TLS12 */ @@ -6725,6 +6735,14 @@ static WC_INLINE void GetSEQIncrement(WOLFSSL* ssl, int verify, word32 seq[2]) #ifdef WOLFSSL_DTLS static WC_INLINE void DtlsGetSEQ(WOLFSSL* ssl, int order, word32 seq[2]) { +#ifdef HAVE_SECURE_RENEGOTIATION + /* if ssl->secure_renegotiation->tmp_keys.dtls_epoch > ssl->keys.dtls_epoch then PREV_ORDER + * refers to the current epoch */ + if (order == PREV_ORDER && ssl->secure_renegotiation && + ssl->secure_renegotiation->tmp_keys.dtls_epoch > ssl->keys.dtls_epoch) { + order = CUR_ORDER; + } +#endif if (order == PREV_ORDER) { /* Previous epoch case */ if (ssl->options.haveMcast) { @@ -6770,6 +6788,14 @@ static WC_INLINE void DtlsGetSEQ(WOLFSSL* ssl, int order, word32 seq[2]) static WC_INLINE void DtlsSEQIncrement(WOLFSSL* ssl, int order) { word32 seq; +#ifdef HAVE_SECURE_RENEGOTIATION + /* if ssl->secure_renegotiation->tmp_keys.dtls_epoch > ssl->keys.dtls_epoch then PREV_ORDER + * refers to the current epoch */ + if (order == PREV_ORDER && ssl->secure_renegotiation && + ssl->secure_renegotiation->tmp_keys.dtls_epoch > ssl->keys.dtls_epoch) { + order = CUR_ORDER; + } +#endif if (order == PREV_ORDER) { seq = ssl->keys.dtls_prev_sequence_number_lo++; @@ -6878,6 +6904,25 @@ void DtlsMsgListDelete(DtlsMsg* head, void* heap) } } +void DtlsTxMsgListClean(WOLFSSL* ssl) +{ + DtlsMsg* head = ssl->dtls_tx_msg_list; + DtlsMsg* next; + while (head) { + next = head->next; + if (VerifyForTxDtlsMsgDelete(ssl, head)) + DtlsMsgDelete(head, ssl->heap); + else + /* Stored packets should be in order so break on first failed + * verify */ + break; + ssl->dtls_tx_msg_list_sz--; + /* Reset timer as deleting a node means that state has progressed */ + ssl->dtls_timeout = ssl->dtls_timeout_init; + head = next; + } + ssl->dtls_tx_msg_list = head; +} /* Create a DTLS Fragment from *begin - end, adjust new *begin and bytesLeft */ static DtlsFrag* CreateFragment(word32* begin, word32 end, const byte* data, @@ -6903,7 +6948,7 @@ static DtlsFrag* CreateFragment(word32* begin, word32 end, const byte* data, } -int DtlsMsgSet(DtlsMsg* msg, word32 seq, const byte* data, byte type, +int DtlsMsgSet(DtlsMsg* msg, word32 seq, word16 epoch, const byte* data, byte type, word32 fragOffset, word32 fragSz, void* heap) { if (msg != NULL && data != NULL && msg->fragSz <= msg->sz && @@ -6916,6 +6961,7 @@ int DtlsMsgSet(DtlsMsg* msg, word32 seq, const byte* data, byte type, word32 added; msg->seq = seq; + msg->epoch = epoch; msg->type = type; if (fragOffset == 0) { @@ -7004,16 +7050,16 @@ int DtlsMsgSet(DtlsMsg* msg, word32 seq, const byte* data, byte type, } -DtlsMsg* DtlsMsgFind(DtlsMsg* head, word32 seq) +DtlsMsg* DtlsMsgFind(DtlsMsg* head, word32 epoch, word32 seq) { - while (head != NULL && head->seq != seq) { + while (head != NULL && head->epoch == epoch && head->seq != seq) { head = head->next; } return head; } -void DtlsMsgStore(WOLFSSL* ssl, word32 seq, const byte* data, +void DtlsMsgStore(WOLFSSL* ssl, word32 epoch, word32 seq, const byte* data, word32 dataSz, byte type, word32 fragOffset, word32 fragSz, void* heap) { /* See if seq exists in the list. If it isn't in the list, make @@ -7036,12 +7082,12 @@ void DtlsMsgStore(WOLFSSL* ssl, word32 seq, const byte* data, DtlsMsg* head = ssl->dtls_rx_msg_list; if (head != NULL) { - DtlsMsg* cur = DtlsMsgFind(head, seq); + DtlsMsg* cur = DtlsMsgFind(head, epoch, seq); if (cur == NULL) { cur = DtlsMsgNew(dataSz, heap); if (cur != NULL) { - if (DtlsMsgSet(cur, seq, data, type, - fragOffset, fragSz, heap) < 0) { + if (DtlsMsgSet(cur, seq, epoch, data, type, + fragOffset, fragSz, heap) < 0) { DtlsMsgDelete(cur, heap); } else { @@ -7052,12 +7098,14 @@ void DtlsMsgStore(WOLFSSL* ssl, word32 seq, const byte* data, } else { /* If this fails, the data is just dropped. */ - DtlsMsgSet(cur, seq, data, type, fragOffset, fragSz, heap); + DtlsMsgSet(cur, seq, epoch, data, type, fragOffset, + fragSz, heap); } } else { head = DtlsMsgNew(dataSz, heap); - if (DtlsMsgSet(head, seq, data, type, fragOffset, fragSz, heap) < 0) { + if (DtlsMsgSet(head, seq, epoch, data, type, fragOffset, + fragSz, heap) < 0) { DtlsMsgDelete(head, heap); head = NULL; } @@ -7102,7 +7150,7 @@ DtlsMsg* DtlsMsgInsert(DtlsMsg* head, DtlsMsg* item) /* DtlsMsgPoolSave() adds the message to the end of the stored transmit list. */ -int DtlsMsgPoolSave(WOLFSSL* ssl, const byte* data, word32 dataSz) +int DtlsMsgPoolSave(WOLFSSL* ssl, const byte* data, word32 dataSz, enum HandShakeType type) { DtlsMsg* item; int ret = 0; @@ -7121,7 +7169,10 @@ int DtlsMsgPoolSave(WOLFSSL* ssl, const byte* data, word32 dataSz) XMEMCPY(item->buf, data, dataSz); item->sz = dataSz; - item->seq = ssl->keys.dtls_epoch; + item->epoch = ssl->keys.dtls_epoch; + /* save is called after something incremented this var */ + item->seq = ssl->keys.dtls_handshake_number - 1; + item->type = type; if (cur == NULL) ssl->dtls_tx_msg_list = item; @@ -7163,8 +7214,8 @@ void DtlsMsgPoolReset(WOLFSSL* ssl) ssl->dtls_tx_msg_list = NULL; ssl->dtls_tx_msg = NULL; ssl->dtls_tx_msg_list_sz = 0; - ssl->dtls_timeout = ssl->dtls_timeout_init; } + ssl->dtls_timeout = ssl->dtls_timeout_init; } @@ -7185,12 +7236,37 @@ int VerifyForDtlsMsgPoolSend(WOLFSSL* ssl, byte type, word32 fragOffset) } +int VerifyForTxDtlsMsgDelete(WOLFSSL* ssl, DtlsMsg* item) +{ + if (item->epoch < ssl->keys.dtls_epoch - 1) + return 1; + switch (ssl->options.side) { + case WOLFSSL_CLIENT_END: + if (item->type == client_hello && + ssl->options.serverState >= SERVER_HELLODONE_COMPLETE) + return 1; /* client can forget first client_hello if received full + * flight of packets from server */ + else + return 0; + case WOLFSSL_SERVER_END: + if (ssl->options.clientState >= CLIENT_FINISHED_COMPLETE && + item->type <= server_hello_done) + return 1; + else + return 0; + default: + return 0; + } +} + + /* DtlsMsgPoolSend() will send the stored transmit list. The stored list is * updated with new sequence numbers, and will be re-encrypted if needed. */ int DtlsMsgPoolSend(WOLFSSL* ssl, int sendOnlyFirstPacket) { int ret = 0; DtlsMsg* pool; + int epochOrder; WOLFSSL_ENTER("DtlsMsgPoolSend()"); @@ -7213,9 +7289,8 @@ int DtlsMsgPoolSend(WOLFSSL* ssl, int sendOnlyFirstPacket) } while (pool != NULL) { - if (pool->seq == 0) { + if (pool->epoch == 0) { DtlsRecordLayerHeader* dtls; - int epochOrder; dtls = (DtlsRecordLayerHeader*)pool->buf; /* If the stored record's epoch is 0, and the currently set @@ -7238,7 +7313,8 @@ int DtlsMsgPoolSend(WOLFSSL* ssl, int sendOnlyFirstPacket) ssl->buffers.outputBuffer.idx = 0; ssl->buffers.outputBuffer.length = pool->sz; } - else if (pool->seq == ssl->keys.dtls_epoch) { + else { + /* Handle sending packets from previous epoch */ byte* input; byte* output; int inputSz, sendSz; @@ -7247,6 +7323,28 @@ int DtlsMsgPoolSend(WOLFSSL* ssl, int sendOnlyFirstPacket) inputSz = pool->sz; sendSz = inputSz + MAX_MSG_EXTRA; +#ifdef HAVE_SECURE_RENEGOTIATION + + /* + * CUR_ORDER will use ssl->secure_renegotiation from epoch 2+. + * ssl->keys otherwise + * PREV_ORDER will always use ssl->keys + */ + if (ssl->secure_renegotiation && + ssl->secure_renegotiation->tmp_keys.dtls_epoch != 0) { + if (pool->epoch == ssl->secure_renegotiation->tmp_keys.dtls_epoch) + epochOrder = CUR_ORDER; + else + epochOrder = PREV_ORDER; + } + else { + epochOrder = CUR_ORDER; + } +#else + epochOrder = CUR_ORDER; +#endif + + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { WOLFSSL_ERROR(ret); return ret; @@ -7254,8 +7352,15 @@ int DtlsMsgPoolSend(WOLFSSL* ssl, int sendOnlyFirstPacket) output = ssl->buffers.outputBuffer.buffer + ssl->buffers.outputBuffer.length; - sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - handshake, 0, 0, 0); + if (inputSz != ENUM_LEN) + sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, + handshake, 0, 0, 0, epochOrder); + else + /* inputSz == ENUM_LEN must mean that this is a change cipher + * spec message */ + sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, + change_cipher_spec, 0, 0, 0, epochOrder); + if (sendSz < 0) { WOLFSSL_ERROR(BUILD_MSG_ERROR); return BUILD_MSG_ERROR; @@ -7757,10 +7862,12 @@ int HashInput(WOLFSSL* ssl, const byte* input, int sz) /* add record layer header for message */ -static void AddRecordHeader(byte* output, word32 length, byte type, WOLFSSL* ssl) +static void AddRecordHeader(byte* output, word32 length, byte type, WOLFSSL* ssl, int epochOrder) { RecordLayerHeader* rl; + (void)epochOrder; + /* record layer header */ rl = (RecordLayerHeader*)output; if (rl == NULL) { @@ -7794,7 +7901,7 @@ static void AddRecordHeader(byte* output, word32 length, byte type, WOLFSSL* ssl /* dtls record layer header extensions */ dtls = (DtlsRecordLayerHeader*)output; - WriteSEQ(ssl, 0, dtls->sequence_number); + WriteSEQ(ssl, epochOrder, dtls->sequence_number); c16toa((word16)length, dtls->length); #endif } @@ -7846,7 +7953,7 @@ static void AddHeaders(byte* output, word32 length, byte type, WOLFSSL* ssl) } #endif - AddRecordHeader(output, length + lengthAdj, handshake, ssl); + AddRecordHeader(output, length + lengthAdj, handshake, ssl, CUR_ORDER); AddHandShakeHeader(output + outputAdj, length, 0, length, type, ssl); } #endif /* !WOLFSSL_NO_TLS12 || (HAVE_SESSION_TICKET && !NO_WOLFSSL_SERVER) */ @@ -7869,7 +7976,7 @@ static void AddFragHeaders(byte* output, word32 fragSz, word32 fragOffset, } #endif - AddRecordHeader(output, fragSz + lengthAdj, handshake, ssl); + AddRecordHeader(output, fragSz + lengthAdj, handshake, ssl, CUR_ORDER); AddHandShakeHeader(output + outputAdj, length, fragOffset, fragSz, type, ssl); } #endif /* NO_CERTS */ @@ -7941,7 +8048,7 @@ retry: case WOLFSSL_CBIO_ERR_TIMEOUT: #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl) && - !ssl->options.handShakeDone && + ssl->options.handShakeState != HANDSHAKE_DONE && DtlsMsgPoolTimeout(ssl) == 0 && DtlsMsgPoolSend(ssl, 0) == 0) { @@ -11921,7 +12028,12 @@ int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size, } #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - DtlsMsgPoolReset(ssl); + if ((!ssl->options.resuming && ssl->options.side == WOLFSSL_CLIENT_END) || + (ssl->options.resuming && ssl->options.side == WOLFSSL_SERVER_END)){ + DtlsMsgPoolReset(ssl); + ssl->keys.dtls_handshake_number = 0; + ssl->keys.dtls_expected_peer_handshake_number = 0; + } } #endif @@ -12231,7 +12343,8 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type) if (ssl->options.verifyPeer && ssl->options.havePeerCert) { - if (!ssl->options.havePeerVerify) { + if (!ssl->options.havePeerVerify || + !ssl->msgsReceived.got_certificate_verify) { WOLFSSL_MSG("client didn't send cert verify"); #ifdef WOLFSSL_DTLS if (ssl->options.dtls) @@ -12391,6 +12504,25 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, case hello_verify_request: WOLFSSL_MSG("processing hello verify request"); ret = DoHelloVerifyRequest(ssl, input,inOutIdx, size); + 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) + return BUFFER_E; + *inOutIdx += ssl->keys.padSz + digestSz; + } + else + #endif + { + /* access beyond input + size should be checked against totalSz + */ + if (*inOutIdx + ssl->keys.padSz > totalSz) + return BUFFER_E; + + *inOutIdx += ssl->keys.padSz; + } + } break; case server_hello: @@ -12930,9 +13062,13 @@ static int DtlsMsgDrain(WOLFSSL* ssl) item->fragSz == item->sz && ret == 0) { word32 idx = 0; - ssl->keys.dtls_expected_peer_handshake_number++; - ret = DoHandShakeMsgType(ssl, item->msg, - &idx, item->type, item->sz, item->sz); + /* 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, + item->sz, item->sz)) == 0) { + ssl->keys.dtls_expected_peer_handshake_number++; + DtlsTxMsgListClean(ssl); + } #ifdef WOLFSSL_ASYNC_CRYPT if (ret == WC_PENDING_E) { ssl->keys.dtls_expected_peer_handshake_number--; @@ -12957,6 +13093,7 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 size; word32 fragOffset, fragSz; int ret = 0; + int ignoreFinished = 0; WOLFSSL_ENTER("DoDtlsHandShakeMsg()"); @@ -12992,6 +13129,19 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, return INCOMPLETE_DATA; } + if (type == finished && ssl->keys.dtls_peer_handshake_number >= + ssl->keys.dtls_expected_peer_handshake_number && + ssl->keys.curEpoch == ssl->keys.dtls_epoch) { + /* finished msg should be ignore if it is in the current epoch + * if it comes from a previous handshake */ + if (ssl->options.side == WOLFSSL_CLIENT_END) { + ignoreFinished = ssl->options.connectState < FINISHED_DONE; + } + else { + ignoreFinished = ssl->options.acceptState < ACCEPT_FINISHED_DONE; + } + } + /* Check the handshake sequence number first. If out of order, * add the current message to the list. If the message is in order, * but it is a fragment, add the current message to the list, then @@ -13002,7 +13152,9 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, * head is out of order, return for more processing. */ if (ssl->keys.dtls_peer_handshake_number > - ssl->keys.dtls_expected_peer_handshake_number) { + ssl->keys.dtls_expected_peer_handshake_number && + (type == client_hello || ssl->options.handShakeState != HANDSHAKE_DONE) && + !ignoreFinished) { /* Current message is out of order. It will get stored in the list. * Storing also takes care of defragmentation. If the messages is a * client hello, we need to process this out of order; the server @@ -13012,13 +13164,31 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, * number. (If the cookie changes multiple times in quick succession, * the client could be sending multiple new client hello messages * with newer and newer cookies.) */ + WOLFSSL_MSG("Current message is out of order"); if (type != client_hello) { if (ssl->dtls_rx_msg_list_sz < DTLS_POOL_SZ) { - DtlsMsgStore(ssl, ssl->keys.dtls_peer_handshake_number, + DtlsMsgStore(ssl, ssl->keys.curEpoch, + ssl->keys.dtls_peer_handshake_number, input + *inOutIdx, size, type, fragOffset, fragSz, ssl->heap); } *inOutIdx += fragSz; + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.startedETMRead && ssl->keys.curEpoch != 0) { + word32 digestSz = MacSize(ssl); + if (*inOutIdx + ssl->keys.padSz + digestSz > totalSz) + return BUFFER_E; + *inOutIdx += digestSz; + } + else + #endif + { + if (*inOutIdx + ssl->keys.padSz > totalSz) { + WOLFSSL_ERROR(BUFFER_E); + return BUFFER_E; + } + } + *inOutIdx += ssl->keys.padSz; ret = 0; } else { @@ -13030,25 +13200,27 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, } } else if (ssl->keys.dtls_peer_handshake_number < - ssl->keys.dtls_expected_peer_handshake_number) { + ssl->keys.dtls_expected_peer_handshake_number || + (ssl->keys.dtls_peer_handshake_number > + ssl->keys.dtls_expected_peer_handshake_number && + ssl->options.handShakeState == HANDSHAKE_DONE) || + ignoreFinished) { /* Already saw this message and processed it. It can be ignored. */ + WOLFSSL_MSG("Already saw this message and processed it"); *inOutIdx += fragSz; - if(type == finished ) { #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) - return BUFFER_E; - *inOutIdx += ssl->keys.padSz + digestSz; - } - else + if (ssl->options.startedETMRead && ssl->keys.curEpoch != 0) { + word32 digestSz = MacSize(ssl); + if (*inOutIdx + ssl->keys.padSz + digestSz > totalSz) + return BUFFER_E; + *inOutIdx += digestSz; + } + else #endif - { - if (*inOutIdx + ssl->keys.padSz > totalSz) { - WOLFSSL_ERROR(BUFFER_E); - return BUFFER_E; - } - *inOutIdx += ssl->keys.padSz; + { + if (*inOutIdx + ssl->keys.padSz > totalSz) { + WOLFSSL_ERROR(BUFFER_E); + return BUFFER_E; } } if (IsDtlsNotSctpMode(ssl) && @@ -13056,27 +13228,42 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, ret = DtlsMsgPoolSend(ssl, 0); } + *inOutIdx += ssl->keys.padSz; } else if (fragSz < size) { /* Since this branch is in order, but fragmented, dtls_rx_msg_list will * be pointing to the message with this fragment in it. Check it to see * if it is completed. */ + WOLFSSL_MSG("Branch is in order, but fragmented"); if (ssl->dtls_rx_msg_list_sz < DTLS_POOL_SZ) { - DtlsMsgStore(ssl, ssl->keys.dtls_peer_handshake_number, + DtlsMsgStore(ssl, ssl->keys.curEpoch, + ssl->keys.dtls_peer_handshake_number, input + *inOutIdx, size, type, fragOffset, fragSz, ssl->heap); } *inOutIdx += fragSz; + *inOutIdx += 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 = 0; if (ssl->dtls_rx_msg_list != NULL && ssl->dtls_rx_msg_list->fragSz >= ssl->dtls_rx_msg_list->sz) ret = DtlsMsgDrain(ssl); } else { - /* This branch is in order next, and a complete message. */ + /* This branch is in order next, and a complete message. On success + * clean the tx list. */ + WOLFSSL_MSG("Branch is in order and a complete message"); ret = DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz); if (ret == 0) { - if (type != client_hello || !IsDtlsNotSctpMode(ssl)) + DtlsTxMsgListClean(ssl); + if (type != finished) ssl->keys.dtls_expected_peer_handshake_number++; if (ssl->dtls_rx_msg_list != NULL) { ret = DtlsMsgDrain(ssl); @@ -13869,8 +14056,21 @@ static WC_INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input, c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, ssl->decrypt.additional + AEAD_LEN_OFFSET); - XMEMCPY(ssl->decrypt.nonce, ssl->keys.aead_dec_imp_IV, - AESGCM_IMP_IV_SZ); + + #if defined(WOLFSSL_DTLS) && defined(HAVE_SECURE_RENEGOTIATION) + if (ssl->options.dtls && ssl->secure_renegotiation && + ssl->secure_renegotiation->tmp_keys.dtls_epoch != 0) { + if (ssl->keys.curEpoch == ssl->secure_renegotiation->tmp_keys.dtls_epoch) + XMEMCPY(ssl->decrypt.nonce, ssl->secure_renegotiation->tmp_keys.aead_dec_imp_IV, + AESGCM_IMP_IV_SZ); + else + XMEMCPY(ssl->decrypt.nonce, ssl->keys.aead_dec_imp_IV, + AESGCM_IMP_IV_SZ); + } + else + #endif + XMEMCPY(ssl->decrypt.nonce, ssl->keys.aead_dec_imp_IV, + AESGCM_IMP_IV_SZ); XMEMCPY(ssl->decrypt.nonce + AESGCM_IMP_IV_SZ, input, AESGCM_EXP_IV_SZ); if ((ret = aes_auth_fn(ssl->decrypt.aes, @@ -13994,6 +14194,27 @@ static WC_INLINE int Decrypt(WOLFSSL* ssl, byte* plain, const byte* input, FALL_THROUGH; case CIPHER_STATE_DO: { + #if defined(WOLFSSL_DTLS) && defined(HAVE_SECURE_RENEGOTIATION) + if (ssl->options.dtls && ssl->secure_renegotiation && + ssl->secure_renegotiation->tmp_keys.dtls_epoch != 0) { + if (ssl->keys.curEpoch == ssl->secure_renegotiation->tmp_keys.dtls_epoch) { + if (ssl->decrypt.src != SCR) { + ssl->secure_renegotiation->cache_status = SCR_CACHE_NEEDED; + if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0) + break; + } + WOLFSSL_BUFFER(ssl->secure_renegotiation->tmp_keys.client_write_key, MAX_SYM_KEY_SIZE); + } + else { + if (ssl->decrypt.src != KEYS) { + ssl->secure_renegotiation->cache_status = SCR_CACHE_NULL; + if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0) + break; + } + } + } + #endif + ret = DecryptDo(ssl, plain, input, sz); /* Advance state */ @@ -14229,7 +14450,7 @@ int TimingPadVerify(WOLFSSL* ssl, const byte* input, int padLen, int macSz, * either increment the size by (macSz + padLen + 1) before use or check on * the size to make sure is valid. */ ret = ssl->hmac(ssl, verify, input, pLen - macSz - padLen - 1, padLen, - content, 1); + content, 1, PEER_ORDER); good |= MaskMac(input, pLen, ssl->specs.hash_size, verify); /* Non-zero on failure. */ @@ -14515,7 +14736,7 @@ static WC_INLINE int VerifyMacEnc(WOLFSSL* ssl, const byte* input, word32 msgSz, return VERIFY_MAC_ERROR; } - ret = ssl->hmac(ssl, verify, input, msgSz - digestSz, -1, content, 1); + ret = ssl->hmac(ssl, verify, input, msgSz - digestSz, -1, content, 1, PEER_ORDER); ret |= ConstantCompare(verify, input + msgSz - digestSz, digestSz); if (ret != 0) { return VERIFY_MAC_ERROR; @@ -14568,8 +14789,8 @@ static WC_INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz, badPadLen = 1; } PadCheck(dummy, (byte)pad, MAX_PAD_SIZE); /* timing only */ - ret = ssl->hmac(ssl, verify, input, msgSz - digestSz - pad - 1, pad, - content, 1); + ret = ssl->hmac(ssl, verify, input, msgSz - digestSz - pad - 1, + pad, content, 1, PEER_ORDER); if (ConstantCompare(verify, input + msgSz - digestSz - pad - 1, digestSz) != 0) return VERIFY_MAC_ERROR; @@ -14578,7 +14799,8 @@ static WC_INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz, } } else if (ssl->specs.cipher_type == stream) { - ret = ssl->hmac(ssl, verify, input, msgSz - digestSz, -1, content, 1); + ret = ssl->hmac(ssl, verify, input, msgSz - digestSz, -1, content, 1, + PEER_ORDER); if (ConstantCompare(verify, input + msgSz - digestSz, digestSz) != 0){ return VERIFY_MAC_ERROR; } @@ -14752,12 +14974,6 @@ int ProcessReply(WOLFSSL* ssl) ssl->replayDropCount++; #endif /* WOLFSSL_DTLS_DROP_STATS */ - if (IsDtlsNotSctpMode(ssl) && ssl->options.dtlsHsRetain) { - ret = DtlsMsgPoolSend(ssl, 0); - if (ret != 0) - return ret; - } - continue; } #endif @@ -15109,6 +15325,7 @@ int ProcessReply(WOLFSSL* ssl) switch (ssl->curRL.type) { case handshake : + WOLFSSL_MSG("got HANDSHAKE"); /* debugging in DoHandShakeMsg */ if (ssl->options.dtls) { #ifdef WOLFSSL_DTLS @@ -15166,7 +15383,8 @@ int ProcessReply(WOLFSSL* ssl) AddPacketInfo(ssl, "ChangeCipher", change_cipher_spec, ssl->buffers.inputBuffer.buffer + - ssl->buffers.inputBuffer.idx - RECORD_HEADER_SZ, + ssl->buffers.inputBuffer.idx - RECORD_HEADER_SZ - + (ssl->options.dtls ? DTLS_RECORD_EXTRA : 0), 1 + RECORD_HEADER_SZ, READ_PROTO, ssl->heap); #ifdef WOLFSSL_CALLBACKS AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo); @@ -15199,39 +15417,23 @@ int ProcessReply(WOLFSSL* ssl) #endif #ifndef WOLFSSL_NO_TLS12 - ret = SanityCheckMsgReceived(ssl, change_cipher_hs); - if (ret != 0) { - if (!ssl->options.dtls) { - return ret; - } - else { - #ifdef WOLFSSL_DTLS - /* Check for duplicate CCS message in DTLS mode. - * DTLS allows for duplicate messages, and it should be - * skipped. Also skip if out of order. */ - if (ret != DUPLICATE_MSG_E && ret != OUT_OF_ORDER_E) - return ret; - - if (IsDtlsNotSctpMode(ssl)) { - ret = DtlsMsgPoolSend(ssl, 1); - if (ret != 0) - return ret; - } - - if (ssl->curSize != 1) { - WOLFSSL_MSG("Malicious or corrupted" - " duplicate ChangeCipher msg"); - return LENGTH_ERROR; - } - ssl->buffers.inputBuffer.idx++; - break; - #endif /* WOLFSSL_DTLS */ - } + if (ssl->buffers.inputBuffer.buffer[ + ssl->buffers.inputBuffer.idx] != 1) { + WOLFSSL_MSG("ChangeCipher msg wrong value"); + return LENGTH_ERROR; } if (IsEncryptionOn(ssl, 0) && ssl->options.handShakeDone) { ssl->buffers.inputBuffer.idx += ssl->keys.padSz; - ssl->curSize -= (word16) ssl->buffers.inputBuffer.idx; + ssl->curSize -= ssl->keys.padSz; +#ifdef HAVE_AEAD + if (ssl->specs.cipher_type == aead && + ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) + ssl->curSize -= AESGCM_EXP_IV_SZ; + else +#endif + ssl->curSize -= ssl->specs.iv_size; + #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) if (ssl->options.startedETMRead) { word32 digestSz = MacSize(ssl); @@ -15247,6 +15449,25 @@ int ProcessReply(WOLFSSL* ssl) } ssl->buffers.inputBuffer.idx++; + + ret = SanityCheckMsgReceived(ssl, change_cipher_hs); + if (ret != 0) { + if (!ssl->options.dtls) { + return ret; + } + else { + #ifdef WOLFSSL_DTLS + /* Check for duplicate CCS message in DTLS mode. + * DTLS allows for duplicate messages, and it should be + * skipped. Also skip if out of order. */ + if (ret != DUPLICATE_MSG_E && ret != OUT_OF_ORDER_E) + return ret; + + break; + #endif /* WOLFSSL_DTLS */ + } + } + ssl->keys.encryptionOn = 1; /* setup decrypt keys for following messages */ @@ -15387,7 +15608,6 @@ int ProcessReply(WOLFSSL* ssl) /* more records */ else { WOLFSSL_MSG("More records in input"); - ssl->options.processReply = doProcessInit; continue; } @@ -15441,7 +15661,7 @@ int SendChangeCipher(WOLFSSL* ssl) output = ssl->buffers.outputBuffer.buffer + ssl->buffers.outputBuffer.length; - AddRecordHeader(output, 1, change_cipher_spec, ssl); + AddRecordHeader(output, 1, change_cipher_spec, ssl, CUR_ORDER); output[idx] = 1; /* turn it on */ @@ -15450,19 +15670,26 @@ int SendChangeCipher(WOLFSSL* ssl) int inputSz = ENUM_LEN; input[0] = 1; /* turn it on */ + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl) && + (ret = DtlsMsgPoolSave(ssl, input, inputSz, change_cipher_hs)) != 0) { + return ret; + } + #endif sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - change_cipher_spec, 0, 0, 0); + change_cipher_spec, 0, 0, 0, CUR_ORDER); if (sendSz < 0) { return sendSz; } } - #ifdef WOLFSSL_DTLS + else { if (IsDtlsNotSctpMode(ssl)) { DtlsSEQIncrement(ssl, CUR_ORDER); - if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz, change_cipher_hs)) != 0) return ret; } + } #endif #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) if (ssl->hsInfoOn) AddPacketName(ssl, "ChangeCipher"); @@ -15488,7 +15715,7 @@ int SendChangeCipher(WOLFSSL* ssl) #if !defined(NO_OLD_TLS) && !defined(WOLFSSL_AEAD_ONLY) static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, - int padLen, int content, int verify) + int padLen, int content, int verify, int epochOrder) { byte result[WC_MAX_DIGEST_SIZE]; word32 digestSz = ssl->specs.hash_size; /* actual sizes */ @@ -15501,7 +15728,7 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, /* data */ byte seq[SEQ_SZ]; byte conLen[ENUM_LEN + LENGTH_SZ]; /* content & length */ - const byte* macSecret = wolfSSL_GetMacSecret(ssl, verify); + const byte* macSecret = NULL; (void)padLen; @@ -15510,10 +15737,19 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, ssl->fuzzerCb(ssl, in, sz, FUZZ_HMAC, ssl->fuzzerCtx); #endif +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + macSecret = wolfSSL_GetDtlsMacSecret(ssl, verify, epochOrder); + else + macSecret = wolfSSL_GetMacSecret(ssl, verify); +#else + macSecret = wolfSSL_GetMacSecret(ssl, verify); +#endif + XMEMSET(seq, 0, SEQ_SZ); conLen[0] = (byte)content; c16toa((word16)sz, &conLen[ENUM_LEN]); - WriteSEQ(ssl, verify, seq); + WriteSEQ(ssl, epochOrder, seq); if (ssl->specs.mac_algorithm == md5_mac) { ret = wc_InitMd5_ex(&md5, ssl->heap, ssl->devId); @@ -15774,7 +16010,8 @@ static void FreeBuildMsgArgs(WOLFSSL* ssl, void* pArgs) /* Build SSL Message, encrypted */ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, - int inSz, int type, int hashOutput, int sizeOnly, int asyncOkay) + int inSz, int type, int hashOutput, int sizeOnly, int asyncOkay, + int epochOrder) { #ifndef WOLFSSL_NO_TLS12 int ret = 0; @@ -15793,6 +16030,8 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, return BAD_FUNC_ARG; } + (void)epochOrder; + #ifdef WOLFSSL_NO_TLS12 return BuildTls13Message(ssl, output, outSz, input, inSz, type, hashOutput, sizeOnly, asyncOkay); @@ -15845,6 +16084,42 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, WOLFSSL_MSG("BuildMessage w/sizeOnly doesn't need input/output"); ERROR_OUT(BAD_FUNC_ARG, exit_buildmsg); } + #if defined(WOLFSSL_DTLS) && defined(HAVE_SECURE_RENEGOTIATION) + if (ssl->options.dtls && ssl->secure_renegotiation && + ssl->secure_renegotiation->tmp_keys.dtls_epoch != 0) { + switch (epochOrder) { + case PREV_ORDER: + if (ssl->encrypt.src != KEYS) { + ssl->secure_renegotiation->cache_status = SCR_CACHE_NULL; + if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0) + ERROR_OUT(ret, exit_buildmsg); + WOLFSSL_BUFFER(ssl->keys.client_write_key, MAX_SYM_KEY_SIZE); + } + break; + case CUR_ORDER: + if (ssl->keys.dtls_epoch == ssl->secure_renegotiation->tmp_keys.dtls_epoch) { + if (ssl->encrypt.src != SCR) { + ssl->secure_renegotiation->cache_status = SCR_CACHE_NEEDED; + if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0) + ERROR_OUT(ret, exit_buildmsg); + WOLFSSL_BUFFER(ssl->secure_renegotiation->tmp_keys.client_write_key, MAX_SYM_KEY_SIZE); + } + } + else { + if (ssl->encrypt.src != KEYS) { + ssl->secure_renegotiation->cache_status = SCR_CACHE_NULL; + if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0) + ERROR_OUT(ret, exit_buildmsg); + WOLFSSL_BUFFER(ssl->keys.client_write_key, MAX_SYM_KEY_SIZE); + } + } + break; + default: + WOLFSSL_MSG("BuildMessage only supports PREV_ORDER and CUR_ORDER"); + ERROR_OUT(BAD_FUNC_ARG, exit_buildmsg); + } + } + #endif ssl->options.buildMsgState = BUILD_MSG_SIZE; } @@ -15932,7 +16207,7 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, #endif args->size = (word16)(args->sz - args->headerSz); /* include mac and digest */ - AddRecordHeader(output, args->size, (byte)type, ssl); + AddRecordHeader(output, args->size, (byte)type, ssl, epochOrder); /* write to output */ if (args->ivSz > 0) { @@ -16027,7 +16302,7 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, ret = ssl->hmac(ssl, hmac, output + args->headerSz + args->ivSz, inSz, - -1, type, 0); + -1, type, 0, epochOrder); XMEMCPY(output + args->idx, hmac, args->digestSz); #ifdef WOLFSSL_SMALL_STACK @@ -16038,7 +16313,7 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, #endif { ret = ssl->hmac(ssl, output + args->idx, output + - args->headerSz + args->ivSz, inSz, -1, type, 0); + args->headerSz + args->ivSz, inSz, -1, type, 0, epochOrder); } } #endif /* WOLFSSL_AEAD_ONLY */ @@ -16050,6 +16325,26 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, FALL_THROUGH; case BUILD_MSG_ENCRYPT: { + #if defined(HAVE_SECURE_RENEGOTIATION) && defined(WOLFSSL_DTLS) + /* Modify CUR_ORDER sequence number for all encryption algos + * that use it for encryption parameters */ + word16 dtls_epoch; + word16 dtls_sequence_number_hi; + word32 dtls_sequence_number_lo; + int swap_seq = ssl->options.dtls && epochOrder == PREV_ORDER && + ssl->secure_renegotiation && + ssl->secure_renegotiation->tmp_keys.dtls_epoch != 0 && + ssl->secure_renegotiation->tmp_keys.dtls_epoch == + ssl->keys.dtls_epoch; + if (swap_seq) { + dtls_epoch = ssl->keys.dtls_epoch; + dtls_sequence_number_hi = ssl->keys.dtls_sequence_number_hi; + dtls_sequence_number_lo = ssl->keys.dtls_sequence_number_lo; + ssl->keys.dtls_epoch--; + ssl->keys.dtls_sequence_number_hi = ssl->keys.dtls_prev_sequence_number_hi; + ssl->keys.dtls_sequence_number_lo = ssl->keys.dtls_prev_sequence_number_lo; + } + #endif #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) if (ssl->options.startedETMWrite) { ret = Encrypt(ssl, output + args->headerSz, @@ -16062,6 +16357,14 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, ret = Encrypt(ssl, output + args->headerSz, output + args->headerSz, args->size, asyncOkay); } + #if defined(HAVE_SECURE_RENEGOTIATION) && defined(WOLFSSL_DTLS) + /* Restore sequence numbers */ + if (swap_seq) { + ssl->keys.dtls_epoch = dtls_epoch; + ssl->keys.dtls_sequence_number_hi = dtls_sequence_number_hi; + ssl->keys.dtls_sequence_number_lo = dtls_sequence_number_lo; + } + #endif if (ret != 0) goto exit_buildmsg; ssl->options.buildMsgState = BUILD_MSG_ENCRYPTED_VERIFY_MAC; @@ -16091,7 +16394,7 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, ret = ssl->hmac(ssl, hmac, output + args->headerSz, args->ivSz + inSz + args->pad + 1, -1, type, - 0); + 0, epochOrder); XMEMCPY(output + args->idx + args->pad + 1, hmac, args->digestSz); @@ -16105,7 +16408,7 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, ret = ssl->hmac(ssl, output + args->idx + args->pad + 1, output + args->headerSz, args->ivSz + inSz + args->pad + 1, -1, type, - 0); + 0, epochOrder); } } #endif /* HAVE_ENCRYPT_THEN_MAC && !WOLFSSL_AEAD_ONLY */ @@ -16127,7 +16430,7 @@ exit_buildmsg: #ifdef WOLFSSL_DTLS if (ret == 0 && ssl->options.dtls) - DtlsSEQIncrement(ssl, CUR_ORDER); + DtlsSEQIncrement(ssl, epochOrder); #endif /* return sz on success */ @@ -16212,13 +16515,13 @@ int SendFinished(WOLFSSL* ssl) #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsMsgPoolSave(ssl, input, headerSz + finishedSz)) != 0) + if ((ret = DtlsMsgPoolSave(ssl, input, headerSz + finishedSz, finished)) != 0) return ret; } #endif sendSz = BuildMessage(ssl, output, outputSz, input, headerSz + finishedSz, - handshake, 1, 0, 0); + handshake, 1, 0, 0, CUR_ORDER); if (sendSz < 0) return BUILD_MSG_ERROR; @@ -16261,6 +16564,13 @@ int SendFinished(WOLFSSL* ssl) ret = SendBuffered(ssl); +#ifdef WOLFSSL_DTLS + if (ssl->options.side == WOLFSSL_SERVER_END) { + ssl->keys.dtls_handshake_number = 0; + ssl->keys.dtls_expected_peer_handshake_number = 0; + } +#endif + WOLFSSL_LEAVE("SendFinished", ret); WOLFSSL_END(WC_FUNC_FINISHED_SEND); @@ -16409,6 +16719,14 @@ int CreateOcspResponse(WOLFSSL* ssl, OcspRequest** ocspRequest, #ifndef NO_CERTS #if !defined(NO_WOLFSSL_SERVER) || !defined(WOLFSSL_NO_CLIENT_AUTH) +static int cipherExtraData(WOLFSSL* ssl) +{ + /* Cipher data that may be added by BuildMessage */ + return ssl->specs.hash_size + ssl->specs.block_size + + ssl->specs.aead_mac_size + ssl->specs.iv_size + + ssl->specs.pad_size; +} + /* handle generation of certificate (11) */ int SendCertificate(WOLFSSL* ssl) { @@ -16516,6 +16834,8 @@ int SendCertificate(WOLFSSL* ssl) #endif } + sendSz += cipherExtraData(ssl); + /* check for available size */ if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) return ret; @@ -16534,10 +16854,9 @@ int SendCertificate(WOLFSSL* ssl) else { #ifdef WOLFSSL_DTLS AddHeaders(output, payloadSz, certificate, ssl); - if (!IsEncryptionOn(ssl, 1)) - HashOutputRaw(ssl, - output + RECORD_HEADER_SZ + DTLS_RECORD_EXTRA, - HANDSHAKE_HEADER_SZ + DTLS_HANDSHAKE_EXTRA); + HashOutputRaw(ssl, + output + RECORD_HEADER_SZ + DTLS_RECORD_EXTRA, + HANDSHAKE_HEADER_SZ + DTLS_HANDSHAKE_EXTRA); /* Adding the headers increments these, decrement them for * actual message header. */ ssl->keys.dtls_handshake_number--; @@ -16548,20 +16867,20 @@ int SendCertificate(WOLFSSL* ssl) /* list total */ c32to24(listSz, output + i); - if (!IsEncryptionOn(ssl, 1)) + if (ssl->options.dtls || !IsEncryptionOn(ssl, 1)) HashOutputRaw(ssl, output + i, CERT_HEADER_SZ); i += CERT_HEADER_SZ; length -= CERT_HEADER_SZ; fragSz -= CERT_HEADER_SZ; if (certSz) { c32to24(certSz, output + i); - if (!IsEncryptionOn(ssl, 1)) + if (ssl->options.dtls || !IsEncryptionOn(ssl, 1)) HashOutputRaw(ssl, output + i, CERT_HEADER_SZ); i += CERT_HEADER_SZ; length -= CERT_HEADER_SZ; fragSz -= CERT_HEADER_SZ; - if (!IsEncryptionOn(ssl, 1)) { + if (ssl->options.dtls || !IsEncryptionOn(ssl, 1)) { HashOutputRaw(ssl, ssl->buffers.certificate->buffer, certSz); if (certChainSz) HashOutputRaw(ssl, ssl->buffers.certChain->buffer, @@ -16571,7 +16890,7 @@ int SendCertificate(WOLFSSL* ssl) } else { if (!ssl->options.dtls) { - AddRecordHeader(output, fragSz, handshake, ssl); + AddRecordHeader(output, fragSz, handshake, ssl, CUR_ORDER); } else { #ifdef WOLFSSL_DTLS @@ -16604,7 +16923,12 @@ int SendCertificate(WOLFSSL* ssl) if (IsEncryptionOn(ssl, 1)) { byte* input = NULL; - int inputSz = i - RECORD_HEADER_SZ; /* build msg adds rec hdr */ + int inputSz = i; /* build msg adds rec hdr */ + int recordHeaderSz = RECORD_HEADER_SZ; + + if (ssl->options.dtls) + recordHeaderSz += DTLS_RECORD_EXTRA; + inputSz -= recordHeaderSz; if (inputSz < 0) { WOLFSSL_MSG("Send Cert bad inputSz"); @@ -16616,32 +16940,44 @@ int SendCertificate(WOLFSSL* ssl) DYNAMIC_TYPE_IN_BUFFER); if (input == NULL) return MEMORY_E; - XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); + XMEMCPY(input, output + recordHeaderSz, inputSz); } +#ifndef WOLFSSL_DTLS sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - handshake, 1, 0, 0); + handshake, 1, 0, 0, CUR_ORDER); +#else + if (!ssl->options.dtls) + sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, + handshake, 1, 0, 0, CUR_ORDER); + else /* DTLS 1.2 has to ignore fragmentation in hashing so we need to + * calculate the hash ourselves above */ { + if ((ret = DtlsMsgPoolSave(ssl, input, inputSz, certificate)) != 0) { + XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + return ret; + } + sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, + handshake, 0, 0, 0, CUR_ORDER); + } +#endif - if (inputSz > 0) - XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); if (sendSz < 0) return sendSz; } else { + sendSz = i; #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz, certificate)) != 0) + return ret; + } if (ssl->options.dtls) DtlsSEQIncrement(ssl, CUR_ORDER); #endif } - #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) - return ret; - } - #endif - #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) if (ssl->hsInfoOn) AddPacketName(ssl, "Certificate"); @@ -16724,6 +17060,9 @@ int SendCertificateRequest(WOLFSSL* ssl) i += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; #endif } + + sendSz += cipherExtraData(ssl); + /* check for available size */ if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) return ret; @@ -16778,25 +17117,38 @@ int SendCertificateRequest(WOLFSSL* ssl) if (IsEncryptionOn(ssl, 1)) { byte* input; - int inputSz = i - RECORD_HEADER_SZ; /* build msg adds rec hdr */ + int inputSz = i; /* build msg adds rec hdr */ + int recordHeaderSz = RECORD_HEADER_SZ; + + if (ssl->options.dtls) + recordHeaderSz += DTLS_RECORD_EXTRA; + inputSz -= recordHeaderSz; input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); if (input == NULL) return MEMORY_E; - XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); + XMEMCPY(input, output + recordHeaderSz, inputSz); + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl) && + (ret = DtlsMsgPoolSave(ssl, input, inputSz, certificate_request)) != 0) { + XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + return ret; + } + #endif sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - handshake, 1, 0, 0); + handshake, 1, 0, 0, CUR_ORDER); XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); if (sendSz < 0) return sendSz; } else { + sendSz = i; #ifdef WOLFSSL_DTLS if (ssl->options.dtls) DtlsSEQIncrement(ssl, CUR_ORDER); if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz, certificate_request)) != 0) return ret; } #endif @@ -16881,15 +17233,19 @@ static int BuildCertificateStatus(WOLFSSL* ssl, byte type, buffer* status, if (IsEncryptionOn(ssl, 1)) { byte* input; - int inputSz = idx - RECORD_HEADER_SZ; + int inputSz = idx; /* build msg adds rec hdr */ + int recordHeaderSz = RECORD_HEADER_SZ; + if (ssl->options.dtls) + recordHeaderSz += DTLS_RECORD_EXTRA; + inputSz -= recordHeaderSz; input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); if (input == NULL) return MEMORY_E; - XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); + XMEMCPY(input, output + recordHeaderSz, inputSz); sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - handshake, 1, 0, 0); + handshake, 1, 0, 0, CUR_ORDER); XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); if (sendSz < 0) @@ -16905,7 +17261,7 @@ static int BuildCertificateStatus(WOLFSSL* ssl, byte type, buffer* status, #ifdef WOLFSSL_DTLS if (ret == 0 && IsDtlsNotSctpMode(ssl)) - ret = DtlsMsgPoolSave(ssl, output, sendSz); + ret = DtlsMsgPoolSave(ssl, output, sendSz, certificate_status); #endif #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) @@ -17253,12 +17609,12 @@ int SendData(WOLFSSL* ssl, const void* data, int sz) #endif if (!ssl->options.tls1_3) { sendSz = BuildMessage(ssl, out, outputSz, sendBuffer, buffSz, - application_data, 0, 0, 1); + application_data, 0, 0, 1, CUR_ORDER); } else { #ifdef WOLFSSL_TLS13 sendSz = BuildTls13Message(ssl, out, outputSz, sendBuffer, buffSz, - application_data, 0, 0, 1); + application_data, 0, 0, 1, CUR_ORDER); #else sendSz = BUFFER_ERROR; #endif @@ -17483,11 +17839,11 @@ int SendAlert(WOLFSSL* ssl, int severity, int type) */ if (IsEncryptionOn(ssl, 1)) { sendSz = BuildMessage(ssl, output, outputSz, input, ALERT_SIZE, alert, - 0, 0, 0); + 0, 0, 0, CUR_ORDER); } else { - AddRecordHeader(output, ALERT_SIZE, alert, ssl); + AddRecordHeader(output, ALERT_SIZE, alert, ssl, CUR_ORDER); output += RECORD_HEADER_SZ; #ifdef WOLFSSL_DTLS if (ssl->options.dtls) @@ -19719,15 +20075,26 @@ exit_dpk: if (IsEncryptionOn(ssl, 1)) { byte* input; - int inputSz = idx - RECORD_HEADER_SZ; /* build msg adds rec hdr */ + int inputSz = idx; /* build msg adds rec hdr */ + int recordHeaderSz = RECORD_HEADER_SZ; + if (ssl->options.dtls) + recordHeaderSz += DTLS_RECORD_EXTRA; + inputSz -= recordHeaderSz; input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); if (input == NULL) return MEMORY_E; - XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); + XMEMCPY(input, output + recordHeaderSz, inputSz); + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl) && + (ret = DtlsMsgPoolSave(ssl, input, inputSz, client_hello)) != 0) { + XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + return ret; + } + #endif sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - handshake, 1, 0, 0); + handshake, 1, 0, 0, CUR_ORDER); XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); if (sendSz < 0) @@ -19735,7 +20102,7 @@ exit_dpk: } else { #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz, client_hello)) != 0) return ret; } if (ssl->options.dtls) @@ -20254,12 +20621,6 @@ exit_dpk: ssl->options.resuming = 0; /* server denied resumption try */ } } - #ifdef WOLFSSL_DTLS - if (ssl->options.dtls) { - DtlsMsgPoolReset(ssl); - } - #endif - return SetCipherSpecs(ssl); } @@ -23265,14 +23626,18 @@ int SendClientKeyExchange(WOLFSSL* ssl) idx += args->encSz; if (IsEncryptionOn(ssl, 1)) { - args->inputSz = idx - RECORD_HEADER_SZ; /* buildmsg adds rechdr */ + int recordHeaderSz = RECORD_HEADER_SZ; + + if (ssl->options.dtls) + recordHeaderSz += DTLS_RECORD_EXTRA; + args->inputSz = idx - recordHeaderSz; /* buildmsg adds rechdr */ args->input = (byte*)XMALLOC(args->inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); if (args->input == NULL) { ERROR_OUT(MEMORY_E, exit_scke); } - XMEMCPY(args->input, args->output + RECORD_HEADER_SZ, + XMEMCPY(args->input, args->output + recordHeaderSz, args->inputSz); } @@ -23284,8 +23649,14 @@ int SendClientKeyExchange(WOLFSSL* ssl) case TLS_ASYNC_END: { if (IsEncryptionOn(ssl, 1)) { + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl) && + (ret = DtlsMsgPoolSave(ssl, args->input, args->inputSz, client_key_exchange)) != 0) { + goto exit_scke; + } + #endif ret = BuildMessage(ssl, args->output, args->sendSz, - args->input, args->inputSz, handshake, 1, 0, 0); + args->input, args->inputSz, handshake, 1, 0, 0, CUR_ORDER); XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); args->input = NULL; /* make sure its not double free'd on cleanup */ @@ -23296,6 +23667,11 @@ int SendClientKeyExchange(WOLFSSL* ssl) } else { #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + if ((ret = DtlsMsgPoolSave(ssl, args->output, args->sendSz, client_key_exchange)) != 0) { + goto exit_scke; + } + } if (ssl->options.dtls) DtlsSEQIncrement(ssl, CUR_ORDER); #endif @@ -23306,14 +23682,6 @@ int SendClientKeyExchange(WOLFSSL* ssl) goto exit_scke; } - #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsMsgPoolSave(ssl, args->output, args->sendSz)) != 0) { - goto exit_scke; - } - } - #endif - #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) if (ssl->hsInfoOn) AddPacketName(ssl, "ClientKeyExchange"); @@ -23802,7 +24170,11 @@ int SendCertificateVerify(WOLFSSL* ssl) #endif if (IsEncryptionOn(ssl, 1)) { - args->inputSz = args->sendSz - RECORD_HEADER_SZ; + int recordHeaderSz = RECORD_HEADER_SZ; + + if (ssl->options.dtls) + recordHeaderSz += DTLS_RECORD_EXTRA; + args->inputSz = args->sendSz - recordHeaderSz; /* build msg adds rec hdr */ args->input = (byte*)XMALLOC(args->inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); @@ -23810,7 +24182,7 @@ int SendCertificateVerify(WOLFSSL* ssl) ERROR_OUT(MEMORY_E, exit_scv); } - XMEMCPY(args->input, args->output + RECORD_HEADER_SZ, + XMEMCPY(args->input, args->output + recordHeaderSz, args->inputSz); } @@ -23822,10 +24194,16 @@ int SendCertificateVerify(WOLFSSL* ssl) case TLS_ASYNC_END: { if (IsEncryptionOn(ssl, 1)) { + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl) && + (ret = DtlsMsgPoolSave(ssl, args->input, args->inputSz, certificate_verify)) != 0) { + goto exit_scv; + } + #endif ret = BuildMessage(ssl, args->output, MAX_CERT_VERIFY_SZ + MAX_MSG_EXTRA, args->input, args->inputSz, handshake, - 1, 0, 1); + 1, 0, 1, CUR_ORDER); #ifdef WOLFSSL_ASYNC_CRYPT if (ret == WC_PENDING_E) goto exit_scv; @@ -23841,6 +24219,9 @@ int SendCertificateVerify(WOLFSSL* ssl) } else { #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + ret = DtlsMsgPoolSave(ssl, args->output, args->sendSz, certificate_verify); + } if (ssl->options.dtls) DtlsSEQIncrement(ssl, CUR_ORDER); #endif @@ -23851,13 +24232,6 @@ int SendCertificateVerify(WOLFSSL* ssl) goto exit_scv; } - #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl)) { - ret = DtlsMsgPoolSave(ssl, args->output, args->sendSz); - } - #endif - - #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) if (ssl->hsInfoOn) AddPacketName(ssl, "CertificateVerify"); @@ -24277,21 +24651,36 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (IsEncryptionOn(ssl, 1)) { byte* input; - int inputSz = idx - RECORD_HEADER_SZ; /* build msg adds rec hdr */ + int inputSz = idx; /* build msg adds rec hdr */ + int recordHeaderSz = RECORD_HEADER_SZ; + if (ssl->options.dtls) + recordHeaderSz += DTLS_RECORD_EXTRA; + inputSz -= recordHeaderSz; input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); if (input == NULL) return MEMORY_E; - XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); + XMEMCPY(input, output + recordHeaderSz, inputSz); + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl) && + (ret = DtlsMsgPoolSave(ssl, input, inputSz, server_hello)) != 0) { + XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + return ret; + } + #endif sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - handshake, 1, 0, 0); + handshake, 1, 0, 0, CUR_ORDER); XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); if (sendSz < 0) return sendSz; } else { #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz, server_hello)) != 0) + return ret; + } if (ssl->options.dtls) DtlsSEQIncrement(ssl, CUR_ORDER); #endif @@ -24311,13 +24700,6 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ssl->options.serverState = SERVER_HELLO_COMPLETE; ssl->buffers.outputBuffer.length += sendSz; - #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) - return ret; - } - #endif - if (ssl->options.groupMessages) ret = 0; else @@ -25830,7 +26212,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (IsEncryptionOn(ssl, 1)) { args->inputSz = args->length + HANDSHAKE_HEADER_SZ; - /* buildmsg adds rechdr */ + if (ssl->options.dtls) + args->inputSz += DTLS_HANDSHAKE_EXTRA; args->input = (byte*)XMALLOC(args->inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); if (args->input == NULL) { @@ -25841,10 +26224,22 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ERROR_OUT(BUFFER_ERROR, exit_sske); } - XMEMCPY(args->input, args->output + RECORD_HEADER_SZ, + if (!ssl->options.dtls) + XMEMCPY(args->input, args->output + RECORD_HEADER_SZ, args->inputSz); + else + XMEMCPY(args->input, args->output + DTLS_RECORD_HEADER_SZ, + args->inputSz); + + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl) && + (ret = DtlsMsgPoolSave(ssl, args->input, args->inputSz, server_key_exchange)) + != 0) { + goto exit_sske; + } + #endif ret = BuildMessage(ssl, args->output, args->sendSz, - args->input, args->inputSz, handshake, 1, 0, 0); + args->input, args->inputSz, handshake, 1, 0, 0, CUR_ORDER); XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); args->input = NULL; /* make sure its not double free'd on cleanup */ @@ -25858,7 +26253,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { if ((ret = DtlsMsgPoolSave(ssl, - args->output, args->sendSz)) != 0) { + args->output, args->sendSz, server_key_exchange)) != 0) { goto exit_sske; } } @@ -26490,7 +26885,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, XMEMCPY(&pv, input + i, OPAQUE16_LEN); ssl->chVersion = pv; /* store */ #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl)) { + if (IsDtlsNotSctpMode(ssl) && !IsInitialRenegotiationState(ssl)) { #if defined(NO_SHA) && defined(NO_SHA256) #error "DTLS needs either SHA or SHA-256" #endif /* NO_SHA && NO_SHA256 */ @@ -26640,7 +27035,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* random */ XMEMCPY(ssl->arrays->clientRandom, input + i, RAN_LEN); #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl)) { + if (IsDtlsNotSctpMode(ssl) && !IsInitialRenegotiationState(ssl)) { ret = wc_HmacUpdate(&cookieHmac, input + i, RAN_LEN); if (ret != 0) return ret; } @@ -26673,7 +27068,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, XMEMCPY(ssl->arrays->sessionID, input + i, b); #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl)) { + if (IsDtlsNotSctpMode(ssl) && !IsInitialRenegotiationState(ssl)) { ret = wc_HmacUpdate(&cookieHmac, input + i - 1, b + 1); if (ret != 0) return ret; } @@ -26758,7 +27153,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif #ifdef WOLFSSL_DTLS - if (IsDtlsNotSctpMode(ssl)) { + if (IsDtlsNotSctpMode(ssl) && !IsInitialRenegotiationState(ssl)) { ret = wc_HmacUpdate(&cookieHmac, input + i - OPAQUE16_LEN, clSuites.suiteSz + OPAQUE16_LEN); @@ -26784,33 +27179,35 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { - byte newCookie[MAX_COOKIE_LEN]; + if (!IsInitialRenegotiationState(ssl)) { + byte newCookie[MAX_COOKIE_LEN]; - ret = wc_HmacUpdate(&cookieHmac, input + i - 1, b + 1); - if (ret != 0) return ret; - ret = wc_HmacFinal(&cookieHmac, newCookie); - if (ret != 0) return ret; + ret = wc_HmacUpdate(&cookieHmac, input + i - 1, b + 1); + if (ret != 0) return ret; + ret = wc_HmacFinal(&cookieHmac, newCookie); + if (ret != 0) return ret; - /* If a cookie callback is set, call it to overwrite the cookie. - * This should be deprecated. The code now calculates the cookie - * using an HMAC as expected. */ - if (ssl->ctx->CBIOCookie != NULL && - ssl->ctx->CBIOCookie(ssl, newCookie, cookieSz, - ssl->IOCB_CookieCtx) != cookieSz) { - return COOKIE_ERROR; - } + /* If a cookie callback is set, call it to overwrite the cookie. + * This should be deprecated. The code now calculates the cookie + * using an HMAC as expected. */ + if (ssl->ctx->CBIOCookie != NULL && + ssl->ctx->CBIOCookie(ssl, newCookie, cookieSz, + ssl->IOCB_CookieCtx) != cookieSz) { + return COOKIE_ERROR; + } - /* Check the cookie, see if we progress the state machine. */ - if (peerCookieSz != cookieSz || - XMEMCMP(peerCookie, newCookie, cookieSz) != 0) { + /* Check the cookie, see if we progress the state machine. */ + if (peerCookieSz != cookieSz || + XMEMCMP(peerCookie, newCookie, cookieSz) != 0) { - /* Send newCookie to client in a HelloVerifyRequest message - * and let the state machine alone. */ - ssl->msgsReceived.got_client_hello = 0; - ssl->keys.dtls_handshake_number = 0; - ssl->keys.dtls_expected_peer_handshake_number = 0; - *inOutIdx += helloSz; - return SendHelloVerifyRequest(ssl, newCookie, cookieSz); + /* Send newCookie to client in a HelloVerifyRequest message + * and let the state machine alone. */ + ssl->msgsReceived.got_client_hello = 0; + ssl->keys.dtls_handshake_number = 0; + ssl->keys.dtls_expected_peer_handshake_number = 0; + *inOutIdx += helloSz; + return SendHelloVerifyRequest(ssl, newCookie, cookieSz); + } } /* This was skipped in the DTLS case so we could handle the hello @@ -27004,6 +27401,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, IsEncryptionOn(ssl, 0)) { ssl->secure_renegotiation->startScr = 1; } +#endif +#ifdef WOLFSSL_DTLS + if (ret == 0 && ssl->options.dtls) + DtlsMsgPoolReset(ssl); #endif WOLFSSL_LEAVE("DoClientHello", ret); WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO); @@ -27454,14 +27855,27 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (IsEncryptionOn(ssl, 1)) { byte* input; int inputSz = HANDSHAKE_HEADER_SZ; /* build msg adds rec hdr */ + int recordHeaderSz = RECORD_HEADER_SZ; + + if (ssl->options.dtls) { + recordHeaderSz += DTLS_RECORD_EXTRA; + inputSz += DTLS_HANDSHAKE_EXTRA; + } input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); if (input == NULL) return MEMORY_E; - XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); + XMEMCPY(input, output + recordHeaderSz, inputSz); + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl) && + (ret = DtlsMsgPoolSave(ssl, input, inputSz, server_hello_done)) != 0) { + XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + return ret; + } + #endif sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - handshake, 1, 0, 0); + handshake, 1, 0, 0, CUR_ORDER); XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); if (sendSz < 0) @@ -27469,7 +27883,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } else { #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz, server_hello_done)) != 0) return ret; } if (ssl->options.dtls) @@ -27791,15 +28205,19 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) { byte* input; - int inputSz = idx - RECORD_HEADER_SZ; /* build msg adds rec hdr */ + int inputSz = idx; /* build msg adds rec hdr */ + int recordHeaderSz = RECORD_HEADER_SZ; + if (ssl->options.dtls) + recordHeaderSz += DTLS_RECORD_EXTRA; + inputSz -= recordHeaderSz; input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); if (input == NULL) return MEMORY_E; - XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); + XMEMCPY(input, output + recordHeaderSz, inputSz); sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - handshake, 1, 0, 0); + handshake, 1, 0, 0, CUR_ORDER); XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); if (sendSz < 0) @@ -27808,7 +28226,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, else { #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz, session_ticket)) != 0) return ret; DtlsSEQIncrement(ssl, CUR_ORDER); @@ -27850,6 +28268,9 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (IsEncryptionOn(ssl, 1)) sendSz += MAX_MSG_EXTRA; + if (ssl->options.dtls) + sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + /* check for available size */ if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) return ret; @@ -27863,14 +28284,20 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (IsEncryptionOn(ssl, 1)) { byte* input; int inputSz = HANDSHAKE_HEADER_SZ; /* build msg adds rec hdr */ + int recordHeaderSz = RECORD_HEADER_SZ; + + if (ssl->options.dtls) { + recordHeaderSz += DTLS_RECORD_EXTRA; + inputSz += DTLS_HANDSHAKE_EXTRA; + } input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); if (input == NULL) return MEMORY_E; - XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); + XMEMCPY(input, output + recordHeaderSz, inputSz); sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - handshake, 0, 0, 0); + handshake, 0, 0, 0, CUR_ORDER); XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); if (sendSz < 0) @@ -27900,6 +28327,11 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, int sendSz = length + idx; int ret; + /* are we in scr */ + if (IsEncryptionOn(ssl, 1)) { + sendSz += MAX_MSG_EXTRA; + } + /* check for available size */ if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) return ret; @@ -27936,6 +28368,30 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, sendSz, WRITE_PROTO, ssl->heap); #endif + /* are we in scr */ + if (IsEncryptionOn(ssl, 1)) { + byte* input; + int inputSz = HANDSHAKE_HEADER_SZ + length; /* build msg adds rec hdr */ + int recordHeaderSz = RECORD_HEADER_SZ; + + if (ssl->options.dtls) { + recordHeaderSz += DTLS_RECORD_EXTRA; + inputSz += DTLS_HANDSHAKE_EXTRA; + } + + input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + if (input == NULL) + return MEMORY_E; + + XMEMCPY(input, output + recordHeaderSz, inputSz); + sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, + handshake, 0, 0, 0, CUR_ORDER); + XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + + if (sendSz < 0) + return sendSz; + } + ssl->buffers.outputBuffer.length += sendSz; return SendBuffered(ssl); diff --git a/src/keys.c b/src/keys.c index ca6dd4de3..b620dc96d 100644 --- a/src/keys.c +++ b/src/keys.c @@ -3066,7 +3066,11 @@ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side) #ifdef HAVE_SECURE_RENEGOTIATION if (ssl->secure_renegotiation && ssl->secure_renegotiation->cache_status) { keys = &ssl->secure_renegotiation->tmp_keys; - copy = 1; +#ifdef WOLFSSL_DTLS + /* For DTLS, copy is done in StoreKeys */ + if (!ssl->options.dtls) +#endif + copy = 1; } #endif /* HAVE_SECURE_RENEGOTIATION */ @@ -3141,6 +3145,15 @@ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side) ssl->heap, ssl->devId, ssl->rng, ssl->options.tls1_3); #ifdef HAVE_SECURE_RENEGOTIATION +#ifdef WOLFSSL_DTLS + if (ret == 0 && ssl->options.dtls) { + if (wc_encrypt) + wc_encrypt->src = keys == &ssl->keys ? KEYS : SCR; + if (wc_decrypt) + wc_decrypt->src = keys == &ssl->keys ? KEYS : SCR; + } +#endif + if (copy) { int clientCopy = 0; @@ -3217,11 +3230,25 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side) { int sz, i = 0; Keys* keys = &ssl->keys; +#ifdef WOLFSSL_DTLS + /* In case of DTLS, ssl->keys is updated here */ + int scr_copy = 0; +#endif #ifdef HAVE_SECURE_RENEGOTIATION - if (ssl->secure_renegotiation && ssl->secure_renegotiation->cache_status == - SCR_CACHE_NEEDED) { + if (ssl->options.dtls && + ssl->secure_renegotiation && + ssl->secure_renegotiation->cache_status == SCR_CACHE_NEEDED) { keys = &ssl->secure_renegotiation->tmp_keys; +#ifdef WOLFSSL_DTLS + /* epoch is incremented after StoreKeys call */ + ssl->secure_renegotiation->tmp_keys.dtls_epoch = ssl->keys.dtls_epoch + 1; + /* we only need to copy keys on second and future renegotiations */ + if (ssl->keys.dtls_epoch > 1) + scr_copy = 1; + ssl->encrypt.src = KEYS_NOT_SET; + ssl->decrypt.src = KEYS_NOT_SET; +#endif CacheStatusPP(ssl->secure_renegotiation); } #endif /* HAVE_SECURE_RENEGOTIATION */ @@ -3232,23 +3259,54 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side) if (ssl->specs.cipher_type != aead) { sz = ssl->specs.hash_size; #ifndef WOLFSSL_AEAD_ONLY + + #ifdef WOLFSSL_DTLS + if (scr_copy) { + XMEMCPY(ssl->keys.client_write_MAC_secret, + keys->client_write_MAC_secret, sz); + XMEMCPY(ssl->keys.server_write_MAC_secret, + keys->server_write_MAC_secret, sz); + } + #endif XMEMCPY(keys->client_write_MAC_secret,&keyData[i], sz); XMEMCPY(keys->server_write_MAC_secret,&keyData[i], sz); #endif i += sz; } sz = ssl->specs.key_size; + #ifdef WOLFSSL_DTLS + if (scr_copy) { + XMEMCPY(ssl->keys.client_write_key, + keys->client_write_key, sz); + XMEMCPY(ssl->keys.server_write_key, + keys->server_write_key, sz); + } + #endif XMEMCPY(keys->client_write_key, &keyData[i], sz); XMEMCPY(keys->server_write_key, &keyData[i], sz); i += sz; sz = ssl->specs.iv_size; + #ifdef WOLFSSL_DTLS + if (scr_copy) { + XMEMCPY(ssl->keys.client_write_IV, + keys->client_write_IV, sz); + XMEMCPY(ssl->keys.server_write_IV, + keys->server_write_IV, sz); + } + #endif XMEMCPY(keys->client_write_IV, &keyData[i], sz); XMEMCPY(keys->server_write_IV, &keyData[i], sz); #ifdef HAVE_AEAD if (ssl->specs.cipher_type == aead) { /* Initialize the AES-GCM/CCM explicit IV to a zero. */ + #ifdef WOLFSSL_DTLS + if (scr_copy) { + XMEMCPY(ssl->keys.aead_exp_IV, + keys->aead_exp_IV, AEAD_MAX_EXP_SZ); + } + #endif XMEMSET(keys->aead_exp_IV, 0, AEAD_MAX_EXP_SZ); } #endif /* HAVE_AEAD */ @@ -3261,12 +3319,22 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side) sz = ssl->specs.hash_size; if (side & PROVISION_CLIENT) { #ifndef WOLFSSL_AEAD_ONLY + #ifdef WOLFSSL_DTLS + if (scr_copy) + XMEMCPY(ssl->keys.client_write_MAC_secret, + keys->client_write_MAC_secret, sz); + #endif XMEMCPY(keys->client_write_MAC_secret,&keyData[i], sz); #endif i += sz; } if (side & PROVISION_SERVER) { #ifndef WOLFSSL_AEAD_ONLY + #ifdef WOLFSSL_DTLS + if (scr_copy) + XMEMCPY(ssl->keys.server_write_MAC_secret, + keys->server_write_MAC_secret, sz); + #endif XMEMCPY(keys->server_write_MAC_secret,&keyData[i], sz); #endif i += sz; @@ -3274,25 +3342,51 @@ int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side) } sz = ssl->specs.key_size; if (side & PROVISION_CLIENT) { + #ifdef WOLFSSL_DTLS + if (scr_copy) + XMEMCPY(ssl->keys.client_write_key, + keys->client_write_key, sz); + #endif XMEMCPY(keys->client_write_key, &keyData[i], sz); i += sz; } if (side & PROVISION_SERVER) { + #ifdef WOLFSSL_DTLS + if (scr_copy) + XMEMCPY(ssl->keys.server_write_key, + keys->server_write_key, sz); + #endif XMEMCPY(keys->server_write_key, &keyData[i], sz); i += sz; } sz = ssl->specs.iv_size; if (side & PROVISION_CLIENT) { + #ifdef WOLFSSL_DTLS + if (scr_copy) + XMEMCPY(ssl->keys.client_write_IV, + keys->client_write_IV, sz); + #endif XMEMCPY(keys->client_write_IV, &keyData[i], sz); i += sz; } - if (side & PROVISION_SERVER) + if (side & PROVISION_SERVER) { + #ifdef WOLFSSL_DTLS + if (scr_copy) + XMEMCPY(ssl->keys.server_write_IV, + keys->server_write_IV, sz); + #endif XMEMCPY(keys->server_write_IV, &keyData[i], sz); + } #ifdef HAVE_AEAD if (ssl->specs.cipher_type == aead) { /* Initialize the AES-GCM/CCM explicit IV to a zero. */ + #ifdef WOLFSSL_DTLS + if (scr_copy) + XMEMCPY(ssl->keys.aead_exp_IV, + keys->aead_exp_IV, AEAD_MAX_EXP_SZ); + #endif XMEMSET(keys->aead_exp_IV, 0, AEAD_MAX_EXP_SZ); } #endif diff --git a/src/ssl.c b/src/ssl.c index 145be730a..b22c6efee 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -1647,7 +1647,7 @@ int wolfSSL_GetOutputSize(WOLFSSL* ssl, int inSz) if (inSz > maxSize) return INPUT_SIZE_E; - return BuildMessage(ssl, NULL, 0, NULL, inSz, application_data, 0, 1, 0); + return BuildMessage(ssl, NULL, 0, NULL, inSz, application_data, 0, 1, 0, CUR_ORDER); } @@ -3228,6 +3228,72 @@ int wolfSSL_UseClientSuites(WOLFSSL* ssl) return 0; } +#ifdef WOLFSSL_DTLS +const byte* wolfSSL_GetDtlsMacSecret(WOLFSSL* ssl, int verify, int epochOrder) +{ +#ifndef WOLFSSL_AEAD_ONLY + Keys* keys = NULL; + + (void)epochOrder; + + if (ssl == NULL) + return NULL; + +#ifdef HAVE_SECURE_RENEGOTIATION + switch (epochOrder) { + case PEER_ORDER: + if (ssl->secure_renegotiation && + ssl->secure_renegotiation->tmp_keys.dtls_epoch != 0 && + ssl->keys.curEpoch == + ssl->secure_renegotiation->tmp_keys.dtls_epoch) + keys = &ssl->secure_renegotiation->tmp_keys; + else + keys = &ssl->keys; + break; + case PREV_ORDER: + if (ssl->keys.dtls_epoch > 1 || + (ssl->secure_renegotiation && + ssl->secure_renegotiation->tmp_keys.dtls_epoch != 0)) + keys = &ssl->keys; + else { + WOLFSSL_MSG("No previous cipher epoch"); + return NULL; + } + break; + case CUR_ORDER: + if (ssl->secure_renegotiation && + ssl->secure_renegotiation->tmp_keys.dtls_epoch != 0 && + ssl->secure_renegotiation->tmp_keys.dtls_epoch == + ssl->keys.dtls_epoch) + /* new keys are in scr and are only current when the + * ssl->keys.dtls_epoch matches */ + keys = &ssl->secure_renegotiation->tmp_keys; + else + keys = &ssl->keys; + break; + default: + WOLFSSL_MSG("Unknown epoch order"); + return NULL; + } +#else + keys = &ssl->keys; +#endif + + if ( (ssl->options.side == WOLFSSL_CLIENT_END && !verify) || + (ssl->options.side == WOLFSSL_SERVER_END && verify) ) + return keys->client_write_MAC_secret; + else + return keys->server_write_MAC_secret; +#else + (void)ssl; + (void)verify; + (void)epochOrder; + + return NULL; +#endif +} +#endif /* WOLFSSL_DTLS */ + const byte* wolfSSL_GetMacSecret(WOLFSSL* ssl, int verify) { #ifndef WOLFSSL_AEAD_ONLY diff --git a/src/tls.c b/src/tls.c index ad2effa91..18c911bfb 100644 --- a/src/tls.c +++ b/src/tls.c @@ -667,6 +667,14 @@ static WC_INLINE void GetSEQIncrement(WOLFSSL* ssl, int verify, word32 seq[2]) #ifdef WOLFSSL_DTLS static WC_INLINE void DtlsGetSEQ(WOLFSSL* ssl, int order, word32 seq[2]) { +#ifdef HAVE_SECURE_RENEGOTIATION + /* if ssl->secure_renegotiation->tmp_keys.dtls_epoch > ssl->keys.dtls_epoch then PREV_ORDER + * refers to the current epoch */ + if (order == PREV_ORDER && ssl->secure_renegotiation && + ssl->secure_renegotiation->tmp_keys.dtls_epoch > ssl->keys.dtls_epoch) { + order = CUR_ORDER; + } +#endif if (order == PREV_ORDER) { /* Previous epoch case */ seq[0] = (((word32)ssl->keys.dtls_epoch - 1) << 16) | @@ -1169,11 +1177,12 @@ static int Hmac_UpdateFinal(Hmac* hmac, byte* digest, const byte* in, #endif int TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, int padSz, - int content, int verify) + int content, int verify, int epochOrder) { Hmac hmac; byte myInner[WOLFSSL_TLS_HMAC_INNER_SZ]; int ret = 0; + const byte* macSecret = NULL; word32 hashSz = 0; if (ssl == NULL) @@ -1199,7 +1208,7 @@ int TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, int padSz, } #endif - wolfSSL_SetTlsHmacInner(ssl, myInner, sz, content, verify); + wolfSSL_SetTlsHmacInner(ssl, myInner, sz, content, epochOrder); #if defined(WOLFSSL_RENESAS_TSIP_TLS) && \ !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION) if (tsip_useable(ssl)) { @@ -1219,9 +1228,19 @@ int TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, int padSz, if (ret != 0) return ret; + +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + macSecret = wolfSSL_GetDtlsMacSecret(ssl, verify, epochOrder); + else + macSecret = wolfSSL_GetMacSecret(ssl, verify); +#else + macSecret = wolfSSL_GetMacSecret(ssl, verify); +#endif ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl), - wolfSSL_GetMacSecret(ssl, verify), + macSecret, ssl->specs.hash_size); + if (ret == 0) { /* Constant time verification required. */ if (verify && padSz >= 0) { diff --git a/src/wolfio.c b/src/wolfio.c index 8c9932ff0..95bb6171f 100644 --- a/src/wolfio.c +++ b/src/wolfio.c @@ -318,7 +318,9 @@ int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx) WOLFSSL_ENTER("EmbedReceiveFrom()"); - if (ssl->options.handShakeDone) + /* Don't use ssl->options.handShakeDone since it is true even if + * we are in the process of renegotiation */ + if (ssl->options.handShakeState == HANDSHAKE_DONE) dtls_timeout = 0; if (!wolfSSL_get_using_nonblock(ssl)) { diff --git a/wolfssl/internal.h b/wolfssl/internal.h index a4af16aea..a8a1e0712 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -3003,6 +3003,13 @@ enum CipherType { aead }; #define CIPHER_NONCE #endif +#if defined(WOLFSSL_DTLS) && defined(HAVE_SECURE_RENEGOTIATION) +enum CipherSrc { + KEYS_NOT_SET = 0, + KEYS, /* keys from ssl->keys are loaded */ + SCR /* keys from ssl->secure_renegotiation->tmp_keys are loaded */ +}; +#endif /* cipher for now */ typedef struct Ciphers { @@ -3042,6 +3049,9 @@ typedef struct Ciphers { #endif byte state; byte setup; /* have we set it up flag for detection */ +#if defined(WOLFSSL_DTLS) && defined(HAVE_SECURE_RENEGOTIATION) + enum CipherSrc src; +#endif } Ciphers; @@ -3177,7 +3187,7 @@ WOLFSSL_SESSION* GetSession(WOLFSSL*, byte*, byte); WOLFSSL_LOCAL int SetSession(WOLFSSL*, WOLFSSL_SESSION*); -typedef int (*hmacfp) (WOLFSSL*, byte*, const byte*, word32, int, int, int); +typedef int (*hmacfp) (WOLFSSL*, byte*, const byte*, word32, int, int, int, int); #ifndef NO_CLIENT_CACHE WOLFSSL_SESSION* GetSessionClient(WOLFSSL*, const byte*, int); @@ -3734,6 +3744,7 @@ typedef struct DtlsMsg { byte* msg; DtlsFrag* fragList; word32 fragSz; /* Length of fragments received */ + word16 epoch; /* Epoch that this message belongs to */ word32 seq; /* Handshake sequence number */ word32 sz; /* Length of whole message */ byte type; @@ -4355,6 +4366,10 @@ WOLFSSL_LOCAL int IsTLS(const WOLFSSL* ssl); WOLFSSL_LOCAL int IsAtLeastTLSv1_2(const WOLFSSL* ssl); WOLFSSL_LOCAL int IsAtLeastTLSv1_3(const ProtocolVersion pv); +#if defined(WOLFSSL_DTLS) || !defined(WOLFSSL_NO_TLS12) +WOLFSSL_LOCAL int IsInitialRenegotiationState(WOLFSSL* ssl); +#endif /* DTLS || !WOLFSSL_NO_TLS12 */ + WOLFSSL_LOCAL void FreeHandshakeResources(WOLFSSL* ssl); WOLFSSL_LOCAL void ShrinkInputBuffer(WOLFSSL* ssl, int forcedFree); WOLFSSL_LOCAL void ShrinkOutputBuffer(WOLFSSL* ssl); @@ -4451,7 +4466,7 @@ WOLFSSL_LOCAL int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength); WOLFSSL_LOCAL int MakeTlsMasterSecret(WOLFSSL*); #ifndef WOLFSSL_AEAD_ONLY WOLFSSL_LOCAL int TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in, - word32 sz, int padSz, int content, int verify); + word32 sz, int padSz, int content, int verify, int epochOrder); #endif #endif @@ -4473,16 +4488,18 @@ WOLFSSL_LOCAL int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength); WOLFSSL_LOCAL DtlsMsg* DtlsMsgNew(word32, void*); WOLFSSL_LOCAL void DtlsMsgDelete(DtlsMsg*, void*); WOLFSSL_LOCAL void DtlsMsgListDelete(DtlsMsg*, void*); - WOLFSSL_LOCAL int DtlsMsgSet(DtlsMsg*, word32, const byte*, byte, + WOLFSSL_LOCAL void DtlsTxMsgListClean(WOLFSSL* ssl); + WOLFSSL_LOCAL int DtlsMsgSet(DtlsMsg*, word32, word16, const byte*, byte, word32, word32, void*); - WOLFSSL_LOCAL DtlsMsg* DtlsMsgFind(DtlsMsg*, word32); - WOLFSSL_LOCAL void DtlsMsgStore(WOLFSSL*, word32, const byte*, word32, + WOLFSSL_LOCAL DtlsMsg* DtlsMsgFind(DtlsMsg*, word32, word32); + WOLFSSL_LOCAL void DtlsMsgStore(WOLFSSL*, word32, word32, const byte*, word32, byte, word32, word32, void*); WOLFSSL_LOCAL DtlsMsg* DtlsMsgInsert(DtlsMsg*, DtlsMsg*); - WOLFSSL_LOCAL int DtlsMsgPoolSave(WOLFSSL*, const byte*, word32); + WOLFSSL_LOCAL int DtlsMsgPoolSave(WOLFSSL*, const byte*, word32, enum HandShakeType); WOLFSSL_LOCAL int DtlsMsgPoolTimeout(WOLFSSL*); WOLFSSL_LOCAL int VerifyForDtlsMsgPoolSend(WOLFSSL*, byte, word32); + WOLFSSL_LOCAL int VerifyForTxDtlsMsgDelete(WOLFSSL* ssl, DtlsMsg* head); WOLFSSL_LOCAL void DtlsMsgPoolReset(WOLFSSL*); WOLFSSL_LOCAL int DtlsMsgPoolSend(WOLFSSL*, int); #endif /* WOLFSSL_DTLS */ @@ -4587,7 +4604,7 @@ WOLFSSL_LOCAL void FreeHandshakeHashes(WOLFSSL* ssl); WOLFSSL_LOCAL int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, int inSz, int type, int hashOutput, - int sizeOnly, int asyncOkay); + int sizeOnly, int asyncOkay, int epochOrder); #ifdef WOLFSSL_TLS13 int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input, diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 39d7a9911..c7a15a15a 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -2431,6 +2431,7 @@ WOLFSSL_API void wolfSSL_SetVerifyDecryptCtx(WOLFSSL* ssl, void *ctx); WOLFSSL_API void* wolfSSL_GetVerifyDecryptCtx(WOLFSSL* ssl); WOLFSSL_API const unsigned char* wolfSSL_GetMacSecret(WOLFSSL*, int); +WOLFSSL_API const unsigned char* wolfSSL_GetDtlsMacSecret(WOLFSSL*, int, int); WOLFSSL_API const unsigned char* wolfSSL_GetClientWriteKey(WOLFSSL*); WOLFSSL_API const unsigned char* wolfSSL_GetClientWriteIV(WOLFSSL*); WOLFSSL_API const unsigned char* wolfSSL_GetServerWriteKey(WOLFSSL*);