mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-07-30 10:47:28 +02:00
Don't over-allocate memory for DTLS fragments
Don't reserve the full message length of memory. Instead we only allocate memory for the fragments that we have already received. We also dynamically combine memory fragments when we receive overlap.
This commit is contained in:
22
src/dtls13.c
22
src/dtls13.c
@ -345,11 +345,11 @@ int Dtls13ProcessBufferedMessages(WOLFSSL* ssl)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
/* message not complete */
|
/* message not complete */
|
||||||
if (msg->fragSz != msg->sz)
|
if (!msg->ready)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
ret = DoTls13HandShakeMsgType(ssl, msg->msg, &idx, msg->type, msg->sz,
|
ret = DoTls13HandShakeMsgType(ssl, msg->fullMsg, &idx, msg->type,
|
||||||
msg->sz);
|
msg->sz, msg->sz);
|
||||||
|
|
||||||
/* processing certificate_request triggers a connect. The error came
|
/* processing certificate_request triggers a connect. The error came
|
||||||
* from there, the message can be considered processed successfully */
|
* from there, the message can be considered processed successfully */
|
||||||
@ -375,7 +375,7 @@ int Dtls13ProcessBufferedMessages(WOLFSSL* ssl)
|
|||||||
static int Dtls13NextMessageComplete(WOLFSSL* ssl)
|
static int Dtls13NextMessageComplete(WOLFSSL* ssl)
|
||||||
{
|
{
|
||||||
return ssl->dtls_rx_msg_list != NULL &&
|
return ssl->dtls_rx_msg_list != NULL &&
|
||||||
ssl->dtls_rx_msg_list->fragSz == ssl->dtls_rx_msg_list->sz &&
|
ssl->dtls_rx_msg_list->ready &&
|
||||||
ssl->dtls_rx_msg_list->seq ==
|
ssl->dtls_rx_msg_list->seq ==
|
||||||
ssl->keys.dtls_expected_peer_handshake_number;
|
ssl->keys.dtls_expected_peer_handshake_number;
|
||||||
}
|
}
|
||||||
@ -677,8 +677,18 @@ static int Dtls13DetectDisruption(WOLFSSL* ssl, word32 fragOffset)
|
|||||||
/* is not the next fragment in the message (the check is not 100% perfect,
|
/* is not the next fragment in the message (the check is not 100% perfect,
|
||||||
in the worst case, we don't detect the disruption and wait for the other
|
in the worst case, we don't detect the disruption and wait for the other
|
||||||
peer retransmission) */
|
peer retransmission) */
|
||||||
if (ssl->dtls_rx_msg_list == NULL ||
|
if (ssl->dtls_rx_msg_list != NULL) {
|
||||||
ssl->dtls_rx_msg_list->fragSz != fragOffset) {
|
DtlsFragBucket* last = ssl->dtls_rx_msg_list->fragBucketList;
|
||||||
|
while (last != NULL && last->next != NULL)
|
||||||
|
last = last->next;
|
||||||
|
/* Does this fragment start right after the last fragment we
|
||||||
|
* have stored? */
|
||||||
|
if (last != NULL && (last->offset + last->sz) != fragOffset)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* ssl->dtls_rx_msg_list is NULL and fragOffset != 0 so this is not in
|
||||||
|
* order */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
442
src/internal.c
442
src/internal.c
@ -8109,7 +8109,7 @@ void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out)
|
|||||||
* has the headers, and will include those headers in the hash. The store
|
* has the headers, and will include those headers in the hash. The store
|
||||||
* routines need to take that into account as well. New will allocate
|
* routines need to take that into account as well. New will allocate
|
||||||
* extra space for the headers. */
|
* extra space for the headers. */
|
||||||
DtlsMsg* DtlsMsgNew(word32 sz, void* heap)
|
DtlsMsg* DtlsMsgNew(word32 sz, byte tx, void* heap)
|
||||||
{
|
{
|
||||||
DtlsMsg* msg;
|
DtlsMsg* msg;
|
||||||
WOLFSSL_ENTER("DtlsMsgNew()");
|
WOLFSSL_ENTER("DtlsMsgNew()");
|
||||||
@ -8119,16 +8119,17 @@ DtlsMsg* DtlsMsgNew(word32 sz, void* heap)
|
|||||||
|
|
||||||
if (msg != NULL) {
|
if (msg != NULL) {
|
||||||
XMEMSET(msg, 0, sizeof(DtlsMsg));
|
XMEMSET(msg, 0, sizeof(DtlsMsg));
|
||||||
msg->buf = (byte*)XMALLOC(sz + DTLS_HANDSHAKE_HEADER_SZ,
|
msg->sz = sz;
|
||||||
heap, DYNAMIC_TYPE_DTLS_BUFFER);
|
msg->type = no_shake;
|
||||||
if (msg->buf != NULL) {
|
if (tx) {
|
||||||
msg->sz = sz;
|
msg->raw = msg->fullMsg =
|
||||||
msg->type = no_shake;
|
(byte*)XMALLOC(sz + DTLS_HANDSHAKE_HEADER_SZ, heap,
|
||||||
msg->msg = msg->buf + DTLS_HANDSHAKE_HEADER_SZ;
|
DYNAMIC_TYPE_DTLS_FRAG);
|
||||||
}
|
msg->ready = 1;
|
||||||
else {
|
if (msg->raw == NULL) {
|
||||||
XFREE(msg, heap, DYNAMIC_TYPE_DTLS_MSG);
|
DtlsMsgDelete(msg, heap);
|
||||||
msg = NULL;
|
msg = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8141,14 +8142,13 @@ void DtlsMsgDelete(DtlsMsg* item, void* heap)
|
|||||||
WOLFSSL_ENTER("DtlsMsgDelete()");
|
WOLFSSL_ENTER("DtlsMsgDelete()");
|
||||||
|
|
||||||
if (item != NULL) {
|
if (item != NULL) {
|
||||||
DtlsFrag* cur = item->fragList;
|
while (item->fragBucketList != NULL) {
|
||||||
while (cur != NULL) {
|
DtlsFragBucket* next = item->fragBucketList->next;
|
||||||
DtlsFrag* next = cur->next;
|
DtlsMsgDestroyFragBucket(item->fragBucketList, heap);
|
||||||
XFREE(cur, heap, DYNAMIC_TYPE_DTLS_FRAG);
|
item->fragBucketList = next;
|
||||||
cur = next;
|
|
||||||
}
|
}
|
||||||
if (item->buf != NULL)
|
if (item->raw != NULL)
|
||||||
XFREE(item->buf, heap, DYNAMIC_TYPE_DTLS_BUFFER);
|
XFREE(item->raw, heap, DYNAMIC_TYPE_DTLS_FRAG);
|
||||||
XFREE(item, heap, DYNAMIC_TYPE_DTLS_MSG);
|
XFREE(item, heap, DYNAMIC_TYPE_DTLS_MSG);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -8187,131 +8187,279 @@ void DtlsTxMsgListClean(WOLFSSL* ssl)
|
|||||||
ssl->dtls_tx_msg_list = head;
|
ssl->dtls_tx_msg_list = head;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a DTLS Fragment from *begin - end, adjust new *begin and bytesLeft */
|
static DtlsFragBucket* DtlsMsgCreateFragBucket(word32 offset, const byte* data,
|
||||||
static DtlsFrag* CreateFragment(word32* begin, word32 end, const byte* data,
|
word32 dataSz, void* heap)
|
||||||
byte* buf, word32* bytesLeft, void* heap)
|
|
||||||
{
|
{
|
||||||
DtlsFrag* newFrag;
|
DtlsFragBucket* bucket =
|
||||||
word32 added = end - *begin + 1;
|
(DtlsFragBucket*)XMALLOC(sizeof(DtlsFragBucket) + dataSz, heap,
|
||||||
|
DYNAMIC_TYPE_DTLS_FRAG);
|
||||||
WOLFSSL_ENTER("CreateFragment()");
|
if (bucket != NULL) {
|
||||||
|
XMEMSET(bucket, 0, sizeof(*bucket));
|
||||||
(void)heap;
|
bucket->next = NULL;
|
||||||
newFrag = (DtlsFrag*)XMALLOC(sizeof(DtlsFrag), heap,
|
bucket->offset = offset;
|
||||||
DYNAMIC_TYPE_DTLS_FRAG);
|
bucket->sz = dataSz;
|
||||||
if (newFrag != NULL) {
|
if (data != NULL)
|
||||||
newFrag->next = NULL;
|
XMEMCPY(bucket->buf, data, dataSz);
|
||||||
newFrag->begin = *begin;
|
|
||||||
newFrag->end = end;
|
|
||||||
|
|
||||||
XMEMCPY(buf + *begin, data, added);
|
|
||||||
*bytesLeft -= added;
|
|
||||||
*begin = newFrag->end + 1;
|
|
||||||
}
|
}
|
||||||
|
return bucket;
|
||||||
return newFrag;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DtlsMsgDestroyFragBucket(DtlsFragBucket* fragBucket, void* heap)
|
||||||
int DtlsMsgSet(DtlsMsg* msg, word32 seq, word16 epoch, const byte* data, byte type,
|
|
||||||
word32 fragOffset, word32 fragSz, void* heap)
|
|
||||||
{
|
{
|
||||||
WOLFSSL_ENTER("DtlsMsgSet()");
|
(void)heap;
|
||||||
if (msg != NULL && data != NULL && msg->fragSz <= msg->sz &&
|
XFREE(fragBucket, heap, DYNAMIC_TYPE_DTLS_FRAG);
|
||||||
fragSz <= msg->sz && fragOffset <= msg->sz &&
|
}
|
||||||
(fragOffset + fragSz) <= msg->sz) {
|
|
||||||
DtlsFrag* cur = msg->fragList;
|
|
||||||
DtlsFrag* prev = cur;
|
|
||||||
DtlsFrag* newFrag;
|
|
||||||
word32 bytesLeft = fragSz; /* could be overlapping fragment */
|
|
||||||
word32 startOffset = fragOffset;
|
|
||||||
word32 added;
|
|
||||||
|
|
||||||
msg->seq = seq;
|
/*
|
||||||
msg->epoch = epoch;
|
* data overlaps with cur but is before next.
|
||||||
msg->type = type;
|
* data + dataSz has to end before or inside next. next can be NULL.
|
||||||
|
*/
|
||||||
|
static DtlsFragBucket* DtlsMsgCombineFragBuckets(DtlsMsg* msg,
|
||||||
|
DtlsFragBucket* cur, DtlsFragBucket* next, word32 offset,
|
||||||
|
const byte* data, word32 dataSz, void* heap)
|
||||||
|
{
|
||||||
|
word32 offsetEnd = offset + dataSz;
|
||||||
|
word32 newOffset = min(cur->offset, offset);
|
||||||
|
word32 newOffsetEnd;
|
||||||
|
word32 newSz;
|
||||||
|
word32 overlapSz = cur->sz;
|
||||||
|
DtlsFragBucket** chosenBucket;
|
||||||
|
DtlsFragBucket* newBucket;
|
||||||
|
DtlsFragBucket* otherBucket;
|
||||||
|
byte combineNext = FALSE;
|
||||||
|
|
||||||
if (fragOffset == 0) {
|
if (next != NULL && offsetEnd >= next->offset)
|
||||||
XMEMCPY(msg->buf, data - DTLS_HANDSHAKE_HEADER_SZ,
|
combineNext = TRUE;
|
||||||
DTLS_HANDSHAKE_HEADER_SZ);
|
|
||||||
c32to24(msg->sz, msg->msg - DTLS_HANDSHAKE_FRAG_SZ);
|
if (combineNext)
|
||||||
|
newOffsetEnd = next->offset + next->sz;
|
||||||
|
else
|
||||||
|
newOffsetEnd = max(cur->offset + cur->sz, offsetEnd);
|
||||||
|
|
||||||
|
newSz = newOffsetEnd - newOffset;
|
||||||
|
|
||||||
|
/* Expand the larger bucket if data bridges the gap between cur and next */
|
||||||
|
if (!combineNext || cur->sz >= next->sz) {
|
||||||
|
chosenBucket = &cur;
|
||||||
|
otherBucket = next;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
chosenBucket = &next;
|
||||||
|
otherBucket = cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
DtlsFragBucket* tmp = (DtlsFragBucket*)XREALLOC(*chosenBucket,
|
||||||
|
sizeof(DtlsFragBucket) + newSz, heap, DYNAMIC_TYPE_DTLS_FRAG);
|
||||||
|
if (tmp == NULL)
|
||||||
|
return NULL;
|
||||||
|
if (chosenBucket == &next) {
|
||||||
|
/* Update the link */
|
||||||
|
DtlsFragBucket* beforeNext = cur;
|
||||||
|
while (beforeNext->next != next)
|
||||||
|
beforeNext = beforeNext->next;
|
||||||
|
beforeNext->next = tmp;
|
||||||
}
|
}
|
||||||
|
newBucket = *chosenBucket = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
/* if no message data, just return */
|
if (combineNext) {
|
||||||
if (fragSz == 0)
|
/* Put next first since it will always be at the end. Use memmove since
|
||||||
return 0;
|
* newBucket may be next. */
|
||||||
|
XMEMMOVE(newBucket->buf + (next->offset - newOffset), next->buf,
|
||||||
|
next->sz);
|
||||||
|
/* memory after newOffsetEnd is already copied. Don't do extra work. */
|
||||||
|
newOffsetEnd = next->offset;
|
||||||
|
}
|
||||||
|
|
||||||
/* if list is empty add full fragment to front */
|
if (newOffset == offset) {
|
||||||
if (cur == NULL) {
|
/* data comes first */
|
||||||
newFrag = CreateFragment(&fragOffset, fragOffset + fragSz - 1, data,
|
if (newOffsetEnd <= offsetEnd) {
|
||||||
msg->msg, &bytesLeft, heap);
|
/* data encompasses cur. only copy data */
|
||||||
if (newFrag == NULL)
|
XMEMCPY(newBucket->buf, data,
|
||||||
return MEMORY_E;
|
min(dataSz, newOffsetEnd - newOffset));
|
||||||
|
|
||||||
msg->fragSz = fragSz;
|
|
||||||
msg->fragList = newFrag;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
/* add to front if before current front, up to next->begin */
|
/* data -> cur. memcpy as much possible as its faster. */
|
||||||
if (fragOffset < cur->begin) {
|
XMEMMOVE(newBucket->buf + dataSz, cur->buf,
|
||||||
word32 end = fragOffset + fragSz - 1;
|
cur->sz - (offsetEnd - cur->offset));
|
||||||
|
XMEMCPY(newBucket->buf, data, dataSz);
|
||||||
if (end >= cur->begin)
|
|
||||||
end = cur->begin - 1;
|
|
||||||
|
|
||||||
added = end - fragOffset + 1;
|
|
||||||
newFrag = CreateFragment(&fragOffset, end, data, msg->msg,
|
|
||||||
&bytesLeft, heap);
|
|
||||||
if (newFrag == NULL)
|
|
||||||
return MEMORY_E;
|
|
||||||
|
|
||||||
msg->fragSz += added;
|
|
||||||
|
|
||||||
newFrag->next = cur;
|
|
||||||
msg->fragList = newFrag;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* while we have bytes left, try to find a gap to fill */
|
|
||||||
while (bytesLeft > 0) {
|
|
||||||
/* get previous packet in list */
|
|
||||||
while (cur && (fragOffset >= cur->begin)) {
|
|
||||||
prev = cur;
|
|
||||||
cur = cur->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* don't add duplicate data */
|
|
||||||
if (prev->end >= fragOffset) {
|
|
||||||
if ( (fragOffset + bytesLeft - 1) <= prev->end)
|
|
||||||
return 0;
|
|
||||||
fragOffset = prev->end + 1;
|
|
||||||
bytesLeft = startOffset + fragSz - fragOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cur == NULL)
|
|
||||||
/* we're at the end */
|
|
||||||
added = bytesLeft;
|
|
||||||
else
|
|
||||||
/* we're in between two frames */
|
|
||||||
added = min(bytesLeft, cur->begin - fragOffset);
|
|
||||||
|
|
||||||
/* data already there */
|
|
||||||
if (added == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
newFrag = CreateFragment(&fragOffset, fragOffset + added - 1,
|
|
||||||
data + fragOffset - startOffset,
|
|
||||||
msg->msg, &bytesLeft, heap);
|
|
||||||
if (newFrag == NULL)
|
|
||||||
return MEMORY_E;
|
|
||||||
|
|
||||||
msg->fragSz += added;
|
|
||||||
|
|
||||||
newFrag->next = prev->next;
|
|
||||||
prev->next = newFrag;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
/* cur -> data */
|
||||||
|
word32 curOffsetEnd = cur->offset + cur->sz;
|
||||||
|
if (newBucket != cur)
|
||||||
|
XMEMCPY(newBucket->buf, cur->buf, cur->sz);
|
||||||
|
XMEMCPY(newBucket->buf + cur->sz,
|
||||||
|
data + (curOffsetEnd - offset),
|
||||||
|
newOffsetEnd - curOffsetEnd);
|
||||||
|
}
|
||||||
|
/* FINALLY the newBucket is populated correctly */
|
||||||
|
|
||||||
|
/* All buckets up to and including next (if combining) have to be free'd */
|
||||||
|
{
|
||||||
|
DtlsFragBucket* toFree = cur->next;
|
||||||
|
while (toFree != next) {
|
||||||
|
DtlsFragBucket* n = toFree->next;
|
||||||
|
overlapSz += toFree->sz;
|
||||||
|
DtlsMsgDestroyFragBucket(toFree, heap);
|
||||||
|
msg->fragBucketListCount--;
|
||||||
|
toFree = n;
|
||||||
|
}
|
||||||
|
if (combineNext) {
|
||||||
|
newBucket->next = next->next;
|
||||||
|
overlapSz += next->sz;
|
||||||
|
DtlsMsgDestroyFragBucket(otherBucket, heap);
|
||||||
|
msg->fragBucketListCount--;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
newBucket->next = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Adjust size in msg */
|
||||||
|
msg->bytesReceived += newSz - overlapSz;
|
||||||
|
newBucket->offset = newOffset;
|
||||||
|
newBucket->sz = newSz;
|
||||||
|
return newBucket;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DtlsMsgAssembleCompleteMessage(DtlsMsg* msg)
|
||||||
|
{
|
||||||
|
/* We have received all necessary fragments. Reconstruct the header. */
|
||||||
|
if (msg->fragBucketListCount != 1 || msg->fragBucketList->offset != 0 ||
|
||||||
|
msg->fragBucketList->sz != msg->sz) {
|
||||||
|
WOLFSSL_MSG("Major error in fragment assembly logic");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Re-cycle the DtlsFragBucket as the buffer that holds the complete
|
||||||
|
* handshake message and the header. */
|
||||||
|
msg->raw = (byte*)msg->fragBucketList;
|
||||||
|
msg->fullMsg = msg->fragBucketList->buf;
|
||||||
|
msg->ready = 1;
|
||||||
|
|
||||||
|
/* frag->padding makes sure we can fit the entire DTLS handshake header
|
||||||
|
* before frag->buf */
|
||||||
|
DtlsHandShakeHeader* dtls =
|
||||||
|
(DtlsHandShakeHeader*)(msg->fragBucketList->buf -
|
||||||
|
DTLS_HANDSHAKE_HEADER_SZ);
|
||||||
|
|
||||||
|
msg->fragBucketList = NULL;
|
||||||
|
msg->fragBucketListCount = 0;
|
||||||
|
|
||||||
|
dtls->type = msg->type;
|
||||||
|
c32to24(msg->sz, dtls->length);
|
||||||
|
c16toa(msg->seq, dtls->message_seq);
|
||||||
|
c32to24(0, dtls->fragment_offset);
|
||||||
|
c32to24(msg->sz, dtls->fragment_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
int DtlsMsgSet(DtlsMsg* msg, word32 seq, word16 epoch, const byte* data, byte type,
|
||||||
|
word32 fragOffset, word32 fragSz, void* heap, word32 totalLen)
|
||||||
|
{
|
||||||
|
word32 fragOffsetEnd = fragOffset + fragSz;
|
||||||
|
|
||||||
|
WOLFSSL_ENTER("DtlsMsgSet()");
|
||||||
|
|
||||||
|
if (msg == NULL || data == NULL || msg->sz != totalLen ||
|
||||||
|
fragOffsetEnd > totalLen) {
|
||||||
|
WOLFSSL_ERROR_VERBOSE(BAD_FUNC_ARG);
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg->ready)
|
||||||
|
return 0; /* msg is already complete */
|
||||||
|
|
||||||
|
if (msg->type != no_shake) {
|
||||||
|
/* msg is already populated with the correct seq, epoch, and type */
|
||||||
|
if (msg->type != type || msg->epoch != epoch || msg->seq != seq) {
|
||||||
|
WOLFSSL_ERROR_VERBOSE(SEQUENCE_ERROR);
|
||||||
|
return SEQUENCE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
msg->type = type;
|
||||||
|
msg->epoch = epoch;
|
||||||
|
msg->seq = seq;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg->fragBucketList == NULL) {
|
||||||
|
/* Clean list. Create first fragment. */
|
||||||
|
msg->fragBucketList = DtlsMsgCreateFragBucket(fragOffset, data, fragSz, heap);
|
||||||
|
msg->bytesReceived = fragSz;
|
||||||
|
msg->fragBucketListCount++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* See if we can expand any existing bucket to fit this new data into */
|
||||||
|
DtlsFragBucket* prev = NULL;
|
||||||
|
DtlsFragBucket* cur = msg->fragBucketList;
|
||||||
|
byte done = 0;
|
||||||
|
for (; cur != NULL; prev = cur, cur = cur->next) {
|
||||||
|
word32 curOffset = cur->offset;
|
||||||
|
word32 curEnd = cur->offset + cur->sz;
|
||||||
|
|
||||||
|
if (fragOffset >= curOffset && fragOffsetEnd <= curEnd) {
|
||||||
|
/* We already have this fragment */
|
||||||
|
done = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (fragOffset <= curEnd) {
|
||||||
|
/* found place to store fragment */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!done) {
|
||||||
|
if (cur == NULL) {
|
||||||
|
/* We reached the end of the list. data is after and disjointed
|
||||||
|
* from anything we have received so far. */
|
||||||
|
if (msg->fragBucketListCount >= DTLS_FRAG_POOL_SZ) {
|
||||||
|
WOLFSSL_ERROR_VERBOSE(DTLS_TOO_MANY_FRAGMENTS_E);
|
||||||
|
return DTLS_TOO_MANY_FRAGMENTS_E;
|
||||||
|
}
|
||||||
|
prev->next = DtlsMsgCreateFragBucket(fragOffset, data, fragSz, heap);
|
||||||
|
if (prev->next != NULL) {
|
||||||
|
msg->bytesReceived += fragSz;
|
||||||
|
msg->fragBucketListCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (prev == NULL && fragOffsetEnd < cur->offset) {
|
||||||
|
/* This is the new first fragment we have received */
|
||||||
|
if (msg->fragBucketListCount >= DTLS_FRAG_POOL_SZ) {
|
||||||
|
WOLFSSL_ERROR_VERBOSE(DTLS_TOO_MANY_FRAGMENTS_E);
|
||||||
|
return DTLS_TOO_MANY_FRAGMENTS_E;
|
||||||
|
}
|
||||||
|
msg->fragBucketList = DtlsMsgCreateFragBucket(fragOffset, data,
|
||||||
|
fragSz, heap);
|
||||||
|
if (msg->fragBucketList != NULL) {
|
||||||
|
msg->fragBucketList->next = cur;
|
||||||
|
msg->bytesReceived += fragSz;
|
||||||
|
msg->fragBucketListCount++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* reset on error */
|
||||||
|
msg->fragBucketList = cur;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Find if this fragment overlaps with any more */
|
||||||
|
DtlsFragBucket* next = cur->next;
|
||||||
|
DtlsFragBucket** prev_next = prev != NULL
|
||||||
|
? &prev->next : &msg->fragBucketList;
|
||||||
|
while (next != NULL &&
|
||||||
|
(next->offset + next->sz) <= fragOffsetEnd)
|
||||||
|
next = next->next;
|
||||||
|
/* We can combine the buckets */
|
||||||
|
*prev_next = DtlsMsgCombineFragBuckets(msg, cur, next,
|
||||||
|
fragOffset, data, fragSz, heap);
|
||||||
|
if (*prev_next == NULL) /* reset on error */
|
||||||
|
*prev_next = cur;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg->bytesReceived == msg->sz)
|
||||||
|
DtlsMsgAssembleCompleteMessage(msg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -8353,10 +8501,10 @@ void DtlsMsgStore(WOLFSSL* ssl, word16 epoch, word32 seq, const byte* data,
|
|||||||
if (head != NULL) {
|
if (head != NULL) {
|
||||||
DtlsMsg* cur = DtlsMsgFind(head, epoch, seq);
|
DtlsMsg* cur = DtlsMsgFind(head, epoch, seq);
|
||||||
if (cur == NULL) {
|
if (cur == NULL) {
|
||||||
cur = DtlsMsgNew(dataSz, heap);
|
cur = DtlsMsgNew(dataSz, 0, heap);
|
||||||
if (cur != NULL) {
|
if (cur != NULL) {
|
||||||
if (DtlsMsgSet(cur, seq, epoch, data, type,
|
if (DtlsMsgSet(cur, seq, epoch, data, type,
|
||||||
fragOffset, fragSz, heap) < 0) {
|
fragOffset, fragSz, heap, dataSz) < 0) {
|
||||||
DtlsMsgDelete(cur, heap);
|
DtlsMsgDelete(cur, heap);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -8368,13 +8516,13 @@ void DtlsMsgStore(WOLFSSL* ssl, word16 epoch, word32 seq, const byte* data,
|
|||||||
else {
|
else {
|
||||||
/* If this fails, the data is just dropped. */
|
/* If this fails, the data is just dropped. */
|
||||||
DtlsMsgSet(cur, seq, epoch, data, type, fragOffset,
|
DtlsMsgSet(cur, seq, epoch, data, type, fragOffset,
|
||||||
fragSz, heap);
|
fragSz, heap, dataSz);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
head = DtlsMsgNew(dataSz, heap);
|
head = DtlsMsgNew(dataSz, 0, heap);
|
||||||
if (DtlsMsgSet(head, seq, epoch, data, type, fragOffset,
|
if (DtlsMsgSet(head, seq, epoch, data, type, fragOffset,
|
||||||
fragSz, heap) < 0) {
|
fragSz, heap, dataSz) < 0) {
|
||||||
DtlsMsgDelete(head, heap);
|
DtlsMsgDelete(head, heap);
|
||||||
head = NULL;
|
head = NULL;
|
||||||
}
|
}
|
||||||
@ -8439,12 +8587,12 @@ int DtlsMsgPoolSave(WOLFSSL* ssl, const byte* data, word32 dataSz,
|
|||||||
return DTLS_POOL_SZ_E;
|
return DTLS_POOL_SZ_E;
|
||||||
}
|
}
|
||||||
|
|
||||||
item = DtlsMsgNew(dataSz, ssl->heap);
|
item = DtlsMsgNew(dataSz, 1, ssl->heap);
|
||||||
|
|
||||||
if (item != NULL) {
|
if (item != NULL) {
|
||||||
DtlsMsg* cur = ssl->dtls_tx_msg_list;
|
DtlsMsg* cur = ssl->dtls_tx_msg_list;
|
||||||
|
|
||||||
XMEMCPY(item->buf, data, dataSz);
|
XMEMCPY(item->raw, data, dataSz);
|
||||||
item->sz = dataSz;
|
item->sz = dataSz;
|
||||||
item->epoch = ssl->keys.dtls_epoch;
|
item->epoch = ssl->keys.dtls_epoch;
|
||||||
item->seq = ssl->keys.dtls_handshake_number;
|
item->seq = ssl->keys.dtls_handshake_number;
|
||||||
@ -8580,7 +8728,7 @@ int DtlsMsgPoolSend(WOLFSSL* ssl, int sendOnlyFirstPacket)
|
|||||||
if (pool->epoch == 0) {
|
if (pool->epoch == 0) {
|
||||||
DtlsRecordLayerHeader* dtls;
|
DtlsRecordLayerHeader* dtls;
|
||||||
|
|
||||||
dtls = (DtlsRecordLayerHeader*)pool->buf;
|
dtls = (DtlsRecordLayerHeader*)pool->raw;
|
||||||
/* If the stored record's epoch is 0, and the currently set
|
/* If the stored record's epoch is 0, and the currently set
|
||||||
* epoch is 0, use the "current order" sequence number.
|
* epoch is 0, use the "current order" sequence number.
|
||||||
* If the stored record's epoch is 0 and the currently set
|
* If the stored record's epoch is 0 and the currently set
|
||||||
@ -8599,7 +8747,7 @@ int DtlsMsgPoolSend(WOLFSSL* ssl, int sendOnlyFirstPacket)
|
|||||||
XMEMCPY(ssl->buffers.outputBuffer.buffer +
|
XMEMCPY(ssl->buffers.outputBuffer.buffer +
|
||||||
ssl->buffers.outputBuffer.idx +
|
ssl->buffers.outputBuffer.idx +
|
||||||
ssl->buffers.outputBuffer.length,
|
ssl->buffers.outputBuffer.length,
|
||||||
pool->buf, pool->sz);
|
pool->raw, pool->sz);
|
||||||
ssl->buffers.outputBuffer.length += pool->sz;
|
ssl->buffers.outputBuffer.length += pool->sz;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -8608,7 +8756,7 @@ int DtlsMsgPoolSend(WOLFSSL* ssl, int sendOnlyFirstPacket)
|
|||||||
byte* output;
|
byte* output;
|
||||||
int inputSz, sendSz;
|
int inputSz, sendSz;
|
||||||
|
|
||||||
input = pool->buf;
|
input = pool->raw;
|
||||||
inputSz = pool->sz;
|
inputSz = pool->sz;
|
||||||
sendSz = inputSz + cipherExtraData(ssl);
|
sendSz = inputSz + cipherExtraData(ssl);
|
||||||
|
|
||||||
@ -9380,8 +9528,8 @@ static int SendHandshakeMsg(WOLFSSL* ssl, byte* input, word32 inputSz,
|
|||||||
if (ssl->options.dtls) {
|
if (ssl->options.dtls) {
|
||||||
data -= DTLS_HANDSHAKE_HEADER_SZ;
|
data -= DTLS_HANDSHAKE_HEADER_SZ;
|
||||||
dataSz += DTLS_HANDSHAKE_HEADER_SZ;
|
dataSz += DTLS_HANDSHAKE_HEADER_SZ;
|
||||||
AddHandShakeHeader(data,
|
AddHandShakeHeader(data, inputSz, ssl->fragOffset, fragSz,
|
||||||
inputSz, ssl->fragOffset, fragSz, type, ssl);
|
type, ssl);
|
||||||
ssl->keys.dtls_handshake_number--;
|
ssl->keys.dtls_handshake_number--;
|
||||||
}
|
}
|
||||||
if (IsDtlsNotSctpMode(ssl) &&
|
if (IsDtlsNotSctpMode(ssl) &&
|
||||||
@ -16112,15 +16260,14 @@ int DtlsMsgDrain(WOLFSSL* ssl)
|
|||||||
* last message... */
|
* last message... */
|
||||||
while (item != NULL &&
|
while (item != NULL &&
|
||||||
ssl->keys.dtls_expected_peer_handshake_number == item->seq &&
|
ssl->keys.dtls_expected_peer_handshake_number == item->seq &&
|
||||||
item->fragSz == item->sz &&
|
item->ready && ret == 0) {
|
||||||
ret == 0) {
|
|
||||||
word32 idx = 0;
|
word32 idx = 0;
|
||||||
|
|
||||||
#ifdef WOLFSSL_NO_TLS12
|
#ifdef WOLFSSL_NO_TLS12
|
||||||
ret = DoTls13HandShakeMsgType(ssl, item->msg, &idx, item->type,
|
ret = DoTls13HandShakeMsgType(ssl, item->fullMsg, &idx, item->type,
|
||||||
item->sz, item->sz);
|
item->sz, item->sz);
|
||||||
#else
|
#else
|
||||||
ret = DoHandShakeMsgType(ssl, item->msg, &idx, item->type,
|
ret = DoHandShakeMsgType(ssl, item->fullMsg, &idx, item->type,
|
||||||
item->sz, item->sz);
|
item->sz, item->sz);
|
||||||
#endif
|
#endif
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
@ -16356,8 +16503,7 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
ret = 0;
|
ret = 0;
|
||||||
if (ssl->dtls_rx_msg_list != NULL &&
|
if (ssl->dtls_rx_msg_list != NULL && ssl->dtls_rx_msg_list->ready)
|
||||||
ssl->dtls_rx_msg_list->fragSz >= ssl->dtls_rx_msg_list->sz)
|
|
||||||
ret = DtlsMsgDrain(ssl);
|
ret = DtlsMsgDrain(ssl);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
134
tests/api.c
134
tests/api.c
@ -57640,6 +57640,139 @@ static int test_wolfSSL_DtlsUpdateWindow(void)
|
|||||||
}
|
}
|
||||||
#endif /* WOLFSSL_DTLS */
|
#endif /* WOLFSSL_DTLS */
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_DTLS
|
||||||
|
static int DFB_TEST(WOLFSSL* ssl, word32 seq, word32 len, word32 f_offset,
|
||||||
|
word32 f_len, word32 f_count, byte ready, word32 bytesReceived)
|
||||||
|
{
|
||||||
|
DtlsMsg* cur;
|
||||||
|
static byte msg[100];
|
||||||
|
static byte msgInit = 0;
|
||||||
|
|
||||||
|
if (!msgInit) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 100; i++)
|
||||||
|
msg[i] = i + 1;
|
||||||
|
msgInit = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sanitize test parameters */
|
||||||
|
if (len > sizeof(msg))
|
||||||
|
return -1;
|
||||||
|
if (f_offset + f_len > sizeof(msg))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
DtlsMsgStore(ssl, 0, seq, msg + f_offset, len, certificate, f_offset, f_len, NULL);
|
||||||
|
|
||||||
|
if (ssl->dtls_rx_msg_list == NULL)
|
||||||
|
return -100;
|
||||||
|
|
||||||
|
if ((cur = DtlsMsgFind(ssl->dtls_rx_msg_list, 0, seq)) == NULL)
|
||||||
|
return -200;
|
||||||
|
if (cur->fragBucketListCount != f_count)
|
||||||
|
return -300;
|
||||||
|
if (cur->ready != ready)
|
||||||
|
return -400;
|
||||||
|
if (cur->bytesReceived != bytesReceived)
|
||||||
|
return -500;
|
||||||
|
if (ready) {
|
||||||
|
if (cur->fragBucketList != NULL)
|
||||||
|
return -600;
|
||||||
|
if (XMEMCMP(cur->fullMsg, msg, cur->sz) != 0)
|
||||||
|
return -700;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DtlsFragBucket* fb;
|
||||||
|
if (cur->fragBucketList == NULL)
|
||||||
|
return -800;
|
||||||
|
for (fb = cur->fragBucketList; fb != NULL; fb = fb->next) {
|
||||||
|
if (XMEMCMP(fb->buf, msg + fb->offset, fb->sz) != 0)
|
||||||
|
return -900;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DFB_TEST_RESET(WOLFSSL* ssl)
|
||||||
|
{
|
||||||
|
DtlsMsgListDelete(ssl->dtls_rx_msg_list, ssl->heap);
|
||||||
|
ssl->dtls_rx_msg_list = NULL;
|
||||||
|
ssl->dtls_rx_msg_list_sz = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_wolfSSL_DTLS_fragment_buckets(void)
|
||||||
|
{
|
||||||
|
WOLFSSL ssl[1];
|
||||||
|
|
||||||
|
printf(testingFmt, "wolfSSL_DTLS_fragment_buckets()");
|
||||||
|
|
||||||
|
XMEMSET(ssl, 0, sizeof(*ssl));
|
||||||
|
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 0, 100, 0, 100, 0, 1, 100), 0); /* 0-100 */
|
||||||
|
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 1, 100, 0, 20, 1, 0, 20), 0); /* 0-20 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 1, 100, 20, 20, 1, 0, 40), 0); /* 20-40 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 1, 100, 40, 20, 1, 0, 60), 0); /* 40-60 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 1, 100, 60, 20, 1, 0, 80), 0); /* 60-80 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 1, 100, 80, 20, 0, 1, 100), 0); /* 80-100 */
|
||||||
|
|
||||||
|
/* Test all permutations of 3 regions */
|
||||||
|
/* 1 2 3 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 2, 100, 0, 30, 1, 0, 30), 0); /* 0-30 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 2, 100, 30, 30, 1, 0, 60), 0); /* 30-60 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 2, 100, 60, 40, 0, 1, 100), 0); /* 60-100 */
|
||||||
|
/* 1 3 2 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 3, 100, 0, 30, 1, 0, 30), 0); /* 0-30 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 3, 100, 60, 40, 2, 0, 70), 0); /* 60-100 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 3, 100, 30, 30, 0, 1, 100), 0); /* 30-60 */
|
||||||
|
/* 2 1 3 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 4, 100, 30, 30, 1, 0, 30), 0); /* 30-60 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 4, 100, 0, 30, 1, 0, 60), 0); /* 0-30 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 4, 100, 60, 40, 0, 1, 100), 0); /* 60-100 */
|
||||||
|
/* 2 3 1 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 5, 100, 30, 30, 1, 0, 30), 0); /* 30-60 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 5, 100, 60, 40, 1, 0, 70), 0); /* 60-100 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 5, 100, 0, 30, 0, 1, 100), 0); /* 0-30 */
|
||||||
|
/* 3 1 2 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 6, 100, 60, 40, 1, 0, 40), 0); /* 60-100 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 6, 100, 0, 30, 2, 0, 70), 0); /* 0-30 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 6, 100, 30, 30, 0, 1, 100), 0); /* 30-60 */
|
||||||
|
/* 3 2 1 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 7, 100, 60, 40, 1, 0, 40), 0); /* 60-100 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 7, 100, 30, 30, 1, 0, 70), 0); /* 30-60 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 7, 100, 0, 30, 0, 1, 100), 0); /* 0-30 */
|
||||||
|
|
||||||
|
/* Test overlapping regions */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 8, 100, 0, 30, 1, 0, 30), 0); /* 0-30 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 8, 100, 20, 10, 1, 0, 30), 0); /* 20-30 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 8, 100, 70, 10, 2, 0, 40), 0); /* 70-80 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 8, 100, 20, 30, 2, 0, 60), 0); /* 20-50 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 8, 100, 40, 60, 0, 1, 100), 0); /* 40-100 */
|
||||||
|
|
||||||
|
/* Test overlapping multiple regions */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 9, 100, 0, 20, 1, 0, 20), 0); /* 0-20 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 9, 100, 30, 5, 2, 0, 25), 0); /* 30-35 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 9, 100, 40, 5, 3, 0, 30), 0); /* 40-45 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 9, 100, 50, 5, 4, 0, 35), 0); /* 50-55 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 9, 100, 60, 5, 5, 0, 40), 0); /* 60-65 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 9, 100, 70, 5, 6, 0, 45), 0); /* 70-75 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 9, 100, 30, 25, 4, 0, 55), 0); /* 30-55 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 9, 100, 55, 15, 2, 0, 65), 0); /* 55-70 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 9, 100, 75, 25, 2, 0, 90), 0); /* 75-100 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 9, 100, 10, 25, 0, 1, 100), 0); /* 10-35 */
|
||||||
|
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 10, 100, 0, 20, 1, 0, 20), 0); /* 0-20 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 10, 100, 30, 20, 2, 0, 40), 0); /* 30-50 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 10, 100, 0, 40, 1, 0, 50), 0); /* 0-40 */
|
||||||
|
AssertIntEQ(DFB_TEST(ssl, 10, 100, 50, 50, 0, 1, 100), 0); /* 10-35 */
|
||||||
|
|
||||||
|
DFB_TEST_RESET(ssl);
|
||||||
|
|
||||||
|
printf(resultFmt, passed);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*
|
/*----------------------------------------------------------------------------*
|
||||||
| Main
|
| Main
|
||||||
*----------------------------------------------------------------------------*/
|
*----------------------------------------------------------------------------*/
|
||||||
@ -58535,6 +58668,7 @@ TEST_CASE testCases[] = {
|
|||||||
TEST_DECL(test_wolfSSL_FIPS_mode),
|
TEST_DECL(test_wolfSSL_FIPS_mode),
|
||||||
#ifdef WOLFSSL_DTLS
|
#ifdef WOLFSSL_DTLS
|
||||||
TEST_DECL(test_wolfSSL_DtlsUpdateWindow),
|
TEST_DECL(test_wolfSSL_DtlsUpdateWindow),
|
||||||
|
TEST_DECL(test_wolfSSL_DTLS_fragment_buckets),
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TEST_DECL(test_ForceZero),
|
TEST_DECL(test_ForceZero),
|
||||||
|
@ -1115,6 +1115,9 @@ enum {
|
|||||||
#define WOLFSSL_DTLS_MTU_ADDITIONAL_READ_BUFFER 500
|
#define WOLFSSL_DTLS_MTU_ADDITIONAL_READ_BUFFER 500
|
||||||
#endif /* WOLFSSL_DTLS_MTU_ADDITIONAL_READ_BUFFER */
|
#endif /* WOLFSSL_DTLS_MTU_ADDITIONAL_READ_BUFFER */
|
||||||
|
|
||||||
|
#ifndef WOLFSSL_DTLS_FRAG_POOL_SZ
|
||||||
|
#define WOLFSSL_DTLS_FRAG_POOL_SZ 10
|
||||||
|
#endif
|
||||||
|
|
||||||
/* set minimum DH key size allowed */
|
/* set minimum DH key size allowed */
|
||||||
#ifndef WOLFSSL_MIN_DHKEY_BITS
|
#ifndef WOLFSSL_MIN_DHKEY_BITS
|
||||||
@ -1398,6 +1401,8 @@ enum Misc {
|
|||||||
DTLS_HANDSHAKE_FRAG_SZ = 3, /* fragment offset and length are 24 bit */
|
DTLS_HANDSHAKE_FRAG_SZ = 3, /* fragment offset and length are 24 bit */
|
||||||
DTLS_POOL_SZ = 20, /* allowed number of list items in TX and
|
DTLS_POOL_SZ = 20, /* allowed number of list items in TX and
|
||||||
* RX pool */
|
* RX pool */
|
||||||
|
DTLS_FRAG_POOL_SZ = WOLFSSL_DTLS_FRAG_POOL_SZ,
|
||||||
|
/* allowed number of fragments per msg */
|
||||||
DTLS_EXPORT_PRO = 165,/* wolfSSL protocol for serialized session */
|
DTLS_EXPORT_PRO = 165,/* wolfSSL protocol for serialized session */
|
||||||
DTLS_EXPORT_STATE_PRO = 166,/* wolfSSL protocol for serialized state */
|
DTLS_EXPORT_STATE_PRO = 166,/* wolfSSL protocol for serialized state */
|
||||||
TLS_EXPORT_PRO = 167,/* wolfSSL protocol for serialized TLS */
|
TLS_EXPORT_PRO = 167,/* wolfSSL protocol for serialized TLS */
|
||||||
@ -4435,23 +4440,36 @@ typedef struct DtlsRecordLayerHeader {
|
|||||||
} DtlsRecordLayerHeader;
|
} DtlsRecordLayerHeader;
|
||||||
|
|
||||||
|
|
||||||
typedef struct DtlsFrag {
|
/* Padding necessary to fit DTLS_HANDSHAKE_HEADER_SZ bytes before the buf member
|
||||||
word32 begin;
|
* of the DtlsFragBucket struct. */
|
||||||
word32 end;
|
#define WOLFSSL_DTLS_FRAG_BUCKET_PADDING \
|
||||||
struct DtlsFrag* next;
|
((DTLS_HANDSHAKE_HEADER_SZ > (sizeof(struct DtlsFragBucket*) + \
|
||||||
} DtlsFrag;
|
sizeof(word32) + sizeof(word32))) ? \
|
||||||
|
(DTLS_HANDSHAKE_HEADER_SZ - sizeof(struct DtlsFragBucket*) - \
|
||||||
|
sizeof(word32) - sizeof(word32)) : 0)
|
||||||
|
|
||||||
|
typedef struct DtlsFragBucket {
|
||||||
|
struct DtlsFragBucket* next;
|
||||||
|
word32 offset;
|
||||||
|
word32 sz;
|
||||||
|
byte padding[WOLFSSL_DTLS_FRAG_BUCKET_PADDING];
|
||||||
|
byte buf[];
|
||||||
|
/* Add new member initialization to CreateFragBucket */
|
||||||
|
} DtlsFragBucket;
|
||||||
|
|
||||||
typedef struct DtlsMsg {
|
typedef struct DtlsMsg {
|
||||||
struct DtlsMsg* next;
|
struct DtlsMsg* next;
|
||||||
byte* buf;
|
byte* raw;
|
||||||
byte* msg;
|
byte* fullMsg; /* for TX fullMsg == raw. For RX this points to
|
||||||
DtlsFrag* fragList;
|
* the start of the message after headers. */
|
||||||
word32 fragSz; /* Length of fragments received */
|
DtlsFragBucket* fragBucketList;
|
||||||
|
word32 bytesReceived;
|
||||||
word16 epoch; /* Epoch that this message belongs to */
|
word16 epoch; /* Epoch that this message belongs to */
|
||||||
word32 seq; /* Handshake sequence number */
|
word32 seq; /* Handshake sequence number */
|
||||||
word32 sz; /* Length of whole message */
|
word32 sz; /* Length of whole message */
|
||||||
byte type;
|
byte type;
|
||||||
|
byte fragBucketListCount;
|
||||||
|
byte ready:1;
|
||||||
} DtlsMsg;
|
} DtlsMsg;
|
||||||
|
|
||||||
|
|
||||||
@ -5462,13 +5480,14 @@ WOLFSSL_LOCAL int cipherExtraData(WOLFSSL* ssl);
|
|||||||
#endif /* NO_WOLFSSL_SERVER */
|
#endif /* NO_WOLFSSL_SERVER */
|
||||||
|
|
||||||
#ifdef WOLFSSL_DTLS
|
#ifdef WOLFSSL_DTLS
|
||||||
WOLFSSL_LOCAL DtlsMsg* DtlsMsgNew(word32 sz, void* heap);
|
WOLFSSL_LOCAL DtlsMsg* DtlsMsgNew(word32 sz, byte tx, void* heap);
|
||||||
WOLFSSL_LOCAL void DtlsMsgDelete(DtlsMsg* item, void* heap);
|
WOLFSSL_LOCAL void DtlsMsgDelete(DtlsMsg* item, void* heap);
|
||||||
WOLFSSL_LOCAL void DtlsMsgListDelete(DtlsMsg* head, void* heap);
|
WOLFSSL_LOCAL void DtlsMsgListDelete(DtlsMsg* head, void* heap);
|
||||||
WOLFSSL_LOCAL void DtlsTxMsgListClean(WOLFSSL* ssl);
|
WOLFSSL_LOCAL void DtlsTxMsgListClean(WOLFSSL* ssl);
|
||||||
WOLFSSL_LOCAL int DtlsMsgSet(DtlsMsg* msg, word32 seq, word16 epoch,
|
WOLFSSL_LOCAL int DtlsMsgSet(DtlsMsg* msg, word32 seq, word16 epoch,
|
||||||
const byte* data, byte type,
|
const byte* data, byte type,
|
||||||
word32 fragOffset, word32 fragSz, void* heap);
|
word32 fragOffset, word32 fragSz, void* heap,
|
||||||
|
word32 totalLen);
|
||||||
WOLFSSL_LOCAL DtlsMsg* DtlsMsgFind(DtlsMsg* head, word16 epoch, word32 seq);
|
WOLFSSL_LOCAL DtlsMsg* DtlsMsgFind(DtlsMsg* head, word16 epoch, word32 seq);
|
||||||
|
|
||||||
WOLFSSL_LOCAL void DtlsMsgStore(WOLFSSL* ssl, word16 epoch, word32 seq,
|
WOLFSSL_LOCAL void DtlsMsgStore(WOLFSSL* ssl, word16 epoch, word32 seq,
|
||||||
@ -5485,6 +5504,7 @@ WOLFSSL_LOCAL int cipherExtraData(WOLFSSL* ssl);
|
|||||||
WOLFSSL_LOCAL int VerifyForTxDtlsMsgDelete(WOLFSSL* ssl, DtlsMsg* item);
|
WOLFSSL_LOCAL int VerifyForTxDtlsMsgDelete(WOLFSSL* ssl, DtlsMsg* item);
|
||||||
WOLFSSL_LOCAL void DtlsMsgPoolReset(WOLFSSL* ssl);
|
WOLFSSL_LOCAL void DtlsMsgPoolReset(WOLFSSL* ssl);
|
||||||
WOLFSSL_LOCAL int DtlsMsgPoolSend(WOLFSSL* ssl, int sendOnlyFirstPacket);
|
WOLFSSL_LOCAL int DtlsMsgPoolSend(WOLFSSL* ssl, int sendOnlyFirstPacket);
|
||||||
|
WOLFSSL_LOCAL void DtlsMsgDestroyFragBucket(DtlsFragBucket* fragBucket, void* heap);
|
||||||
WOLFSSL_LOCAL int GetDtlsHandShakeHeader(WOLFSSL *ssl, const byte *input,
|
WOLFSSL_LOCAL int GetDtlsHandShakeHeader(WOLFSSL *ssl, const byte *input,
|
||||||
word32 *inOutIdx, byte *type, word32 *size, word32 *fragOffset,
|
word32 *inOutIdx, byte *type, word32 *size, word32 *fragOffset,
|
||||||
word32 *fragSz, word32 totalSz);
|
word32 *fragSz, word32 totalSz);
|
||||||
|
Reference in New Issue
Block a user