Line data Source code
1 : /* 2 : * Copyright (C) 2000-2012 Free Software Foundation, Inc. 3 : * Copyright (C) 2017 Red Hat, Inc. 4 : * 5 : * Author: Nikos Mavrogiannopoulos 6 : * 7 : * This file is part of GnuTLS. 8 : * 9 : * The GnuTLS is free software; you can redistribute it and/or 10 : * modify it under the terms of the GNU Lesser General Public License 11 : * as published by the Free Software Foundation; either version 2.1 of 12 : * the License, or (at your option) any later version. 13 : * 14 : * This library is distributed in the hope that it will be useful, but 15 : * WITHOUT ANY WARRANTY; without even the implied warranty of 16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 : * Lesser General Public License for more details. 18 : * 19 : * You should have received a copy of the GNU Lesser General Public License 20 : * along with this program. If not, see <https://www.gnu.org/licenses/> 21 : * 22 : */ 23 : 24 : #ifndef GNUTLS_LIB_HANDSHAKE_H 25 : #define GNUTLS_LIB_HANDSHAKE_H 26 : 27 : #include "errors.h" 28 : #include "record.h" 29 : #include <assert.h> 30 : 31 : /* The following two macros are used in the handshake state machines; the first 32 : * (IMED_RET) accounts for non-fatal errors and re-entry to current state, while 33 : * the latter invalidates the handshake on any error (to be used by functions 34 : * that are not expected to return non-fatal errors). 35 : */ 36 : #define IMED_RET( str, ret, allow_alert) do { \ 37 : if (ret < 0) { \ 38 : /* EAGAIN and INTERRUPTED are always non-fatal */ \ 39 : if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) \ 40 : return ret; \ 41 : if (ret == GNUTLS_E_GOT_APPLICATION_DATA && session->internals.initial_negotiation_completed != 0) \ 42 : return ret; \ 43 : if (session->internals.handshake_suspicious_loops < 16) { \ 44 : if (ret == GNUTLS_E_LARGE_PACKET) { \ 45 : session->internals.handshake_suspicious_loops++; \ 46 : return ret; \ 47 : } \ 48 : /* a warning alert might interrupt handshake */ \ 49 : if (allow_alert != 0 && ret==GNUTLS_E_WARNING_ALERT_RECEIVED) { \ 50 : session->internals.handshake_suspicious_loops++; \ 51 : return ret; \ 52 : } \ 53 : } \ 54 : gnutls_assert(); \ 55 : /* do not allow non-fatal errors at this point */ \ 56 : if (gnutls_error_is_fatal(ret) == 0) ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); \ 57 : session_invalidate(session); \ 58 : _gnutls_handshake_hash_buffers_clear(session); \ 59 : return ret; \ 60 : } } while (0) 61 : 62 : #define IMED_RET_FATAL( str, ret, allow_alert) do { \ 63 : if (ret < 0) { \ 64 : gnutls_assert(); \ 65 : if (gnutls_error_is_fatal(ret) == 0) \ 66 : ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); \ 67 : session_invalidate(session); \ 68 : _gnutls_handshake_hash_buffers_clear(session); \ 69 : return ret; \ 70 : } } while (0) 71 : 72 : int _gnutls_send_handshake(gnutls_session_t session, mbuffer_st * bufel, 73 : gnutls_handshake_description_t type); 74 : int _gnutls_recv_handshake(gnutls_session_t session, 75 : gnutls_handshake_description_t type, 76 : unsigned int optional, gnutls_buffer_st * buf); 77 : 78 : int 79 : _gnutls_send_handshake2(gnutls_session_t session, mbuffer_st * bufel, 80 : gnutls_handshake_description_t type, unsigned queue_only); 81 : 82 : int _gnutls_generate_session_id(uint8_t * session_id, uint8_t * len); 83 : int _gnutls_gen_server_random(gnutls_session_t session, int version); 84 : void _gnutls_set_client_random(gnutls_session_t session, uint8_t * rnd); 85 : 86 : ssize_t _gnutls_send_change_cipher_spec(gnutls_session_t session, int again); 87 : 88 : int _gnutls_send_server_hello(gnutls_session_t session, int again); 89 : 90 : int _gnutls_find_pk_algos_in_ciphersuites(uint8_t * data, int datalen); 91 : int _gnutls_server_select_suite(gnutls_session_t session, uint8_t * data, 92 : unsigned int datalen, unsigned int scsv_only); 93 : 94 : int _gnutls_negotiate_version(gnutls_session_t session, 95 : uint8_t major, uint8_t minor, 96 : unsigned allow_tls13); 97 : int _gnutls_user_hello_func(gnutls_session_t session, 98 : uint8_t major, uint8_t minor); 99 : 100 : void _gnutls_handshake_hash_buffers_clear(gnutls_session_t session); 101 : 102 : int _gnutls13_handshake_hash_buffers_synth(gnutls_session_t session, 103 : const mac_entry_st *prf, 104 : unsigned client); 105 : 106 : #define STATE session->internals.handshake_state 107 : #define FINAL_STATE session->internals.handshake_final_state 108 : /* This returns true if we have got there 109 : * before (and not finished due to an interrupt). 110 : */ 111 : #define AGAIN(target) (STATE==target?1:0) 112 : #define FAGAIN(target) (FINAL_STATE==target?1:0) 113 : #define AGAIN2(state, target) (state==target?1:0) 114 : 115 : /* return the remaining time in ms */ 116 20373728 : inline static int handshake_remaining_time(gnutls_session_t session) 117 : { 118 20373728 : struct timespec *end = &session->internals.handshake_abs_timeout; 119 : 120 20373728 : if (end->tv_sec || end->tv_nsec) { 121 7538952 : struct timespec now; 122 7538952 : gnutls_gettime(&now); 123 : 124 7538952 : if (now.tv_sec < end->tv_sec || 125 1 : (now.tv_sec == end->tv_sec && now.tv_nsec < end->tv_nsec)) 126 : { 127 7538952 : long long now_ms = now.tv_sec * 1000LL + now.tv_nsec / 1000000; 128 7538952 : long long end_ms = end->tv_sec * 1000LL + end->tv_nsec / 1000000; 129 : 130 7538952 : return end_ms - now_ms; 131 : } else 132 0 : return gnutls_assert_val(GNUTLS_E_TIMEDOUT); 133 : } 134 : return 0; 135 : } 136 : 137 : /* Returns non-zero if the present credentials are sufficient for TLS1.3 negotiation. 138 : * This is to be used in client side only. On server side, it is allowed to start 139 : * without credentials. 140 : */ 141 8145 : inline static unsigned have_creds_for_tls13(gnutls_session_t session) 142 : { 143 8145 : assert(session->security_parameters.entity == GNUTLS_CLIENT); 144 10072 : if (_gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE) != NULL || 145 1927 : _gnutls_get_cred(session, GNUTLS_CRD_PSK) != NULL) 146 7609 : return 1; 147 : 148 : return 0; 149 : } 150 : 151 : int _gnutls_handshake_get_session_hash(gnutls_session_t session, gnutls_datum_t *shash); 152 : 153 : int _gnutls_check_id_for_change(gnutls_session_t session); 154 : int _gnutls_check_if_cert_hash_is_same(gnutls_session_t session, gnutls_certificate_credentials_t cred); 155 : 156 : #include "handshake-defs.h" 157 : 158 : int _gnutls_call_hook_func(gnutls_session_t session, 159 : gnutls_handshake_description_t type, 160 : int post, unsigned incoming, 161 : const uint8_t *data, unsigned data_size); 162 : 163 : int _gnutls_run_verify_callback(gnutls_session_t session, unsigned int side); 164 : int _gnutls_recv_finished(gnutls_session_t session); 165 : int _gnutls_send_finished(gnutls_session_t session, int again); 166 : 167 : int _gnutls13_handshake_client(gnutls_session_t session); 168 : int _gnutls13_handshake_server(gnutls_session_t session); 169 : 170 : int 171 : _gnutls13_recv_hello_retry_request(gnutls_session_t session, 172 : gnutls_buffer_st *buf); 173 : 174 : int 175 : _gnutls13_recv_async_handshake(gnutls_session_t session); 176 : 177 : #endif /* GNUTLS_LIB_HANDSHAKE_H */