Line data Source code
1 : /* 2 : * Copyright (C) 2017 Free Software Foundation, Inc. 3 : * 4 : * Author: Ander Juaristi 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 : #include "gnutls_int.h" 24 : #include "ext/psk_ke_modes.h" 25 : #include "ext/pre_shared_key.h" 26 : #include <assert.h> 27 : 28 : #define PSK_KE 0 29 : #define PSK_DHE_KE 1 30 : 31 : static int 32 5627 : psk_ke_modes_send_params(gnutls_session_t session, 33 : gnutls_buffer_t extdata) 34 : { 35 5627 : int ret; 36 5627 : const version_entry_st *vers; 37 5627 : uint8_t data[2]; 38 5627 : unsigned pos, i; 39 5627 : unsigned have_dhpsk = 0; 40 5627 : unsigned have_psk = 0; 41 : 42 : /* Server doesn't send psk_key_exchange_modes */ 43 5627 : if (session->security_parameters.entity == GNUTLS_SERVER) 44 : return 0; 45 : 46 : /* If session ticket is disabled and no PSK key exchange is 47 : * enabled, don't send the extension */ 48 3467 : if ((session->internals.flags & GNUTLS_NO_TICKETS) && 49 105 : !session->internals.priorities->have_psk) 50 : return 0; 51 : 52 3389 : vers = _gnutls_version_max(session); 53 3389 : if (!vers || !vers->tls13_sem) 54 : return 0; 55 : 56 : /* We send the list prioritized according to our preferences as a convention 57 : * (used throughout the protocol), even if the protocol doesn't mandate that 58 : * for this particular message. That way we can keep the TLS 1.2 semantics/ 59 : * prioritization when negotiating PSK or DHE-PSK. Receiving servers would 60 : * very likely respect our prioritization if they parse the message serially. */ 61 : pos = 0; 62 7487 : for (i=0;i<session->internals.priorities->_kx.num_priorities;i++) { 63 5960 : if (session->internals.priorities->_kx.priorities[i] == GNUTLS_KX_PSK && !have_psk) { 64 423 : assert(pos <= 1); 65 423 : data[pos++] = PSK_KE; 66 423 : session->internals.hsk_flags |= HSK_PSK_KE_MODE_PSK; 67 423 : have_psk = 1; 68 5537 : } else if ((session->internals.priorities->_kx.priorities[i] == GNUTLS_KX_DHE_PSK || 69 761 : session->internals.priorities->_kx.priorities[i] == GNUTLS_KX_ECDHE_PSK) && !have_dhpsk) { 70 414 : assert(pos <= 1); 71 414 : data[pos++] = PSK_DHE_KE; 72 414 : session->internals.hsk_flags |= HSK_PSK_KE_MODE_DHE_PSK; 73 414 : have_dhpsk = 1; 74 : } 75 : 76 5960 : if (have_psk && have_dhpsk) 77 : break; 78 : } 79 : 80 : /* For session resumption we need to send at least one */ 81 1900 : if (pos == 0) { 82 1436 : if (session->internals.flags & GNUTLS_NO_TICKETS) 83 : return 0; 84 : 85 1436 : data[pos++] = PSK_DHE_KE; 86 1436 : data[pos++] = PSK_KE; 87 1436 : session->internals.hsk_flags |= HSK_PSK_KE_MODE_DHE_PSK; 88 1436 : session->internals.hsk_flags |= HSK_PSK_KE_MODE_PSK; 89 : } 90 : 91 1900 : ret = _gnutls_buffer_append_data_prefix(extdata, 8, data, pos); 92 1900 : if (ret < 0) 93 0 : return gnutls_assert_val(ret); 94 : 95 1900 : session->internals.hsk_flags |= HSK_PSK_KE_MODES_SENT; 96 : 97 1900 : return 0; 98 : } 99 : 100 : #define MAX_POS INT_MAX 101 : 102 : /* 103 : * Since we only support ECDHE-authenticated PSKs, the server 104 : * just verifies that a "psk_key_exchange_modes" extension was received, 105 : * and that it contains the value one. 106 : */ 107 : static int 108 3001 : psk_ke_modes_recv_params(gnutls_session_t session, 109 : const unsigned char *data, size_t len) 110 : { 111 3001 : uint8_t ke_modes_len; 112 3001 : const version_entry_st *vers = get_version(session); 113 3001 : gnutls_psk_server_credentials_t cred; 114 3001 : int dhpsk_pos = MAX_POS; 115 3001 : int psk_pos = MAX_POS; 116 3001 : int cli_psk_pos = MAX_POS; 117 3001 : int cli_dhpsk_pos = MAX_POS; 118 3001 : unsigned i; 119 : 120 : /* Client doesn't receive psk_key_exchange_modes */ 121 3001 : if (session->security_parameters.entity == GNUTLS_CLIENT) 122 0 : return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION); 123 : 124 : /* we set hsk_flags to HSK_PSK_KE_MODE_INVALID on failure to ensure that 125 : * when we parse the pre-shared key extension we detect PSK_KE_MODES as 126 : * received. */ 127 3001 : if (!vers || !vers->tls13_sem) { 128 125 : session->internals.hsk_flags |= HSK_PSK_KE_MODE_INVALID; 129 127 : return gnutls_assert_val(0); 130 : } 131 : 132 2876 : cred = (gnutls_psk_server_credentials_t)_gnutls_get_cred(session, GNUTLS_CRD_PSK); 133 2876 : if (cred == NULL && (session->internals.flags & GNUTLS_NO_TICKETS)) { 134 517 : session->internals.hsk_flags |= HSK_PSK_KE_MODE_INVALID; 135 517 : return gnutls_assert_val(0); 136 : } 137 : 138 2359 : DECR_LEN(len, 1); 139 2359 : ke_modes_len = *(data++); 140 : 141 11452 : for (i=0;i<session->internals.priorities->_kx.num_priorities;i++) { 142 9873 : if (session->internals.priorities->_kx.priorities[i] == GNUTLS_KX_PSK && psk_pos == MAX_POS) { 143 1748 : psk_pos = i; 144 8125 : } else if ((session->internals.priorities->_kx.priorities[i] == GNUTLS_KX_DHE_PSK || 145 1074 : session->internals.priorities->_kx.priorities[i] == GNUTLS_KX_ECDHE_PSK) && 146 : dhpsk_pos == MAX_POS) { 147 1066 : dhpsk_pos = i; 148 : } 149 : 150 9873 : if (dhpsk_pos != MAX_POS && psk_pos != MAX_POS) 151 : break; 152 : } 153 : 154 2359 : if (psk_pos == MAX_POS && dhpsk_pos == MAX_POS) { 155 325 : if (!(session->internals.flags & GNUTLS_NO_TICKETS)) 156 : dhpsk_pos = 0; 157 0 : else if (session->internals.priorities->groups.size == 0) 158 0 : return gnutls_assert_val(0); 159 : } 160 : 161 4718 : for (i=0;i<ke_modes_len;i++) { 162 3279 : DECR_LEN(len, 1); 163 3279 : if (data[i] == PSK_DHE_KE) 164 1387 : cli_dhpsk_pos = i; 165 1892 : else if (data[i] == PSK_KE) 166 1892 : cli_psk_pos = i; 167 : 168 3279 : _gnutls_handshake_log("EXT[%p]: PSK KE mode %.2x received\n", 169 : session, (unsigned)data[i]); 170 3279 : if (cli_psk_pos != MAX_POS && cli_dhpsk_pos != MAX_POS) 171 : break; 172 : } 173 : 174 2359 : if (session->internals.priorities->server_precedence) { 175 130 : if (dhpsk_pos != MAX_POS && cli_dhpsk_pos != MAX_POS && dhpsk_pos < psk_pos) 176 0 : session->internals.hsk_flags |= HSK_PSK_KE_MODE_DHE_PSK; 177 130 : else if (psk_pos != MAX_POS && cli_psk_pos != MAX_POS && psk_pos < dhpsk_pos) 178 130 : session->internals.hsk_flags |= HSK_PSK_KE_MODE_PSK; 179 : } else { 180 2229 : if (dhpsk_pos != MAX_POS && cli_dhpsk_pos != MAX_POS && cli_dhpsk_pos < cli_psk_pos) 181 927 : session->internals.hsk_flags |= HSK_PSK_KE_MODE_DHE_PSK; 182 1302 : else if (psk_pos != MAX_POS && cli_psk_pos != MAX_POS && cli_psk_pos < cli_dhpsk_pos) 183 1299 : session->internals.hsk_flags |= HSK_PSK_KE_MODE_PSK; 184 : } 185 : 186 2359 : if ((session->internals.hsk_flags & HSK_PSK_KE_MODE_PSK) || 187 : (session->internals.hsk_flags & HSK_PSK_KE_MODE_DHE_PSK)) { 188 : 189 : return 0; 190 : } else { 191 3 : session->internals.hsk_flags |= HSK_PSK_KE_MODE_INVALID; 192 4 : return gnutls_assert_val(0); 193 : } 194 : } 195 : 196 : const hello_ext_entry_st ext_mod_psk_ke_modes = { 197 : .name = "PSK Key Exchange Modes", 198 : .tls_id = 45, 199 : .gid = GNUTLS_EXTENSION_PSK_KE_MODES, 200 : .client_parse_point = GNUTLS_EXT_TLS, 201 : .server_parse_point = GNUTLS_EXT_TLS, 202 : .validity = GNUTLS_EXT_FLAG_TLS | GNUTLS_EXT_FLAG_CLIENT_HELLO | GNUTLS_EXT_FLAG_TLS13_SERVER_HELLO, 203 : .send_func = psk_ke_modes_send_params, 204 : .recv_func = psk_ke_modes_recv_params 205 : };