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