diff --git a/src/internal.c b/src/internal.c index 4ce862173..f64b56dd4 100755 --- a/src/internal.c +++ b/src/internal.c @@ -3644,10 +3644,11 @@ void SSL_ResourceFree(WOLFSSL* ssl) if (ssl->buffers.outputBuffer.dynamicFlag) ShrinkOutputBuffer(ssl); #ifdef WOLFSSL_DTLS - DtlsPoolDelete(ssl); - if (ssl->dtls_msg_list != NULL) { - DtlsMsgListDelete(ssl->dtls_msg_list, ssl->heap); - ssl->dtls_msg_list = NULL; + DtlsMsgPoolReset(ssl); + if (ssl->dtls_rx_msg_list != NULL) { + DtlsMsgListDelete(ssl->dtls_rx_msg_list, ssl->heap); + ssl->dtls_rx_msg_list = NULL; + ssl->dtls_rx_msg_list_sz = 0; } XFREE(ssl->buffers.dtlsCtx.peer.sa, ssl->heap, DYNAMIC_TYPE_SOCKADDR); ssl->buffers.dtlsCtx.peer.sa = NULL; @@ -3810,9 +3811,10 @@ void FreeHandshakeResources(WOLFSSL* ssl) #ifdef WOLFSSL_DTLS /* DTLS_POOL */ if (ssl->options.dtls) { - DtlsPoolDelete(ssl); - DtlsMsgListDelete(ssl->dtls_msg_list, ssl->heap); - ssl->dtls_msg_list = NULL; + DtlsMsgPoolReset(ssl); + DtlsMsgListDelete(ssl->dtls_rx_msg_list, ssl->heap); + ssl->dtls_rx_msg_list = NULL; + ssl->dtls_rx_msg_list_sz = 0; } #endif @@ -4033,183 +4035,6 @@ static INLINE void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out) #ifdef WOLFSSL_DTLS -int DtlsPoolInit(WOLFSSL* ssl) -{ - if (ssl->dtls_pool == NULL) { - DtlsPool *pool = (DtlsPool*)XMALLOC(sizeof(DtlsPool), - ssl->heap, DYNAMIC_TYPE_DTLS_POOL); - if (pool == NULL) { - WOLFSSL_MSG("DTLS Buffer Pool Memory error"); - return MEMORY_E; - } - else { - int i; - - for (i = 0; i < DTLS_POOL_SZ; i++) { - pool->buf[i].length = 0; - pool->buf[i].buffer = NULL; - } - pool->used = 0; - ssl->dtls_pool = pool; - } - } - return 0; -} - - -int DtlsPoolSave(WOLFSSL* ssl, const byte *src, int sz) -{ - DtlsPool *pool = ssl->dtls_pool; - if (src == NULL) { - return BAD_FUNC_ARG; - } - if (pool != NULL && pool->used < DTLS_POOL_SZ) { - buffer *pBuf = &pool->buf[pool->used]; - pBuf->buffer = (byte*)XMALLOC(sz, ssl->heap, DYNAMIC_TYPE_DTLS_POOL); - if (pBuf->buffer == NULL) { - WOLFSSL_MSG("DTLS Buffer Memory error"); - return MEMORY_ERROR; - } - XMEMCPY(pBuf->buffer, src, sz); - pool->epoch[pool->used] = ssl->keys.dtls_epoch; - pBuf->length = (word32)sz; - pool->used++; - } - return 0; -} - - -void DtlsPoolReset(WOLFSSL* ssl) -{ - DtlsPool *pool = ssl->dtls_pool; - if (pool != NULL) { - buffer *pBuf; - int i, used; - - used = pool->used; - for (i = 0, pBuf = &pool->buf[0]; i < used; i++, pBuf++) { - XFREE(pBuf->buffer, ssl->heap, DYNAMIC_TYPE_DTLS_POOL); - pBuf->buffer = NULL; - pBuf->length = 0; - } - pool->used = 0; - } - ssl->dtls_timeout = ssl->dtls_timeout_init; -} - - -void DtlsPoolDelete(WOLFSSL* ssl) -{ - if (ssl->dtls_pool != NULL) { - DtlsPoolReset(ssl); - XFREE(ssl->dtls_pool, ssl->heap, DYNAMIC_TYPE_DTLS_POOL); - ssl->dtls_pool = NULL; - } -} - - -int DtlsPoolTimeout(WOLFSSL* ssl) -{ - int result = -1; - if (ssl->dtls_timeout < ssl->dtls_timeout_max) { - ssl->dtls_timeout *= DTLS_TIMEOUT_MULTIPLIER; - result = 0; - } - return result; -} - -int VerifyForDtlsPoolSend(WOLFSSL* ssl, byte type, word32 fragOffset) -{ - /** - * only the first message from previous flight should be valid - * to be used for triggering retransmission of whole DtlsPool. - * change cipher suite type is not verified here - */ - return ((fragOffset == 0) && - (((ssl->options.side == WOLFSSL_SERVER_END) && - ((type == client_hello) || - ((ssl->options.verifyPeer) && (type == certificate)) || - ((!ssl->options.verifyPeer) && (type == client_key_exchange)))) || - ((ssl->options.side == WOLFSSL_CLIENT_END) && - (type == server_hello)))); -} - -int DtlsPoolSend(WOLFSSL* ssl, byte sendOnlyFirstPacket) -{ - DtlsPool* pool = ssl->dtls_pool; - - if (pool != NULL && pool->used > 0) { - int ret = 0; - int i; - buffer* buf; - /** - * on server side, retranmission is being triggered only by sending - * first message of given flight, in order to trigger client - * to retransmit its whole flight. Sending the whole previous flight - * could lead to retranmission of previous client flight for each - * server message from previous flight. Therefore one message should be - * enough to do the trick. - */ - int maxPoolIndex = (((sendOnlyFirstPacket == 1) && - (ssl->options.side == WOLFSSL_SERVER_END) && - (pool->used >= 1)) ? 1 : pool->used); - - for (i = 0, buf = pool->buf; i < maxPoolIndex; i++, buf++) { - if (pool->epoch[i] == 0) { - DtlsRecordLayerHeader* dtls; - int epochOrder; - - dtls = (DtlsRecordLayerHeader*)buf->buffer; - /* If the stored record's epoch is 0, and the currently set - * epoch is 0, use the "current order" sequence number. - * If the stored record's epoch is 0 and the currently set - * epoch is not 0, the stored record is considered a "previous - * order" sequence number. */ - epochOrder = (ssl->keys.dtls_epoch == 0) ? - CUR_ORDER : PREV_ORDER; - - WriteSEQ(ssl, epochOrder, dtls->sequence_number); - DtlsSEQIncrement(ssl, epochOrder); - if ((ret = CheckAvailableSize(ssl, buf->length)) != 0) - return ret; - - XMEMCPY(ssl->buffers.outputBuffer.buffer, - buf->buffer, buf->length); - ssl->buffers.outputBuffer.idx = 0; - ssl->buffers.outputBuffer.length = buf->length; - } - else if (pool->epoch[i] == ssl->keys.dtls_epoch) { - byte* input; - byte* output; - int inputSz, sendSz; - - input = buf->buffer; - inputSz = buf->length; - sendSz = inputSz + MAX_MSG_EXTRA; - - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) - return ret; - - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; - sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, - handshake, 0, 0); - if (sendSz < 0) - return BUILD_MSG_ERROR; - - ssl->buffers.outputBuffer.length += sendSz; - } - - ret = SendBuffered(ssl); - if (ret < 0) { - return ret; - } - } - } - return 0; -} - - /* functions for managing DTLS datagram reordering */ /* Need to allocate space for the handshake message header. The hashing @@ -4403,10 +4228,9 @@ DtlsMsg* DtlsMsgFind(DtlsMsg* head, word32 seq) } -DtlsMsg* DtlsMsgStore(DtlsMsg* head, word32 seq, const byte* data, +void DtlsMsgStore(WOLFSSL* ssl, 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 * a new item of size dataSz, copy fragSz bytes from data to msg->msg * starting at offset fragOffset, and add fragSz to msg->fragSz. If @@ -4424,6 +4248,8 @@ DtlsMsg* DtlsMsgStore(DtlsMsg* head, word32 seq, const byte* data, * belongs without overlaps. */ + DtlsMsg* head = ssl->dtls_rx_msg_list; + if (head != NULL) { DtlsMsg* cur = DtlsMsgFind(head, seq); if (cur == NULL) { @@ -4432,9 +4258,11 @@ DtlsMsg* DtlsMsgStore(DtlsMsg* head, word32 seq, const byte* data, if (DtlsMsgSet(cur, seq, data, type, fragOffset, fragSz, heap) < 0) { DtlsMsgDelete(cur, heap); - return head; } - head = DtlsMsgInsert(head, cur); + else { + ssl->dtls_rx_msg_list_sz++; + head = DtlsMsgInsert(head, cur); + } } } else { @@ -4446,11 +4274,14 @@ DtlsMsg* DtlsMsgStore(DtlsMsg* head, word32 seq, const byte* data, head = DtlsMsgNew(dataSz, heap); if (DtlsMsgSet(head, seq, data, type, fragOffset, fragSz, heap) < 0) { DtlsMsgDelete(head, heap); - return NULL; + head = NULL; + } + else { + ssl->dtls_rx_msg_list_sz++; } } - return head; + ssl->dtls_rx_msg_list = head; } @@ -4484,6 +4315,164 @@ DtlsMsg* DtlsMsgInsert(DtlsMsg* head, DtlsMsg* item) return head; } + +/* DtlsMsgPoolSave() adds the message to the end of the stored transmit list. */ +int DtlsMsgPoolSave(WOLFSSL* ssl, const byte* data, word32 dataSz) +{ + DtlsMsg* item; + int ret = 0; + + if (ssl->dtls_tx_msg_list_sz > DTLS_POOL_SZ) + return DTLS_POOL_SZ_E; + + item = DtlsMsgNew(dataSz, ssl->heap); + + if (item != NULL) { + DtlsMsg* cur = ssl->dtls_tx_msg_list; + + XMEMCPY(item->buf, data, dataSz); + item->sz = dataSz; + item->seq = ssl->keys.dtls_epoch; + + if (cur == NULL) + ssl->dtls_tx_msg_list = item; + else { + while (cur->next) + cur = cur->next; + cur->next = item; + } + ssl->dtls_tx_msg_list_sz++; + } + else + ret = MEMORY_E; + + return ret; +} + + +/* DtlsMsgPoolTimeout() updates the timeout time. */ +int DtlsMsgPoolTimeout(WOLFSSL* ssl) +{ + int result = -1; + if (ssl->dtls_timeout < ssl->dtls_timeout_max) { + ssl->dtls_timeout *= DTLS_TIMEOUT_MULTIPLIER; + result = 0; + } + return result; +} + + +/* DtlsMsgPoolReset() deletes the stored transmit list and resets the timeout + * value. */ +void DtlsMsgPoolReset(WOLFSSL* ssl) +{ + if (ssl->dtls_tx_msg_list) { + DtlsMsgListDelete(ssl->dtls_tx_msg_list, ssl->heap); + ssl->dtls_tx_msg_list = NULL; + ssl->dtls_tx_msg_list_sz = 0; + ssl->dtls_timeout = ssl->dtls_timeout_init; + } +} + + +int VerifyForDtlsMsgPoolSend(WOLFSSL* ssl, byte type, word32 fragOffset) +{ + /** + * only the first message from previous flight should be valid + * to be used for triggering retransmission of whole DtlsMsgPool. + * change cipher suite type is not verified here + */ + return ((fragOffset == 0) && + (((ssl->options.side == WOLFSSL_SERVER_END) && + ((type == client_hello) || + ((ssl->options.verifyPeer) && (type == certificate)) || + ((!ssl->options.verifyPeer) && (type == client_key_exchange)))) || + ((ssl->options.side == WOLFSSL_CLIENT_END) && + (type == server_hello)))); +} + + +/* 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 = ssl->dtls_tx_msg_list; + + if (pool != NULL) { + + while (pool != NULL) { + if (pool->seq == 0) { + DtlsRecordLayerHeader* dtls; + int epochOrder; + + dtls = (DtlsRecordLayerHeader*)pool->buf; + /* If the stored record's epoch is 0, and the currently set + * epoch is 0, use the "current order" sequence number. + * If the stored record's epoch is 0 and the currently set + * epoch is not 0, the stored record is considered a "previous + * order" sequence number. */ + epochOrder = (ssl->keys.dtls_epoch == 0) ? + CUR_ORDER : PREV_ORDER; + + WriteSEQ(ssl, epochOrder, dtls->sequence_number); + DtlsSEQIncrement(ssl, epochOrder); + if ((ret = CheckAvailableSize(ssl, pool->sz)) != 0) + return ret; + + XMEMCPY(ssl->buffers.outputBuffer.buffer, + pool->buf, pool->sz); + ssl->buffers.outputBuffer.idx = 0; + ssl->buffers.outputBuffer.length = pool->sz; + } + else if (pool->seq == ssl->keys.dtls_epoch) { + byte* input; + byte* output; + int inputSz, sendSz; + + input = pool->buf; + inputSz = pool->sz; + sendSz = inputSz + MAX_MSG_EXTRA; + + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, + handshake, 0, 0); + if (sendSz < 0) + return BUILD_MSG_ERROR; + + ssl->buffers.outputBuffer.length += sendSz; + } + + ret = SendBuffered(ssl); + if (ret < 0) { + return ret; + } + + /** + * on server side, retranmission is being triggered only by sending + * first message of given flight, in order to trigger client + * to retransmit its whole flight. Sending the whole previous flight + * could lead to retranmission of previous client flight for each + * server message from previous flight. Therefore one message should + * be enough to do the trick. + */ + if (sendOnlyFirstPacket && + ssl->options.side == WOLFSSL_SERVER_END) { + + pool = NULL; + } + else + pool = pool->next; + } + } + + return ret; +} + #endif /* WOLFSSL_DTLS */ #if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS) @@ -4963,8 +4952,8 @@ retry: #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl) && !ssl->options.handShakeDone && - DtlsPoolTimeout(ssl) == 0 && - DtlsPoolSend(ssl, 0) == 0) { + DtlsMsgPoolTimeout(ssl) == 0 && + DtlsMsgPoolSend(ssl, 0) == 0) { goto retry; } @@ -7525,6 +7514,16 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type) WOLFSSL_MSG("No ServerHelloDone before ChangeCipher"); return OUT_OF_ORDER_E; } + #ifdef HAVE_SESSION_TICKET + if (ssl->expect_session_ticket) { + WOLFSSL_MSG("Expected session ticket missing"); + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + return OUT_OF_ORDER_E; + #endif + return SESSION_TICKET_EXPECT_E; + } + #endif } #endif #ifndef NO_WOLFSSL_SERVER @@ -7534,6 +7533,20 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type) WOLFSSL_MSG("No ClientKeyExchange before ChangeCipher"); return OUT_OF_ORDER_E; } + #ifndef NO_CERTS + if (ssl->options.verifyPeer && + ssl->options.havePeerCert) { + + if (!ssl->options.havePeerVerify) { + WOLFSSL_MSG("client didn't send cert verify"); + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + return OUT_OF_ORDER_E; + #endif + return NO_PEER_VERIFY; + } + } + #endif } #endif if (ssl->options.dtls) @@ -7936,7 +7949,7 @@ static INLINE int DtlsUpdateWindow(WOLFSSL* ssl) static int DtlsMsgDrain(WOLFSSL* ssl) { - DtlsMsg* item = ssl->dtls_msg_list; + DtlsMsg* item = ssl->dtls_rx_msg_list; int ret = 0; /* While there is an item in the store list, and it is the expected @@ -7950,9 +7963,10 @@ static int DtlsMsgDrain(WOLFSSL* ssl) ssl->keys.dtls_expected_peer_handshake_number++; ret = DoHandShakeMsgType(ssl, item->msg, &idx, item->type, item->sz, item->sz); - ssl->dtls_msg_list = item->next; + ssl->dtls_rx_msg_list = item->next; DtlsMsgDelete(item, ssl->heap); - item = ssl->dtls_msg_list; + item = ssl->dtls_rx_msg_list; + ssl->dtls_rx_msg_list_sz--; } return ret; @@ -7996,10 +8010,11 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, * the client could be sending multiple new client hello messages * with newer and newer cookies.) */ if (type != client_hello) { - ssl->dtls_msg_list = DtlsMsgStore(ssl->dtls_msg_list, - ssl->keys.dtls_peer_handshake_number, - input + *inOutIdx, size, type, - fragOffset, fragSz, ssl->heap); + if (ssl->dtls_rx_msg_list_sz < DTLS_POOL_SZ) { + DtlsMsgStore(ssl, ssl->keys.dtls_peer_handshake_number, + input + *inOutIdx, size, type, + fragOffset, fragSz, ssl->heap); + } *inOutIdx += fragSz; ret = 0; } @@ -8021,20 +8036,25 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, } *inOutIdx += ssl->keys.padSz; } - if (IsDtlsNotSctpMode(ssl) && VerifyForDtlsPoolSend(ssl, type, fragOffset)) - ret = DtlsPoolSend(ssl, 0); + if (IsDtlsNotSctpMode(ssl) && + VerifyForDtlsMsgPoolSend(ssl, type, fragOffset)) { + + ret = DtlsMsgPoolSend(ssl, 0); + } } else if (fragSz < size) { - /* Since this branch is in order, but fragmented, dtls_msg_list will be - * pointing to the message with this fragment in it. Check it to see + /* 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. */ - ssl->dtls_msg_list = DtlsMsgStore(ssl->dtls_msg_list, - ssl->keys.dtls_peer_handshake_number, input + *inOutIdx, - size, type, fragOffset, fragSz, ssl->heap); + if (ssl->dtls_rx_msg_list_sz < DTLS_POOL_SZ) { + DtlsMsgStore(ssl, ssl->keys.dtls_peer_handshake_number, + input + *inOutIdx, size, type, + fragOffset, fragSz, ssl->heap); + } *inOutIdx += fragSz; ret = 0; - if (ssl->dtls_msg_list != NULL && - ssl->dtls_msg_list->fragSz >= ssl->dtls_msg_list->sz) + if (ssl->dtls_rx_msg_list != NULL && + ssl->dtls_rx_msg_list->fragSz >= ssl->dtls_rx_msg_list->sz) ret = DtlsMsgDrain(ssl); } else { @@ -8042,7 +8062,7 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, ret = DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz); if (ret == 0) { ssl->keys.dtls_expected_peer_handshake_number++; - if (ssl->dtls_msg_list != NULL) { + if (ssl->dtls_rx_msg_list != NULL) { ret = DtlsMsgDrain(ssl); } } @@ -9382,7 +9402,7 @@ int ProcessReply(WOLFSSL* ssl) ssl->buffers.inputBuffer.idx = 0; if (IsDtlsNotSctpMode(ssl) && ssl->options.dtlsHsRetain) { - ret = DtlsPoolSend(ssl, 0); + ret = DtlsMsgPoolSend(ssl, 0); if (ret != 0) return ret; } @@ -9541,7 +9561,7 @@ int ProcessReply(WOLFSSL* ssl) return ret; if (IsDtlsNotSctpMode(ssl)) { - ret = DtlsPoolSend(ssl, 1); + ret = DtlsMsgPoolSend(ssl, 1); if (ret != 0) return ret; } @@ -9557,14 +9577,6 @@ int ProcessReply(WOLFSSL* ssl) } } -#ifdef HAVE_SESSION_TICKET - if (ssl->options.side == WOLFSSL_CLIENT_END && - ssl->expect_session_ticket) { - WOLFSSL_MSG("Expected session ticket missing"); - return SESSION_TICKET_EXPECT_E; - } -#endif - if (IsEncryptionOn(ssl, 0) && ssl->options.handShakeDone) { ssl->buffers.inputBuffer.idx += ssl->keys.padSz; ssl->curSize -= (word16) ssl->buffers.inputBuffer.idx; @@ -9574,16 +9586,6 @@ int ProcessReply(WOLFSSL* ssl) WOLFSSL_MSG("Malicious or corrupted ChangeCipher msg"); return LENGTH_ERROR; } - #ifndef NO_CERTS - if (ssl->options.side == WOLFSSL_SERVER_END && - ssl->options.verifyPeer && - ssl->options.havePeerCert) - if (!ssl->options.havePeerVerify) { - WOLFSSL_MSG("client didn't send cert verify"); - return NO_PEER_VERIFY; - } - #endif - ssl->buffers.inputBuffer.idx++; ssl->keys.encryptionOn = 1; @@ -9594,7 +9596,7 @@ int ProcessReply(WOLFSSL* ssl) #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - DtlsPoolReset(ssl); + DtlsMsgPoolReset(ssl); ssl->keys.nextEpoch++; ssl->keys.nextSeq_lo = 0; ssl->keys.prevWindow = ssl->keys.window; @@ -9738,7 +9740,7 @@ int SendChangeCipher(WOLFSSL* ssl) #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) return ret; } #endif @@ -10185,7 +10187,7 @@ int SendFinished(WOLFSSL* ssl) #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsPoolSave(ssl, input, headerSz + finishedSz)) != 0) + if ((ret = DtlsMsgPoolSave(ssl, input, headerSz + finishedSz)) != 0) return ret; } #endif @@ -10436,7 +10438,7 @@ int SendCertificate(WOLFSSL* ssl) #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) return ret; } #endif @@ -10531,7 +10533,7 @@ int SendCertificateRequest(WOLFSSL* ssl) #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) return ret; } if (ssl->options.dtls) @@ -10637,7 +10639,7 @@ static int BuildCertificateStatus(WOLFSSL* ssl, byte type, buffer* status, #ifdef WOLFSSL_DTLS if (ret == 0 && IsDtlsNotSctpMode(ssl)) - ret = DtlsPoolSave(ssl, output, sendSz); + ret = DtlsMsgPoolSave(ssl, output, sendSz); #endif #ifdef WOLFSSL_CALLBACKS @@ -11639,6 +11641,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case EXT_MASTER_SECRET_NEEDED_E: return "Extended Master Secret must be enabled to resume EMS session"; + case DTLS_POOL_SZ_E: + return "Maximum DTLS pool size exceeded"; + default : return "unknown error number"; } @@ -13076,7 +13081,7 @@ static void PickHashSigAlgo(WOLFSSL* ssl, #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) return ret; } #endif @@ -13111,7 +13116,7 @@ static void PickHashSigAlgo(WOLFSSL* ssl, #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - DtlsPoolReset(ssl); + DtlsMsgPoolReset(ssl); } #endif @@ -13429,7 +13434,7 @@ static void PickHashSigAlgo(WOLFSSL* ssl, } #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - DtlsPoolReset(ssl); + DtlsMsgPoolReset(ssl); } #endif @@ -15602,7 +15607,7 @@ int SendClientKeyExchange(WOLFSSL* ssl) #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) { + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) { goto exit_scke; } } @@ -16083,7 +16088,7 @@ int SendCertificateVerify(WOLFSSL* ssl) #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { - ret = DtlsPoolSave(ssl, output, sendSz); + ret = DtlsMsgPoolSave(ssl, output, sendSz); } #endif @@ -16379,7 +16384,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ssl->buffers.outputBuffer.length += sendSz; #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) return ret; } @@ -17713,7 +17718,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) { + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) { goto exit_sske; } } @@ -18935,7 +18940,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef WOLFSSL_DTLS if (IsDtlsNotSctpMode(ssl)) { - if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) return 0; } @@ -19157,7 +19162,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef WOLFSSL_DTLS if (ssl->options.dtls) { - if ((ret = DtlsPoolSave(ssl, output, sendSz)) != 0) + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) return ret; DtlsSEQIncrement(ssl, CUR_ORDER); diff --git a/src/ssl.c b/src/ssl.c index 3291d24af..3babee741 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -6750,7 +6750,7 @@ int wolfSSL_dtls_got_timeout(WOLFSSL* ssl) int result = SSL_SUCCESS; if (!ssl->options.handShakeDone && - (DtlsPoolTimeout(ssl) < 0 || DtlsPoolSend(ssl, 0) < 0)) { + (DtlsMsgPoolTimeout(ssl) < 0 || DtlsMsgPoolSend(ssl, 0) < 0)) { result = SSL_FATAL_ERROR; } @@ -6923,12 +6923,6 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, ssl->options.dtls = 1; ssl->options.tls = 1; ssl->options.tls1_1 = 1; - - if (DtlsPoolInit(ssl) != 0) { - ssl->error = MEMORY_ERROR; - WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; - } } #endif @@ -7285,12 +7279,6 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, ssl->options.dtls = 1; ssl->options.tls = 1; ssl->options.tls1_1 = 1; - - if (DtlsPoolInit(ssl) != 0) { - ssl->error = MEMORY_ERROR; - WOLFSSL_ERROR(ssl->error); - return SSL_FATAL_ERROR; - } } #endif diff --git a/wolfssl/error-ssl.h b/wolfssl/error-ssl.h index bf9861946..fded9efa8 100644 --- a/wolfssl/error-ssl.h +++ b/wolfssl/error-ssl.h @@ -150,6 +150,7 @@ enum wolfSSL_ErrorCodes { INPUT_SIZE_E = -412, /* input size too big error */ CTX_INIT_MUTEX_E = -413, /* initialize ctx mutex error */ EXT_MASTER_SECRET_NEEDED_E = -414, /* need EMS enabled to resume */ + DTLS_POOL_SZ_E = -415, /* exceeded DTLS pool size */ /* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */ /* begin negotiation parameter errors */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index d51fb23a3..d89770443 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -952,7 +952,7 @@ enum Misc { DTLS_RECORD_EXTRA = 8, /* diff from normal */ DTLS_HANDSHAKE_SEQ_SZ = 2, /* handshake header sequence number */ DTLS_HANDSHAKE_FRAG_SZ = 3, /* fragment offset and length are 24 bit */ - DTLS_POOL_SZ = 5, /* buffers to hold in the retry pool */ + DTLS_POOL_SZ = 255,/* allowed number of list items in TX pool */ DTLS_EXPORT_PRO = 165,/* wolfSSL protocol for serialized session */ DTLS_EXPORT_VERSION = 2, /* wolfSSL version for serialized session */ DTLS_EXPORT_OPT_SZ = 57, /* amount of bytes used from Options */ @@ -2584,13 +2584,6 @@ typedef struct DtlsRecordLayerHeader { } DtlsRecordLayerHeader; -typedef struct DtlsPool { - buffer buf[DTLS_POOL_SZ]; - word16 epoch[DTLS_POOL_SZ]; - int used; -} DtlsPool; - - typedef struct DtlsFrag { word32 begin; word32 end; @@ -2758,8 +2751,10 @@ struct WOLFSSL { int dtls_timeout_init; /* starting timeout value */ int dtls_timeout_max; /* maximum timeout value */ int dtls_timeout; /* current timeout value, changes */ - DtlsPool* dtls_pool; - DtlsMsg* dtls_msg_list; + word32 dtls_tx_msg_list_sz; + word32 dtls_rx_msg_list_sz; + DtlsMsg* dtls_tx_msg_list; + DtlsMsg* dtls_rx_msg_list; void* IOCB_CookieCtx; /* gen cookie ctx */ word32 dtls_expected_rx; wc_dtls_export dtls_export; /* export function for session */ @@ -3070,23 +3065,21 @@ WOLFSSL_LOCAL int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength); #endif /* NO_WOLFSSL_SERVER */ #ifdef WOLFSSL_DTLS - WOLFSSL_LOCAL int DtlsPoolInit(WOLFSSL*); - WOLFSSL_LOCAL int DtlsPoolSave(WOLFSSL*, const byte*, int); - WOLFSSL_LOCAL int DtlsPoolTimeout(WOLFSSL*); - WOLFSSL_LOCAL int DtlsPoolSend(WOLFSSL*, byte); - WOLFSSL_LOCAL int VerifyForDtlsPoolSend(WOLFSSL*, byte, word32); - WOLFSSL_LOCAL void DtlsPoolReset(WOLFSSL*); - WOLFSSL_LOCAL void DtlsPoolDelete(WOLFSSL*); - 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, word32, word32, void*); WOLFSSL_LOCAL DtlsMsg* DtlsMsgFind(DtlsMsg*, word32); - WOLFSSL_LOCAL DtlsMsg* DtlsMsgStore(DtlsMsg*, word32, const byte*, word32, + WOLFSSL_LOCAL void DtlsMsgStore(WOLFSSL*, 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 DtlsMsgPoolTimeout(WOLFSSL*); + WOLFSSL_LOCAL int VerifyForDtlsMsgPoolSend(WOLFSSL*, byte, word32); + WOLFSSL_LOCAL void DtlsMsgPoolReset(WOLFSSL*); + WOLFSSL_LOCAL int DtlsMsgPoolSend(WOLFSSL*, int); #endif /* WOLFSSL_DTLS */ #ifndef NO_TLS