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