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-2026 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneSSL Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.6.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL TLS_TRACE_LEVEL
33 
34 //Dependencies
35 #include "tls.h"
36 #include "tls_handshake.h"
37 #include "tls_common.h"
38 #include "tls_misc.h"
39 #include "dtls_misc.h"
40 #include "debug.h"
41 
42 //Check TLS library configuration
43 #if (TLS_SUPPORT == ENABLED && DTLS_SUPPORT == ENABLED)
44 
45 
46 /**
47  * @brief Set the DTLS version to be used
48  * @param[in] context Pointer to the TLS context
49  * @param[in] version DTLS version
50  * @return Error code
51  **/
52 
54 {
55  error_t error;
56 
57  //Initialize status code
59 
60  //Check DTLS version
62  {
63  //DTLS 1.0 is defined as a series of deltas from TLS 1.1
64  if(context->versionMin <= TLS_VERSION_1_1 &&
65  context->versionMax >= TLS_VERSION_1_1)
66  {
67  //Save protocol version
68  context->version = TLS_VERSION_1_1;
69  //The specified DTLS version is acceptable
70  error = NO_ERROR;
71  }
72  }
73  else if(version == DTLS_VERSION_1_2)
74  {
75  //DTLS 1.2 is defined as a series of deltas from TLS 1.2
76  if(context->versionMin <= TLS_VERSION_1_2 &&
77  context->versionMax >= TLS_VERSION_1_2)
78  {
79  //Save protocol version
80  context->version = TLS_VERSION_1_2;
81  //The specified DTLS version is acceptable
82  error = NO_ERROR;
83  }
84  }
85  else if(version == DTLS_VERSION_1_3)
86  {
87  //DTLS 1.3 is defined as a series of deltas from TLS 1.3
88  if(context->versionMin <= TLS_VERSION_1_3 &&
89  context->versionMax >= TLS_VERSION_1_3)
90  {
91  //Save protocol version
92  context->version = TLS_VERSION_1_3;
93  //The specified DTLS version is acceptable
94  error = NO_ERROR;
95  }
96  }
97  else
98  {
99  //Unknown DTLS version
100  }
101 
102  //Check whether the DTLS version is supported
103  if(!error)
104  {
105  //Initial handshake?
106  if(context->encryptionEngine.epoch == 0)
107  {
108  //Save the negotiated version
109  context->encryptionEngine.version = context->version;
110  }
111  }
112 
113  //Return status code
114  return error;
115 }
116 
117 
118 /**
119  * @brief Translate TLS version into DTLS version
120  * @param[in] version TLS version
121  * @return DTLS version
122  **/
123 
124 uint16_t dtlsTranslateVersion(uint16_t version)
125 {
126  //Check current version
127  if(version == TLS_VERSION_1_2)
128  {
129  //DTLS 1.2 is defined as a series of deltas from TLS 1.2
131  }
132  else if(version == TLS_VERSION_1_3)
133  {
134  //DTLS 1.3 is defined as a series of deltas from TLS 1.3
136  }
137  else
138  {
139  //DTLS 1.0 is defined as a series of deltas from TLS 1.1
141  }
142 
143  //Return the version of the DTLS protocol
144  return version;
145 }
146 
147 
148 /**
149  * @brief Format Cookie field
150  * @param[in] context Pointer to the TLS context
151  * @param[in] p Output stream where to write the Cookie field
152  * @param[out] written Total number of bytes that have been written
153  * @return Error code
154  **/
155 
156 error_t dtlsFormatCookie(TlsContext *context, uint8_t *p, size_t *written)
157 {
159 
160  //Add Cookie field
161  cookie = (DtlsCookie *) p;
162 
163  //Updated ClientHello?
164  if(context->state == TLS_STATE_CLIENT_HELLO_2)
165  {
166  //The client must retransmit the ClientHello with the cookie added (refer
167  //to RFC 6347 section 4.2.1)
168  if(context->cookieLen > 0)
169  {
170  //Copy cookie
171  osMemcpy(cookie->value, context->cookie, context->cookieLen);
172  }
173 
174  //Set the length of the cookie
175  cookie->length = (uint8_t) context->cookieLen;
176  }
177  else
178  {
179  //When sending the first ClientHello, the client does not have a cookie
180  //yet. In this case, the Cookie field is left empty
181  cookie->length = 0;
182  }
183 
184  //Total number of bytes that have been written
185  *written = sizeof(DtlsCookie) + cookie->length;
186 
187  //Successful processing
188  return NO_ERROR;
189 }
190 
191 
192 /**
193  * @brief Cookie verification
194  * @param[in] context Pointer to the TLS context
195  * @param[in] cookie Pointer to the client's cookie
196  * @param[in] clientParams Client's parameters
197  * @return Error code
198  **/
199 
201  const DtlsClientParameters *clientParams)
202 {
203  error_t error;
204 
205  //Any registered callbacks?
206  if(context->cookieVerifyCallback != NULL &&
207  context->cookieGenerateCallback != NULL)
208  {
209  //Verify that the cookie is valid
210  error = context->cookieVerifyCallback(context, clientParams,
211  cookie->value, cookie->length, context->cookieParam);
212 
213  //Invalid cookie?
214  if(error == ERROR_WRONG_COOKIE)
215  {
216  //Set the cookie size limit (32 or 255 bytes depending on DTLS version)
217  context->cookieLen = DTLS_MAX_COOKIE_SIZE;
218 
219  //Allocate a memory block to hold the cookie
220  if(context->cookie == NULL)
221  {
222  context->cookie = tlsAllocMem(context->cookieLen);
223  }
224 
225  //Successful memory allocation?
226  if(context->cookie != NULL)
227  {
228  //The DTLS server should generate cookies in such a way that they can
229  //be verified without retaining any per-client state on the server
230  error = context->cookieGenerateCallback(context, clientParams,
231  context->cookie, &context->cookieLen, context->cookieParam);
232  }
233  else
234  {
235  //Failed to allocate memory
236  error = ERROR_OUT_OF_MEMORY;
237  }
238 
239  //Check status code
240  if(!error)
241  {
242  //Version of DTLS prior to DTLS 1.3?
243  if(context->version <= TLS_VERSION_1_2)
244  {
245  //DTLS 1.2 uses the HelloVerifyRequest message to pass a cookie
246  //to the client and does not utilize the extension mechanism
248  }
249  else
250  {
251  //The DTLS 1.3 specification changes how cookies are exchanged
252  //compared to DTLS 1.2. DTLS 1.3 reuses the HelloRetryRequest
253  //message and conveys the cookie to the client via an extension
255  }
256  }
257  }
258  }
259  else
260  {
261  //The server may be configured not to perform a cookie exchange
262  error = NO_ERROR;
263  }
264 
265  //Return status code
266  return error;
267 }
268 
269 
270 /**
271  * @brief Send HelloVerifyRequest message
272  *
273  * When the client sends its ClientHello message to the server, the server may
274  * respond with a HelloVerifyRequest message. This message contains a stateless
275  * cookie
276  *
277  * @param[in] context Pointer to the TLS context
278  * @return Error code
279  **/
280 
282 {
283  error_t error;
284  size_t length;
286 
287  //Point to the buffer where to format the message
288  message = (DtlsHelloVerifyRequest *) (context->txBuffer + context->txBufferLen);
289 
290  //Format HelloVerifyRequest message
291  error = dtlsFormatHelloVerifyRequest(context, message, &length);
292 
293  //Check status code
294  if(!error)
295  {
296  //Debug message
297  TRACE_INFO("Sending HelloVerifyRequest message (%" PRIuSIZE " bytes)...\r\n", length);
299 
300  //Send handshake message
301  error = tlsSendHandshakeMessage(context, message, length,
303  }
304 
305  //Check status code
306  if(error == NO_ERROR || error == ERROR_WOULD_BLOCK || error == ERROR_TIMEOUT)
307  {
308  //The client must retransmit the ClientHello with the cookie added
310  }
311 
312  //Return status code
313  return error;
314 }
315 
316 
317 /**
318  * @brief Format HelloVerifyRequest message
319  * @param[in] context Pointer to the TLS context
320  * @param[out] message Buffer where to format the HelloVerifyRequest message
321  * @param[out] length Length of the resulting HelloVerifyRequest message
322  * @return Error code
323  **/
324 
327 {
328  //In order to avoid the requirement to do version negotiation in the initial
329  //handshake, DTLS 1.2 server implementations should use DTLS version 1.0
330  //regardless of the version of TLS that is expected to be negotiated
331  message->serverVersion = HTONS(DTLS_VERSION_1_0);
332 
333  //Valid cookie?
334  if(context->cookieLen > 0)
335  {
336  //Copy cookie
337  osMemcpy(message->cookie, context->cookie, context->cookieLen);
338  }
339 
340  //Set the length of the cookie
341  message->cookieLength = (uint8_t) context->cookieLen;
342 
343  //Length of the handshake message
344  *length = sizeof(DtlsHelloVerifyRequest) + context->cookieLen;
345 
346  //Successful processing
347  return NO_ERROR;
348 }
349 
350 
351 /**
352  * @brief Parse HelloVerifyRequest message
353  *
354  * When the client sends its ClientHello message to the server,
355  * the server may respond with a HelloVerifyRequest message
356  *
357  * @param[in] context Pointer to the TLS context
358  * @param[in] message Incoming HelloVerifyRequest message to parse
359  * @param[in] length Message length
360  * @return Error code
361  **/
362 
364  const DtlsHelloVerifyRequest *message, size_t length)
365 {
366  //Debug message
367  TRACE_INFO("HelloVerifyRequest message received (%" PRIuSIZE " bytes)...\r\n", length);
369 
370  //DTLS protocol?
371  if(context->transportProtocol == TLS_TRANSPORT_PROTOCOL_DATAGRAM)
372  {
373  //Check the length of the HelloVerifyRequest message
374  if(length < sizeof(DtlsHelloVerifyRequest))
375  return ERROR_DECODING_FAILED;
376 
377  //Clients may receive multiple HelloVerifyRequest messages with different
378  //cookies (refer to RFC 6347, section 4.2.1)
379  if(context->state != TLS_STATE_SERVER_HELLO &&
380  context->state != TLS_STATE_SERVER_HELLO_2)
381  {
383  }
384 
385  //Remaining bytes to process
386  length -= sizeof(DtlsHelloVerifyRequest);
387 
388  //If the amount of data in the message does not precisely match the format
389  //of the HelloVerifyRequest message, then send a fatal alert
390  if(message->cookieLength != length)
391  return ERROR_DECODING_FAILED;
392 
393  //Sanity check
394  if(context->cookie != NULL)
395  {
396  //Release memory
397  tlsFreeMem(context->cookie);
398  context->cookie = NULL;
399  context->cookieLen = 0;
400  }
401 
402  //Valid cookie received?
403  if(message->cookieLength > 0)
404  {
405  //Allocate a memory block to store the cookie
406  context->cookie = tlsAllocMem(message->cookieLength);
407  //Failed to allocate memory?
408  if(context->cookie == NULL)
409  return ERROR_OUT_OF_MEMORY;
410 
411  //Save cookie
412  osMemcpy(context->cookie, message->cookie, message->cookieLength);
413  }
414 
415  //Save the length of the cookie
416  context->cookieLen = message->cookieLength;
417 
418  //The client sends a second ClientHello message
420 
421  //Successful processing
422  return NO_ERROR;
423  }
424  else
425  {
426  //Report an error
428  }
429 }
430 
431 
432 /**
433  * @brief Parse SupportedVersions extension
434  * @param[in] context Pointer to the TLS context
435  * @param[in] supportedVersionList Pointer to the SupportedVersions extension
436  * @return Error code
437  **/
438 
440  const DtlsSupportedVersionList *supportedVersionList)
441 {
442  error_t error;
443  uint_t i;
444  uint_t j;
445  uint_t n;
446 
447  //Supported DTLS versions
448  const uint16_t supportedVersions[] =
449  {
453  };
454 
455  //Initialize status code
457 
458  //Retrieve the number of items in the list
459  n = supportedVersionList->length / sizeof(uint16_t);
460 
461  //Loop through the list of DTLS versions supported by the server
462  for(i = 0; i < arraysize(supportedVersions) && error; i++)
463  {
464  //The extension contains a list of DTLS versions supported by the client
465  for(j = 0; j < n && error; j++)
466  {
467  //Servers must only select a version of DTLS present in that extension
468  //and must ignore any unknown versions
469  if(ntohs(supportedVersionList->value[j]) == supportedVersions[i])
470  {
471  //Set the DTLS version to be used
472  error = dtlsSelectVersion(context, supportedVersions[i]);
473  }
474  }
475  }
476 
477  //Return status code
478  return error;
479 }
480 
481 
482 /**
483  * @brief Initialize sliding window
484  * @param[in] context Pointer to the TLS context
485  **/
486 
488 {
489 #if (DTLS_REPLAY_DETECTION_SUPPORT == ENABLED)
490  uint_t i;
491 
492  //Clear the bitmap window
493  for(i = 0; i < (DTLS_REPLAY_WINDOW_SIZE + 31) / 32; i++)
494  {
495  context->replayWindow[i] = 0;
496  }
497 #endif
498 }
499 
500 
501 /**
502  * @brief Perform replay detection
503  * @param[in] context Pointer to the TLS context
504  * @param[in] seqNum Sequence number of the received DTLS record
505  * @return Error code
506  **/
507 
509 {
510  error_t error;
511 
512 #if (DTLS_REPLAY_DETECTION_SUPPORT == ENABLED)
513  //Check whether anti-replay mechanism is enabled
514  if(context->replayDetectionEnabled)
515  {
516  uint_t j;
517  uint_t k;
518  uint64_t n;
519  uint64_t right;
520 
521  //Get the sequence number of the received DTLS record
522  n = LOAD48BE(seqNum);
523 
524  //The right edge of the window represents the highest validated sequence
525  //number value received on this session
526  right = LOAD48BE(&context->decryptionEngine.dtlsSeqNum);
527 
528  //Check sequence number
529  if(n <= right)
530  {
531  //Calculate the position relative to the right edge of the window
532  n = right - n;
533 
534  //Check whether the sequence number falls within the window
536  {
537  //Records falling within the window are checked against a list of
538  //received packets within the window
539  j = (uint_t) (n / 32);
540  k = (uint_t) (n % 32);
541 
542  //Duplicate record are rejected through the use of a sliding
543  //receive window
544  if(context->replayWindow[j] & (1U << k))
545  {
546  //The received record is a duplicate
548  }
549  else
550  {
551  //If the received record falls within the window and is new,
552  //then the receiver proceeds to MAC verification
553  error = NO_ERROR;
554  }
555 
556  }
557  else
558  {
559  //Records that contain sequence numbers lower than the left edge
560  //of the window are rejected
562  }
563  }
564  else
565  {
566  //If the packet is to the right of the window, then the receiver
567  //proceeds to MAC verification
568  error = NO_ERROR;
569  }
570  }
571  else
572 #endif
573  {
574  //Anti-replay mechanism is disabled
575  error = NO_ERROR;
576  }
577 
578  //Return status code
579  return error;
580 }
581 
582 
583 /**
584  * @brief Update sliding window
585  * @param[in] context Pointer to the TLS context
586  * @param[in] seqNum Sequence number of the received DTLS record
587  **/
588 
590 {
591  uint64_t n;
592  uint64_t right;
593 
594  //Get the sequence number of the received DTLS record
595  n = LOAD48BE(seqNum);
596 
597  //The right edge of the window represents the highest validated sequence
598  //number value received on this session
599  right = LOAD48BE(&context->decryptionEngine.dtlsSeqNum);
600 
601  //Check sequence number
602  if(n <= right)
603  {
604 #if (DTLS_REPLAY_DETECTION_SUPPORT == ENABLED)
605  uint_t j;
606  uint_t k;
607 
608  //Calculate the position relative to the right edge of the window
609  n = right - n;
610 
611  //Check whether the sequence number falls within the window
613  {
614  j = (uint_t) (n / 32);
615  k = (uint_t) (n % 32);
616 
617  //Set the corresponding bit in the bitmap window
618  context->replayWindow[j] |= 1U << k;
619  }
620 #endif
621  }
622  else
623  {
624 #if (DTLS_REPLAY_DETECTION_SUPPORT == ENABLED)
625  uint_t i;
626  uint_t j;
627  uint_t k;
628 
629  //Calculate the position relative to the right edge of the window
630  n -= right;
631 
632  //Check resulting value
634  {
635  j = (uint_t) (n / 32);
636  k = (uint_t) (n % 32);
637 
638  //First, shift words
639  if(j > 0)
640  {
641  //Shift the most significant words of the window
642  for(i = (DTLS_REPLAY_WINDOW_SIZE - 1) / 32; i >= j; i--)
643  {
644  context->replayWindow[i] = context->replayWindow[i - j];
645  }
646 
647  //Fill the least significant words with zeroes
648  for(i = 0; i < j; i++)
649  {
650  context->replayWindow[i] = 0;
651  }
652  }
653 
654  //Then shift bits
655  if(k > 0)
656  {
657  //Shift the most significant words of the window
658  for(i = (DTLS_REPLAY_WINDOW_SIZE - 1) / 32; i >= 1; i--)
659  {
660  context->replayWindow[i] = (context->replayWindow[i] << k) |
661  (context->replayWindow[i - 1] >> (32 - k));
662  }
663 
664  //Shift the least significant word
665  context->replayWindow[0] <<= k;
666  }
667  }
668  else
669  {
670  //Clear the bitmap window
671  for(i = 0; i < (DTLS_REPLAY_WINDOW_SIZE + 31) / 32; i++)
672  {
673  context->replayWindow[i] = 0;
674  }
675  }
676 
677  //Set the corresponding bit in the bitmap window
678  context->replayWindow[0] |= 1;
679 #endif
680 
681  //Save the highest sequence number value received on this session
682  context->decryptionEngine.dtlsSeqNum = *seqNum;
683  }
684 }
685 
686 #endif
#define tlsAllocMem(size)
Definition: tls.h:888
DTLS (Datagram Transport Layer Security)
TLS helper functions.
@ TLS_STATE_HELLO_RETRY_REQUEST
Definition: tls.h:1547
void dtlsInitReplayWindow(TlsContext *context)
Initialize sliding window.
Definition: dtls_misc.c:487
error_t dtlsSelectVersion(TlsContext *context, uint16_t version)
Set the DTLS version to be used.
Definition: dtls_misc.c:53
error_t dtlsFormatHelloVerifyRequest(TlsContext *context, DtlsHelloVerifyRequest *message, size_t *length)
Format HelloVerifyRequest message.
Definition: dtls_misc.c:325
@ ERROR_WOULD_BLOCK
Definition: error.h:96
TLS handshake.
@ ERROR_VERSION_NOT_SUPPORTED
Definition: error.h:67
@ ERROR_UNEXPECTED_MESSAGE
Definition: error.h:195
uint8_t p
Definition: ndp.h:300
uint8_t message[]
Definition: chap.h:154
@ TLS_TRANSPORT_PROTOCOL_DATAGRAM
Definition: tls.h:1000
#define DTLS_REPLAY_WINDOW_SIZE
Definition: dtls_misc.h:69
error_t dtlsCheckReplayWindow(TlsContext *context, DtlsSequenceNumber *seqNum)
Perform replay detection.
Definition: dtls_misc.c:508
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
@ ERROR_WRONG_COOKIE
Definition: error.h:92
uint8_t version
Definition: coap_common.h:177
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:439
#define DTLS_MAX_COOKIE_SIZE
Definition: dtls_misc.h:76
@ TLS_STATE_CLIENT_HELLO
Definition: tls.h:1542
@ TLS_STATE_SERVER_HELLO
Definition: tls.h:1548
@ TLS_STATE_HELLO_VERIFY_REQUEST
Definition: tls.h:1546
#define DTLS_VERSION_1_0
Definition: dtls_misc.h:35
#define osMemcpy(dest, src, length)
Definition: os_port.h:144
#define TlsContext
Definition: tls.h:36
error_t
Error codes.
Definition: error.h:43
uint32_t seqNum
Definition: tcp.h:348
#define TLS_VERSION_1_2
Definition: tls.h:96
Client parameters.
Definition: dtls_misc.h:223
#define TLS_VERSION_1_3
Definition: tls.h:97
Handshake message processing (TLS client and server)
#define TRACE_INFO(...)
Definition: debug.h:105
uint8_t length
Definition: tcp.h:375
#define LOAD48BE(p)
Definition: cpu_endian.h:226
@ TLS_TYPE_HELLO_VERIFY_REQUEST
Definition: tls.h:1087
uint16_t dtlsTranslateVersion(uint16_t version)
Translate TLS version into DTLS version.
Definition: dtls_misc.c:124
void dtlsUpdateReplayWindow(TlsContext *context, DtlsSequenceNumber *seqNum)
Update sliding window.
Definition: dtls_misc.c:589
#define ntohs(value)
Definition: cpu_endian.h:421
@ ERROR_TIMEOUT
Definition: error.h:95
#define TLS_VERSION_1_1
Definition: tls.h:95
@ TLS_STATE_CLIENT_HELLO_2
Definition: tls.h:1543
#define TRACE_DEBUG_ARRAY(p, a, n)
Definition: debug.h:120
#define HTONS(value)
Definition: cpu_endian.h:410
uint8_t n
#define DTLS_VERSION_1_3
Definition: dtls_misc.h:37
DtlsSequenceNumber
Definition: dtls_misc.h:143
TLS (Transport Layer Security)
uint8_t cookie[]
Definition: dtls_misc.h:206
error_t dtlsSendHelloVerifyRequest(TlsContext *context)
Send HelloVerifyRequest message.
Definition: dtls_misc.c:281
DtlsSupportedVersionList
Definition: dtls_misc.h:165
void tlsChangeState(TlsContext *context, TlsState newState)
Update TLS state.
Definition: tls_misc.c:54
@ ERROR_DECODING_FAILED
Definition: error.h:242
#define PRIuSIZE
unsigned int uint_t
Definition: compiler_port.h:57
#define tlsFreeMem(p)
Definition: tls.h:893
@ TLS_STATE_SERVER_HELLO_2
Definition: tls.h:1549
DtlsCookie
Definition: dtls_misc.h:154
error_t dtlsFormatCookie(TlsContext *context, uint8_t *p, size_t *written)
Format Cookie field.
Definition: dtls_misc.c:156
DtlsHelloVerifyRequest
Definition: dtls_misc.h:207
error_t dtlsParseHelloVerifyRequest(TlsContext *context, const DtlsHelloVerifyRequest *message, size_t length)
Parse HelloVerifyRequest message.
Definition: dtls_misc.c:363
#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:200
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
@ ERROR_INVALID_SEQUENCE_NUMBER
Definition: error.h:109
#define arraysize(a)
Definition: os_port.h:71