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