dtls13_misc.c
Go to the documentation of this file.
1 /**
2  * @file dtls13_misc.c
3  * @brief DTLS 1.3 (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.2
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL TLS_TRACE_LEVEL
33 
34 //Dependencies
35 #include "tls/tls.h"
36 #include "tls/tls_misc.h"
37 #include "dtls/dtls_record.h"
38 #include "dtls13/dtls13_misc.h"
39 #include "debug.h"
40 
41 //Check TLS library configuration
42 #if (TLS_SUPPORT == ENABLED && DTLS_SUPPORT == ENABLED && \
43  TLS_MAX_VERSION >= TLS_VERSION_1_3)
44 
45 
46 /**
47  * @brief Update the list of record numbers
48  * @param[in] context Pointer to the TLS context
49  * @param[in] epoch Epoch number of the received DTLS record
50  * @param[in] seqNum Sequence number of the received DTLS record
51  **/
52 
53 void dtls13SaveRecordNumber(TlsContext *context, uint64_t epoch,
54  uint64_t seqNum)
55 {
56  uint_t i;
57 
58  //Discard duplicate record numbers
59  for(i = 0; i < context->numAckRecords; i++)
60  {
61  if(context->ackRecords[i].epoch == epoch &&
62  context->ackRecords[i].seqNum == seqNum)
63  {
64  return;
65  }
66  }
67 
68  //If space is limited, implementations should favor including records which
69  //have not yet been acknowledged (refer to RFC 9147, section 7.1)
70  if(context->numAckRecords < DTLS13_MAX_ACK_RECORDS)
71  {
72  //Append the record number to the end of the list
73  i = context->numAckRecords;
74  context->ackRecords[i].epoch = epoch;
75  context->ackRecords[i].seqNum = seqNum;
76 
77  //Update the length of the list
78  context->numAckRecords++;
79  }
80  else
81  {
82  //Make room for the new record number
83  for(i = 1; i < context->numAckRecords; i++)
84  {
85  context->ackRecords[i - 1] = context->ackRecords[i];
86  }
87 
88  //Append the record number to the end of the list
89  i = context->numAckRecords - 1;
90  context->ackRecords[i].epoch = epoch;
91  context->ackRecords[i].seqNum = seqNum;
92  }
93 
94  //DTLS 1.3 currently selected?
95  if(context->version == TLS_VERSION_1_3)
96  {
97  //Start the ACK timer when the first record in the flight is received
98  if(!context->ackTimerRunning)
99  {
100  context->ackTimestamp = osGetSystemTime();
101  context->ackTimerRunning = TRUE;
102  }
103  }
104 }
105 
106 
107 /**
108  * @brief Send ACK message
109  *
110  * The ACK message is used by an endpoint to indicate which handshake records
111  * it has received and processed from the other side
112  *
113  * @param[in] context Pointer to the TLS context
114  * @return Error code
115  **/
116 
118 {
119  error_t error;
120  size_t length;
122 
123  //Point to the buffer where to format the message
124  message = (Dtls13Ack *) (context->txBuffer + context->txBufferLen);
125 
126  //Format ACK message
127  error = dtls13FormatAck(context, message, &length);
128 
129  //Check status code
130  if(!error)
131  {
132  //Debug message
133  TRACE_INFO("Sending ACK message (%" PRIuSIZE " bytes)...\r\n", length);
135 
136  //ACK is not a handshake message but is rather a separate content type,
137  //with code point 26 (refer to RFC 9147, section 7)
138  error = dtlsWriteProtocolData(context, (uint8_t *) message, length,
139  TLS_TYPE_ACK);
140  }
141 
142  //Check status code
143  if(error == NO_ERROR || error == ERROR_WOULD_BLOCK || error == ERROR_TIMEOUT)
144  {
145  //For post-handshake messages, ACKs should be sent once for each received
146  //and processed handshake record (refer to RFC 9147, section 7)
147  if(context->state == TLS_STATE_APPLICATION_DATA ||
148  context->state == TLS_STATE_CLIENT_FINISHED_ACK ||
149  context->state == TLS_STATE_NEW_SESSION_TICKET_ACK ||
150  context->state == TLS_STATE_KEY_UPDATE_ACK)
151  {
152  context->numAckRecords = 0;
153  }
154 
155  //Check whether the ACK message was for the client's final flight
156  if(context->entity == TLS_CONNECTION_END_SERVER &&
157  context->state == TLS_STATE_FINAL_ACK)
158  {
159 #if (TLS_TICKET_SUPPORT == ENABLED)
160  //Check whether session ticket mechanism is enabled
161  if(context->ticketEncryptCallback != NULL &&
162  context->pskKeModeSupported)
163  {
164  //At any time after the server has received the client Finished
165  //message, it may send a NewSessionTicket message
167  }
168  else
169 #endif
170  {
171  //The client and server can now exchange application-layer data
173  }
174  }
175  }
176 
177  //Return status code
178  return error;
179 }
180 
181 
182 /**
183  * @brief Format ACK message
184  * @param[in] context Pointer to the TLS context
185  * @param[out] message Buffer where to format the ACK message
186  * @param[out] length Length of the resulting ACK message
187  * @return Error code
188  **/
189 
191  size_t *length)
192 {
193  uint_t i;
194  uint_t j;
195  size_t n;
198 
199  //Point to the record_numbers field
200  p = message->recordNumbers;
201 
202  //Record numbers are formed by combining the epoch and sequence numbers
203  for(i = 0; i < context->numAckRecords; i++)
204  {
205  p[i].epoch = context->ackRecords[i].epoch;
206  p[i].seqNum = context->ackRecords[i].seqNum;
207  }
208 
209  //The record_numbers field is a list of the records containing handshake
210  //messages in the current flight which the endpoint has received and
211  //either processed or buffered, in numerically increasing order (refer to
212  //RFC 9147, section 7)
213  for(i = 0; i < context->numAckRecords; i++)
214  {
215  for(j = i + 1; j < context->numAckRecords; j++)
216  {
217  //Compare record numbers
218  if((p[i].epoch == p[j].epoch && p[i].seqNum > p[j].seqNum) ||
219  p[i].epoch > p[j].epoch)
220  {
221  //Swap record numbers
222  t = p[i];
223  p[i] = p[j];
224  p[j] = t;
225  }
226  }
227  }
228 
229  //Convert epoch and sequence numbers to network byte order
230  for(i = 0; i < context->numAckRecords; i++)
231  {
232  p[i].epoch = htonll(p[i].epoch);
233  p[i].seqNum = htonll(p[i].seqNum);
234  }
235 
236  //Compute the length of the list
237  n = context->numAckRecords * sizeof(Dtls13RecordNumber);
238  //Set the length of the record_numbers field
239  message->length = htons(n);
240 
241  //Length of the ACK message
242  *length = sizeof(Dtls13Ack) + n;
243 
244  //Successful processing
245  return NO_ERROR;
246 }
247 
248 
249 /**
250  * @brief Parse ACK message
251  * @param[in] context Pointer to the TLS context
252  * @param[in] message Incoming ACK message to parse
253  * @param[in] length Message length
254  * @return Error code
255  **/
256 
258  size_t length)
259 {
260  uint_t i;
261  uint_t j;
262  uint64_t epoch;
263  uint64_t seqNum;
264  uint_t index;
265  uint_t numRecords;
266  Dtls13RetransmitState *state;
267 
268  //Debug message
269  TRACE_INFO("ACK message received (%" PRIuSIZE " bytes)...\r\n", length);
271 
272  //Check transport protocol
273  if(context->transportProtocol != TLS_TRANSPORT_PROTOCOL_DATAGRAM)
275 
276  //Check TLS version
277  if(context->version != TLS_VERSION_1_3)
278  {
279  //The client must tolerate ACKs in response to its initial ClientHello
280  if(context->versionMax >= TLS_VERSION_1_3 &&
281  context->entity == TLS_CONNECTION_END_CLIENT &&
282  context->state == TLS_STATE_SERVER_HELLO)
283  {
284  //Drop the ACK message
285  return NO_ERROR;
286  }
287  else
288  {
289  //Report an error
291  }
292  }
293 
294  //Check message length
295  if(length < sizeof(Dtls13Ack))
296  return ERROR_INVALID_LENGTH;
297 
298  //Malformed ACK message?
299  if(((length - sizeof(Dtls13Ack)) % sizeof(Dtls13RecordNumber)) != 0)
300  return ERROR_INVALID_LENGTH;
301 
302  //Dtermine the number of records in the list
303  numRecords = (length - sizeof(Dtls13Ack)) / sizeof(Dtls13RecordNumber);
304 
305  //The ACK message is used by an endpoint to indicate which handshake records
306  //it has received and processed from the other side
307  for(i = 0; i < numRecords; i++)
308  {
309  //A record number combines an epoch and a sequence number
310  epoch = ntohll(message->recordNumbers[i].epoch);
311  seqNum = ntohll(message->recordNumbers[i].seqNum);
312 
313  //Loop through the encryption engines
314  for(state = NULL, j = 0; j < TLS_MAX_ENCRYPTION_ENGINES; j++)
315  {
316  //Compare epochs
317  if(context->encryptionEngine[j].epoch == epoch)
318  {
319  state = &context->encryptionEngine[j].retransmitState;
320  break;
321  }
322  }
323 
324  //Matching epoch?
325  if(state != NULL)
326  {
327  //Implementations must treat a record as having been acknowledged if
328  //it appears in any ACK (refer to RFC9147, section 7.2)
329  if(seqNum >= state->start && state->count > 0 && state->count <= 32)
330  {
331  if(context->state == TLS_STATE_CLIENT_FINISHED_ACK ||
332  context->state == TLS_STATE_NEW_SESSION_TICKET_ACK ||
333  context->state == TLS_STATE_KEY_UPDATE_ACK)
334  {
335  if(seqNum < (state->start + state->count))
336  {
337  index = (uint_t) (seqNum - state->start);
338  state->mask &= ~(1 << index);
339  }
340  }
341  else
342  {
343  index = (seqNum - state->start) % state->count;
344  state->mask &= ~(1 << index);
345  }
346  }
347  }
348  }
349 
350  //Check whether all the messages have been acknowledged
351  if(context->encryptionEngine[0].retransmitState.mask == 0 &&
352  context->encryptionEngine[1].retransmitState.mask == 0 &&
353  context->encryptionEngine[2].retransmitState.mask == 0)
354  {
355  //Once all the messages in a flight have been acknowledged, the
356  //implementation must cancel all retransmissions of that flight
357  context->txBufferLen = 0;
358 
359  //Check current state
360  if(context->state == TLS_STATE_CLIENT_FINISHED_ACK ||
361  context->state == TLS_STATE_NEW_SESSION_TICKET_ACK ||
362  context->state == TLS_STATE_KEY_UPDATE_ACK)
363  {
364  context->state = TLS_STATE_APPLICATION_DATA;
365  }
366  }
367 
368  //Successful processing
369  return NO_ERROR;
370 }
371 
372 
373 /**
374  * @brief Format nonce
375  * @param[in] encryptionEngine Pointer to the encryption engine
376  * @param[in] seqNum Pointer to the sequence number
377  * @param[out] nonce Pointer to the buffer where to store the resulting nonce
378  * @param[out] nonceLen Length of the nonce, in bytes
379  **/
380 
381 void dtls13FormatNonce(TlsEncryptionEngine *encryptionEngine,
382  const DtlsSequenceNumber *seqNum, uint8_t *nonce, size_t *nonceLen)
383 {
384  size_t i;
385  size_t n;
386 
387  //Calculate the total length of the nonce
388  n = encryptionEngine->fixedIvLen;
389 
390  //In DTLS 1.3 the 64-bit sequence_number is used as the sequence number for
391  //the AEAD computation; unlike DTLS 1.2, the epoch is not included (refer to
392  //RFC 9147, section 4)
393  osMemset(nonce + n - 8, 0, 2);
394  osMemcpy(nonce + n - 6, seqNum->b, 6);
395 
396  //The 64-bit record sequence number is padded on the left by zeros
397  osMemset(nonce, 0, n - 8);
398 
399  //The padded sequence number is XORed with the IV to form the nonce
400  for(i = 0; i < n; i++)
401  {
402  nonce[i] ^= encryptionEngine->iv[i];
403  }
404 
405  //Return the total length of the nonce
406  *nonceLen = n;
407 }
408 
409 
410 /**
411  * @brief Compute overhead caused by encryption
412  * @param[in] encryptionEngine Pointer to the encryption engine
413  * @return Overhead, in bytes, caused by encryption
414  **/
415 
417 {
418  size_t n;
419 
420  //Initialize variable
421  n = 6;
422 
423  //Check cipher mode of operation
424  //Message authentication?
425  if(encryptionEngine->cipherMode == CIPHER_MODE_CCM ||
426  encryptionEngine->cipherMode == CIPHER_MODE_GCM ||
427  encryptionEngine->cipherMode == CIPHER_MODE_CHACHA20_POLY1305)
428  {
429  n += encryptionEngine->authTagLen;
430  }
431  else if(encryptionEngine->cipherMode == CIPHER_MODE_NULL)
432  {
433  n += encryptionEngine->hashAlgo->digestSize;
434  }
435 
436  //Return the total overhead caused by encryption
437  return n;
438 }
439 
440 #endif
Dtls13Ack
Definition: dtls13_misc.h:84
#define htons(value)
Definition: cpu_endian.h:413
TLS helper functions.
#define ntohll(value)
Definition: cpu_endian.h:423
@ ERROR_WOULD_BLOCK
Definition: error.h:96
@ ERROR_UNEXPECTED_MESSAGE
Definition: error.h:195
uint8_t p
Definition: ndp.h:300
@ CIPHER_MODE_GCM
Definition: crypto.h:1068
uint8_t message[]
Definition: chap.h:154
uint8_t t
Definition: lldp_ext_med.h:212
#define TRUE
Definition: os_port.h:50
@ TLS_TRANSPORT_PROTOCOL_DATAGRAM
Definition: tls.h:1017
@ TLS_STATE_APPLICATION_DATA
Definition: tls.h:1589
@ TLS_TYPE_ACK
Definition: tls.h:1091
Dtls13RecordNumber
Definition: dtls13_misc.h:73
#define DTLS13_MAX_ACK_RECORDS
Definition: dtls13_misc.h:39
Retransmission state.
Definition: dtls13_misc.h:100
@ TLS_STATE_SERVER_HELLO
Definition: tls.h:1564
#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
DTLS record layer.
@ TLS_CONNECTION_END_SERVER
Definition: tls.h:1030
DTLS 1.3 (Datagram Transport Layer Security)
#define TLS_VERSION_1_3
Definition: tls.h:98
@ ERROR_INVALID_LENGTH
Definition: error.h:111
#define htonll(value)
Definition: cpu_endian.h:415
uint16_t epoch
Definition: dtls_misc.h:181
error_t dtls13FormatAck(TlsContext *context, Dtls13Ack *message, size_t *length)
Format ACK message.
Definition: dtls13_misc.c:190
error_t dtlsWriteProtocolData(TlsContext *context, const uint8_t *data, size_t length, TlsContentType contentType)
Write protocol data.
Definition: dtls_record.c:62
#define TRACE_INFO(...)
Definition: debug.h:105
uint8_t length
Definition: tcp.h:375
void dtls13FormatNonce(TlsEncryptionEngine *encryptionEngine, const DtlsSequenceNumber *seqNum, uint8_t *nonce, size_t *nonceLen)
Format nonce.
Definition: dtls13_misc.c:381
@ TLS_STATE_NEW_SESSION_TICKET_2
Definition: tls.h:1582
@ ERROR_TIMEOUT
Definition: error.h:95
error_t dtls13ParseAck(TlsContext *context, const Dtls13Ack *message, size_t length)
Parse ACK message.
Definition: dtls13_misc.c:257
@ CIPHER_MODE_CCM
Definition: crypto.h:1067
#define TRACE_DEBUG_ARRAY(p, a, n)
Definition: debug.h:120
uint8_t n
@ TLS_STATE_CLIENT_FINISHED_ACK
Definition: tls.h:1590
@ TLS_CONNECTION_END_CLIENT
Definition: tls.h:1029
DtlsSequenceNumber
Definition: dtls_misc.h:148
TLS (Transport Layer Security)
size_t dtls13ComputeEncryptionOverhead(TlsEncryptionEngine *encryptionEngine)
Compute overhead caused by encryption.
Definition: dtls13_misc.c:416
@ TLS_STATE_FINAL_ACK
Definition: tls.h:1588
error_t dtls13SendAck(TlsContext *context)
Send ACK message.
Definition: dtls13_misc.c:117
@ CIPHER_MODE_NULL
Definition: crypto.h:1060
@ CIPHER_MODE_CHACHA20_POLY1305
Definition: crypto.h:1070
void tlsChangeState(TlsContext *context, TlsState newState)
Update TLS state.
Definition: tls_misc.c:54
#define PRIuSIZE
unsigned int uint_t
Definition: compiler_port.h:57
#define osMemset(p, value, length)
Definition: os_port.h:138
@ TLS_STATE_KEY_UPDATE_ACK
Definition: tls.h:1593
#define TLS_MAX_ENCRYPTION_ENGINES
Definition: tls.h:972
void dtls13SaveRecordNumber(TlsContext *context, uint64_t epoch, uint64_t seqNum)
Update the list of record numbers.
Definition: dtls13_misc.c:53
#define TlsEncryptionEngine
Definition: tls.h:40
uint8_t nonce[]
Definition: ntp_common.h:239
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
@ TLS_STATE_NEW_SESSION_TICKET_ACK
Definition: tls.h:1591
systime_t osGetSystemTime(void)
Retrieve system time.