diff --git a/cyassl/ctaocrypt/types.h b/cyassl/ctaocrypt/types.h index 82bbaec5b..f6a06e19e 100644 --- a/cyassl/ctaocrypt/types.h +++ b/cyassl/ctaocrypt/types.h @@ -228,7 +228,8 @@ enum { DYNAMIC_TYPE_SOCKADDR = 35, DYNAMIC_TYPE_LIBZ = 36, DYNAMIC_TYPE_ECC = 37, - DYNAMIC_TYPE_TMP_BUFFER = 38 + DYNAMIC_TYPE_TMP_BUFFER = 38, + DYNAMIC_TYPE_DTLS_MSG = 39 }; /* stack protection */ diff --git a/cyassl/internal.h b/cyassl/internal.h index a7d7bdad4..9a68f0faf 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -1385,6 +1385,13 @@ typedef struct DtlsPool { int used; } DtlsPool; +typedef struct DtlsMsg { + struct DtlsMsg* next; + word32 seq; + word32 sz; + byte msg[1500]; +} DtlsMsg; + /* CyaSSL ssl type */ struct CYASSL { @@ -1457,6 +1464,7 @@ struct CYASSL { #ifdef CYASSL_DTLS int dtls_timeout; DtlsPool* dtls_pool; + DtlsMsg* dtls_msg_list; #endif #ifdef CYASSL_CALLBACKS HandShakeInfo handShakeInfo; /* info saved during handshake */ @@ -1677,6 +1685,10 @@ CYASSL_LOCAL int GrowInputBuffer(CYASSL* ssl, int size, int usedLength); CYASSL_LOCAL int DtlsPoolTimeout(CYASSL*); CYASSL_LOCAL int DtlsPoolSend(CYASSL*); CYASSL_LOCAL void DtlsPoolReset(CYASSL*); + CYASSL_LOCAL DtlsMsg* DtlsMsgNew(word32, byte*, word32, void*); + CYASSL_LOCAL void DtlsMsgDelete(DtlsMsg*, void*); + CYASSL_LOCAL void DtlsMsgListFree(DtlsMsg*, void*); + CYASSL_LOCAL DtlsMsg* DtlsMsgInsert(DtlsMsg*, DtlsMsg*); #endif /* CYASSL_DTLS */ #ifndef NO_TLS diff --git a/src/internal.c b/src/internal.c index f4c34a648..ad596254d 100644 --- a/src/internal.c +++ b/src/internal.c @@ -1164,6 +1164,7 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx) ssl->keys.dtls_expected_peer_epoch = 0; ssl->dtls_timeout = DTLS_DEFAULT_TIMEOUT; ssl->dtls_pool = NULL; + ssl->dtls_msg_list = NULL; #endif ssl->keys.encryptionOn = 0; /* initially off */ ssl->keys.decryptedCur = 0; /* initially off */ @@ -1412,6 +1413,10 @@ void SSL_ResourceFree(CYASSL* ssl) DtlsPoolReset(ssl); XFREE(ssl->dtls_pool, ssl->heap, DYNAMIC_TYPE_NONE); } + if (ssl->dtls_msg_list != NULL) { + DtlsMsgListFree(ssl->dtls_msg_list, ssl->heap); + ssl->dtls_msg_list = NULL; + } XFREE(ssl->buffers.dtlsCtx.peer.sa, ssl->heap, DYNAMIC_TYPE_SOCKADDR); ssl->buffers.dtlsCtx.peer.sa = NULL; #endif @@ -1644,7 +1649,76 @@ int DtlsPoolSend(CYASSL* ssl) return 0; } -#endif + +/* functions for managing DTLS datagram reordering */ + +DtlsMsg* DtlsMsgNew(word32 dataSz, byte* data, word32 seq, void* heap) +{ + DtlsMsg* msg = NULL; + + if (dataSz > 0) + msg = (DtlsMsg*)XMALLOC(sizeof(DtlsMsg), heap, DYNAMIC_TYPE_DTLS_MSG); + + if (msg != NULL) { + msg->next = NULL; + msg->seq = seq; + msg->sz = dataSz; + XMEMCPY(msg->msg, data, dataSz); + } + + return msg; +} + + +void DtlsMsgDelete(DtlsMsg* msg, void* heap) +{ + (void)heap; + if (msg != NULL) + XFREE(msg, heap, DYNAMIC_TYPE_DTLS_MSG); +} + + +void DtlsMsgListFree(DtlsMsg* head, void* heap) +{ + DtlsMsg* next; + while (head) { + next = head->next; + DtlsMsgDelete(head, heap); + head = next; + } +} + + +DtlsMsg* DtlsMsgInsert(DtlsMsg* head, DtlsMsg* item) +{ + if (head == NULL || item->seq < head->seq) { + item->next = head; + head = item; + } + else if (head->next == NULL) { + head->next = item; + } + else { + DtlsMsg* cur = head->next; + DtlsMsg* prev = head; + while (cur) { + if (item->seq < cur->seq) { + item->next = cur; + prev->next = item; + break; + } + prev = cur; + cur = cur->next; + } + if (cur == NULL) { + prev->next = item; + } + } + + return head; +} + +#endif /* CYASSL_DTLS */ #ifndef NO_OLD_TLS