dtls_record.c
Go to the documentation of this file.
1 /**
2  * @file dtls_record.c
3  * @brief DTLS record protocol
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneSSL Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.5.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL TLS_TRACE_LEVEL
33 
34 //Dependencies
35 #include "tls.h"
36 #include "tls_common.h"
37 #include "tls_record.h"
38 #include "tls_record_encryption.h"
39 #include "tls_record_decryption.h"
40 #include "tls_misc.h"
41 #include "dtls_misc.h"
42 #include "dtls_record.h"
43 #include "debug.h"
44 
45 //Check TLS library configuration
46 #if (TLS_SUPPORT == ENABLED && DTLS_SUPPORT == ENABLED)
47 
48 
49 /**
50  * @brief Write protocol data
51  * @param[in] context Pointer to the TLS context
52  * @param[in] data Pointer to the data buffer
53  * @param[in] length Number of data bytes to be written
54  * @param[in] contentType Higher level protocol
55  * @return Error code
56  **/
57 
59  const uint8_t *data, size_t length, TlsContentType contentType)
60 {
61  error_t error;
62 
63  //Prepare DTLS record
64  error = dtlsWriteRecord(context, data, length, contentType);
65 
66  //Check status code
67  if(!error)
68  {
69  //DTLS operates as a client or a server?
70  if(context->entity == TLS_CONNECTION_END_CLIENT)
71  {
72  //Client messages are grouped into a series of message flights
73  if(context->state == TLS_STATE_CLIENT_HELLO ||
74  context->state == TLS_STATE_CLIENT_HELLO_2 ||
75  context->state == TLS_STATE_CLIENT_FINISHED)
76  {
77  //Reset retransmission counter
78  context->retransmitCount = 0;
79  //Implementations should use an initial timer value of 1 second
80  context->retransmitTimeout = DTLS_INIT_TIMEOUT;
81 
82  //Transmit the buffered flight of messages
83  error = dtlsSendFlight(context);
84  }
85  }
86  else
87  {
88  //Server messages are grouped into a series of message flights
89  if(context->state == TLS_STATE_SERVER_HELLO_DONE ||
90  context->state == TLS_STATE_SERVER_FINISHED)
91  {
92  //Reset retransmission counter
93  context->retransmitCount = 0;
94  //Implementations should use an initial timer value of 1 second
95  context->retransmitTimeout = DTLS_INIT_TIMEOUT;
96 
97  //Transmit the buffered flight of messages
98  error = dtlsSendFlight(context);
99  }
100  else if(context->state == TLS_STATE_HELLO_VERIFY_REQUEST ||
101  context->state == TLS_STATE_HELLO_RETRY_REQUEST)
102  {
103  //Reset retransmission counter
104  context->retransmitCount = 0;
105 
106  //Transmit the HelloVerifyRequest or HelloRetryRequest message
107  error = dtlsSendFlight(context);
108 
109  //Timeout and retransmission do not apply to HelloVerifyRequest and
110  //HelloRetryRequest messages, because this would require creating
111  //state on the server
112  context->txBufferLen = 0;
113  }
114  }
115  }
116 
117  //Return status code
118  return error;
119 }
120 
121 
122 /**
123  * @brief Read protocol data
124  * @param[in] context Pointer to the TLS context
125  * @param[out] data Pointer to the received data
126  * @param[out] length Number of data bytes that were received
127  * @param[out] contentType Higher level protocol
128  * @return Error code
129  **/
130 
132  uint8_t **data, size_t *length, TlsContentType *contentType)
133 {
134  error_t error;
135 
136  //Initialize status code
137  error = NO_ERROR;
138 
139  //Receive process
140  while(error == NO_ERROR)
141  {
142  if(context->rxBufferLen > 0)
143  {
144  //Pass the received data to the higher layer
145  break;
146  }
147  else if(context->rxRecordLen > 0)
148  {
149  //Process the incoming DTLS record
150  error = dtlsProcessRecord(context);
151 
152  //Invalid record?
153  if(error)
154  {
155  //Debug message
156  TRACE_WARNING("Discarding DTLS record!\r\n");
157 
158  //DTLS implementations should silently discard records with
159  //bad MACs and continue with the connection
160  error = NO_ERROR;
161  }
162  }
163  else if(context->rxDatagramLen > 0)
164  {
165  //Read a new DTLS record from the datagram
166  error = dtlsReadRecord(context);
167 
168  //Malformed record?
169  if(error != NO_ERROR && error != ERROR_RECORD_OVERFLOW)
170  {
171  //Debug message
172  TRACE_WARNING("Discarding DTLS record!\r\n");
173 
174  //The receiving implementation should discard the offending record
175  error = NO_ERROR;
176  }
177  }
178  else
179  {
180  //Read a new datagram
181  error = dtlsReadDatagram(context, context->rxBuffer + context->rxFragQueueLen,
182  context->rxBufferSize - context->rxFragQueueLen, &context->rxDatagramLen);
183 
184  //Check whether a valid datagram has been received
185  if(!error)
186  {
187  //Make room for the fragment reassembly process
188  context->rxDatagramPos = context->rxBufferSize - context->rxDatagramLen;
189 
190  //Copy the received datagram
191  osMemmove(context->rxBuffer + context->rxDatagramPos,
192  context->rxBuffer + context->rxFragQueueLen, context->rxDatagramLen);
193  }
194  }
195  }
196 
197  //Successful processing?
198  if(!error)
199  {
200 #if (TLS_MAX_WARNING_ALERTS > 0)
201  //Reset the count of consecutive warning alerts
202  if(context->rxBufferType != TLS_TYPE_ALERT)
203  context->alertCount = 0;
204 #endif
205 
206  //Pointer to the received data
207  *data = context->rxBuffer + context->rxBufferPos;
208  //Length, in byte, of the data
209  *length = context->rxBufferLen;
210  //Protocol type
211  *contentType = context->rxBufferType;
212  }
213 
214  //Return status code
215  return error;
216 }
217 
218 
219 /**
220  * @brief Send a DTLS record
221  * @param[in] context Pointer to the TLS context
222  * @param[in] data Pointer to the record data
223  * @param[in] length Length of the record data
224  * @param[in] contentType Record type
225  * @return Error code
226  **/
227 
228 error_t dtlsWriteRecord(TlsContext *context, const uint8_t *data,
229  size_t length, TlsContentType contentType)
230 {
231  error_t error;
232  size_t n;
233  DtlsRecord *record;
234  TlsEncryptionEngine *encryptionEngine;
235 
236  //Calculate the length of the DTLS record
237  n = length + sizeof(DtlsRecord);
238 
239  //Make sure the buffer is large enough to hold the DTLS record
240  if((context->txBufferLen + n) > context->txBufferSize)
241  return ERROR_BUFFER_OVERFLOW;
242 
243  //Point to the encryption engine
244  encryptionEngine = &context->encryptionEngine;
245 
246  //Point to the DTLS record header
247  record = (DtlsRecord *) (context->txBuffer + context->txBufferLen);
248 
249  //Copy record data
250  osMemmove(record->data, data, length);
251 
252  //Format DTLS record
253  record->type = contentType;
254  record->version = htons(dtlsTranslateVersion(encryptionEngine->version));
255  record->epoch = htons(encryptionEngine->epoch);
256  record->length = htons(length);
257 
258  //Check record type
259  if(contentType == TLS_TYPE_HANDSHAKE ||
260  contentType == TLS_TYPE_CHANGE_CIPHER_SPEC)
261  {
262  //Sequence numbers are handled at record layer
263  osMemset(&record->seqNum, 0, sizeof(DtlsSequenceNumber));
264 
265  //Adjust the length of the buffered flight of messages
266  context->txBufferLen += n;
267  }
268  else
269  {
270  //This record will have a new sequence number
271  record->seqNum = encryptionEngine->dtlsSeqNum;
272 
273  //Take into account the overhead caused by encryption
274  n += tlsComputeEncryptionOverhead(encryptionEngine, n);
275 
276  //Make sure the buffer is large enough to hold the encrypted record
277  if((context->txBufferLen + n) > context->txBufferSize)
278  return ERROR_BUFFER_OVERFLOW;
279 
280  //Protect record payload?
281  if(encryptionEngine->cipherMode != CIPHER_MODE_NULL ||
282  encryptionEngine->hashAlgo != NULL)
283  {
284  //Encrypt DTLS record
285  error = tlsEncryptRecord(context, encryptionEngine, record);
286  //Any error to report?
287  if(error)
288  return error;
289  }
290 
291  //Debug message
292  TRACE_DEBUG("Encrypted DTLS record (%" PRIuSIZE " bytes)...\r\n", ntohs(record->length));
293  TRACE_DEBUG_ARRAY(" ", record, ntohs(record->length) + sizeof(DtlsRecord));
294 
295  //Increment sequence number
296  dtlsIncSequenceNumber(&encryptionEngine->dtlsSeqNum);
297 
298  //Length of the resulting datagram, in bytes
299  n = ntohs(record->length) + sizeof(DtlsRecord);
300 
301  //Debug message
302  TRACE_INFO("Sending UDP datagram (%" PRIuSIZE " bytes)...\r\n", n);
303 
304  //Send datagram
305  error = context->socketSendCallback(context->socketHandle, record, n, &n, 0);
306  //Any error to report?
307  if(error)
308  return error;
309  }
310 
311  //Successful processing
312  return NO_ERROR;
313 }
314 
315 
316 /**
317  * @brief Receive a DTLS record
318  * @param[in] context Pointer to the TLS context
319  * @return Error code
320  **/
321 
323 {
324  error_t error;
325  DtlsRecord *record;
326  size_t recordLen;
327  TlsEncryptionEngine *decryptionEngine;
328 
329  //Point to the decryption engine
330  decryptionEngine = &context->decryptionEngine;
331 
332  //Make sure the datagram is large enough to hold a DTLS record
333  if(context->rxDatagramLen < sizeof(DtlsRecord))
334  {
335  //Drop received datagram
336  context->rxDatagramLen = 0;
337  //Report an error
338  return ERROR_INVALID_LENGTH;
339  }
340 
341  //Point to the DTLS record
342  record = (DtlsRecord *) (context->rxBuffer + context->rxDatagramPos);
343  //Retrieve the length of the record
344  recordLen = ntohs(record->length);
345 
346  //Sanity check
347  if((recordLen + sizeof(DtlsRecord)) > context->rxDatagramLen)
348  {
349  //Drop received datagram
350  context->rxDatagramLen = 0;
351  //Report an error
352  return ERROR_INVALID_LENGTH;
353  }
354 
355  //Debug message
356  TRACE_DEBUG("DTLS encrypted record received (%" PRIuSIZE " bytes)...\r\n", recordLen);
357  TRACE_DEBUG_ARRAY(" ", record, recordLen + sizeof(DtlsRecord));
358 
359  //Point to the payload data
360  context->rxRecordPos = context->rxDatagramPos + sizeof(DtlsRecord);
361 
362  //It is acceptable to pack multiple DTLS records in the same datagram
363  context->rxDatagramPos += recordLen + sizeof(DtlsRecord);
364  context->rxDatagramLen -= recordLen + sizeof(DtlsRecord);
365 
366  //Compliant servers must accept any value {254,XX} as the record layer
367  //version number for ClientHello
368  if(LSB(record->version) != MSB(DTLS_VERSION_1_0))
370 
371  //Discard packets from earlier epochs
372  if(ntohs(record->epoch) != context->decryptionEngine.epoch)
373  return ERROR_INVALID_EPOCH;
374 
375  //Perform replay detection
376  error = dtlsCheckReplayWindow(context, &record->seqNum);
377  //Any error to report?
378  if(error)
379  return error;
380 
381  //Check whether the record payload is protected
382  if(decryptionEngine->cipherMode != CIPHER_MODE_NULL ||
383  decryptionEngine->hashAlgo != NULL)
384  {
385  //Decrypt DTLS record
386  error = tlsDecryptRecord(context, decryptionEngine, record);
387  //If the MAC validation fails, the receiver must discard the record
388  if(error)
389  return error;
390 
391  //The length of the plaintext record must not exceed 2^14 bytes
392  if(ntohs(record->length) > TLS_MAX_RECORD_LENGTH)
393  return ERROR_RECORD_OVERFLOW;
394  }
395 
396  //The receive window is updated only if the MAC verification succeeds
397  dtlsUpdateReplayWindow(context, &record->seqNum);
398 
399  //Retrieve the length of the record
400  recordLen = ntohs(record->length);
401 
402  //Debug message
403  TRACE_DEBUG("DTLS decrypted record received (%" PRIuSIZE " bytes)...\r\n", recordLen);
404  TRACE_DEBUG_ARRAY(" ", record, recordLen + sizeof(DtlsRecord));
405 
406  //Save record version
407  context->rxRecordVersion = ntohs(record->version);
408  //Save record type
409  context->rxBufferType = (TlsContentType) record->type;
410  //Save record length
411  context->rxRecordLen = recordLen;
412 
413  //Successful processing
414  return NO_ERROR;
415 }
416 
417 
418 /**
419  * @brief Process incoming DTLS record
420  * @param[in] context Pointer to the TLS context
421  * @return Error code
422  **/
423 
425 {
426  error_t error;
427  systime_t time;
428 
429  //Handshake message received?
430  if(context->rxBufferType == TLS_TYPE_HANDSHAKE)
431  {
432  size_t fragLength;
434 
435  //Make sure the DTLS record is large enough to hold a handshake message
436  if(context->rxRecordLen < sizeof(DtlsHandshake))
437  {
438  //Drop the received DTLS record
439  context->rxRecordLen = 0;
440  //Report an error
441  return ERROR_INVALID_LENGTH;
442  }
443 
444  //Point to the handshake message
445  message = (DtlsHandshake *) (context->rxBuffer + context->rxRecordPos);
446 
447  //Debug message
448  TRACE_DEBUG("Handshake message fragment received (%" PRIuSIZE " bytes)...\r\n",
449  LOAD24BE(message->fragLength));
450  TRACE_DEBUG(" msgType = %u\r\n", message->msgType);
451  TRACE_DEBUG(" msgSeq = %u\r\n", ntohs(message->msgSeq));
452  TRACE_DEBUG(" fragOffset = %u\r\n", LOAD24BE(message->fragOffset));
453  TRACE_DEBUG(" fragLength = %u\r\n", LOAD24BE(message->fragLength));
454  TRACE_DEBUG(" length = %u\r\n", LOAD24BE(message->length));
455 
456  //Retrieve fragment length
457  fragLength = LOAD24BE(message->fragLength) + sizeof(DtlsHandshake);
458 
459  //Sanity check
460  if(fragLength > context->rxRecordLen)
461  {
462  //Drop the received DTLS record
463  context->rxRecordLen = 0;
464  //Report an error
465  return ERROR_INVALID_LENGTH;
466  }
467 
468  //It is acceptable to pack multiple handshake messages in the same record
469  context->rxRecordPos += fragLength;
470  context->rxRecordLen -= fragLength;
471 
472  //Invalid fragment length?
473  if(LOAD24BE(message->fragLength) > LOAD24BE(message->length))
474  return ERROR_INVALID_LENGTH;
475 
476  //Empty fragment?
477  if(LOAD24BE(message->fragLength) == 0 && LOAD24BE(message->length) != 0)
478  return ERROR_INVALID_LENGTH;
479 
480  //Check whether TLS operates as a client or a server
481  if(context->entity == TLS_CONNECTION_END_CLIENT)
482  {
483  //HelloRequest message received?
484  if(message->msgType == TLS_TYPE_HELLO_REQUEST &&
485  context->state == TLS_STATE_APPLICATION_DATA)
486  {
487  //Re-initialize message sequence numbers
488  context->rxMsgSeq = ntohs(message->msgSeq);
489  context->txMsgSeq = 0;
490  }
491  }
492  else
493  {
494  //ClientHello message received?
495  if(message->msgType == TLS_TYPE_CLIENT_HELLO &&
496  context->state == TLS_STATE_CLIENT_HELLO)
497  {
498  //Initial handshake?
499  if(context->decryptionEngine.epoch == 0)
500  {
501  //The server must use the record sequence number in the ClientHello
502  //as the record sequence number in its response (HelloVerifyRequest
503  //or ServerHello)
504  context->encryptionEngine.dtlsSeqNum = context->decryptionEngine.dtlsSeqNum;
505 
506  //Re-initialize message sequence numbers
507  context->rxMsgSeq = ntohs(message->msgSeq);
508  context->txMsgSeq = ntohs(message->msgSeq);
509  }
510  }
511  }
512 
513  //When a peer receives a handshake message, it can quickly determine
514  //whether that message is the next message it expects
515  if(ntohs(message->msgSeq) < context->rxMsgSeq)
516  {
517  //Retransmitted flight from the peer?
518  if(message->msgType == TLS_TYPE_CLIENT_HELLO ||
519  message->msgType == TLS_TYPE_SERVER_HELLO_DONE ||
520  message->msgType == TLS_TYPE_FINISHED)
521  {
522  //First fragment of the handshake message?
523  if(LOAD24BE(message->fragOffset) == 0)
524  {
525  //Check whether a flight of messages is buffered
526  if(context->txBufferLen > 0)
527  {
528  //Get current time
529  time = osGetSystemTime();
530 
531  //Send only one response in the case multiple retransmitted
532  //flights are received from the peer
533  if(timeCompare(time, context->retransmitTimestamp +
534  DTLS_MIN_TIMEOUT) >= 0)
535  {
536  //The implementation transitions to the SENDING state,
537  //where it retransmits the flight, resets the retransmit
538  //timer, and returns to the WAITING state
539  if(context->retransmitCount < DTLS_MAX_RETRIES)
540  {
541  dtlsSendFlight(context);
542  }
543  }
544  }
545  }
546  }
547 
548  //If the sequence number of the received message is less than
549  //the expected value, the message must be discarded
551  }
552  else if(ntohs(message->msgSeq) > context->rxMsgSeq)
553  {
554  //If the sequence number of the received message is greater than
555  //the expected value, the implementation may discard it
557  }
558  else
559  {
560  //If the sequence number of the received message matches the
561  //expected value, the message is processed
562  }
563 
564  //Check current state
565  if(context->state > TLS_STATE_SERVER_HELLO_2)
566  {
567  //Once the server has sent the ServerHello message, enforce the version
568  //of incoming records
569  if(context->rxRecordVersion != dtlsTranslateVersion(context->version))
571  }
572 
573  //When a DTLS implementation receives a handshake message fragment,
574  //it must buffer it until it has the entire handshake message. DTLS
575  //implementations must be able to handle overlapping fragment ranges
576  error = dtlsReassembleHandshakeMessage(context, message);
577  //Unacceptable message received?
578  if(error)
579  {
580  //Flush the reassembly queue
581  context->rxFragQueueLen = 0;
582  //Report an error
583  return error;
584  }
585 
586  //Point to the first fragment of the reassembly queue
587  message = (DtlsHandshake *) context->rxBuffer;
588 
589  //An unfragmented message is a degenerate case with fragment_offset = 0
590  //and fragment_length = length
591  if(LOAD24BE(message->fragOffset) == 0 &&
592  LOAD24BE(message->fragLength) == LOAD24BE(message->length))
593  {
594  //The reassembly process is now complete
595  context->rxFragQueueLen = 0;
596 
597  //Number of bytes available for reading
598  context->rxBufferLen = LOAD24BE(message->length) + sizeof(DtlsHandshake);
599  //Rewind to the beginning of the buffer
600  context->rxBufferPos = 0;
601 
602  //The message sequence number is incremented by one
603  context->rxMsgSeq++;
604 
605  //Check whether a complete flight of messages has been received
606  if(message->msgType == TLS_TYPE_CLIENT_HELLO ||
608  message->msgType == TLS_TYPE_SERVER_HELLO_DONE ||
609  message->msgType == TLS_TYPE_FINISHED)
610  {
611  //Exit from the WAITING state
612  context->txBufferLen = 0;
613  }
614  }
615  }
616  else
617  {
618  //ChangeCipherSpec message received?
619  if(context->rxBufferType == TLS_TYPE_CHANGE_CIPHER_SPEC)
620  {
621  //Sanity check
622  if(context->rxRecordLen < sizeof(TlsChangeCipherSpec))
623  {
624  //Drop the received DTLS record
625  context->rxRecordLen = 0;
626  //Report an error
627  return ERROR_INVALID_LENGTH;
628  }
629 
630  //DTLS operates as a client or a server?
631  if(context->entity == TLS_CONNECTION_END_CLIENT)
632  {
633  //Check current state
634  if(context->state != TLS_STATE_SERVER_CHANGE_CIPHER_SPEC)
635  {
636  //Drop the received DTLS record
637  context->rxRecordLen = 0;
638  //Report an error
640  }
641  }
642  else
643  {
644  //Check current state
645  if(context->state != TLS_STATE_CLIENT_CHANGE_CIPHER_SPEC)
646  {
647  //Drop the received DTLS record
648  context->rxRecordLen = 0;
649  //Report an error
651  }
652  }
653 
654  //Enforce the version the received DTLS record
655  if(context->rxRecordVersion != dtlsTranslateVersion(context->version))
657  }
658  //Alert message received?
659  else if(context->rxBufferType == TLS_TYPE_ALERT)
660  {
661  //Sanity check
662  if(context->rxRecordLen < sizeof(TlsAlert))
663  {
664  //Drop the received DTLS record
665  context->rxRecordLen = 0;
666  //Report an error
667  return ERROR_INVALID_LENGTH;
668  }
669  }
670  //Application data received?
671  else if(context->rxBufferType == TLS_TYPE_APPLICATION_DATA)
672  {
673  //Check current state
674  if(context->state == TLS_STATE_APPLICATION_DATA)
675  {
676  //The last flight of messages has been received by the peer
677  context->txBufferLen = 0;
678  }
679  else
680  {
681  //Drop the received DTLS record
682  context->rxRecordLen = 0;
683  //Report an error
685  }
686 
687  //Enforce the version the received DTLS record
688  if(context->rxRecordVersion != dtlsTranslateVersion(context->version))
690  }
691  //Unknown content type?
692  else
693  {
694  //Drop the received DTLS record
695  context->rxRecordLen = 0;
696  //Report an error
698  }
699 
700  //Number of bytes available for reading
701  context->rxBufferLen = context->rxRecordLen;
702  //Rewind to the beginning of the buffer
703  context->rxBufferPos = 0;
704 
705  //Copy application data
706  osMemcpy(context->rxBuffer, context->rxBuffer + context->rxRecordPos,
707  context->rxRecordLen);
708 
709  //The DTLS record has been entirely processed
710  context->rxRecordLen = 0;
711  //Flush the reassembly queue
712  context->rxFragQueueLen = 0;
713  }
714 
715  //Successful processing
716  return NO_ERROR;
717 }
718 
719 
720 /**
721  * @brief Send the buffered flight of messages
722  * @param[in] context Pointer to the TLS context
723  * @return Error code
724  **/
725 
727 {
728  error_t error;
729  size_t n;
730  size_t pmtu;
731  uint8_t *datagram;
732  DtlsRecord *record;
734  TlsEncryptionEngine *encryptionEngine;
735 
736  //Determine the value of the PMTU
737  pmtu = MIN(context->pmtu, context->txBufferSize - context->txBufferLen);
738 
739  //Make sure the PMTU value is acceptable
740  if(pmtu < DTLS_MIN_PMTU)
741  return ERROR_BUFFER_OVERFLOW;
742 
743  //Point to the buffer where to format the datagram
744  datagram = context->txBuffer + context->txBufferLen;
745  //Length of the datagram, in bytes
746  context->txDatagramLen = 0;
747  //Point to the first message of the flight
748  context->txBufferPos = 0;
749 
750  //In the SENDING state, the implementation transmits the buffered
751  //flight of messages
752  while(context->txBufferPos < context->txBufferLen)
753  {
754  //Point to the current DTLS record
755  record = (DtlsRecord *) (context->txBuffer + context->txBufferPos);
756 
757  //Advance data pointer
758  context->txBufferPos += ntohs(record->length) + sizeof(DtlsRecord);
759 
760  //Select the relevant encryption engine
761  if(ntohs(record->epoch) == context->encryptionEngine.epoch)
762  {
763  encryptionEngine = &context->encryptionEngine;
764  }
765  else
766  {
767  encryptionEngine = &context->prevEncryptionEngine;
768  }
769 
770  //Handshake message?
771  if(record->type == TLS_TYPE_HANDSHAKE)
772  {
773  //Point to the handshake message header to be fragmented
774  message = (DtlsHandshake *) record->data;
775 
776  //Fragment handshake message into smaller fragments
777  error = dtlsFragmentHandshakeMessage(context, ntohs(record->version),
778  encryptionEngine, message);
779  //Any error to report?
780  if(error)
781  return error;
782  }
783  else
784  {
785  //Any datagram pending to be sent?
786  if(context->txDatagramLen > 0)
787  {
788  //Estimate the length of the DTLS record
789  n = ntohs(record->length) + sizeof(DtlsRecord);
790  //Take into account the overhead caused by encryption
791  n += tlsComputeEncryptionOverhead(encryptionEngine, n);
792 
793  //Records may not span datagrams
794  if((context->txDatagramLen + n) > pmtu)
795  {
796  //Debug message
797  TRACE_INFO("Sending UDP datagram (%" PRIuSIZE " bytes)...\r\n",
798  context->txDatagramLen);
799 
800  //Send datagram
801  error = context->socketSendCallback(context->socketHandle,
802  datagram, context->txDatagramLen, &n, 0);
803  //Any error to report?
804  if(error)
805  return error;
806 
807  //The datagram has been successfully transmitted
808  context->txDatagramLen = 0;
809  }
810  }
811 
812  //Estimate the length of the DTLS record
813  n = ntohs(record->length) + sizeof(DtlsRecord);
814  //Take into account the overhead caused by encryption
815  n += tlsComputeEncryptionOverhead(encryptionEngine, n);
816 
817  //Make sure the buffer is large enough to hold the DTLS record
818  if((context->txBufferLen + context->txDatagramLen + n) > context->txBufferSize)
819  return ERROR_BUFFER_OVERFLOW;
820 
821  //Multiple DTLS records may be placed in a single datagram. They are
822  //simply encoded consecutively
823  osMemcpy(datagram + context->txDatagramLen, record,
824  ntohs(record->length) + sizeof(DtlsRecord));
825 
826  //Point to the DTLS record header
827  record = (DtlsRecord *) (datagram + context->txDatagramLen);
828 
829  //From the perspective of the DTLS record layer, the retransmission is
830  //a new record. This record will have a new sequence number
831  record->seqNum = encryptionEngine->dtlsSeqNum;
832 
833  //Protect record payload?
834  if(encryptionEngine->cipherMode != CIPHER_MODE_NULL ||
835  encryptionEngine->hashAlgo != NULL)
836  {
837  //Encrypt DTLS record
838  error = tlsEncryptRecord(context, encryptionEngine, record);
839  //Any error to report?
840  if(error)
841  return error;
842  }
843 
844  //Debug message
845  TRACE_DEBUG("Encrypted DTLS record (%" PRIuSIZE " bytes)...\r\n", ntohs(record->length));
846  TRACE_DEBUG_ARRAY(" ", record, ntohs(record->length) + sizeof(DtlsRecord));
847 
848  //Increment sequence number
849  dtlsIncSequenceNumber(&encryptionEngine->dtlsSeqNum);
850 
851  //Adjust the length of the datagram
852  context->txDatagramLen += ntohs(record->length) + sizeof(DtlsRecord);
853  }
854  }
855 
856  //Any datagram pending to be sent?
857  if(context->txDatagramLen > 0)
858  {
859  //Debug message
860  TRACE_INFO("Sending UDP datagram (%" PRIuSIZE " bytes)...\r\n",
861  context->txDatagramLen);
862 
863  //Send datagram
864  error = context->socketSendCallback(context->socketHandle, datagram,
865  context->txDatagramLen, &n, 0);
866  //Any error to report?
867  if(error)
868  return error;
869 
870  //The datagram has been successfully transmitted
871  context->txDatagramLen = 0;
872  }
873 
874  //Save the time at which the flight of messages was sent
875  context->retransmitTimestamp = osGetSystemTime();
876  //Increment retransmission counter
877  context->retransmitCount++;
878 
879  //Successful processing
880  return NO_ERROR;
881 }
882 
883 
884 /**
885  * @brief Handshake message fragmentation
886  * @param[in] context Pointer to the TLS context
887  * @param[in] version DTLS version to be used
888  * @param[in] encryptionEngine Pointer to the encryption engine
889  * @param[in] message Pointer the handshake message to be fragmented
890  * @return Error code
891  **/
892 
894  TlsEncryptionEngine *encryptionEngine, const DtlsHandshake *message)
895 {
896  error_t error;
897  size_t n;
898  size_t pmtu;
899  size_t totalLength;
900  size_t fragOffset;
901  size_t fragLength;
902  size_t maxFragSize;
903  uint8_t *datagram;
904  DtlsRecord *record;
905  DtlsHandshake *fragment;
906 
907  //Determine the value of the PMTU
908  pmtu = MIN(context->pmtu, context->txBufferSize - context->txBufferLen);
909 
910  //DTLS has 25 bytes overhead per packet
911  n = sizeof(DtlsRecord) + sizeof(DtlsHandshake);
912  //Take into account the overhead caused by encryption
913  n += tlsComputeEncryptionOverhead(encryptionEngine, 0);
914 
915  //Make sure the PMTU value is acceptable
916  if(pmtu <= n || pmtu < DTLS_MIN_PMTU)
917  return ERROR_BUFFER_OVERFLOW;
918 
919  //Determine the maximum payload size for fragmented messages
920  maxFragSize = pmtu - n;
921 
922  //Point to the buffer where to format the datagram
923  datagram = context->txBuffer + context->txBufferLen;
924  //Get the length of the handshake message
925  totalLength = LOAD24BE(message->length);
926  //Prepare to send the first fragment
927  fragOffset = 0;
928 
929  //Fragmentation process
930  do
931  {
932  //Calculate the length of the current fragment
933  fragLength = MIN(totalLength - fragOffset, maxFragSize);
934 
935  //Any datagram pending to be sent?
936  if(context->txDatagramLen > 0)
937  {
938  //Estimate the length of the DTLS record
939  n = fragLength + sizeof(DtlsRecord) + sizeof(DtlsHandshake);
940  //Take into account the overhead caused by encryption
941  n += tlsComputeEncryptionOverhead(encryptionEngine, n);
942 
943  //Records may not span datagrams
944  if((context->txDatagramLen + n) > pmtu)
945  {
946  //Debug message
947  TRACE_INFO("Sending UDP datagram (%" PRIuSIZE " bytes)...\r\n",
948  context->txDatagramLen);
949 
950  //Send datagram
951  error = context->socketSendCallback(context->socketHandle,
952  datagram, context->txDatagramLen, &n, 0);
953  //Any error to report?
954  if(error)
955  return error;
956 
957  //The datagram has been successfully transmitted
958  context->txDatagramLen = 0;
959  }
960  }
961 
962  //Multiple DTLS records may be placed in a single datagram. They are
963  //simply encoded consecutively
964  record = (DtlsRecord *) (datagram + context->txDatagramLen);
965 
966  //Format DTLS record
967  record->type = TLS_TYPE_HANDSHAKE;
968  record->version = htons(version);
969  record->epoch = htons(encryptionEngine->epoch);
970  record->seqNum = encryptionEngine->dtlsSeqNum;
971  record->length = htons(fragLength + sizeof(DtlsHandshake));
972 
973  //Point to the handshake message header
974  fragment = (DtlsHandshake *) record->data;
975 
976  //Handshake message type
977  fragment->msgType = message->msgType;
978  //Number of bytes in the message
979  STORE24BE(totalLength, fragment->length);
980  //Message sequence number
981  fragment->msgSeq = message->msgSeq;
982  //Fragment offset
983  STORE24BE(fragOffset, fragment->fragOffset);
984  //Fragment length
985  STORE24BE(fragLength, fragment->fragLength);
986 
987  //Copy data
988  osMemcpy(fragment->data, message->data + fragOffset, fragLength);
989 
990  //Debug message
991  TRACE_DEBUG("Sending handshake message fragment (%" PRIuSIZE " bytes)...\r\n",
992  LOAD24BE(fragment->fragLength));
993  TRACE_DEBUG(" msgType = %u\r\n", fragment->msgType);
994  TRACE_DEBUG(" msgSeq = %u\r\n", ntohs(fragment->msgSeq));
995  TRACE_DEBUG(" fragOffset = %u\r\n", LOAD24BE(fragment->fragOffset));
996  TRACE_DEBUG(" fragLength = %u\r\n", LOAD24BE(fragment->fragLength));
997  TRACE_DEBUG(" length = %u\r\n", LOAD24BE(fragment->length));
998 
999  //Protect record payload?
1000  if(encryptionEngine->cipherMode != CIPHER_MODE_NULL ||
1001  encryptionEngine->hashAlgo != NULL)
1002  {
1003  //Encrypt DTLS record
1004  error = tlsEncryptRecord(context, encryptionEngine, record);
1005  //Any error to report?
1006  if(error)
1007  return error;
1008  }
1009 
1010  //Debug message
1011  TRACE_DEBUG("Encrypted DTLS record (%" PRIuSIZE " bytes)...\r\n", ntohs(record->length));
1012  TRACE_DEBUG_ARRAY(" ", record, ntohs(record->length) + sizeof(DtlsRecord));
1013 
1014  //Increment sequence number
1015  dtlsIncSequenceNumber(&encryptionEngine->dtlsSeqNum);
1016 
1017  //Adjust the length of the datagram
1018  context->txDatagramLen += ntohs(record->length) + sizeof(DtlsRecord);
1019 
1020  //Next fragment
1022 
1023  //Check whether fragmentation process is complete
1024  } while(fragOffset < totalLength);
1025 
1026  //Successful processing
1027  return NO_ERROR;
1028 }
1029 
1030 
1031 /**
1032  * @brief Handshake message reassembly algorithm
1033  * @param[in] context Pointer to the TLS context
1034  * @param[in] message Pointer the newly arrived fragment
1035  * @return Error code
1036  **/
1037 
1039  const DtlsHandshake *message)
1040 {
1041  size_t n;
1042  size_t pos;
1043  size_t fragOffset;
1044  size_t fragLength;
1045  size_t prevFragOffset;
1046  size_t prevFragLength;
1047  DtlsHandshake *fragment;
1048  DtlsHandshake *prevFragment;
1049 
1050  //Retrieve fragment offset
1051  fragOffset = LOAD24BE(message->fragOffset);
1052  //Retrieve fragment length
1053  fragLength = LOAD24BE(message->fragLength) + sizeof(DtlsHandshake);
1054 
1055  //Point to the beginning of the reassembly queue
1056  pos = 0;
1057 
1058  //Loop through the reassembly queue
1059  while(pos < context->rxFragQueueLen)
1060  {
1061  //Point to the current fragment
1062  fragment = (DtlsHandshake *) (context->rxBuffer + pos);
1063 
1064  //Message type mismatch?
1065  if(message->msgType != fragment->msgType)
1066  return ERROR_UNEXPECTED_MESSAGE;
1067 
1068  //Message length mismatch?
1069  if(LOAD24BE(message->length) != LOAD24BE(fragment->length))
1070  return ERROR_UNEXPECTED_MESSAGE;
1071 
1072  //Sort fragments in ascending order
1073  if(fragOffset < LOAD24BE(fragment->fragOffset))
1074  break;
1075 
1076  //Next fragment
1077  pos += LOAD24BE(fragment->fragLength) + sizeof(DtlsHandshake);
1078  }
1079 
1080  //Sanity check
1081  if((context->rxFragQueueLen + fragLength) > (context->rxBufferSize - context->rxDatagramLen))
1082  return ERROR_BUFFER_OVERFLOW;
1083 
1084  //Position where to insert the new fragment
1085  fragment = (DtlsHandshake *) (context->rxBuffer + pos);
1086 
1087  //Make room for the new fragment
1088  osMemmove(context->rxBuffer + pos + fragLength, fragment,
1089  context->rxFragQueueLen - pos);
1090 
1091  //Insert the new fragment in the reassembly queue
1092  osMemcpy(fragment, message, fragLength);
1093  //Update the length of the reassembly queue
1094  context->rxFragQueueLen += fragLength;
1095 
1096  //Point to the first fragment of the reassembly queue
1097  prevFragment = (DtlsHandshake *) context->rxBuffer;
1098  //Retrieve fragment offset
1099  prevFragOffset = LOAD24BE(prevFragment->fragOffset);
1100  //Retrieve fragment length
1101  prevFragLength = LOAD24BE(prevFragment->fragLength);
1102 
1103  //Position of the next fragment
1104  pos = prevFragLength + sizeof(DtlsHandshake);
1105 
1106  //Loop through the reassembly queue
1107  while(pos < context->rxFragQueueLen)
1108  {
1109  //Point to the current fragment
1110  fragment = (DtlsHandshake *) (context->rxBuffer + pos);
1111  //Retrieve fragment offset
1112  fragOffset = LOAD24BE(fragment->fragOffset);
1113  //Retrieve fragment length
1114  fragLength = LOAD24BE(fragment->fragLength);
1115 
1116  //Check whether the current fragment interacts in some way with the
1117  //previous fragment
1118  if(fragOffset <= (prevFragOffset + prevFragLength))
1119  {
1120  //DTLS implementations must be able to handle overlapping fragment
1121  //ranges
1122  if((fragOffset + fragLength) > (prevFragOffset + prevFragLength))
1123  {
1124  //Coalesce overlapping fragments
1125  osMemmove(prevFragment->data + fragOffset - prevFragOffset, fragment->data,
1126  context->rxFragQueueLen - pos - sizeof(DtlsHandshake));
1127 
1128  //Number of bytes that do not overlap with the previous fragment
1129  n = fragOffset + fragLength - prevFragOffset - prevFragLength;
1130 
1131  //Update the length of the reassembly queue
1132  context->rxFragQueueLen -= fragLength - n + sizeof(DtlsHandshake);
1133 
1134  //Adjust the length of the previous fragment
1135  prevFragLength += n;
1136  //Fix fragment length field
1137  STORE24BE(prevFragLength, prevFragment->fragLength);
1138 
1139  //Jump to the next fragment
1140  pos += n;
1141  }
1142  else
1143  {
1144  //Drop current fragment
1145  osMemmove(fragment, fragment->data + fragLength,
1146  context->rxFragQueueLen - fragLength - sizeof(DtlsHandshake));
1147 
1148  //Update the length of the reassembly queue
1149  context->rxFragQueueLen -= fragLength + sizeof(DtlsHandshake);
1150  }
1151  }
1152  else
1153  {
1154  //Jump to the next fragment
1155  pos += fragLength + sizeof(DtlsHandshake);
1156 
1157  //Keep track of the previous fragment
1158  prevFragment = fragment;
1159  prevFragOffset = fragOffset;
1160  prevFragLength = fragLength;
1161  }
1162  }
1163 
1164  //Successful processing
1165  return NO_ERROR;
1166 }
1167 
1168 
1169 /**
1170  * @brief Receive a datagram
1171  * @param[in] context Pointer to the TLS context
1172  * @param[out] data Buffer where to store the incoming datagram
1173  * @param[in] size Maximum number of bytes that can be received
1174  * @param[out] length Number of bytes that have been received
1175  * @return Error code
1176  **/
1177 
1179  size_t size, size_t *length)
1180 {
1181  error_t error;
1182  systime_t time;
1183 
1184  //Initialize status code
1185  error = NO_ERROR;
1186 
1187  //Wait for an incoming datagram
1188  while(!error)
1189  {
1190  //Receive datagram
1191  error = context->socketReceiveCallback(context->socketHandle, data,
1192  size, length, 0);
1193 
1194  //Check status code
1195  if(error == NO_ERROR)
1196  {
1197  //Debug message
1198  TRACE_INFO("UDP datagram received (%" PRIuSIZE " bytes)...\r\n", *length);
1199  TRACE_DEBUG_ARRAY(" ", data, *length);
1200 
1201  //A datagram has been successfully received
1202  break;
1203  }
1204  else if(error == ERROR_WOULD_BLOCK)
1205  {
1206  //Manage retransmission timer
1207  error = dtlsTick(context);
1208 
1209  //Check status code
1210  if(!error)
1211  {
1212  //Exit immediately
1213  error = ERROR_WOULD_BLOCK;
1214  }
1215  }
1216  else if(error == ERROR_TIMEOUT)
1217  {
1218  //Manage retransmission timer
1219  error = dtlsTick(context);
1220 
1221  //Check status code
1222  if(!error)
1223  {
1224  //Check whether a timeout has been specified
1225  if(context->timeout != INFINITE_DELAY)
1226  {
1227  //Get current time
1228  time = osGetSystemTime();
1229 
1230  //Check whether the timeout has elapsed
1231  if(timeCompare(time, context->startTime + context->timeout) >= 0)
1232  {
1233  //Exit immediately
1234  error = ERROR_TIMEOUT;
1235  }
1236  }
1237  }
1238  }
1239  else
1240  {
1241  //The read operation has failed
1242  error = ERROR_READ_FAILED;
1243  }
1244  }
1245 
1246  //Return status code
1247  return error;
1248 }
1249 
1250 
1251 /**
1252  * @brief Manage retransmission timer
1253  * @param[in] context Pointer to the TLS context
1254  * @return Error code
1255  **/
1256 
1258 {
1259  error_t error;
1260  systime_t time;
1261 
1262  //Initialize status code
1263  error = NO_ERROR;
1264 
1265  //Check current state
1266  if(context->state != TLS_STATE_APPLICATION_DATA)
1267  {
1268  //Any flight of messages buffered?
1269  if(context->txBufferLen > 0)
1270  {
1271  //Get current time
1272  time = osGetSystemTime();
1273 
1274  //Check whether the retransmission timer has expired
1275  if(timeCompare(time, context->retransmitTimestamp +
1276  context->retransmitTimeout) >= 0)
1277  {
1278  //Check retransmission counter
1279  if(context->retransmitCount < DTLS_MAX_RETRIES)
1280  {
1281  //The implementation transitions to the SENDING state, where
1282  //it retransmits the flight, resets the retransmit timer, and
1283  //returns to the WAITING state
1284  error = dtlsSendFlight(context);
1285 
1286  //Double the value at each retransmission, up to no less than
1287  //the RFC 6298 maximum of 60 seconds
1288  context->retransmitTimeout = MIN(context->retransmitTimeout * 2,
1290  }
1291  else
1292  {
1293  //The maximum number of retransmissions has been exceeded
1294  error = ERROR_TIMEOUT;
1295  }
1296  }
1297  }
1298  }
1299 
1300  //Return status code
1301  return error;
1302 }
1303 
1304 
1305 /**
1306  * @brief Increment sequence number
1307  * @param[in,out] seqNum Pointer to the 48-bit sequence number
1308  **/
1309 
1311 {
1312  uint16_t temp;
1313 
1314  //Sequence numbers are stored MSB first
1315  temp = seqNum->b[5] + 1;
1316  seqNum->b[5] = temp & 0xFF;
1317  temp = (temp >> 8) + seqNum->b[4];
1318  seqNum->b[4] = temp & 0xFF;
1319  temp = (temp >> 8) + seqNum->b[3];
1320  seqNum->b[3] = temp & 0xFF;
1321  temp = (temp >> 8) + seqNum->b[2];
1322  seqNum->b[2] = temp & 0xFF;
1323  temp = (temp >> 8) + seqNum->b[1];
1324  seqNum->b[1] = temp & 0xFF;
1325  temp = (temp >> 8) + seqNum->b[0];
1326  seqNum->b[0] = temp & 0xFF;
1327 }
1328 
1329 #endif
TLS record decryption.
#define TLS_MAX_RECORD_LENGTH
Definition: tls.h:956
#define htons(value)
Definition: cpu_endian.h:413
DTLS (Datagram Transport Layer Security)
TLS helper functions.
@ TLS_STATE_HELLO_RETRY_REQUEST
Definition: tls.h:1498
TLS record encryption.
@ ERROR_WOULD_BLOCK
Definition: error.h:96
error_t dtlsTick(TlsContext *context)
Manage retransmission timer.
Definition: dtls_record.c:1257
@ TLS_TYPE_SERVER_HELLO_DONE
Definition: tls.h:1075
@ ERROR_BUFFER_OVERFLOW
Definition: error.h:143
@ ERROR_VERSION_NOT_SUPPORTED
Definition: error.h:67
@ ERROR_UNEXPECTED_MESSAGE
Definition: error.h:195
DtlsRecord
Definition: dtls_misc.h:180
uint8_t message[]
Definition: chap.h:154
@ TLS_TYPE_CHANGE_CIPHER_SPEC
Definition: tls.h:1046
uint8_t data[]
Definition: ethernet.h:222
@ TLS_TYPE_HANDSHAKE
Definition: tls.h:1048
error_t dtlsCheckReplayWindow(TlsContext *context, DtlsSequenceNumber *seqNum)
Perform replay detection.
Definition: dtls_misc.c:473
@ TLS_STATE_APPLICATION_DATA
Definition: tls.h:1523
error_t dtlsReadDatagram(TlsContext *context, uint8_t *data, size_t size, size_t *length)
Receive a datagram.
Definition: dtls_record.c:1178
#define DTLS_MIN_TIMEOUT
Definition: dtls_misc.h:97
uint16_t totalLength
Definition: ipv4.h:323
uint8_t version
Definition: coap_common.h:177
TlsChangeCipherSpec
Definition: tls.h:1900
#define timeCompare(t1, t2)
Definition: os_port.h:40
#define DTLS_MIN_PMTU
Definition: dtls_misc.h:55
@ TLS_STATE_CLIENT_HELLO
Definition: tls.h:1494
@ TLS_STATE_HELLO_VERIFY_REQUEST
Definition: tls.h:1497
#define DTLS_VERSION_1_0
Definition: dtls_misc.h:35
#define osMemcpy(dest, src, length)
Definition: os_port.h:144
#define TlsContext
Definition: tls.h:36
error_t
Error codes.
Definition: error.h:43
uint32_t seqNum
Definition: tcp.h:348
DTLS record protocol.
error_t dtlsReadRecord(TlsContext *context)
Receive a DTLS record.
Definition: dtls_record.c:322
TlsAlert
Definition: tls.h:1911
error_t dtlsReassembleHandshakeMessage(TlsContext *context, const DtlsHandshake *message)
Handshake message reassembly algorithm.
Definition: dtls_record.c:1038
@ TLS_TYPE_APPLICATION_DATA
Definition: tls.h:1049
@ TLS_TYPE_CLIENT_HELLO
Definition: tls.h:1063
@ TLS_STATE_SERVER_FINISHED
Definition: tls.h:1518
uint8_t fragLength[3]
Definition: dtls_misc.h:193
error_t dtlsFragmentHandshakeMessage(TlsContext *context, uint16_t version, TlsEncryptionEngine *encryptionEngine, const DtlsHandshake *message)
Handshake message fragmentation.
Definition: dtls_record.c:893
@ TLS_TYPE_ALERT
Definition: tls.h:1047
Handshake message processing (TLS client and server)
@ ERROR_INVALID_LENGTH
Definition: error.h:111
TLS record protocol.
@ TLS_STATE_SERVER_CHANGE_CIPHER_SPEC
Definition: tls.h:1516
#define DTLS_MAX_RETRIES
Definition: dtls_misc.h:83
uint8_t fragOffset[3]
Definition: dtls_misc.h:192
#define MSB(x)
Definition: os_port.h:59
error_t dtlsWriteProtocolData(TlsContext *context, const uint8_t *data, size_t length, TlsContentType contentType)
Write protocol data.
Definition: dtls_record.c:58
size_t tlsComputeEncryptionOverhead(TlsEncryptionEngine *encryptionEngine, size_t payloadLen)
Compute overhead caused by encryption.
Definition: tls_misc.c:1542
#define TRACE_INFO(...)
Definition: debug.h:105
uint8_t length
Definition: tcp.h:375
#define LSB(x)
Definition: os_port.h:55
@ TLS_TYPE_HELLO_VERIFY_REQUEST
Definition: tls.h:1065
#define MIN(a, b)
Definition: os_port.h:63
error_t dtlsWriteRecord(TlsContext *context, const uint8_t *data, size_t length, TlsContentType contentType)
Send a DTLS record.
Definition: dtls_record.c:228
uint16_t dtlsTranslateVersion(uint16_t version)
Translate TLS version into DTLS version.
Definition: dtls_misc.c:112
@ TLS_STATE_CLIENT_CHANGE_CIPHER_SPEC
Definition: tls.h:1512
@ ERROR_INVALID_EPOCH
Definition: error.h:108
void dtlsUpdateReplayWindow(TlsContext *context, DtlsSequenceNumber *seqNum)
Update sliding window.
Definition: dtls_misc.c:554
uint32_t systime_t
System time.
#define ntohs(value)
Definition: cpu_endian.h:421
#define TRACE_WARNING(...)
Definition: debug.h:93
#define TRACE_DEBUG(...)
Definition: debug.h:119
@ ERROR_TIMEOUT
Definition: error.h:95
#define DTLS_MAX_TIMEOUT
Definition: dtls_misc.h:104
@ TLS_STATE_CLIENT_HELLO_2
Definition: tls.h:1495
uint32_t time
TlsContentType
Content type.
Definition: tls.h:1044
#define TRACE_DEBUG_ARRAY(p, a, n)
Definition: debug.h:120
error_t dtlsReadProtocolData(TlsContext *context, uint8_t **data, size_t *length, TlsContentType *contentType)
Read protocol data.
Definition: dtls_record.c:131
#define DTLS_INIT_TIMEOUT
Definition: dtls_misc.h:90
uint8_t n
DtlsHandshake
Definition: dtls_misc.h:195
@ ERROR_READ_FAILED
Definition: error.h:224
@ TLS_TYPE_FINISHED
Definition: tls.h:1078
#define LOAD24BE(p)
Definition: cpu_endian.h:197
@ TLS_CONNECTION_END_CLIENT
Definition: tls.h:990
error_t dtlsSendFlight(TlsContext *context)
Send the buffered flight of messages.
Definition: dtls_record.c:726
error_t tlsEncryptRecord(TlsContext *context, TlsEncryptionEngine *encryptionEngine, void *record)
Encrypt an outgoing TLS record.
DtlsSequenceNumber
Definition: dtls_misc.h:143
TLS (Transport Layer Security)
#define STORE24BE(a, p)
Definition: cpu_endian.h:273
@ CIPHER_MODE_NULL
Definition: crypto.h:998
@ TLS_TYPE_HELLO_REQUEST
Definition: tls.h:1062
@ ERROR_RECORD_OVERFLOW
Definition: error.h:233
error_t dtlsProcessRecord(TlsContext *context)
Process incoming DTLS record.
Definition: dtls_record.c:424
#define PRIuSIZE
#define osMemset(p, value, length)
Definition: os_port.h:138
@ TLS_STATE_SERVER_HELLO_DONE
Definition: tls.h:1508
@ TLS_STATE_SERVER_HELLO_2
Definition: tls.h:1500
@ TLS_STATE_CLIENT_FINISHED
Definition: tls.h:1514
error_t tlsDecryptRecord(TlsContext *context, TlsEncryptionEngine *decryptionEngine, void *record)
Decrypt an incoming TLS record.
#define TlsEncryptionEngine
Definition: tls.h:40
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
#define osMemmove(dest, src, length)
Definition: os_port.h:150
#define INFINITE_DELAY
Definition: os_port.h:75
@ ERROR_INVALID_SEQUENCE_NUMBER
Definition: error.h:109
systime_t osGetSystemTime(void)
Retrieve system time.
void dtlsIncSequenceNumber(DtlsSequenceNumber *seqNum)
Increment sequence number.
Definition: dtls_record.c:1310