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