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