dtls_misc.c
Go to the documentation of this file.
1 /**
2  * @file dtls_misc.c
3  * @brief DTLS (Datagram Transport Layer Security)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2022 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.2.0
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 <ctype.h>
37 #include "tls.h"
38 #include "tls_handshake.h"
39 #include "tls_common.h"
40 #include "dtls_misc.h"
41 #include "debug.h"
42 
43 //Check TLS library configuration
44 #if (TLS_SUPPORT == ENABLED && DTLS_SUPPORT == ENABLED)
45 
46 
47 /**
48  * @brief Set the DTLS version to be used
49  * @param[in] context Pointer to the TLS context
50  * @param[in] version DTLS version
51  * @return Error code
52  **/
53 
55 {
56  error_t error;
57 
58  //Initialize status code
60 
61  //Check DTLS version
63  {
64  //DTLS 1.0 is defined as a series of deltas from TLS 1.1
65  if(context->versionMin <= TLS_VERSION_1_1 &&
66  context->versionMax >= TLS_VERSION_1_1)
67  {
68  //Save protocol version
69  context->version = TLS_VERSION_1_1;
70  //The specified DTLS version is acceptable
71  error = NO_ERROR;
72  }
73  }
74  else if(version == DTLS_VERSION_1_2)
75  {
76  //DTLS 1.2 is defined as a series of deltas from TLS 1.2
77  if(context->versionMin <= TLS_VERSION_1_2 &&
78  context->versionMax >= TLS_VERSION_1_2)
79  {
80  //Save protocol version
81  context->version = TLS_VERSION_1_2;
82  //The specified DTLS version is acceptable
83  error = NO_ERROR;
84  }
85  }
86  else
87  {
88  //Unknown DTLS version
89  }
90 
91  //Check whether the DTLS version is supported
92  if(!error)
93  {
94  //Initial handshake?
95  if(context->encryptionEngine.epoch == 0)
96  {
97  //Save the negotiated version
98  context->encryptionEngine.version = context->version;
99  }
100  }
101 
102  //Return status code
103  return error;
104 }
105 
106 
107 /**
108  * @brief Translate TLS version into DTLS version
109  * @param[in] version TLS version
110  * @return DTLS version
111  **/
112 
113 uint16_t dtlsTranslateVersion(uint16_t version)
114 {
115  //Check current version
116  if(version == TLS_VERSION_1_2)
117  {
118  //DTLS 1.2 is defined as a series of deltas from TLS 1.2
120  }
121  else if(version == TLS_VERSION_1_3)
122  {
123  //DTLS 1.3 is defined as a series of deltas from TLS 1.3
125  }
126  else
127  {
128  //DTLS 1.0 is defined as a series of deltas from TLS 1.1
130  }
131 
132  //Return the version of the DTLS protocol
133  return version;
134 }
135 
136 
137 /**
138  * @brief Format Cookie field
139  * @param[in] context Pointer to the TLS context
140  * @param[in] p Output stream where to write the Cookie field
141  * @param[out] written Total number of bytes that have been written
142  * @return Error code
143  **/
144 
145 error_t dtlsFormatCookie(TlsContext *context, uint8_t *p, size_t *written)
146 {
148 
149  //Add Cookie field
150  cookie = (DtlsCookie *) p;
151 
152  //When a HelloVerifyRequest message has been received by the client, it
153  //must retransmit the ClientHello with the cookie added
154  if(context->cookieLen > 0)
155  {
156  //Copy cookie
157  osMemcpy(cookie->value, context->cookie, context->cookieLen);
158  }
159 
160  //Set the length of the cookie
161  cookie->length = (uint8_t) context->cookieLen;
162 
163  //Total number of bytes that have been written
164  *written = sizeof(DtlsCookie) + cookie->length;
165 
166  //Successful processing
167  return NO_ERROR;
168 }
169 
170 
171 /**
172  * @brief Cookie verification
173  * @param[in] context Pointer to the TLS context
174  * @param[in] cookie Pointer to the client's cookie
175  * @param[in] clientParams Client's parameters
176  * @return Error code
177  **/
178 
180  const DtlsClientParameters *clientParams)
181 {
182  error_t error;
183 
184  //Any registered callbacks?
185  if(context->cookieVerifyCallback != NULL &&
186  context->cookieGenerateCallback != NULL)
187  {
188  //Verify that the cookie is valid
189  error = context->cookieVerifyCallback(context, clientParams,
190  cookie->value, cookie->length, context->cookieParam);
191 
192  //Invalid cookie?
193  if(error == ERROR_WRONG_COOKIE)
194  {
195  //Set the cookie size limit (32 or 255 bytes depending on DTLS version)
196  context->cookieLen = DTLS_MAX_COOKIE_SIZE;
197 
198  //Allocate a memory block to hold the cookie
199  if(context->cookie == NULL)
200  {
201  context->cookie = tlsAllocMem(context->cookieLen);
202  }
203 
204  //Successful memory allocation?
205  if(context->cookie != NULL)
206  {
207  //The DTLS server should generate cookies in such a way that they can
208  //be verified without retaining any per-client state on the server
209  error = context->cookieGenerateCallback(context, clientParams,
210  context->cookie, &context->cookieLen, context->cookieParam);
211  }
212  else
213  {
214  //Failed to allocate memory
215  error = ERROR_OUT_OF_MEMORY;
216  }
217 
218  //Check status code
219  if(!error)
220  {
221  //Send a HelloVerifyRequest message to the DTLS client
222  context->state = TLS_STATE_HELLO_VERIFY_REQUEST;
223  }
224  }
225  }
226  else
227  {
228  //The server may be configured not to perform a cookie exchange
229  error = NO_ERROR;
230  }
231 
232  //Return status code
233  return error;
234 }
235 
236 
237 /**
238  * @brief Send HelloVerifyRequest message
239  *
240  * When the client sends its ClientHello message to the server, the server may
241  * respond with a HelloVerifyRequest message. This message contains a stateless
242  * cookie
243  *
244  * @param[in] context Pointer to the TLS context
245  * @return Error code
246  **/
247 
249 {
250  error_t error;
251  size_t length;
253 
254  //Point to the buffer where to format the message
255  message = (DtlsHelloVerifyRequest *) (context->txBuffer + context->txBufferLen);
256 
257  //Format HelloVerifyRequest message
258  error = dtlsFormatHelloVerifyRequest(context, message, &length);
259 
260  //Check status code
261  if(!error)
262  {
263  //Debug message
264  TRACE_INFO("Sending HelloVerifyRequest message (%" PRIuSIZE " bytes)...\r\n", length);
266 
267  //Send handshake message
268  error = tlsSendHandshakeMessage(context, message, length,
270  }
271 
272  //Check status code
273  if(error == NO_ERROR || error == ERROR_WOULD_BLOCK || error == ERROR_TIMEOUT)
274  {
275  //The client must retransmit the ClientHello with the cookie added
276  context->state = TLS_STATE_CLIENT_HELLO;
277  }
278 
279  //Return status code
280  return error;
281 }
282 
283 
284 /**
285  * @brief Format HelloVerifyRequest message
286  * @param[in] context Pointer to the TLS context
287  * @param[out] message Buffer where to format the HelloVerifyRequest message
288  * @param[out] length Length of the resulting HelloVerifyRequest message
289  * @return Error code
290  **/
291 
294 {
295  //In order to avoid the requirement to do version negotiation in the initial
296  //handshake, DTLS 1.2 server implementations should use DTLS version 1.0
297  //regardless of the version of TLS that is expected to be negotiated
298  message->serverVersion = HTONS(DTLS_VERSION_1_0);
299 
300  //Valid cookie?
301  if(context->cookieLen > 0)
302  {
303  //Copy cookie
304  osMemcpy(message->cookie, context->cookie, context->cookieLen);
305  }
306 
307  //Set the length of the cookie
308  message->cookieLength = (uint8_t) context->cookieLen;
309 
310  //Length of the handshake message
311  *length = sizeof(DtlsHelloVerifyRequest) + context->cookieLen;
312 
313  //Successful processing
314  return NO_ERROR;
315 }
316 
317 
318 /**
319  * @brief Parse HelloVerifyRequest message
320  *
321  * When the client sends its ClientHello message to the server,
322  * the server may respond with a HelloVerifyRequest message
323  *
324  * @param[in] context Pointer to the TLS context
325  * @param[in] message Incoming HelloVerifyRequest message to parse
326  * @param[in] length Message length
327  * @return Error code
328  **/
329 
331  const DtlsHelloVerifyRequest *message, size_t length)
332 {
333  //Debug message
334  TRACE_INFO("HelloVerifyRequest message received (%" PRIuSIZE " bytes)...\r\n", length);
336 
337  //DTLS protocol?
338  if(context->transportProtocol == TLS_TRANSPORT_PROTOCOL_DATAGRAM)
339  {
340  //Check the length of the HelloVerifyRequest message
341  if(length < sizeof(DtlsHelloVerifyRequest))
342  return ERROR_DECODING_FAILED;
343 
344  //Check current state
345  if(context->state != TLS_STATE_SERVER_HELLO)
347 
348  //Remaining bytes to process
349  length -= sizeof(DtlsHelloVerifyRequest);
350 
351  //If the amount of data in the message does not precisely match the format
352  //of the HelloVerifyRequest message, then send a fatal alert
353  if(message->cookieLength != length)
354  return ERROR_DECODING_FAILED;
355 
356  //Sanity check
357  if(context->cookie != NULL)
358  {
359  //Release memory
360  tlsFreeMem(context->cookie);
361  context->cookie = NULL;
362  context->cookieLen = 0;
363  }
364 
365  //Valid cookie received?
366  if(message->cookieLength > 0)
367  {
368  //Allocate a memory block to store the cookie
369  context->cookie = tlsAllocMem(message->cookieLength);
370  //Failed to allocate memory?
371  if(context->cookie == NULL)
372  return ERROR_OUT_OF_MEMORY;
373 
374  //Save cookie
375  osMemcpy(context->cookie, message->cookie, message->cookieLength);
376  }
377 
378  //Save the length of the cookie
379  context->cookieLen = message->cookieLength;
380 
381  //The client sends a second ClientHello message
382  context->state = TLS_STATE_CLIENT_HELLO;
383 
384  //Successful processing
385  return NO_ERROR;
386  }
387  else
388  {
389  //Report an error
391  }
392 }
393 
394 
395 /**
396  * @brief Parse SupportedVersions extension
397  * @param[in] context Pointer to the TLS context
398  * @param[in] supportedVersionList Pointer to the SupportedVersions extension
399  * @return Error code
400  **/
401 
403  const DtlsSupportedVersionList *supportedVersionList)
404 {
405  error_t error;
406  uint_t i;
407  uint_t j;
408  uint_t n;
409 
410  //Supported DTLS versions
411  const uint16_t supportedVersions[] =
412  {
415  };
416 
417  //Initialize status code
419 
420  //Retrieve the number of items in the list
421  n = supportedVersionList->length / sizeof(uint16_t);
422 
423  //Loop through the list of DTLS versions supported by the server
424  for(i = 0; i < arraysize(supportedVersions) && error; i++)
425  {
426  //The extension contains a list of DTLS versions supported by the client
427  for(j = 0; j < n && error; j++)
428  {
429  //Servers must only select a version of DTLS present in that extension
430  //and must ignore any unknown versions
431  if(ntohs(supportedVersionList->value[j]) == supportedVersions[i])
432  {
433  //Set the DTLS version to be used
434  error = dtlsSelectVersion(context, supportedVersions[i]);
435  }
436  }
437  }
438 
439  //Return status code
440  return error;
441 }
442 
443 
444 /**
445  * @brief Initialize sliding window
446  * @param[in] context Pointer to the TLS context
447  **/
448 
450 {
451 #if (DTLS_REPLAY_DETECTION_SUPPORT == ENABLED)
452  uint_t i;
453 
454  //Clear the bitmap window
455  for(i = 0; i < (DTLS_REPLAY_WINDOW_SIZE + 31) / 32; i++)
456  {
457  context->replayWindow[i] = 0;
458  }
459 #endif
460 }
461 
462 
463 /**
464  * @brief Perform replay detection
465  * @param[in] context Pointer to the TLS context
466  * @param[in] seqNum Sequence number of the received DTLS record
467  * @return Error code
468  **/
469 
471 {
472  error_t error;
473 
474 #if (DTLS_REPLAY_DETECTION_SUPPORT == ENABLED)
475  //Check whether anti-replay mechanism is enabled
476  if(context->replayDetectionEnabled)
477  {
478  uint_t j;
479  uint_t k;
480  uint64_t n;
481  uint64_t right;
482 
483  //Get the sequence number of the received DTLS record
484  n = LOAD48BE(seqNum);
485 
486  //The right edge of the window represents the highest validated sequence
487  //number value received on this session
488  right = LOAD48BE(&context->decryptionEngine.dtlsSeqNum);
489 
490  //Check sequence number
491  if(n <= right)
492  {
493  //Calculate the position relative to the right edge of the window
494  n = right - n;
495 
496  //Check whether the sequence number falls within the window
498  {
499  //Records falling within the window are checked against a list of
500  //received packets within the window
501  j = (uint_t) (n / 32);
502  k = (uint_t) (n % 32);
503 
504  //Duplicate record are rejected through the use of a sliding
505  //receive window
506  if(context->replayWindow[j] & (1 << k))
507  {
508  //The received record is a duplicate
510  }
511  else
512  {
513  //If the received record falls within the window and is new,
514  //then the receiver proceeds to MAC verification
515  error = NO_ERROR;
516  }
517 
518  }
519  else
520  {
521  //Records that contain sequence numbers lower than the left edge
522  //of the window are rejected
524  }
525  }
526  else
527  {
528  //If the packet is to the right of the window, then the receiver
529  //proceeds to MAC verification
530  error = NO_ERROR;
531  }
532  }
533  else
534 #endif
535  {
536  //Anti-replay mechanism is disabled
537  error = NO_ERROR;
538  }
539 
540  //Return status code
541  return error;
542 }
543 
544 
545 /**
546  * @brief Update sliding window
547  * @param[in] context Pointer to the TLS context
548  * @param[in] seqNum Sequence number of the received DTLS record
549  **/
550 
552 {
553  uint64_t n;
554  uint64_t right;
555 
556  //Get the sequence number of the received DTLS record
557  n = LOAD48BE(seqNum);
558 
559  //The right edge of the window represents the highest validated sequence
560  //number value received on this session
561  right = LOAD48BE(&context->decryptionEngine.dtlsSeqNum);
562 
563  //Check sequence number
564  if(n <= right)
565  {
566 #if (DTLS_REPLAY_DETECTION_SUPPORT == ENABLED)
567  uint_t j;
568  uint_t k;
569 
570  //Calculate the position relative to the right edge of the window
571  n = right - n;
572 
573  //Check whether the sequence number falls within the window
575  {
576  j = (uint_t) (n / 32);
577  k = (uint_t) (n % 32);
578 
579  //Set the corresponding bit in the bitmap window
580  context->replayWindow[j] |= 1 << k;
581  }
582 #endif
583  }
584  else
585  {
586 #if (DTLS_REPLAY_DETECTION_SUPPORT == ENABLED)
587  uint_t i;
588  uint_t j;
589  uint_t k;
590 
591  //Calculate the position relative to the right edge of the window
592  n -= right;
593 
594  //Check resulting value
596  {
597  j = (uint_t) (n / 32);
598  k = (uint_t) (n % 32);
599 
600  //First, shift words
601  if(j > 0)
602  {
603  //Shift the most significant words of the window
604  for(i = (DTLS_REPLAY_WINDOW_SIZE - 1) / 32; i >= j; i--)
605  {
606  context->replayWindow[i] = context->replayWindow[i - j];
607  }
608 
609  //Fill the least significant words with zeroes
610  for(i = 0; i < j; i++)
611  {
612  context->replayWindow[i] = 0;
613  }
614  }
615 
616  //Then shift bits
617  if(k > 0)
618  {
619  //Shift the most significant words of the window
620  for(i = (DTLS_REPLAY_WINDOW_SIZE - 1) / 32; i >= 1; i--)
621  {
622  context->replayWindow[i] = (context->replayWindow[i] << k) |
623  (context->replayWindow[i - 1] >> (32 - k));
624  }
625 
626  //Shift the least significant word
627  context->replayWindow[0] <<= k;
628  }
629  }
630  else
631  {
632  //Clear the bitmap window
633  for(i = 0; i < (DTLS_REPLAY_WINDOW_SIZE + 31) / 32; i++)
634  {
635  context->replayWindow[i] = 0;
636  }
637  }
638 
639  //Set the corresponding bit in the bitmap window
640  context->replayWindow[0] |= 1;
641 #endif
642 
643  //Save the highest sequence number value received on this session
644  context->decryptionEngine.dtlsSeqNum = *seqNum;
645  }
646 }
647 
648 #endif
#define tlsAllocMem(size)
Definition: tls.h:806
uint8_t length
Definition: coap_common.h:193
DTLS (Datagram Transport Layer Security)
void dtlsInitReplayWindow(TlsContext *context)
Initialize sliding window.
Definition: dtls_misc.c:449
error_t dtlsSelectVersion(TlsContext *context, uint16_t version)
Set the DTLS version to be used.
Definition: dtls_misc.c:54
error_t dtlsFormatHelloVerifyRequest(TlsContext *context, DtlsHelloVerifyRequest *message, size_t *length)
Format HelloVerifyRequest message.
Definition: dtls_misc.c:292
@ ERROR_WOULD_BLOCK
Definition: error.h:95
TLS handshake.
@ ERROR_VERSION_NOT_SUPPORTED
Definition: error.h:67
@ ERROR_UNEXPECTED_MESSAGE
Definition: error.h:193
uint8_t p
Definition: ndp.h:298
@ TLS_TRANSPORT_PROTOCOL_DATAGRAM
Definition: tls.h:898
#define DTLS_REPLAY_WINDOW_SIZE
Definition: dtls_misc.h:69
error_t dtlsCheckReplayWindow(TlsContext *context, DtlsSequenceNumber *seqNum)
Perform replay detection.
Definition: dtls_misc.c:470
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
@ ERROR_WRONG_COOKIE
Definition: error.h:91
uint8_t version
Definition: coap_common.h:175
error_t tlsSendHandshakeMessage(TlsContext *context, const void *data, size_t length, TlsMessageType type)
Send handshake message.
error_t dtlsParseClientSupportedVersionsExtension(TlsContext *context, const DtlsSupportedVersionList *supportedVersionList)
Parse SupportedVersions extension.
Definition: dtls_misc.c:402
#define DTLS_MAX_COOKIE_SIZE
Definition: dtls_misc.h:76
@ TLS_STATE_CLIENT_HELLO
Definition: tls.h:1361
__start_packed struct @1 DtlsCookie
Cookie.
@ TLS_STATE_SERVER_HELLO
Definition: tls.h:1366
@ TLS_STATE_HELLO_VERIFY_REQUEST
Definition: tls.h:1364
#define DTLS_VERSION_1_0
Definition: dtls_misc.h:35
#define osMemcpy(dest, src, length)
Definition: os_port.h:137
#define TlsContext
Definition: tls.h:36
error_t
Error codes.
Definition: error.h:43
uint32_t seqNum
Definition: tcp.h:339
__start_packed struct @5 DtlsHelloVerifyRequest
HelloVerifyRequest message.
#define TLS_VERSION_1_2
Definition: tls.h:98
Client parameters.
Definition: dtls_misc.h:219
#define TLS_VERSION_1_3
Definition: tls.h:99
Handshake message processing (TLS client and server)
#define TRACE_INFO(...)
Definition: debug.h:95
#define LOAD48BE(p)
Definition: cpu_endian.h:226
@ TLS_TYPE_HELLO_VERIFY_REQUEST
Definition: tls.h:983
uint16_t dtlsTranslateVersion(uint16_t version)
Translate TLS version into DTLS version.
Definition: dtls_misc.c:113
__start_packed struct @0 DtlsSequenceNumber
Sequence number.
void dtlsUpdateReplayWindow(TlsContext *context, DtlsSequenceNumber *seqNum)
Update sliding window.
Definition: dtls_misc.c:551
#define ntohs(value)
Definition: cpu_endian.h:421
@ ERROR_TIMEOUT
Definition: error.h:94
#define TLS_VERSION_1_1
Definition: tls.h:97
#define TRACE_DEBUG_ARRAY(p, a, n)
Definition: debug.h:108
#define HTONS(value)
Definition: cpu_endian.h:410
uint8_t n
#define DTLS_VERSION_1_3
Definition: dtls_misc.h:37
__start_packed struct @2 DtlsSupportedVersionList
List of supported versions.
uint8_t message[]
Definition: chap.h:152
TLS (Transport Layer Security)
uint8_t cookie[]
Definition: dtls_misc.h:204
error_t dtlsSendHelloVerifyRequest(TlsContext *context)
Send HelloVerifyRequest message.
Definition: dtls_misc.c:248
@ ERROR_DECODING_FAILED
Definition: error.h:239
#define PRIuSIZE
unsigned int uint_t
Definition: compiler_port.h:45
#define tlsFreeMem(p)
Definition: tls.h:811
error_t dtlsFormatCookie(TlsContext *context, uint8_t *p, size_t *written)
Format Cookie field.
Definition: dtls_misc.c:145
error_t dtlsParseHelloVerifyRequest(TlsContext *context, const DtlsHelloVerifyRequest *message, size_t length)
Parse HelloVerifyRequest message.
Definition: dtls_misc.c:330
#define DTLS_VERSION_1_2
Definition: dtls_misc.h:36
error_t dtlsVerifyCookie(TlsContext *context, const DtlsCookie *cookie, const DtlsClientParameters *clientParams)
Cookie verification.
Definition: dtls_misc.c:179
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
@ ERROR_INVALID_SEQUENCE_NUMBER
Definition: error.h:108
#define arraysize(a)
Definition: os_port.h:70