tls13_server_misc.c
Go to the documentation of this file.
1 /**
2  * @file tls13_server_misc.c
3  * @brief Helper functions for TLS 1.3 server
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 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.4.4
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_server_misc.h"
37 #include "tls_transcript_hash.h"
38 #include "tls_ffdhe.h"
39 #include "tls_misc.h"
41 #include "tls13_server_misc.h"
42 #include "debug.h"
43 
44 //Check TLS library configuration
45 #if (TLS_SUPPORT == ENABLED && TLS_SERVER_SUPPORT == ENABLED && \
46  TLS_MAX_VERSION >= TLS_VERSION_1_3)
47 
48 
49 /**
50  * @brief Cipher suite and key exchange method negotiation
51  * @param[in] context Pointer to the TLS context
52  * @param[in] clientHello Pointer to the ClientHello message
53  * @param[in] clientHelloLen Length of the ClientHello message
54  * @param[in] cipherSuites List of cipher suites offered by the client
55  * @param[in] extensions ClientHello extensions offered by the client
56  * @return Error code
57  **/
58 
59 error_t tls13NegotiateCipherSuite(TlsContext *context, const void *clientHello,
60  size_t clientHelloLen, const TlsCipherSuites *cipherSuites,
62 {
63  error_t error;
64 
65  //In TLS 1.3, the cipher suite concept has been changed. The key exchange
66  //mechanism is negotiated separately from the cipher suite
67  context->keyExchMethod = TLS_KEY_EXCH_NONE;
68 
69  //The PreSharedKey extension is used to negotiate the identity of the
70  //pre-shared key to be used with a given handshake in association with
71  //PSK key establishment
72  error = tls13ParseClientPreSharedKeyExtension(context, clientHello,
73  clientHelloLen, extensions->identityList, extensions->binderList);
74  //Any error to report?
75  if(error)
76  return error;
77 
78  //Externally established PSKs should influence cipher suite selection
79  if(context->selectedIdentity >= 0)
80  {
81  //Select a cipher suite indicating a hash associated with the PSK
82  error = tlsNegotiateCipherSuite(context, context->cipherSuite.prfHashAlgo,
83  cipherSuites, extensions);
84 
85  //The server must ensure that it selects a compatible PSK and cipher suite
86  if(!error)
87  {
88  //Perform PSK handshake
89  context->keyExchMethod = TLS13_KEY_EXCH_PSK;
90  }
91  else
92  {
93  //Perform a non-PSK handshake if possible
94  context->keyExchMethod = TLS_KEY_EXCH_NONE;
95  context->selectedIdentity = -1;
96  }
97  }
98 
99  //Check key exchange method
100  if(context->keyExchMethod == TLS_KEY_EXCH_NONE)
101  {
102  //Perform cipher suite negotiation
103  error = tlsNegotiateCipherSuite(context, NULL, cipherSuites, extensions);
104  //If no acceptable choices are presented, terminate the handshake
105  if(error)
106  return ERROR_HANDSHAKE_FAILED;
107  }
108 
109  //If the handshake includes a HelloRetryRequest, the initial ClientHello
110  //and HelloRetryRequest are included in the transcript along with the new
111  //ClientHello
112  if(context->state != TLS_STATE_CLIENT_HELLO_2)
113  {
114  //Initialize handshake message hashing
115  error = tlsInitTranscriptHash(context);
116  //Any error to report?
117  if(error)
118  return error;
119  }
120 
121  //If the client opts to send 0-RTT data, it must supply an EarlyData
122  //extension in its ClientHello
123  error = tls13ParseClientEarlyDataExtension(context,
124  extensions->earlyDataIndication);
125  //Any error to report?
126  if(error)
127  return error;
128 
129  //The KeyShare extension contains the client's cryptographic parameters
130  error = tls13ParseClientKeyShareExtension(context, extensions->keyShareList,
131  extensions->supportedGroupList);
132  //Any error to report?
133  if(error)
134  return error;
135 
136  //Incorrect (EC)DHE share?
137  if(extensions->keyShareList != NULL && context->namedGroup == TLS_GROUP_NONE)
138  {
139  //Select an appropriate ECDHE or FFDHE group
140  error = tls13SelectGroup(context, extensions->supportedGroupList);
141  //Any error to report?
142  if(error)
143  return error;
144 
145  //The server corrects the mismatch with a HelloRetryRequest
147  }
148  else
149  {
150  //Check key exchange method
151  if(context->keyExchMethod == TLS13_KEY_EXCH_DHE ||
152  context->keyExchMethod == TLS13_KEY_EXCH_ECDHE ||
153  context->keyExchMethod == TLS13_KEY_EXCH_HYBRID)
154  {
155  //Check whether the client supports session resumption with a PSK
156  error = tls13ParsePskKeModesExtension(context,
157  extensions->pskKeModeList);
158  //Any error to report?
159  if(error)
160  return error;
161  }
162  else if(context->keyExchMethod == TLS13_KEY_EXCH_PSK ||
163  context->keyExchMethod == TLS13_KEY_EXCH_PSK_DHE ||
164  context->keyExchMethod == TLS13_KEY_EXCH_PSK_ECDHE ||
165  context->keyExchMethod == TLS13_KEY_EXCH_PSK_HYBRID)
166  {
167  //Servers must not select a key exchange mode that is not listed by
168  //the client in the PskKeyExchangeModes extension
169  error = tls13ParsePskKeModesExtension(context,
170  extensions->pskKeModeList);
171  //Any error to report?
172  if(error)
173  return error;
174 
175  //Prior to accepting PSK key establishment, the server must validate
176  //the corresponding binder value
177  error = tls13VerifyPskBinder(context, clientHello, clientHelloLen,
178  extensions->identityList, extensions->binderList,
179  context->selectedIdentity);
180  //If this value does not validate, the server must abort the handshake
181  if(error)
182  return error;
183  }
184  else
185  {
186  //If no common cryptographic parameters can be negotiated, the server
187  //must abort the handshake with an appropriate alert
188  return ERROR_HANDSHAKE_FAILED;
189  }
190  }
191 
192  //Successful processing
193  return NO_ERROR;
194 }
195 
196 
197 /**
198  * @brief Select the group to be used when performing (EC)DHE key exchange
199  * @param[in] context Pointer to the TLS context
200  * @param[in] groupList List of named groups supported by the client
201  * @return Error code
202  **/
203 
205  const TlsSupportedGroupList *groupList)
206 {
207  error_t error;
208 
209  //Initialize status code
210  error = ERROR_HANDSHAKE_FAILED;
211 
212  //Reset the named group to its default value
213  context->namedGroup = TLS_GROUP_NONE;
214 
215 #if (TLS13_DHE_KE_SUPPORT == ENABLED || TLS13_PSK_DHE_KE_SUPPORT == ENABLED || \
216  TLS13_ECDHE_KE_SUPPORT == ENABLED || TLS13_PSK_ECDHE_KE_SUPPORT == ENABLED || \
217  TLS13_HYBRID_KE_SUPPORT == ENABLED || TLS13_PSK_HYBRID_KE_SUPPORT == ENABLED)
218  //Valid SupportedGroups extension?
219  if(groupList != NULL)
220  {
221  uint_t i;
222  uint_t n;
223  uint16_t namedGroup;
224 
225  //Any preferred ECDHE or FFDHE groups?
226  if(context->numSupportedGroups > 0)
227  {
228  //Loop through the list of allowed groups (most preferred first)
229  for(i = 0; i < context->numSupportedGroups && error; i++)
230  {
231  //Get current named group
232  namedGroup = context->supportedGroups[i];
233 
234  //The named group to be used when performing (EC)DHE key exchange
235  //must be one of those present in the SupportedGroups extension
236  if(tls13IsGroupOffered(namedGroup, groupList))
237  {
238  //Check whether the ECDHE or FFDHE group is supported
239  if(tls13IsGroupSupported(context, namedGroup))
240  {
241  //Save the named group
242  context->namedGroup = namedGroup;
243  error = NO_ERROR;
244  }
245  }
246  }
247  }
248  else
249  {
250  //Get the number of named groups present in the list
251  n = ntohs(groupList->length) / sizeof(uint16_t);
252 
253  //The named group to be used when performing (EC)DHE key exchange must
254  //be one of those present in the SupportedGroups extension
255  for(i = 0; i < n && error; i++)
256  {
257  //Convert the named group to host byte order
258  namedGroup = ntohs(groupList->value[i]);
259 
260  //Check whether the ECDHE or FFDHE group is supported
261  if(tls13IsGroupSupported(context, namedGroup))
262  {
263  //Save the named group
264  context->namedGroup = namedGroup;
265  error = NO_ERROR;
266  }
267  }
268  }
269  }
270 #endif
271 
272  //Return status code
273  return error;
274 }
275 
276 
277 /**
278  * @brief Check whether a group is offered in the SupportedGroups extension
279  * @param[in] namedGroup Named group
280  * @param[in] groupList List of named groups supported by the client
281  * @return TRUE if the group is offered in the SupportedGroups extension,
282  * else FALSE
283  **/
284 
285 bool_t tls13IsGroupOffered(uint16_t namedGroup,
286  const TlsSupportedGroupList *groupList)
287 {
288  uint_t i;
289  uint_t n;
290  bool_t found;
291 
292  //Initialize flag
293  found = FALSE;
294 
295  //Valid SupportedGroups extension?
296  if(groupList != NULL)
297  {
298  //Get the number of named groups present in the list
299  n = ntohs(groupList->length) / sizeof(uint16_t);
300 
301  //Loop through the list of named groups the client supports
302  for(i = 0; i < n && !found; i++)
303  {
304  //Matching group?
305  if(ntohs(groupList->value[i]) == namedGroup)
306  {
307  found = TRUE;
308  }
309  }
310  }
311 
312  //Return TRUE if the group is offered in the SupportedGroups extension
313  return found;
314 }
315 
316 
317 /**
318  * @brief Verify PSK binder value
319  * @param[in] context Pointer to the TLS context
320  * @param[in] clientHello Pointer to the ClientHello message
321  * @param[in] clientHelloLen Length of the ClientHello message
322  * @param[in] identityList List of the identities that the client is willing
323  * to negotiate with the server
324  * @param[in] binderList List of HMAC values, one for each PSK offered in the
325  * PreSharedKey extension
326  * @param[in] selectedIdentity Selected PSK identity
327  * @return Error code
328  **/
329 
330 error_t tls13VerifyPskBinder(TlsContext *context, const void *clientHello,
331  size_t clientHelloLen, const Tls13PskIdentityList *identityList,
332  const Tls13PskBinderList *binderList, int_t selectedIdentity)
333 {
334 #if (TLS13_PSK_KE_SUPPORT == ENABLED || TLS13_PSK_DHE_KE_SUPPORT == ENABLED || \
335  TLS13_PSK_ECDHE_KE_SUPPORT == ENABLED || TLS13_PSK_HYBRID_KE_SUPPORT == ENABLED)
336  error_t error;
337  int_t i;
338  size_t n;
339  const uint8_t *p;
340  const Tls13PskIdentity *identity;
341  const Tls13PskBinder *binder;
342  uint8_t calculatedBinder[TLS_MAX_HKDF_DIGEST_SIZE];
343 
344  //Initialize variables
345  identity = NULL;
346  binder = NULL;
347 
348  //Make sure the PreSharedKey extension is valid
349  if(identityList == NULL || binderList == NULL)
350  return ERROR_FAILURE;
351 
352  //Make sure the selected identity is valid
353  if(selectedIdentity < 0)
354  return ERROR_FAILURE;
355 
356  //Point to the list of the identities that the client is willing to
357  //negotiate with the server
358  p = identityList->value;
359  n = ntohs(identityList->length);
360 
361  //Loop through the list of PSK identities
362  for(i = 0; i <= selectedIdentity && n > 0; i++)
363  {
364  //Point to the current PskIdentity entry
365  identity = (Tls13PskIdentity *) p;
366 
367  //Malformed PreSharedKey extension?
368  if(n < sizeof(TlsPskIdentity))
369  return ERROR_DECODING_FAILED;
370  if(n < (sizeof(TlsPskIdentity) + ntohs(identity->length)))
371  return ERROR_DECODING_FAILED;
372 
373  //Point to the obfuscated_ticket_age field
374  p += sizeof(TlsPskIdentity) + ntohs(identity->length);
375  n -= sizeof(TlsPskIdentity) + ntohs(identity->length);
376 
377  //The obfuscated_ticket_age field is a 32-bit unsigned integer
378  if(n < sizeof(uint32_t))
379  return ERROR_DECODING_FAILED;
380 
381  //Point to the next PskIdentity entry
382  p += sizeof(uint32_t);
383  n -= sizeof(uint32_t);
384  }
385 
386  //Make sure the selected identity is within the range supplied by the client
387  if(selectedIdentity >= i)
388  return ERROR_FAILURE;
389 
390  //Point to the list of HMAC values, one for each PSK offered in the
391  //PreSharedKey extension
392  p = binderList->value;
393  n = ntohs(binderList->length);
394 
395  //Loop through the list of PSK binders
396  for(i = 0; i <= selectedIdentity && n > 0; i++)
397  {
398  //Point to the PskBinderEntry
399  binder = (Tls13PskBinder *) p;
400 
401  //Malformed PreSharedKey extension?
402  if(n < sizeof(Tls13PskBinder))
403  return ERROR_DECODING_FAILED;
404  if(n < (sizeof(Tls13PskBinder) + binder->length))
405  return ERROR_DECODING_FAILED;
406 
407  //Point to the next PskBinderEntry
408  p += sizeof(Tls13PskBinder) + binder->length;
409  n -= sizeof(Tls13PskBinder) + binder->length;
410  }
411 
412  //Make sure the selected identity is within the range supplied by the client
413  if(selectedIdentity >= i)
414  return ERROR_FAILURE;
415 
416  //Check the length of the PSK binder
417  if(binder->length > TLS_MAX_HKDF_DIGEST_SIZE)
419 
420  //The PSK binder is computed as an HMAC over a transcript hash containing
421  //a partial ClientHello up to the binders list itself
422  n = (uint8_t *) binderList - (uint8_t *) clientHello;
423 
424  //Compute PSK binder value
425  error = tls13ComputePskBinder(context, clientHello, clientHelloLen,
426  n, identity, calculatedBinder, binder->length);
427  //Any error to report?
428  if(error)
430 
431  //Debug message
432  TRACE_DEBUG("PSK binder:\r\n");
433  TRACE_DEBUG_ARRAY(" ", binder->value, binder->length);
434  TRACE_DEBUG("Calculated PSK binder:\r\n");
435  TRACE_DEBUG_ARRAY(" ", calculatedBinder, binder->length);
436 
437  //Prior to accepting PSK key establishment, the server must validate the
438  //corresponding binder value
439  if(osMemcmp(calculatedBinder, binder->value, binder->length))
440  {
441  //If this value does not validate, the server must abort the handshake
443  }
444 
445  //Successful verification
446  return NO_ERROR;
447 #else
448  //Not implemented
449  return ERROR_NOT_IMPLEMENTED;
450 #endif
451 }
452 
453 
454 /**
455  * @brief Process early data
456  * @param[in] context Pointer to the TLS context
457  * @param[in] data Pointer to the early data
458  * @param[in] length Length of the early data, in bytes
459  * @return Error code
460  **/
461 
462 error_t tls13ProcessEarlyData(TlsContext *context, const uint8_t *data,
463  size_t length)
464 {
465  //Check TLS version
466  if(context->version != TLS_VERSION_1_3)
468 
469  //Check current state
470  if(context->state != TLS_STATE_CLIENT_HELLO_2)
472 
473  //If the client opts to send 0-RTT data, it must supply an EarlyData
474  //extension in its ClientHello (refer to RFC 8446, section 4.2.10)
475  if(!context->earlyDataExtReceived)
477 
478  //Amount of 0-RTT data received by the server
479  context->earlyDataLen += length;
480 
481  //Discard records which fail deprotection (up to the configured
482  //max_early_data_size)
483  if(context->earlyDataLen > context->maxEarlyDataSize)
484  return ERROR_BAD_RECORD_MAC;
485 
486  //Debug message
487  TRACE_INFO("Discarding early data (%" PRIuSIZE " bytes)...\r\n", length);
488 
489  //The server may opt to reject early data
490  return NO_ERROR;
491 }
492 
493 #endif
@ TLS13_KEY_EXCH_PSK
Definition: tls.h:1161
TLS helper functions.
uint8_t extensions[]
Definition: ntp_common.h:207
Tls13PskBinderList
Definition: tls13_misc.h:261
@ TLS_STATE_HELLO_RETRY_REQUEST
Definition: tls.h:1460
int bool_t
Definition: compiler_port.h:53
error_t tls13ParsePskKeModesExtension(TlsContext *context, const Tls13PskKeModeList *pskKeModeList)
Parse PskKeyExchangeModes extension.
@ TLS13_KEY_EXCH_PSK_DHE
Definition: tls.h:1162
signed int int_t
Definition: compiler_port.h:49
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
@ ERROR_DECRYPTION_FAILED
Definition: error.h:242
@ ERROR_UNEXPECTED_MESSAGE
Definition: error.h:194
uint8_t p
Definition: ndp.h:300
#define TRUE
Definition: os_port.h:50
uint8_t data[]
Definition: ethernet.h:222
TlsPskIdentity
Definition: tls.h:1695
error_t tls13VerifyPskBinder(TlsContext *context, const void *clientHello, size_t clientHelloLen, const Tls13PskIdentityList *identityList, const Tls13PskBinderList *binderList, int_t selectedIdentity)
Verify PSK binder value.
error_t tls13SelectGroup(TlsContext *context, const TlsSupportedGroupList *groupList)
Select the group to be used when performing (EC)DHE key exchange.
#define osMemcmp(p1, p2, length)
Definition: os_port.h:153
@ ERROR_HANDSHAKE_FAILED
Definition: error.h:233
@ TLS13_KEY_EXCH_ECDHE
Definition: tls.h:1159
@ ERROR_BAD_RECORD_MAC
Definition: error.h:231
error_t tls13NegotiateCipherSuite(TlsContext *context, const void *clientHello, size_t clientHelloLen, const TlsCipherSuites *cipherSuites, TlsHelloExtensions *extensions)
Cipher suite and key exchange method negotiation.
@ TLS13_KEY_EXCH_PSK_HYBRID
Definition: tls.h:1164
TlsCipherSuites
Definition: tls.h:1517
#define FALSE
Definition: os_port.h:46
#define TlsContext
Definition: tls.h:36
error_t
Error codes.
Definition: error.h:43
bool_t tls13IsGroupSupported(TlsContext *context, uint16_t namedGroup)
Check whether a given named group is supported.
Definition: tls13_misc.c:808
@ TLS_GROUP_NONE
Definition: tls.h:1370
Formatting and parsing of extensions (TLS 1.3 server)
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
@ TLS13_KEY_EXCH_DHE
Definition: tls.h:1158
#define TLS_VERSION_1_3
Definition: tls.h:97
error_t tlsNegotiateCipherSuite(TlsContext *context, const HashAlgo *hashAlgo, const TlsCipherSuites *cipherSuites, TlsHelloExtensions *extensions)
Cipher suite negotiation.
error_t tls13ParseClientEarlyDataExtension(TlsContext *context, const TlsExtension *earlyDataIndication)
Parse EarlyData extension.
Tls13PskBinder
Definition: tls13_misc.h:250
#define TRACE_INFO(...)
Definition: debug.h:95
uint8_t length
Definition: tcp.h:368
Helper functions for TLS 1.3 server.
Hello extensions.
Definition: tls.h:2098
Transcript hash calculation.
#define ntohs(value)
Definition: cpu_endian.h:421
#define TRACE_DEBUG(...)
Definition: debug.h:107
@ TLS_KEY_EXCH_NONE
Definition: tls.h:1139
@ TLS13_KEY_EXCH_PSK_ECDHE
Definition: tls.h:1163
@ TLS_STATE_CLIENT_HELLO_2
Definition: tls.h:1457
#define TRACE_DEBUG_ARRAY(p, a, n)
Definition: debug.h:108
error_t tls13ComputePskBinder(TlsContext *context, const void *clientHello, size_t clientHelloLen, size_t truncatedClientHelloLen, const Tls13PskIdentity *identity, uint8_t *binder, size_t binderLen)
Compute PSK binder value.
Definition: tls13_misc.c:86
uint8_t n
error_t tls13ParseClientKeyShareExtension(TlsContext *context, const Tls13KeyShareList *keyShareList, const TlsSupportedGroupList *groupList)
Parse KeyShare extension.
@ TLS13_KEY_EXCH_HYBRID
Definition: tls.h:1160
error_t tlsInitTranscriptHash(TlsContext *context)
Initialize handshake message hashing.
#define TLS_MAX_HKDF_DIGEST_SIZE
Definition: tls.h:921
TLS (Transport Layer Security)
bool_t tls13IsGroupOffered(uint16_t namedGroup, const TlsSupportedGroupList *groupList)
Check whether a group is offered in the SupportedGroups extension.
FFDHE key exchange.
Helper functions for TLS server.
void tlsChangeState(TlsContext *context, TlsState newState)
Update TLS state.
Definition: tls_misc.c:54
Tls13PskIdentity
Definition: tls13_misc.h:228
@ ERROR_DECODING_FAILED
Definition: error.h:241
Tls13PskIdentityList
Definition: tls13_misc.h:239
#define PRIuSIZE
unsigned int uint_t
Definition: compiler_port.h:50
TlsSupportedGroupList
Definition: tls.h:1651
error_t tls13ProcessEarlyData(TlsContext *context, const uint8_t *data, size_t length)
Process early data.
@ NO_ERROR
Success.
Definition: error.h:44
error_t tls13ParseClientPreSharedKeyExtension(TlsContext *context, const TlsClientHello *clientHello, size_t clientHelloLen, const Tls13PskIdentityList *identityList, const Tls13PskBinderList *binderList)
Parse PreSharedKey extension.
Debugging facilities.