tls13_client_misc.c
Go to the documentation of this file.
1 /**
2  * @file tls13_client_misc.c
3  * @brief Helper functions for TLS 1.3 client
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 "tls.h"
35 #include "tls_handshake.h"
36 #include "tls_client.h"
37 #include "tls_common.h"
38 #include "tls_transcript_hash.h"
39 #include "tls_record.h"
40 #include "tls_misc.h"
41 #include "tls13_client_misc.h"
42 #include "tls13_key_material.h"
43 #include "debug.h"
44 
45 //Check TLS library configuration
46 #if (TLS_SUPPORT == ENABLED && TLS_CLIENT_SUPPORT == ENABLED && \
47  TLS_MAX_VERSION >= TLS_VERSION_1_3)
48 
49 
50 /**
51  * @brief Check whether an incoming ServerHello message is a HelloRetryRequest
52  * @param[in] message Pointer to the ServerHello message
53  * @param[in] length Length of the ServerHello message
54  * @return TRUE is the message is a HelloRetryRequest, else FALSE
55  **/
56 
58 {
59  bool_t res;
60 
61  //Initialize flag
62  res = FALSE;
63 
64  //Check the length of the incoming ServerHello message
65  if(length >= sizeof(TlsServerHello))
66  {
67  //Upon receiving a message with type ServerHello, implementations must
68  //first examine the Random field
69  if(!memcmp(&message->random, tls13HelloRetryRequestRandom,
71  {
72  //The Random field matches the special value
73  res = TRUE;
74  }
75  }
76 
77  //Return TRUE is the message is a HelloRetryRequest, else FALSE
78  return res;
79 }
80 
81 
82 /**
83  * @brief Compute PSK binder values
84  * @param[in] context Pointer to the TLS context
85  * @param[in] clientHello Pointer to the ClientHello message
86  * @param[in] clientHelloLen Length of the ClientHello message
87  * @param[in] identityList List of the identities that the client is willing
88  * to negotiate with the server
89  * @param[in,out] binderList List of HMAC values, one for each PSK offered in
90  * the PreSharedKey extension
91  * @return Error code
92  **/
93 
94 error_t tls13ComputePskBinders(TlsContext *context, const void *clientHello,
95  size_t clientHelloLen, const Tls13PskIdentityList *identityList,
96  Tls13PskBinderList *binderList)
97 {
98  error_t error;
99  size_t n;
100  size_t m;
101  size_t truncatedClientHelloLen;
102  uint8_t *q;
103  const uint8_t *p;
104  Tls13PskBinder *binder;
105  const Tls13PskIdentity *identity;
106 
107  //Initialize status code
108  error = NO_ERROR;
109 
110 #if (TLS13_PSK_KE_SUPPORT == ENABLED || TLS13_PSK_DHE_KE_SUPPORT == ENABLED || \
111  TLS13_PSK_ECDHE_KE_SUPPORT == ENABLED)
112  //Check whether the ClientHello message contains a PreSharedKey extension
113  if(identityList != NULL && binderList != NULL)
114  {
115  //Point to the list of the identities that the client is willing to
116  //negotiate with the server
117  p = identityList->value;
118  n = ntohs(identityList->length);
119 
120  //Point to the list of HMAC values, one for each PSK offered in the
121  //PreSharedKey extension
122  q = binderList->value;
123  m = ntohs(binderList->length);
124 
125  //Each entry in the binders list is computed as an HMAC over a transcript
126  //hash containing a partial ClientHello up to the binders list itself
127  truncatedClientHelloLen = (uint8_t *) binderList - (uint8_t *) clientHello;
128 
129  //Loop through the list of PSK identities
130  while(n > 0)
131  {
132  //Point to the current PskIdentity entry
133  identity = (Tls13PskIdentity *) p;
134 
135  //Malformed PreSharedKey extension?
136  if(n < sizeof(TlsPskIdentity))
137  return ERROR_DECODING_FAILED;
138  if(n < (sizeof(TlsPskIdentity) + ntohs(identity->length)))
139  return ERROR_DECODING_FAILED;
140 
141  //Point to the obfuscated_ticket_age field
142  p += sizeof(TlsPskIdentity) + ntohs(identity->length);
143  n -= sizeof(TlsPskIdentity) + ntohs(identity->length);
144 
145  //The obfuscated_ticket_age field is a 32-bit unsigned integer
146  if(n < sizeof(uint32_t))
147  return ERROR_DECODING_FAILED;
148 
149  //Point to the next PskIdentity entry
150  p += sizeof(uint32_t);
151  n -= sizeof(uint32_t);
152 
153  //Point to the PskBinderEntry
154  binder = (Tls13PskBinder *) q;
155 
156  //Malformed PreSharedKey extension?
157  if(m < sizeof(Tls13PskBinder))
158  return ERROR_DECODING_FAILED;
159  if(m < (sizeof(Tls13PskBinder) + binder->length))
160  return ERROR_DECODING_FAILED;
161 
162  //Point to the next PskBinderEntry
163  q += sizeof(Tls13PskBinder) + binder->length;
164  m -= sizeof(Tls13PskBinder) + binder->length;
165 
166  //Fix the value of the PSK binder
167  error = tls13ComputePskBinder(context, clientHello, clientHelloLen,
168  truncatedClientHelloLen, identity, binder->value, binder->length);
169  //Any error to report?
170  if(error)
171  break;
172  }
173  }
174 #endif
175 
176  //Return status code
177  return error;
178 }
179 
180 
181 /**
182  * @brief Send early data to the remote TLS server
183  * @param[in] context Pointer to the TLS context
184  * @param[in] data Pointer to a buffer containing the data to be transmitted
185  * @param[in] length Number of bytes to be transmitted
186  * @param[out] written Actual number of bytes written
187  * @return Error code
188  **/
189 
190 error_t tls13SendEarlyData(TlsContext *context, const void *data,
191  size_t length, size_t *written)
192 {
193 #if (TLS13_EARLY_DATA_SUPPORT == ENABLED)
194  error_t error;
195  size_t n;
196 
197  //Actual number of bytes written
198  *written = 0;
199 
200  //Valid PSK?
201  if(tls13IsPskValid(context))
202  {
203  //Make sure a valid cipher suite has been provisioned
204  if(context->pskCipherSuite == 0)
205  return ERROR_END_OF_STREAM;
206  }
207  else if(tls13IsTicketValid(context))
208  {
209  //Make sure the cipher suite associated with the ticket is valid
210  if(context->ticketCipherSuite == 0)
211  return ERROR_END_OF_STREAM;
212  }
213  else
214  {
215  //The pre-shared key is not valid
216  return ERROR_END_OF_STREAM;
217  }
218 
219  //Initialize status code
220  error = NO_ERROR;
221 
222  //TLS 1.3 allows clients to send data on the first flight
223  while(!error)
224  {
225  //TLS protocol?
226  if(context->transportProtocol == TLS_TRANSPORT_PROTOCOL_STREAM)
227  {
228  //Check current state
229  if(context->state != TLS_STATE_INIT &&
230  context->state != TLS_STATE_CLOSED)
231  {
232  //Flush send buffer
233  error = tlsWriteProtocolData(context, NULL, 0, TLS_TYPE_NONE);
234  //Any error to report?
235  if(error)
236  break;
237  }
238  }
239 
240  //The TLS handshake is implemented as a state machine representing the
241  //current location in the protocol
242  if(context->state == TLS_STATE_INIT)
243  {
244  //TLS handshake initialization
245  error = tlsInitHandshake(context);
246  }
247  else if(context->state == TLS_STATE_CLIENT_HELLO)
248  {
249  //If the client opts to send application data in its first flight
250  //of messages, it must supply both the PreSharedKey and EarlyData
251  //extensions
252  context->earlyDataEnabled = TRUE;
253 
254  //When a client first connects to a server, it is required to send
255  //the ClientHello as its first message
256  error = tlsSendClientHello(context);
257  }
258  else if(context->state == TLS_STATE_SERVER_HELLO)
259  {
260  //Initialize handshake message hashing
261  error = tlsInitTranscriptHash(context);
262 
263 #if (TLS13_MIDDLEBOX_COMPAT_SUPPORT == ENABLED)
264  //In middlebox compatibility mode, the client sends a dummy
265  //ChangeCipherSpec record immediately before its second flight
266  context->state = TLS_STATE_CLIENT_CHANGE_CIPHER_SPEC;
267 #else
268  //The client can send its second flight
269  context->state = TLS_STATE_CLIENT_HELLO_2;
270 #endif
271  }
272  else if(context->state == TLS_STATE_CLIENT_CHANGE_CIPHER_SPEC)
273  {
274  //Send a dummy ChangeCipherSpec record
275  error = tlsSendChangeCipherSpec(context);
276  }
277  else if(context->state == TLS_STATE_CLIENT_HELLO_2)
278  {
279  //Compute early traffic keys
280  error = tls13GenerateEarlyTrafficKeys(context);
281  }
282  else if(context->state == TLS_STATE_EARLY_DATA)
283  {
284  //Send as much data as possible
285  if(*written < length &&
286  context->earlyDataLen < context->maxEarlyDataSize)
287  {
288  //Calculate the number of bytes to write at a time
289  n = MIN(context->txBufferMaxLen, length - *written);
290  n = MIN(n, context->maxEarlyDataSize - context->earlyDataLen);
291 
292  //The record length must not exceed 16384 bytes
294 
295  //Debug message
296  TRACE_INFO("Sending early data (%" PRIuSIZE " bytes)...\r\n", n);
297 
298  //Send 0-RTT data
299  error = tlsWriteProtocolData(context, data, n,
301 
302  //Check status code
303  if(!error)
304  {
305  //Advance data pointer
306  data = (uint8_t *) data + n;
307  //Update byte counter
308  *written += n;
309 
310  //Total amount of 0-RTT data that have been sent by the client
311  context->earlyDataLen += n;
312  }
313  }
314  else
315  {
316  //Clients must not more than max_early_data_size bytes of 0-RTT data
317  break;
318  }
319  }
320  else
321  {
322  //Report an error
323  error = ERROR_UNEXPECTED_STATE;
324  }
325  }
326 
327  //Check status code
328  if(error == NO_ERROR && length != 0 && *written == 0)
329  {
330  error = ERROR_END_OF_STREAM;
331  }
332 
333  //Return status code
334  return error;
335 #else
336  //Not implemented
337  return ERROR_NOT_IMPLEMENTED;
338 #endif
339 }
340 
341 #endif
TLS (Transport Layer Security)
__start_packed struct @98 Tls13PskIdentity
PSK identity.
Handshake message processing (TLS client)
bool_t tls13IsTicketValid(TlsContext *context)
Debugging facilities.
uint8_t res[]
uint8_t p
Definition: ndp.h:295
TLS 1.3 key schedule.
uint8_t message[]
Definition: chap.h:150
error_t tlsSendChangeCipherSpec(TlsContext *context)
Send ChangeCipherSpec message.
Definition: tls_common.c:266
uint8_t m
Definition: ndp.h:299
__start_packed struct @100 Tls13PskBinder
PSK binder.
error_t tlsInitTranscriptHash(TlsContext *context)
Initialize handshake message hashing.
bool_t tls13IsHelloRetryRequest(const TlsServerHello *message, size_t length)
#define TRUE
Definition: os_port.h:48
#define TLS_MAX_RECORD_LENGTH
Definition: tls.h:828
__start_packed struct @86 TlsServerHello
ServerHello message.
error_t tlsWriteProtocolData(TlsContext *context, const uint8_t *data, size_t length, TlsContentType contentType)
Write protocol data.
Definition: tls_record.c:58
TLS record protocol.
__start_packed struct @101 Tls13PskBinderList
List of PSK binders.
TLS helper functions.
#define ntohs(value)
Definition: cpu_endian.h:396
TLS handshake.
error_t tls13GenerateEarlyTrafficKeys(TlsContext *context)
Handshake message processing (TLS client and server)
__start_packed struct @79 TlsPskIdentity
PSK identity.
#define MIN(a, b)
Definition: os_port.h:60
error_t tls13ComputePskBinder(TlsContext *context, const void *clientHello, size_t clientHelloLen, size_t truncatedClientHelloLen, const Tls13PskIdentity *identity, uint8_t *binder, size_t binderLen)
#define TRACE_INFO(...)
Definition: debug.h:86
error_t tls13ComputePskBinders(TlsContext *context, const void *clientHello, size_t clientHelloLen, const Tls13PskIdentityList *identityList, Tls13PskBinderList *binderList)
Success.
Definition: error.h:42
error_t tls13SendEarlyData(TlsContext *context, const void *data, size_t length, size_t *written)
error_t
Error codes.
Definition: error.h:40
bool_t tls13IsPskValid(TlsContext *context)
__start_packed struct @99 Tls13PskIdentityList
List of PSK identities.
uint8_t data[]
Definition: dtls_misc.h:167
#define PRIuSIZE
Definition: compiler_port.h:72
const uint8_t tls13HelloRetryRequestRandom[32]
Transcript hash calculation.
error_t tlsSendClientHello(TlsContext *context)
Send ClientHello message.
Definition: tls_client.c:80
error_t tlsInitHandshake(TlsContext *context)
TLS handshake initialization.
Definition: tls_handshake.c:62
Helper functions for TLS 1.3 client.
uint8_t length
Definition: dtls_misc.h:140
uint8_t n
#define FALSE
Definition: os_port.h:44
#define TlsContext
Definition: tls.h:34
int bool_t
Definition: compiler_port.h:47