/src/gnutls/lib/handshake-tls13.c
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /*  | 
2  |  |  * Copyright (C) 2017-2018 Red Hat, Inc.  | 
3  |  |  *  | 
4  |  |  * Author: Nikos Mavrogiannopoulos  | 
5  |  |  *  | 
6  |  |  * This file is part of GnuTLS.  | 
7  |  |  *  | 
8  |  |  * The GnuTLS is free software; you can redistribute it and/or  | 
9  |  |  * modify it under the terms of the GNU Lesser General Public License  | 
10  |  |  * as published by the Free Software Foundation; either version 2.1 of  | 
11  |  |  * the License, or (at your option) any later version.  | 
12  |  |  *  | 
13  |  |  * This library is distributed in the hope that it will be useful, but  | 
14  |  |  * WITHOUT ANY WARRANTY; without even the implied warranty of  | 
15  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  | 
16  |  |  * Lesser General Public License for more details.  | 
17  |  |  *  | 
18  |  |  * You should have received a copy of the GNU Lesser General Public License  | 
19  |  |  * along with this program.  If not, see <https://www.gnu.org/licenses/>  | 
20  |  |  *  | 
21  |  |  */  | 
22  |  |  | 
23  |  | /* Functions that relate to the TLS handshake procedure.  | 
24  |  |  */  | 
25  |  |  | 
26  |  | #include "gnutls_int.h"  | 
27  |  | #include "errors.h"  | 
28  |  | #include "dh.h"  | 
29  |  | #include "debug.h"  | 
30  |  | #include "algorithms.h"  | 
31  |  | #include "cipher.h"  | 
32  |  | #include "buffers.h"  | 
33  |  | #include "mbuffers.h"  | 
34  |  | #include "kx.h"  | 
35  |  | #include "handshake.h"  | 
36  |  | #include "num.h"  | 
37  |  | #include "hash_int.h"  | 
38  |  | #include "db.h"  | 
39  |  | #include "hello_ext.h"  | 
40  |  | #include "supplemental.h"  | 
41  |  | #include "auth.h"  | 
42  |  | #include "sslv2_compat.h"  | 
43  |  | #include "auth/cert.h"  | 
44  |  | #include "constate.h"  | 
45  |  | #include "record.h"  | 
46  |  | #include "state.h"  | 
47  |  | #include "random.h"  | 
48  |  | #include "dtls.h"  | 
49  |  | #include "secrets.h"  | 
50  |  | #include "tls13/hello_retry.h"  | 
51  |  | #include "tls13/encrypted_extensions.h"  | 
52  |  | #include "tls13/certificate_request.h"  | 
53  |  | #include "tls13/certificate_verify.h"  | 
54  |  | #include "tls13/certificate.h"  | 
55  |  | #include "tls13/early_data.h"  | 
56  |  | #include "tls13/finished.h"  | 
57  |  | #include "tls13/key_update.h"  | 
58  |  | #include "ext/pre_shared_key.h"  | 
59  |  | #include "locks.h"  | 
60  |  |  | 
61  |  | static int generate_rms_keys(gnutls_session_t session);  | 
62  |  | static int generate_hs_traffic_keys(gnutls_session_t session);  | 
63  |  | static int generate_ap_traffic_keys(gnutls_session_t session);  | 
64  |  |  | 
65  |  | #define SAVE_TRANSCRIPT                                                              \  | 
66  | 0  |   if (session->internals.flags & GNUTLS_POST_HANDSHAKE_AUTH) {                 \ | 
67  | 0  |     /* If post-handshake auth is in use we need a copy of the original \  | 
68  | 0  |      * handshake transcript */ \  | 
69  | 0  |     memcpy(&session->internals.post_handshake_hash_buffer,               \  | 
70  | 0  |            &session->internals.handshake_hash_buffer,                    \  | 
71  | 0  |            sizeof(session->internals.handshake_hash_buffer));            \  | 
72  | 0  |     _gnutls_buffer_init(                                                 \  | 
73  | 0  |       &session->internals.handshake_hash_buffer);                  \  | 
74  | 0  |   }  | 
75  |  |  | 
76  |  | /*  | 
77  |  |  * _gnutls13_handshake_client  | 
78  |  |  * This function performs the client side of the handshake of the TLS/SSL protocol.  | 
79  |  |  */  | 
80  |  | int _gnutls13_handshake_client(gnutls_session_t session)  | 
81  | 0  | { | 
82  | 0  |   int ret = 0;  | 
83  |  | 
  | 
84  | 0  |   switch (STATE) { | 
85  | 0  |   case STATE99:  | 
86  | 0  |   case STATE100:  | 
87  | 0  | #ifdef TLS13_APPENDIX_D4  | 
88  | 0  |     if (session->internals.priorities->tls13_compat_mode &&  | 
89  |  |         /* Key change is indicated by sending an EndOfEarlyData below */  | 
90  | 0  |         !(session->internals.hsk_flags &  | 
91  | 0  |           HSK_EARLY_DATA_IN_FLIGHT)) { | 
92  |  |       /* We send it before keys are generated. That works because CCS  | 
93  |  |        * is always being cached and queued and not being sent directly */  | 
94  | 0  |       ret = _gnutls_send_change_cipher_spec(session,  | 
95  | 0  |                     AGAIN(STATE100));  | 
96  | 0  |       STATE = STATE100;  | 
97  | 0  |       IMED_RET("send change cipher spec", ret, 0); | 
98  | 0  |     }  | 
99  | 0  | #endif  | 
100  | 0  |     FALLTHROUGH;  | 
101  | 0  |   case STATE101:  | 
102  | 0  |     STATE = STATE101;  | 
103  | 0  |     ret = generate_hs_traffic_keys(session);  | 
104  |  |     /* Note that we check IN_FLIGHT, not ACCEPTED  | 
105  |  |      * here. This is because the client sends early data  | 
106  |  |      * speculatively. */  | 
107  | 0  |     IMED_RET_FATAL("generate hs traffic keys", ret, 0); | 
108  | 0  |     if (session->internals.hsk_flags & HSK_EARLY_DATA_IN_FLIGHT)  | 
109  | 0  |       ret = _tls13_read_connection_state_init(session,  | 
110  | 0  |                 STAGE_HS);  | 
111  | 0  |     else  | 
112  | 0  |       ret = _tls13_connection_state_init(session, STAGE_HS);  | 
113  | 0  |     IMED_RET_FATAL("set hs traffic keys", ret, 0); | 
114  | 0  |     FALLTHROUGH;  | 
115  | 0  |   case STATE102:  | 
116  | 0  |     ret = _gnutls13_recv_encrypted_extensions(session);  | 
117  | 0  |     STATE = STATE102;  | 
118  | 0  |     IMED_RET("recv encrypted extensions", ret, 0); | 
119  | 0  |     FALLTHROUGH;  | 
120  | 0  |   case STATE103:  | 
121  | 0  |     ret = _gnutls13_recv_certificate_request(session);  | 
122  | 0  |     STATE = STATE103;  | 
123  | 0  |     IMED_RET("recv certificate request", ret, 0); | 
124  | 0  |     FALLTHROUGH;  | 
125  | 0  |   case STATE104:  | 
126  | 0  |     ret = _gnutls13_recv_certificate(session);  | 
127  | 0  |     STATE = STATE104;  | 
128  | 0  |     IMED_RET("recv certificate", ret, 0); | 
129  | 0  |     FALLTHROUGH;  | 
130  | 0  |   case STATE105:  | 
131  | 0  |     ret = _gnutls13_recv_certificate_verify(session);  | 
132  | 0  |     STATE = STATE105;  | 
133  | 0  |     IMED_RET("recv server certificate verify", ret, 0); | 
134  | 0  |     FALLTHROUGH;  | 
135  | 0  |   case STATE106:  | 
136  | 0  |     ret = _gnutls_run_verify_callback(session, GNUTLS_CLIENT);  | 
137  | 0  |     STATE = STATE106;  | 
138  | 0  |     if (ret < 0)  | 
139  | 0  |       return gnutls_assert_val(ret);  | 
140  | 0  |     FALLTHROUGH;  | 
141  | 0  |   case STATE107:  | 
142  | 0  |     ret = _gnutls13_recv_finished(session);  | 
143  | 0  |     STATE = STATE107;  | 
144  | 0  |     IMED_RET("recv finished", ret, 0); | 
145  | 0  |     FALLTHROUGH;  | 
146  | 0  |   case STATE108:  | 
147  | 0  |     ret = _gnutls13_send_end_of_early_data(session,  | 
148  | 0  |                    AGAIN(STATE108));  | 
149  | 0  |     STATE = STATE108;  | 
150  | 0  |     IMED_RET("send end of early data", ret, 0); | 
151  |  |  | 
152  |  |     /* Note that we check IN_FLIGHT, not ACCEPTED  | 
153  |  |      * here. This is because the client sends early data  | 
154  |  |      * speculatively. */  | 
155  | 0  |     if (session->internals.hsk_flags & HSK_EARLY_DATA_IN_FLIGHT) { | 
156  | 0  |       session->internals.hsk_flags &=  | 
157  | 0  |         ~HSK_EARLY_DATA_IN_FLIGHT;  | 
158  | 0  |       ret = _tls13_write_connection_state_init(session,  | 
159  | 0  |                  STAGE_HS);  | 
160  | 0  |       IMED_RET_FATAL(  | 
161  | 0  |         "set hs traffic key after sending early data",  | 
162  | 0  |         ret, 0);  | 
163  | 0  |     }  | 
164  | 0  |     FALLTHROUGH;  | 
165  | 0  |   case STATE109:  | 
166  | 0  |     ret = _gnutls13_send_certificate(session, AGAIN(STATE109));  | 
167  | 0  |     STATE = STATE109;  | 
168  | 0  |     IMED_RET("send certificate", ret, 0); | 
169  | 0  |     FALLTHROUGH;  | 
170  | 0  |   case STATE110:  | 
171  | 0  |     ret = _gnutls13_send_certificate_verify(session,  | 
172  | 0  |               AGAIN(STATE110));  | 
173  | 0  |     STATE = STATE110;  | 
174  | 0  |     IMED_RET("send certificate verify", ret, 0); | 
175  | 0  |     FALLTHROUGH;  | 
176  | 0  |   case STATE111:  | 
177  | 0  |     ret = _gnutls13_send_finished(session, AGAIN(STATE111));  | 
178  | 0  |     STATE = STATE111;  | 
179  | 0  |     IMED_RET("send finished", ret, 0); | 
180  | 0  |     FALLTHROUGH;  | 
181  | 0  |   case STATE112:  | 
182  | 0  |     STATE = STATE112;  | 
183  |  | 
  | 
184  | 0  |     ret = generate_ap_traffic_keys(session);  | 
185  | 0  |     IMED_RET_FATAL("generate app keys", ret, 0); | 
186  |  |  | 
187  | 0  |     ret = generate_rms_keys(session);  | 
188  | 0  |     IMED_RET_FATAL("generate rms keys", ret, 0); | 
189  |  |  | 
190  |  |     /* set traffic keys */  | 
191  | 0  |     ret = _tls13_connection_state_init(session, STAGE_APP);  | 
192  | 0  |     IMED_RET_FATAL("set app keys", ret, 0); | 
193  |  |  | 
194  | 0  |     STATE = STATE0;  | 
195  | 0  |     break;  | 
196  | 0  |   default:  | 
197  | 0  |     return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);  | 
198  | 0  |   }  | 
199  |  |  | 
200  |  |   /* no lock of post_negotiation_lock is required here as this is not run  | 
201  |  |    * after handshake */  | 
202  | 0  |   session->internals.recv_state = RECV_STATE_0;  | 
203  | 0  |   session->internals.initial_negotiation_completed = 1;  | 
204  |  | 
  | 
205  | 0  |   SAVE_TRANSCRIPT;  | 
206  |  | 
  | 
207  | 0  |   if (session->internals.resumed)  | 
208  | 0  |     _gnutls_set_resumed_parameters(session);  | 
209  |  | 
  | 
210  | 0  |   return 0;  | 
211  | 0  | }  | 
212  |  |  | 
213  |  | static int generate_non_auth_rms_keys(gnutls_session_t session)  | 
214  | 0  | { | 
215  | 0  |   int ret;  | 
216  |  |   /* we simulate client finished */  | 
217  | 0  |   uint8_t finished[MAX_HASH_SIZE + TLS_HANDSHAKE_HEADER_SIZE];  | 
218  | 0  |   unsigned spos;  | 
219  |  | 
  | 
220  | 0  |   ret = _gnutls13_compute_finished(  | 
221  | 0  |     session->security_parameters.prf,  | 
222  | 0  |     session->key.proto.tls13.hs_ckey,  | 
223  | 0  |     &session->internals.handshake_hash_buffer,  | 
224  | 0  |     finished + TLS_HANDSHAKE_HEADER_SIZE);  | 
225  | 0  |   if (ret < 0)  | 
226  | 0  |     return gnutls_assert_val(ret);  | 
227  |  |  | 
228  | 0  |   spos = session->internals.handshake_hash_buffer.length;  | 
229  |  | 
  | 
230  | 0  |   finished[0] = GNUTLS_HANDSHAKE_FINISHED;  | 
231  | 0  |   _gnutls_write_uint24(session->security_parameters.prf->output_size,  | 
232  | 0  |            finished + 1);  | 
233  |  | 
  | 
234  | 0  |   ret = _gnutls_buffer_append_data(  | 
235  | 0  |     &session->internals.handshake_hash_buffer, finished,  | 
236  | 0  |     TLS_HANDSHAKE_HEADER_SIZE +  | 
237  | 0  |       session->security_parameters.prf->output_size);  | 
238  | 0  |   if (ret < 0)  | 
239  | 0  |     return gnutls_assert_val(ret);  | 
240  |  |  | 
241  | 0  |   ret = _tls13_derive_secret(  | 
242  | 0  |     session, RMS_MASTER_LABEL, sizeof(RMS_MASTER_LABEL) - 1,  | 
243  | 0  |     session->internals.handshake_hash_buffer.data,  | 
244  | 0  |     session->internals.handshake_hash_buffer.length,  | 
245  | 0  |     session->key.proto.tls13.temp_secret,  | 
246  | 0  |     session->key.proto.tls13.ap_rms);  | 
247  | 0  |   if (ret < 0)  | 
248  | 0  |     return gnutls_assert_val(ret);  | 
249  |  |  | 
250  | 0  |   session->internals.handshake_hash_buffer.length = spos;  | 
251  |  | 
  | 
252  | 0  |   return 0;  | 
253  | 0  | }  | 
254  |  |  | 
255  |  | static int generate_rms_keys(gnutls_session_t session)  | 
256  | 0  | { | 
257  | 0  |   int ret;  | 
258  |  | 
  | 
259  | 0  |   ret = _tls13_derive_secret(  | 
260  | 0  |     session, RMS_MASTER_LABEL, sizeof(RMS_MASTER_LABEL) - 1,  | 
261  | 0  |     session->internals.handshake_hash_buffer.data,  | 
262  | 0  |     session->internals.handshake_hash_buffer_client_finished_len,  | 
263  | 0  |     session->key.proto.tls13.temp_secret,  | 
264  | 0  |     session->key.proto.tls13.ap_rms);  | 
265  | 0  |   if (ret < 0)  | 
266  | 0  |     return gnutls_assert_val(ret);  | 
267  |  |  | 
268  | 0  |   return 0;  | 
269  | 0  | }  | 
270  |  |  | 
271  |  | static int generate_ap_traffic_keys(gnutls_session_t session)  | 
272  | 0  | { | 
273  | 0  |   int ret;  | 
274  | 0  |   uint8_t zero[MAX_HASH_SIZE];  | 
275  |  | 
  | 
276  | 0  |   ret = _tls13_derive_secret(session, DERIVED_LABEL,  | 
277  | 0  |            sizeof(DERIVED_LABEL) - 1, NULL, 0,  | 
278  | 0  |            session->key.proto.tls13.temp_secret,  | 
279  | 0  |            session->key.proto.tls13.temp_secret);  | 
280  | 0  |   if (ret < 0)  | 
281  | 0  |     return gnutls_assert_val(ret);  | 
282  |  |  | 
283  | 0  |   memset(zero, 0, session->security_parameters.prf->output_size);  | 
284  | 0  |   ret = _tls13_update_secret(  | 
285  | 0  |     session, zero, session->security_parameters.prf->output_size);  | 
286  | 0  |   if (ret < 0)  | 
287  | 0  |     return gnutls_assert_val(ret);  | 
288  |  |  | 
289  | 0  |   ret = _tls13_derive_secret(  | 
290  | 0  |     session, EXPORTER_MASTER_LABEL,  | 
291  | 0  |     sizeof(EXPORTER_MASTER_LABEL) - 1,  | 
292  | 0  |     session->internals.handshake_hash_buffer.data,  | 
293  | 0  |     session->internals.handshake_hash_buffer_server_finished_len,  | 
294  | 0  |     session->key.proto.tls13.temp_secret,  | 
295  | 0  |     session->key.proto.tls13.ap_expkey);  | 
296  | 0  |   if (ret < 0)  | 
297  | 0  |     return gnutls_assert_val(ret);  | 
298  |  |  | 
299  | 0  |   ret = _gnutls_call_keylog_func(  | 
300  | 0  |     session, "EXPORTER_SECRET", session->key.proto.tls13.ap_expkey,  | 
301  | 0  |     session->security_parameters.prf->output_size);  | 
302  | 0  |   if (ret < 0)  | 
303  | 0  |     return gnutls_assert_val(ret);  | 
304  |  |  | 
305  | 0  |   _gnutls_epoch_bump(session);  | 
306  | 0  |   ret = _gnutls_epoch_dup(session, EPOCH_READ_CURRENT);  | 
307  | 0  |   if (ret < 0)  | 
308  | 0  |     return gnutls_assert_val(ret);  | 
309  |  |  | 
310  | 0  |   return 0;  | 
311  | 0  | }  | 
312  |  |  | 
313  |  | static int generate_hs_traffic_keys(gnutls_session_t session)  | 
314  | 0  | { | 
315  | 0  |   int ret;  | 
316  | 0  |   unsigned null_key = 0;  | 
317  |  | 
  | 
318  | 0  |   if (unlikely(session->key.proto.tls13.temp_secret_size == 0))  | 
319  | 0  |     return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);  | 
320  |  |  | 
321  | 0  |   ret = _tls13_derive_secret(session, DERIVED_LABEL,  | 
322  | 0  |            sizeof(DERIVED_LABEL) - 1, NULL, 0,  | 
323  | 0  |            session->key.proto.tls13.temp_secret,  | 
324  | 0  |            session->key.proto.tls13.temp_secret);  | 
325  | 0  |   if (ret < 0) { | 
326  | 0  |     gnutls_assert();  | 
327  | 0  |     return ret;  | 
328  | 0  |   }  | 
329  |  |  | 
330  | 0  |   if ((session->security_parameters.entity == GNUTLS_CLIENT &&  | 
331  | 0  |        (!(session->internals.hsk_flags & HSK_KEY_SHARE_RECEIVED) ||  | 
332  | 0  |         (!(session->internals.hsk_flags & HSK_PSK_KE_MODE_DHE_PSK) &&  | 
333  | 0  |          session->internals.resumed))) ||  | 
334  | 0  |       (session->security_parameters.entity == GNUTLS_SERVER &&  | 
335  | 0  |        !(session->internals.hsk_flags & HSK_KEY_SHARE_SENT))) { | 
336  | 0  |     if ((session->internals.hsk_flags & HSK_PSK_SELECTED) &&  | 
337  | 0  |         (session->internals.hsk_flags & HSK_PSK_KE_MODE_PSK)) { | 
338  | 0  |       null_key = 1;  | 
339  | 0  |     }  | 
340  | 0  |   }  | 
341  |  | 
  | 
342  | 0  |   if (null_key) { | 
343  | 0  |     uint8_t digest[MAX_HASH_SIZE];  | 
344  | 0  |     unsigned digest_size;  | 
345  |  | 
  | 
346  | 0  |     if (unlikely(session->security_parameters.prf == NULL))  | 
347  | 0  |       return gnutls_assert_val(  | 
348  | 0  |         GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);  | 
349  |  |  | 
350  | 0  |     digest_size = session->security_parameters.prf->output_size;  | 
351  | 0  |     memset(digest, 0, digest_size);  | 
352  |  | 
  | 
353  | 0  |     ret = _tls13_update_secret(session, digest, digest_size);  | 
354  | 0  |     if (ret < 0) { | 
355  | 0  |       gnutls_assert();  | 
356  | 0  |       return ret;  | 
357  | 0  |     }  | 
358  | 0  |   } else { | 
359  | 0  |     if (unlikely(session->key.key.size == 0))  | 
360  | 0  |       return gnutls_assert_val(  | 
361  | 0  |         GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);  | 
362  |  |  | 
363  | 0  |     ret = _tls13_update_secret(session, session->key.key.data,  | 
364  | 0  |              session->key.key.size);  | 
365  | 0  |     if (ret < 0) { | 
366  | 0  |       gnutls_assert();  | 
367  | 0  |       return ret;  | 
368  | 0  |     }  | 
369  | 0  |   }  | 
370  |  |  | 
371  | 0  |   return 0;  | 
372  | 0  | }  | 
373  |  |  | 
374  |  | /*  | 
375  |  |  * _gnutls13_handshake_server  | 
376  |  |  * This function does the server stuff of the handshake protocol.  | 
377  |  |  */  | 
378  |  | int _gnutls13_handshake_server(gnutls_session_t session)  | 
379  | 0  | { | 
380  | 0  |   int ret = 0;  | 
381  |  | 
  | 
382  | 0  |   switch (STATE) { | 
383  | 0  |   case STATE90:  | 
384  | 0  |     ret = _gnutls13_handshake_hash_buffers_synth(  | 
385  | 0  |       session, session->security_parameters.prf, 0);  | 
386  | 0  |     STATE = STATE90;  | 
387  | 0  |     IMED_RET_FATAL("reset handshake buffers", ret, 0); | 
388  | 0  |     FALLTHROUGH;  | 
389  | 0  |   case STATE91:  | 
390  | 0  |     ret = _gnutls13_send_hello_retry_request(session,  | 
391  | 0  |                AGAIN(STATE91));  | 
392  | 0  |     STATE = STATE91;  | 
393  | 0  |     IMED_RET("send hello retry request", ret, 0); | 
394  | 0  |     FALLTHROUGH;  | 
395  | 0  |   case STATE92:  | 
396  | 0  | #ifdef TLS13_APPENDIX_D4  | 
397  | 0  |     if (session->internals.priorities->tls13_compat_mode) { | 
398  | 0  |       ret = _gnutls_send_change_cipher_spec(session,  | 
399  | 0  |                     AGAIN(STATE92));  | 
400  | 0  |       STATE = STATE92;  | 
401  | 0  |       IMED_RET("send change cipher spec", ret, 0); | 
402  | 0  |     }  | 
403  | 0  | #endif  | 
404  | 0  |     FALLTHROUGH;  | 
405  | 0  |   case STATE93:  | 
406  | 0  |     ret = _gnutls_recv_handshake(  | 
407  | 0  |       session, GNUTLS_HANDSHAKE_CLIENT_HELLO, 0, NULL);  | 
408  | 0  |     if (ret == GNUTLS_E_INT_RET_0) { | 
409  |  |       /* this is triggered by post_client_hello, and instructs the  | 
410  |  |        * handshake to proceed but be put on hold */  | 
411  | 0  |       ret = GNUTLS_E_INTERRUPTED;  | 
412  | 0  |       STATE = STATE94; /* hello already parsed -> move to next state */  | 
413  | 0  |     } else { | 
414  | 0  |       STATE = STATE93;  | 
415  | 0  |     }  | 
416  |  | 
  | 
417  | 0  |     IMED_RET("recv client hello", ret, 0); | 
418  | 0  |     FALLTHROUGH;  | 
419  | 0  |   case STATE94:  | 
420  | 0  |     ret = _gnutls_send_server_hello(session, AGAIN(STATE94));  | 
421  | 0  |     STATE = STATE94;  | 
422  | 0  |     IMED_RET("send hello", ret, 0); | 
423  | 0  |     FALLTHROUGH;  | 
424  | 0  |   case STATE99:  | 
425  | 0  |   case STATE100:  | 
426  | 0  | #ifdef TLS13_APPENDIX_D4  | 
427  |  |     /* don't send CCS twice: when HRR has already been  | 
428  |  |      * sent, CCS should have followed it (see above) */  | 
429  | 0  |     if (session->internals.priorities->tls13_compat_mode &&  | 
430  | 0  |         !(session->internals.hsk_flags & HSK_HRR_SENT)) { | 
431  | 0  |       ret = _gnutls_send_change_cipher_spec(session,  | 
432  | 0  |                     AGAIN(STATE100));  | 
433  | 0  |       STATE = STATE100;  | 
434  | 0  |       IMED_RET("send change cipher spec", ret, 0); | 
435  | 0  |     }  | 
436  | 0  | #endif  | 
437  | 0  |     FALLTHROUGH;  | 
438  | 0  |   case STATE101:  | 
439  | 0  |     STATE = STATE101;  | 
440  |  | 
  | 
441  | 0  |     ret = generate_hs_traffic_keys(session);  | 
442  | 0  |     IMED_RET_FATAL("generate hs traffic keys", ret, 0); | 
443  |  |  | 
444  | 0  |     if (session->internals.hsk_flags & HSK_EARLY_DATA_ACCEPTED) { | 
445  | 0  |       ret = _tls13_write_connection_state_init(session,  | 
446  | 0  |                  STAGE_HS);  | 
447  | 0  |     } else { | 
448  | 0  |       ret = _tls13_connection_state_init(session, STAGE_HS);  | 
449  | 0  |     }  | 
450  | 0  |     IMED_RET_FATAL("set hs traffic keys", ret, 0); | 
451  | 0  |     FALLTHROUGH;  | 
452  | 0  |   case STATE102:  | 
453  | 0  |     ret = _gnutls13_send_encrypted_extensions(session,  | 
454  | 0  |                 AGAIN(STATE102));  | 
455  | 0  |     STATE = STATE102;  | 
456  | 0  |     IMED_RET("send encrypted extensions", ret, 0); | 
457  | 0  |     FALLTHROUGH;  | 
458  | 0  |   case STATE103:  | 
459  | 0  |     ret = _gnutls13_send_certificate_request(session,  | 
460  | 0  |                AGAIN(STATE103));  | 
461  | 0  |     STATE = STATE103;  | 
462  | 0  |     IMED_RET("send certificate request", ret, 0); | 
463  | 0  |     FALLTHROUGH;  | 
464  | 0  |   case STATE104:  | 
465  | 0  |     ret = _gnutls13_send_certificate(session, AGAIN(STATE104));  | 
466  | 0  |     STATE = STATE104;  | 
467  | 0  |     IMED_RET("send certificate", ret, 0); | 
468  | 0  |     FALLTHROUGH;  | 
469  | 0  |   case STATE105:  | 
470  | 0  |     ret = _gnutls13_send_certificate_verify(session,  | 
471  | 0  |               AGAIN(STATE105));  | 
472  | 0  |     STATE = STATE105;  | 
473  | 0  |     IMED_RET("send certificate verify", ret, 0); | 
474  | 0  |     FALLTHROUGH;  | 
475  | 0  |   case STATE106:  | 
476  | 0  |     ret = _gnutls13_send_finished(session, AGAIN(STATE106));  | 
477  | 0  |     STATE = STATE106;  | 
478  | 0  |     IMED_RET("send finished", ret, 0); | 
479  | 0  |     FALLTHROUGH;  | 
480  | 0  |   case STATE107:  | 
481  | 0  |     ret = _gnutls13_recv_end_of_early_data(session);  | 
482  | 0  |     STATE = STATE107;  | 
483  | 0  |     IMED_RET("recv end of early data", ret, 0); | 
484  |  |  | 
485  | 0  |     if (session->internals.hsk_flags & HSK_EARLY_DATA_ACCEPTED) { | 
486  | 0  |       ret = _tls13_read_connection_state_init(session,  | 
487  | 0  |                 STAGE_HS);  | 
488  | 0  |       IMED_RET_FATAL(  | 
489  | 0  |         "set hs traffic key after receiving early data",  | 
490  | 0  |         ret, 0);  | 
491  | 0  |     }  | 
492  | 0  |     FALLTHROUGH;  | 
493  | 0  |   case STATE108:  | 
494  |  |     /* At this point our sending keys should be the app keys  | 
495  |  |      * see 4.4.4 at draft-ietf-tls-tls13-28 */  | 
496  | 0  |     ret = generate_ap_traffic_keys(session);  | 
497  | 0  |     IMED_RET_FATAL("generate app keys", ret, 0); | 
498  |  |  | 
499  |  |     /* If the session is unauthenticated, try to optimize the handshake by  | 
500  |  |      * sending the session ticket early. */  | 
501  | 0  |     if (!(session->internals.hsk_flags &  | 
502  | 0  |           (HSK_CRT_REQ_SENT | HSK_PSK_SELECTED))) { | 
503  | 0  |       STATE = STATE108;  | 
504  |  | 
  | 
505  | 0  |       ret = generate_non_auth_rms_keys(session);  | 
506  | 0  |       IMED_RET_FATAL("generate rms keys", ret, 0); | 
507  |  |  | 
508  | 0  |       session->internals.hsk_flags |= HSK_EARLY_START_USED;  | 
509  | 0  |       _gnutls_handshake_log(  | 
510  | 0  |         "HSK[%p]: unauthenticated session eligible for early start\n",  | 
511  | 0  |         session);  | 
512  | 0  |     }  | 
513  |  |  | 
514  | 0  |     ret = _tls13_write_connection_state_init(session, STAGE_APP);  | 
515  | 0  |     IMED_RET_FATAL("set write app keys", ret, 0); | 
516  |  |  | 
517  | 0  |     _gnutls_handshake_log(  | 
518  | 0  |       "HSK[%p]: switching early to application traffic keys\n",  | 
519  | 0  |       session);  | 
520  |  | 
  | 
521  | 0  |     FALLTHROUGH;  | 
522  | 0  |   case STATE109:  | 
523  | 0  |     if (session->internals.resumed)  | 
524  | 0  |       _gnutls_set_resumed_parameters(session);  | 
525  |  | 
  | 
526  | 0  |     if (session->internals.hsk_flags & HSK_EARLY_START_USED) { | 
527  | 0  |       if (!(session->internals.flags &  | 
528  | 0  |             GNUTLS_NO_AUTO_SEND_TICKET) &&  | 
529  | 0  |           _gnutls13_can_send_session_ticket(session)) { | 
530  | 0  |         ret = _gnutls13_send_session_ticket(  | 
531  | 0  |           session, TLS13_TICKETS_TO_SEND,  | 
532  | 0  |           AGAIN(STATE109));  | 
533  | 0  |       }  | 
534  |  | 
  | 
535  | 0  |       STATE = STATE109;  | 
536  | 0  |       IMED_RET("send session ticket", ret, 0); | 
537  |  |  | 
538  |  |       /* complete this phase of the handshake. We  | 
539  |  |        * should be called again by gnutls_record_recv()  | 
540  |  |        */  | 
541  |  |  | 
542  | 0  |       if (session->internals.flags &  | 
543  | 0  |           GNUTLS_ENABLE_EARLY_START) { | 
544  | 0  |         STATE = STATE113; /* finished */  | 
545  | 0  |         gnutls_assert();  | 
546  |  | 
  | 
547  | 0  |         session->internals.recv_state =  | 
548  | 0  |           RECV_STATE_EARLY_START;  | 
549  | 0  |         return 0;  | 
550  | 0  |       }  | 
551  | 0  |     }  | 
552  | 0  |     FALLTHROUGH;  | 
553  | 0  |   case STATE110:  | 
554  | 0  |     ret = _gnutls13_recv_certificate(session);  | 
555  | 0  |     STATE = STATE110;  | 
556  | 0  |     IMED_RET("recv certificate", ret, 0); | 
557  | 0  |     FALLTHROUGH;  | 
558  | 0  |   case STATE111:  | 
559  | 0  |     ret = _gnutls13_recv_certificate_verify(session);  | 
560  | 0  |     STATE = STATE111;  | 
561  | 0  |     IMED_RET("recv certificate verify", ret, 0); | 
562  | 0  |     FALLTHROUGH;  | 
563  | 0  |   case STATE112:  | 
564  | 0  |     ret = _gnutls_run_verify_callback(session, GNUTLS_CLIENT);  | 
565  | 0  |     STATE = STATE112;  | 
566  | 0  |     if (ret < 0)  | 
567  | 0  |       return gnutls_assert_val(ret);  | 
568  | 0  |     FALLTHROUGH;  | 
569  | 0  |   case STATE113: /* can enter from STATE109 */  | 
570  | 0  |     ret = _gnutls13_recv_finished(session);  | 
571  | 0  |     STATE = STATE113;  | 
572  | 0  |     IMED_RET("recv finished", ret, 0); | 
573  | 0  |     FALLTHROUGH;  | 
574  | 0  |   case STATE114:  | 
575  |  |     /* If we did request a client certificate, then we can  | 
576  |  |      * only send the tickets here */  | 
577  | 0  |     STATE = STATE114;  | 
578  |  | 
  | 
579  | 0  |     if (!(session->internals.hsk_flags & HSK_EARLY_START_USED)) { | 
580  | 0  |       ret = generate_rms_keys(session);  | 
581  | 0  |       IMED_RET_FATAL("generate rms keys", ret, 0); | 
582  | 0  |     }  | 
583  |  |  | 
584  | 0  |     ret = _tls13_read_connection_state_init(session, STAGE_APP);  | 
585  | 0  |     IMED_RET_FATAL("set read app keys", ret, 0); | 
586  |  |  | 
587  | 0  |     FALLTHROUGH;  | 
588  | 0  |   case STATE115:  | 
589  | 0  |     if (!(session->internals.hsk_flags &  | 
590  | 0  |           (HSK_TLS13_TICKET_SENT | HSK_EARLY_START_USED)) &&  | 
591  | 0  |         !(session->internals.flags & GNUTLS_NO_AUTO_SEND_TICKET) &&  | 
592  | 0  |         _gnutls13_can_send_session_ticket(session)) { | 
593  | 0  |       ret = _gnutls13_send_session_ticket(  | 
594  | 0  |         session, TLS13_TICKETS_TO_SEND,  | 
595  | 0  |         AGAIN(STATE115));  | 
596  | 0  |       STATE = STATE115;  | 
597  | 0  |       IMED_RET("send session ticket", ret, 0); | 
598  | 0  |     }  | 
599  |  |  | 
600  | 0  |     STATE = STATE0;  | 
601  | 0  |     break;  | 
602  | 0  |   default:  | 
603  | 0  |     return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);  | 
604  | 0  |   }  | 
605  |  |  | 
606  |  |   /* explicitly reset any early start flags */  | 
607  | 0  |   gnutls_mutex_lock(&session->internals.post_negotiation_lock);  | 
608  | 0  |   session->internals.recv_state = RECV_STATE_0;  | 
609  | 0  |   session->internals.initial_negotiation_completed = 1;  | 
610  | 0  |   gnutls_mutex_unlock(&session->internals.post_negotiation_lock);  | 
611  |  | 
  | 
612  | 0  |   SAVE_TRANSCRIPT;  | 
613  |  | 
  | 
614  | 0  |   return 0;  | 
615  | 0  | }  | 
616  |  |  | 
617  |  | /* Processes handshake messages received asynchronously after initial handshake.  | 
618  |  |  *  | 
619  |  |  * It is called once per message and should return success, or a fatal error code.  | 
620  |  |  */  | 
621  |  | int _gnutls13_recv_async_handshake(gnutls_session_t session)  | 
622  | 0  | { | 
623  | 0  |   int ret;  | 
624  | 0  |   handshake_buffer_st hsk;  | 
625  | 0  |   recv_state_t next_state = RECV_STATE_0;  | 
626  |  |  | 
627  |  |   /* The following messages are expected asynchronously after  | 
628  |  |    * the handshake process is complete */  | 
629  | 0  |   if (unlikely(session->internals.handshake_in_progress))  | 
630  | 0  |     return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET);  | 
631  |  |  | 
632  | 0  |   do { | 
633  | 0  |     _gnutls_handshake_buffer_init(&hsk);  | 
634  |  |  | 
635  |  |     /* the received handshake message has already been pushed into  | 
636  |  |      * handshake buffers. As we do not need to use the handshake hash  | 
637  |  |      * buffers we call the lower level receive functions */  | 
638  | 0  |     ret = _gnutls_handshake_io_recv_int(  | 
639  | 0  |       session, GNUTLS_HANDSHAKE_ANY, &hsk, 0);  | 
640  | 0  |     if (ret < 0) { | 
641  | 0  |       gnutls_assert();  | 
642  | 0  |       goto cleanup;  | 
643  | 0  |     }  | 
644  | 0  |     session->internals.last_handshake_in = hsk.htype;  | 
645  |  | 
  | 
646  | 0  |     ret = _gnutls_call_hook_func(session, hsk.htype,  | 
647  | 0  |                GNUTLS_HOOK_PRE, 1, hsk.data.data,  | 
648  | 0  |                hsk.data.length);  | 
649  | 0  |     if (ret < 0) { | 
650  | 0  |       gnutls_assert();  | 
651  | 0  |       goto cleanup;  | 
652  | 0  |     }  | 
653  |  |  | 
654  | 0  |     switch (hsk.htype) { | 
655  | 0  |     case GNUTLS_HANDSHAKE_CERTIFICATE_REQUEST:  | 
656  | 0  |       if (!(session->security_parameters.entity ==  | 
657  | 0  |             GNUTLS_CLIENT) ||  | 
658  | 0  |           !(session->internals.flags &  | 
659  | 0  |             GNUTLS_POST_HANDSHAKE_AUTH)) { | 
660  | 0  |         ret = gnutls_assert_val(  | 
661  | 0  |           GNUTLS_E_UNEXPECTED_PACKET);  | 
662  | 0  |         goto cleanup;  | 
663  | 0  |       }  | 
664  |  |  | 
665  | 0  |       _gnutls_buffer_reset(&session->internals.reauth_buffer);  | 
666  |  |  | 
667  |  |       /* include the handshake headers in reauth buffer */  | 
668  | 0  |       ret = _gnutls_buffer_append_data(  | 
669  | 0  |         &session->internals.reauth_buffer, hsk.header,  | 
670  | 0  |         hsk.header_size);  | 
671  | 0  |       if (ret < 0) { | 
672  | 0  |         gnutls_assert();  | 
673  | 0  |         goto cleanup;  | 
674  | 0  |       }  | 
675  |  |  | 
676  | 0  |       ret = _gnutls_buffer_append_data(  | 
677  | 0  |         &session->internals.reauth_buffer,  | 
678  | 0  |         hsk.data.data, hsk.data.length);  | 
679  | 0  |       if (ret < 0) { | 
680  | 0  |         gnutls_assert();  | 
681  | 0  |         goto cleanup;  | 
682  | 0  |       }  | 
683  |  |  | 
684  | 0  |       if (session->internals.flags & GNUTLS_AUTO_REAUTH) { | 
685  | 0  |         ret = gnutls_reauth(session, 0);  | 
686  | 0  |         if (ret == GNUTLS_E_AGAIN ||  | 
687  | 0  |             ret == GNUTLS_E_INTERRUPTED) { | 
688  | 0  |           next_state = RECV_STATE_REAUTH;  | 
689  | 0  |         } else if (ret < 0) { | 
690  | 0  |           gnutls_assert();  | 
691  | 0  |           goto cleanup;  | 
692  | 0  |         }  | 
693  | 0  |       } else { | 
694  |  |         /* Application is expected to handle re-authentication  | 
695  |  |          * explicitly.  */  | 
696  | 0  |         ret = GNUTLS_E_REAUTH_REQUEST;  | 
697  | 0  |       }  | 
698  |  |  | 
699  | 0  |       goto cleanup;  | 
700  |  |  | 
701  | 0  |     case GNUTLS_HANDSHAKE_KEY_UPDATE:  | 
702  | 0  |       ret = _gnutls13_recv_key_update(session, &hsk.data);  | 
703  | 0  |       if (ret < 0) { | 
704  | 0  |         gnutls_assert();  | 
705  | 0  |         goto cleanup;  | 
706  | 0  |       }  | 
707  |  |  | 
708  |  |       /* Handshake messages MUST NOT span key changes, i.e., we  | 
709  |  |        * should not have any other pending handshake messages from  | 
710  |  |        * the same record. */  | 
711  | 0  |       if (session->internals.handshake_recv_buffer_size !=  | 
712  | 0  |           0) { | 
713  | 0  |         ret = gnutls_assert_val(  | 
714  | 0  |           GNUTLS_E_UNEXPECTED_PACKET);  | 
715  | 0  |         goto cleanup;  | 
716  | 0  |       }  | 
717  | 0  |       break;  | 
718  | 0  |     case GNUTLS_HANDSHAKE_NEW_SESSION_TICKET:  | 
719  | 0  |       if (session->security_parameters.entity !=  | 
720  | 0  |           GNUTLS_CLIENT) { | 
721  | 0  |         ret = gnutls_assert_val(  | 
722  | 0  |           GNUTLS_E_UNEXPECTED_PACKET);  | 
723  | 0  |         goto cleanup;  | 
724  | 0  |       }  | 
725  |  |  | 
726  | 0  |       ret = _gnutls13_recv_session_ticket(session, &hsk.data);  | 
727  | 0  |       if (ret < 0) { | 
728  | 0  |         gnutls_assert();  | 
729  | 0  |         goto cleanup;  | 
730  | 0  |       }  | 
731  |  |  | 
732  | 0  |       memcpy(session->internals.tls13_ticket  | 
733  | 0  |                .resumption_master_secret,  | 
734  | 0  |              session->key.proto.tls13.ap_rms,  | 
735  | 0  |              session->key.proto.tls13.temp_secret_size);  | 
736  |  | 
  | 
737  | 0  |       session->internals.tls13_ticket.prf =  | 
738  | 0  |         session->security_parameters.prf;  | 
739  | 0  |       session->internals.hsk_flags |= HSK_TICKET_RECEIVED;  | 
740  | 0  |       break;  | 
741  | 0  |     default:  | 
742  | 0  |       gnutls_assert();  | 
743  | 0  |       ret = GNUTLS_E_UNEXPECTED_PACKET;  | 
744  | 0  |       goto cleanup;  | 
745  | 0  |     }  | 
746  |  |  | 
747  | 0  |     ret = _gnutls_call_hook_func(session, hsk.htype,  | 
748  | 0  |                GNUTLS_HOOK_POST, 1, hsk.data.data,  | 
749  | 0  |                hsk.data.length);  | 
750  | 0  |     if (ret < 0) { | 
751  | 0  |       gnutls_assert();  | 
752  | 0  |       goto cleanup;  | 
753  | 0  |     }  | 
754  | 0  |     _gnutls_handshake_buffer_clear(&hsk);  | 
755  |  | 
  | 
756  | 0  |   } while (_gnutls_record_buffer_get_size(session) > 0);  | 
757  |  |  | 
758  | 0  |   session->internals.recv_state = next_state;  | 
759  |  | 
  | 
760  | 0  |   return 0;  | 
761  |  |  | 
762  | 0  | cleanup:  | 
763  |  |   /* if we have pending/partial handshake data in buffers, ensure that  | 
764  |  |    * next read will read handshake data */  | 
765  | 0  |   if (_gnutls_record_buffer_get_size(session) > 0)  | 
766  | 0  |     session->internals.recv_state = RECV_STATE_ASYNC_HANDSHAKE;  | 
767  | 0  |   else  | 
768  | 0  |     session->internals.recv_state = next_state;  | 
769  |  | 
  | 
770  | 0  |   _gnutls_handshake_buffer_clear(&hsk);  | 
771  | 0  |   return ret;  | 
772  | 0  | }  | 
773  |  |  | 
774  |  | /**  | 
775  |  |  * gnutls_session_ticket_send:  | 
776  |  |  * @session: is a #gnutls_session_t type.  | 
777  |  |  * @nr: the number of tickets to send  | 
778  |  |  * @flags: must be zero  | 
779  |  |  *  | 
780  |  |  * Sends a fresh session ticket to the peer. This is relevant only  | 
781  |  |  * in server side under TLS1.3. This function may also return %GNUTLS_E_AGAIN  | 
782  |  |  * or %GNUTLS_E_INTERRUPTED and in that case it must be called again.  | 
783  |  |  *  | 
784  |  |  * Returns: %GNUTLS_E_SUCCESS on success, or a negative error code.  | 
785  |  |  **/  | 
786  |  | int gnutls_session_ticket_send(gnutls_session_t session, unsigned nr,  | 
787  |  |              unsigned flags)  | 
788  | 0  | { | 
789  | 0  |   int ret = 0;  | 
790  | 0  |   const version_entry_st *vers = get_version(session);  | 
791  |  | 
  | 
792  | 0  |   if (!vers->tls13_sem ||  | 
793  | 0  |       session->security_parameters.entity == GNUTLS_CLIENT)  | 
794  | 0  |     return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);  | 
795  |  |  | 
796  | 0  |   if (nr == 0)  | 
797  | 0  |     return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);  | 
798  |  |  | 
799  | 0  |   switch (TICKET_STATE) { | 
800  | 0  |   case TICKET_STATE0:  | 
801  | 0  |     ret = _gnutls_io_write_flush(session);  | 
802  | 0  |     TICKET_STATE = TICKET_STATE0;  | 
803  | 0  |     if (ret < 0) { | 
804  | 0  |       gnutls_assert();  | 
805  | 0  |       return ret;  | 
806  | 0  |     }  | 
807  | 0  |     FALLTHROUGH;  | 
808  | 0  |   case TICKET_STATE1:  | 
809  | 0  |     ret = _gnutls13_send_session_ticket(  | 
810  | 0  |       session, nr, TICKET_STATE == TICKET_STATE1 ? 1 : 0);  | 
811  | 0  |     TICKET_STATE = TICKET_STATE1;  | 
812  | 0  |     if (ret < 0) { | 
813  | 0  |       gnutls_assert();  | 
814  | 0  |       return ret;  | 
815  | 0  |     }  | 
816  | 0  |     break;  | 
817  | 0  |   default:  | 
818  | 0  |     gnutls_assert();  | 
819  | 0  |     return GNUTLS_E_INTERNAL_ERROR;  | 
820  | 0  |   }  | 
821  |  |  | 
822  | 0  |   TICKET_STATE = TICKET_STATE0;  | 
823  |  | 
  | 
824  | 0  |   return 0;  | 
825  | 0  | }  |