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