Branch data Line data Source code
1 : : /*
2 : : * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 : : *
4 : : * Licensed under the Apache License, Version 2.0 (the "License").
5 : : * You may not use this file except in compliance with the License.
6 : : * A copy of the License is located at
7 : : *
8 : : * http://aws.amazon.com/apache2.0
9 : : *
10 : : * or in the "license" file accompanying this file. This file is distributed
11 : : * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12 : : * express or implied. See the License for the specific language governing
13 : : * permissions and limitations under the License.
14 : : */
15 : :
16 : : #include "tls/extensions/s2n_client_psk.h"
17 : :
18 : : #include <stdint.h>
19 : :
20 : : #include "crypto/s2n_hash.h"
21 : : #include "tls/s2n_psk.h"
22 : : #include "tls/s2n_tls.h"
23 : : #include "tls/s2n_tls_parameters.h"
24 : : #include "utils/s2n_bitmap.h"
25 : : #include "utils/s2n_safety.h"
26 : :
27 : 1093 : #define SIZE_OF_BINDER_SIZE sizeof(uint8_t)
28 : 2141 : #define SIZE_OF_BINDER_LIST_SIZE sizeof(uint16_t)
29 : :
30 : : /* To avoid a DoS attack triggered by decrypting too many session tickets,
31 : : * set a limit on the number of tickets we will attempt to decrypt before giving up.
32 : : * We may want to make this configurable someday, but just set a reasonable maximum for now. */
33 : 113 : #define MAX_REJECTED_TICKETS 3
34 : :
35 : : static int s2n_client_psk_send(struct s2n_connection *conn, struct s2n_stuffer *out);
36 : : static int s2n_client_psk_recv(struct s2n_connection *conn, struct s2n_stuffer *extension);
37 : : static int s2n_client_psk_is_missing(struct s2n_connection *conn);
38 : :
39 : : const s2n_extension_type s2n_client_psk_extension = {
40 : : .iana_value = TLS_EXTENSION_PRE_SHARED_KEY,
41 : : .minimum_version = S2N_TLS13,
42 : : .is_response = false,
43 : : .send = s2n_client_psk_send,
44 : : .recv = s2n_client_psk_recv,
45 : : .should_send = s2n_client_psk_should_send,
46 : : .if_missing = s2n_client_psk_is_missing,
47 : : };
48 : :
49 : : int s2n_client_psk_is_missing(struct s2n_connection *conn)
50 : 4332 : {
51 [ # # ][ - + ]: 4332 : POSIX_ENSURE_REF(conn);
52 : :
53 : : /* If the PSK extension is missing, we must not have received
54 : : * a request for early data.
55 : : *
56 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-4.2.10
57 : : *# When a PSK is used and early data is allowed for that PSK, the client
58 : : *# can send Application Data in its first flight of messages. If the
59 : : *# client opts to do so, it MUST supply both the "pre_shared_key" and
60 : : *# "early_data" extensions.
61 : : */
62 [ # # ][ - + ]: 4332 : POSIX_ENSURE(conn->early_data_state != S2N_EARLY_DATA_REQUESTED, S2N_ERR_UNSUPPORTED_EXTENSION);
63 : 4332 : return S2N_SUCCESS;
64 : 4332 : }
65 : :
66 : : bool s2n_client_psk_should_send(struct s2n_connection *conn)
67 : 6586 : {
68 [ + + ][ - + ]: 6586 : if (!conn || !conn->secure) {
69 : 1 : return false;
70 : 1 : }
71 : :
72 : : /* If this is NOT the second ClientHello after a retry, then all PSKs are viable.
73 : : * Send the extension if any PSKs are configured.
74 : : */
75 [ + + ]: 6585 : if (!s2n_is_hello_retry_handshake(conn)) {
76 : 5917 : return conn->psk_params.psk_list.len > 0;
77 : 5917 : }
78 : :
79 : : /* If this is the second ClientHello after a retry, then only PSKs that match the cipher suite
80 : : * are viable. Only send the extension if at least one configured PSK matches the cipher suite.
81 : : */
82 [ + + ]: 674 : for (size_t i = 0; i < conn->psk_params.psk_list.len; i++) {
83 : 480 : struct s2n_psk *psk = NULL;
84 [ + - ]: 480 : if (s2n_result_is_ok(s2n_array_get(&conn->psk_params.psk_list, i, (void **) &psk))
85 [ + - ]: 480 : && psk != NULL
86 [ + + ]: 480 : && conn->secure->cipher_suite->prf_alg == psk->hmac_alg) {
87 : 474 : return true;
88 : 474 : }
89 : 480 : }
90 : 194 : return false;
91 : 668 : }
92 : :
93 : : /**
94 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-4.2.11.1
95 : : *# The "obfuscated_ticket_age"
96 : : *# field of each PskIdentity contains an obfuscated version of the
97 : : *# ticket age formed by taking the age in milliseconds and adding the
98 : : *# "ticket_age_add" value that was included with the ticket (see
99 : : *# Section 4.6.1), modulo 2^32.
100 : : */
101 : : static S2N_RESULT s2n_generate_obfuscated_ticket_age(struct s2n_psk *psk, uint64_t current_time, uint32_t *output)
102 : 1093 : {
103 [ - + ][ # # ]: 1093 : RESULT_ENSURE_REF(psk);
104 [ - + ][ # # ]: 1093 : RESULT_ENSURE_MUT(output);
105 : :
106 : : /**
107 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-4.2.11
108 : : *# For identities
109 : : *# established externally, an obfuscated_ticket_age of 0 SHOULD be
110 : : *# used,
111 : : **/
112 [ + + ]: 1093 : if (psk->type == S2N_PSK_TYPE_EXTERNAL) {
113 : 980 : *output = 0;
114 : 980 : return S2N_RESULT_OK;
115 : 980 : }
116 : :
117 [ - + ][ # # ]: 113 : RESULT_ENSURE(current_time >= psk->ticket_issue_time, S2N_ERR_SAFETY);
118 : :
119 : : /* Calculate ticket age */
120 : 113 : uint64_t ticket_age_in_nanos = current_time - psk->ticket_issue_time;
121 : :
122 : : /* Convert ticket age to milliseconds */
123 : 113 : uint64_t ticket_age_in_millis = ticket_age_in_nanos / ONE_MILLISEC_IN_NANOS;
124 [ - + ][ # # ]: 113 : RESULT_ENSURE(ticket_age_in_millis <= UINT32_MAX, S2N_ERR_SAFETY);
125 : :
126 : : /* Add the ticket_age_add value to the ticket age in milliseconds. The resulting uint32_t value
127 : : * may wrap, resulting in the modulo 2^32 operation. */
128 : 113 : *output = ticket_age_in_millis + psk->ticket_age_add;
129 : :
130 : 113 : return S2N_RESULT_OK;
131 : 113 : }
132 : :
133 : : static int s2n_client_psk_send(struct s2n_connection *conn, struct s2n_stuffer *out)
134 : 1077 : {
135 [ - + ][ # # ]: 1077 : POSIX_ENSURE_REF(conn);
136 [ - + ][ # # ]: 1077 : POSIX_ENSURE_REF(conn->secure);
137 : :
138 : 1077 : struct s2n_psk_parameters *psk_params = &conn->psk_params;
139 : 1077 : struct s2n_array *psk_list = &psk_params->psk_list;
140 : :
141 : 1077 : struct s2n_stuffer_reservation identity_list_size = { 0 };
142 [ - + ]: 1077 : POSIX_GUARD(s2n_stuffer_reserve_uint16(out, &identity_list_size));
143 : :
144 : 1077 : uint16_t binder_list_size = SIZE_OF_BINDER_LIST_SIZE;
145 : :
146 [ + + ]: 2170 : for (size_t i = 0; i < psk_list->len; i++) {
147 : 1093 : struct s2n_psk *psk = NULL;
148 [ - + ]: 1093 : POSIX_GUARD_RESULT(s2n_array_get(psk_list, i, (void **) &psk));
149 [ - + ][ # # ]: 1093 : POSIX_ENSURE_REF(psk);
150 : :
151 : : /**
152 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-4.1.4
153 : : *# In addition, in its updated ClientHello, the client SHOULD NOT offer
154 : : *# any pre-shared keys associated with a hash other than that of the
155 : : *# selected cipher suite.
156 : : */
157 [ + + ][ - + ]: 1093 : if (s2n_is_hello_retry_handshake(conn) && conn->secure->cipher_suite->prf_alg != psk->hmac_alg) {
158 : 0 : continue;
159 : 0 : }
160 : :
161 : : /* Write the identity */
162 [ - + ]: 1093 : POSIX_GUARD(s2n_stuffer_write_uint16(out, psk->identity.size));
163 [ - + ]: 1093 : POSIX_GUARD(s2n_stuffer_write(out, &psk->identity));
164 : :
165 : : /* Write obfuscated ticket age */
166 : 1093 : uint32_t obfuscated_ticket_age = 0;
167 : 1093 : uint64_t current_time = 0;
168 [ - + ]: 1093 : POSIX_GUARD_RESULT(s2n_config_wall_clock(conn->config, ¤t_time));
169 [ - + ]: 1093 : POSIX_GUARD_RESULT(s2n_generate_obfuscated_ticket_age(psk, current_time, &obfuscated_ticket_age));
170 [ - + ]: 1093 : POSIX_GUARD(s2n_stuffer_write_uint32(out, obfuscated_ticket_age));
171 : :
172 : : /* Calculate binder size */
173 : 1093 : uint8_t hash_size = 0;
174 [ - + ]: 1093 : POSIX_GUARD(s2n_hmac_digest_size(psk->hmac_alg, &hash_size));
175 : 1093 : binder_list_size += hash_size + SIZE_OF_BINDER_SIZE;
176 : 1093 : }
177 : :
178 [ - + ]: 1077 : POSIX_GUARD(s2n_stuffer_write_vector_size(&identity_list_size));
179 : :
180 : : /* Calculating the binders requires a complete ClientHello, and at this point
181 : : * the extension size, extension list size, and message size are all blank.
182 : : *
183 : : * We'll write placeholder data to ensure the extension and extension list sizes
184 : : * are calculated correctly, then rewrite the binders with real data later. */
185 : 1077 : psk_params->binder_list_size = binder_list_size;
186 [ - + ]: 1077 : POSIX_GUARD(s2n_stuffer_skip_write(out, binder_list_size));
187 : :
188 : 1077 : return S2N_SUCCESS;
189 : 1077 : }
190 : :
191 : : /* Find the first of the server's PSK identities that matches the client's identities.
192 : : * This method compares all server identities to all client identities.
193 : : *
194 : : * While both the client's identities and whether a match was found are public, we should make an attempt
195 : : * to keep the server's identities a secret. We will make comparisons to the server's identities constant
196 : : * time (to hide partial matches) and not end the search early when a match is found (to hide the ordering).
197 : : *
198 : : * Keeping these comparisons constant time is not high priority. There's no known attack using these timings,
199 : : * and an attacker could probably guess the server's known identities just by observing the public identities
200 : : * sent by clients.
201 : : */
202 : : static S2N_RESULT s2n_select_external_psk(struct s2n_connection *conn, struct s2n_offered_psk_list *client_identity_list)
203 : 958 : {
204 [ - + ][ # # ]: 958 : RESULT_ENSURE_REF(conn);
205 [ - + ][ # # ]: 958 : RESULT_ENSURE_REF(client_identity_list);
206 : :
207 : 958 : struct s2n_array *server_psks = &conn->psk_params.psk_list;
208 : 958 : conn->psk_params.chosen_psk = NULL;
209 : :
210 [ + + ]: 1929 : for (size_t i = 0; i < server_psks->len; i++) {
211 : 971 : struct s2n_psk *server_psk = NULL;
212 [ - + ]: 971 : RESULT_GUARD(s2n_array_get(server_psks, i, (void **) &server_psk));
213 [ - + ][ # # ]: 971 : RESULT_ENSURE_REF(server_psk);
214 : :
215 : 971 : struct s2n_offered_psk client_psk = { 0 };
216 : 971 : uint16_t wire_index = 0;
217 : :
218 [ - + ]: 971 : RESULT_GUARD_POSIX(s2n_offered_psk_list_reread(client_identity_list));
219 [ + + ]: 1980 : while (s2n_offered_psk_list_has_next(client_identity_list)) {
220 [ - + ]: 1009 : RESULT_GUARD_POSIX(s2n_offered_psk_list_next(client_identity_list, &client_psk));
221 [ + + ]: 1009 : uint16_t compare_size = S2N_MIN(client_psk.identity.size, server_psk->identity.size);
222 [ + + ]: 1009 : if (s2n_constant_time_equals(client_psk.identity.data, server_psk->identity.data, compare_size)
223 : 1009 : & (client_psk.identity.size == server_psk->identity.size)
224 : 1009 : & (conn->psk_params.chosen_psk == NULL)) {
225 : 955 : conn->psk_params.chosen_psk = server_psk;
226 : 955 : conn->psk_params.chosen_psk_wire_index = wire_index;
227 : 955 : }
228 : 1009 : wire_index++;
229 : 1009 : };
230 : 971 : }
231 [ + + ][ + - ]: 958 : RESULT_ENSURE_REF(conn->psk_params.chosen_psk);
232 : 955 : return S2N_RESULT_OK;
233 : 958 : }
234 : :
235 : : static S2N_RESULT s2n_select_resumption_psk(struct s2n_connection *conn, struct s2n_offered_psk_list *client_identity_list)
236 : 114 : {
237 [ - + ][ # # ]: 114 : RESULT_ENSURE_REF(conn);
238 [ - + ][ # # ]: 114 : RESULT_ENSURE_REF(client_identity_list);
239 : :
240 : 114 : struct s2n_offered_psk client_psk = { 0 };
241 : 114 : conn->psk_params.chosen_psk = NULL;
242 : :
243 : : /* s2n does not support resumption when client auth is enabled: a resumed
244 : : * handshake skips the CertificateRequest, and the ticket carries no client
245 : : * certificate or peer identity. Bailing here leaves chosen_psk NULL, so the
246 : : * caller falls back to a full handshake. Mirrors the TLS1.2 behavior in
247 : : * s2n_allowed_to_cache_connection() and s2n_client_session_ticket_recv().
248 : : */
249 [ + + ]: 114 : if (s2n_connection_is_client_auth_enabled(conn)) {
250 [ + - ]: 1 : RESULT_BAIL(S2N_ERR_INVALID_SESSION_TICKET);
251 : 1 : }
252 : :
253 : 113 : uint8_t rejected_count = 0;
254 [ + + ][ + - ]: 118 : while (s2n_offered_psk_list_has_next(client_identity_list) && (rejected_count < MAX_REJECTED_TICKETS)) {
255 [ - + ]: 113 : RESULT_GUARD_POSIX(s2n_offered_psk_list_next(client_identity_list, &client_psk));
256 : : /* Select the first resumption PSK that can be decrypted */
257 [ + + ]: 113 : if (s2n_offered_psk_list_choose_psk(client_identity_list, &client_psk) == S2N_SUCCESS) {
258 : 108 : return S2N_RESULT_OK;
259 : 108 : }
260 : 5 : rejected_count++;
261 : 5 : }
262 : :
263 [ + - ]: 5 : RESULT_BAIL(S2N_ERR_INVALID_SESSION_TICKET);
264 : 5 : }
265 : :
266 : : static S2N_RESULT s2n_client_psk_recv_identity_list(struct s2n_connection *conn, struct s2n_stuffer *wire_identities_in)
267 : 1073 : {
268 [ # # ][ - + ]: 1073 : RESULT_ENSURE_REF(conn);
269 [ # # ][ - + ]: 1073 : RESULT_ENSURE_REF(conn->config);
270 [ # # ][ - + ]: 1073 : RESULT_ENSURE_REF(wire_identities_in);
271 : :
272 : 1073 : struct s2n_offered_psk_list identity_list = {
273 : 1073 : .conn = conn,
274 : 1073 : .wire_data = *wire_identities_in,
275 : 1073 : };
276 : :
277 [ + + ]: 1073 : if (conn->config->psk_selection_cb) {
278 [ - + ]: 1 : RESULT_GUARD_POSIX(conn->config->psk_selection_cb(conn, conn->config->psk_selection_ctx, &identity_list));
279 [ + + ]: 1072 : } else if (conn->psk_params.type == S2N_PSK_TYPE_EXTERNAL) {
280 [ + + ]: 958 : RESULT_GUARD(s2n_select_external_psk(conn, &identity_list));
281 [ + - ]: 958 : } else if (conn->psk_params.type == S2N_PSK_TYPE_RESUMPTION) {
282 [ + + ]: 114 : RESULT_GUARD(s2n_select_resumption_psk(conn, &identity_list));
283 : 114 : }
284 : :
285 [ - + ][ # # ]: 1064 : RESULT_ENSURE_REF(conn->psk_params.chosen_psk);
286 : 1064 : return S2N_RESULT_OK;
287 : 1064 : }
288 : :
289 : : static S2N_RESULT s2n_client_psk_recv_binder_list(struct s2n_connection *conn, struct s2n_blob *partial_client_hello,
290 : : struct s2n_stuffer *wire_binders_in)
291 : 1064 : {
292 [ - + ][ # # ]: 1064 : RESULT_ENSURE_REF(conn);
293 [ - + ][ # # ]: 1064 : RESULT_ENSURE_REF(wire_binders_in);
294 : :
295 : 1064 : uint16_t wire_index = 0;
296 [ + - ]: 1073 : while (s2n_stuffer_data_available(wire_binders_in) > 0) {
297 : 1073 : uint8_t wire_binder_size = 0;
298 [ - + ]: 1073 : RESULT_GUARD_POSIX(s2n_stuffer_read_uint8(wire_binders_in, &wire_binder_size));
299 : :
300 : 1073 : uint8_t *wire_binder_data = NULL;
301 [ - + ][ # # ]: 1073 : RESULT_ENSURE_REF(wire_binder_data = s2n_stuffer_raw_read(wire_binders_in, wire_binder_size));
302 : :
303 : 1073 : struct s2n_blob wire_binder = { 0 };
304 [ - + ]: 1073 : RESULT_GUARD_POSIX(s2n_blob_init(&wire_binder, wire_binder_data, wire_binder_size));
305 : :
306 [ + + ]: 1073 : if (wire_index == conn->psk_params.chosen_psk_wire_index) {
307 [ - + ]: 1064 : RESULT_GUARD_POSIX(s2n_psk_verify_binder(conn, conn->psk_params.chosen_psk,
308 : 1064 : partial_client_hello, &wire_binder));
309 : 1064 : return S2N_RESULT_OK;
310 : 1064 : }
311 : 9 : wire_index++;
312 : 9 : }
313 [ # # ]: 0 : RESULT_BAIL(S2N_ERR_BAD_MESSAGE);
314 : 0 : }
315 : :
316 : : static S2N_RESULT s2n_client_psk_recv_identities(struct s2n_connection *conn, struct s2n_stuffer *extension)
317 : 1073 : {
318 [ - + ][ # # ]: 1073 : RESULT_ENSURE_REF(conn);
319 : :
320 : 1073 : uint16_t identity_list_size = 0;
321 [ - + ]: 1073 : RESULT_GUARD_POSIX(s2n_stuffer_read_uint16(extension, &identity_list_size));
322 : :
323 : 1073 : uint8_t *identity_list_data = NULL;
324 [ # # ][ - + ]: 1073 : RESULT_ENSURE_REF(identity_list_data = s2n_stuffer_raw_read(extension, identity_list_size));
325 : :
326 : 1073 : struct s2n_blob identity_list_blob = { 0 };
327 [ - + ]: 1073 : RESULT_GUARD_POSIX(s2n_blob_init(&identity_list_blob, identity_list_data, identity_list_size));
328 : :
329 : 1073 : struct s2n_stuffer identity_list = { 0 };
330 [ - + ]: 1073 : RESULT_GUARD_POSIX(s2n_stuffer_init(&identity_list, &identity_list_blob));
331 [ - + ]: 1073 : RESULT_GUARD_POSIX(s2n_stuffer_skip_write(&identity_list, identity_list_blob.size));
332 : :
333 : 1073 : return s2n_client_psk_recv_identity_list(conn, &identity_list);
334 : 1073 : }
335 : :
336 : : static S2N_RESULT s2n_client_psk_recv_binders(struct s2n_connection *conn, struct s2n_stuffer *extension)
337 : 1064 : {
338 [ # # ][ - + ]: 1064 : RESULT_ENSURE_REF(conn);
339 : :
340 : 1064 : uint16_t binder_list_size = 0;
341 [ - + ]: 1064 : RESULT_GUARD_POSIX(s2n_stuffer_read_uint16(extension, &binder_list_size));
342 : :
343 : 1064 : uint8_t *binder_list_data = NULL;
344 [ # # ][ - + ]: 1064 : RESULT_ENSURE_REF(binder_list_data = s2n_stuffer_raw_read(extension, binder_list_size));
345 : :
346 : 1064 : struct s2n_blob binder_list_blob = { 0 };
347 [ - + ]: 1064 : RESULT_GUARD_POSIX(s2n_blob_init(&binder_list_blob, binder_list_data, binder_list_size));
348 : :
349 : 1064 : struct s2n_stuffer binder_list = { 0 };
350 [ - + ]: 1064 : RESULT_GUARD_POSIX(s2n_stuffer_init(&binder_list, &binder_list_blob));
351 [ - + ]: 1064 : RESULT_GUARD_POSIX(s2n_stuffer_skip_write(&binder_list, binder_list_blob.size));
352 : :
353 : : /* Record the ClientHello message up to but not including the binder list.
354 : : * This is required to calculate the binder for the chosen PSK. */
355 : 1064 : struct s2n_blob partial_client_hello = { 0 };
356 : 1064 : const struct s2n_stuffer *client_hello = &conn->handshake.io;
357 : 1064 : uint32_t binders_size = binder_list_blob.size + SIZE_OF_BINDER_LIST_SIZE;
358 [ # # ][ - + ]: 1064 : RESULT_ENSURE_GTE(client_hello->write_cursor, binders_size);
359 : 1064 : uint32_t partial_client_hello_size = client_hello->write_cursor - binders_size;
360 [ - + ]: 1064 : RESULT_GUARD_POSIX(s2n_blob_slice(&client_hello->blob, &partial_client_hello, 0, partial_client_hello_size));
361 : :
362 : 1064 : return s2n_client_psk_recv_binder_list(conn, &partial_client_hello, &binder_list);
363 : 1064 : }
364 : :
365 : : int s2n_client_psk_recv(struct s2n_connection *conn, struct s2n_stuffer *extension)
366 : 1073 : {
367 [ # # ][ - + ]: 1073 : POSIX_ENSURE_REF(conn);
368 : :
369 : : /**
370 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-4.2.11
371 : : *# The "pre_shared_key" extension MUST be the last extension in the
372 : : *# ClientHello (this facilitates implementation as described below).
373 : : *# Servers MUST check that it is the last extension and otherwise fail
374 : : *# the handshake with an "illegal_parameter" alert.
375 : : */
376 : 1073 : s2n_extension_type_id psk_ext_id = 0;
377 [ - + ]: 1073 : POSIX_GUARD(s2n_extension_supported_iana_value_to_id(TLS_EXTENSION_PRE_SHARED_KEY, &psk_ext_id));
378 [ # # ][ - + ]: 1073 : POSIX_ENSURE_NE(conn->client_hello.extensions.count, 0);
379 : 1073 : uint16_t last_wire_index = conn->client_hello.extensions.count - 1;
380 : 1073 : uint16_t extension_wire_index = conn->client_hello.extensions.parsed_extensions[psk_ext_id].wire_index;
381 [ - + ][ # # ]: 1073 : POSIX_ENSURE(extension_wire_index == last_wire_index, S2N_ERR_UNSUPPORTED_EXTENSION);
382 : :
383 : : /**
384 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-4.2.9
385 : : *# If clients offer "pre_shared_key" without a "psk_key_exchange_modes" extension,
386 : : *# servers MUST abort the handshake.
387 : : *
388 : : * We can safely do this check here because s2n_client_psk is
389 : : * required to be the last extension sent in the list.
390 : : */
391 : 1073 : s2n_extension_type_id psk_ke_mode_ext_id = 0;
392 [ - + ]: 1073 : POSIX_GUARD(s2n_extension_supported_iana_value_to_id(TLS_EXTENSION_PSK_KEY_EXCHANGE_MODES, &psk_ke_mode_ext_id));
393 [ - + ][ # # ]: 1073 : POSIX_ENSURE(S2N_CBIT_TEST(conn->extension_requests_received, psk_ke_mode_ext_id), S2N_ERR_MISSING_EXTENSION);
394 : :
395 [ + - ]: 1073 : if (conn->psk_params.psk_ke_mode == S2N_PSK_DHE_KE) {
396 : 1073 : s2n_extension_type_id key_share_ext_id = 0;
397 [ - + ]: 1073 : POSIX_GUARD(s2n_extension_supported_iana_value_to_id(TLS_EXTENSION_KEY_SHARE, &key_share_ext_id));
398 : : /* A key_share extension must have been received in order to use a pre-shared key
399 : : * in (EC)DHE key exchange mode.
400 : : */
401 [ # # ][ - + ]: 1073 : POSIX_ENSURE(S2N_CBIT_TEST(conn->extension_requests_received, key_share_ext_id), S2N_ERR_MISSING_EXTENSION);
402 : 1073 : } else {
403 : : /* s2n currently only supports pre-shared keys in (EC)DHE key exchange mode. If we receive keys with any other
404 : : * exchange mode we fall back to a full handshake.
405 : : */
406 : 0 : return S2N_SUCCESS;
407 : 0 : }
408 : :
409 [ + + ]: 1073 : if (s2n_result_is_error(s2n_client_psk_recv_identities(conn, extension))) {
410 : : /**
411 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-4.2.11
412 : : *# If no acceptable PSKs are found, the server SHOULD perform a non-PSK
413 : : *# handshake if possible.
414 : : */
415 : 9 : conn->psk_params.chosen_psk = NULL;
416 : 9 : }
417 : :
418 [ + + ]: 1073 : if (conn->psk_params.chosen_psk) {
419 : : /**
420 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-4.2.11
421 : : *# Prior to accepting PSK key establishment, the server MUST validate
422 : : *# the corresponding binder value (see Section 4.2.11.2 below). If this
423 : : *# value is not present or does not validate, the server MUST abort the
424 : : *# handshake.
425 : : */
426 [ - + ]: 1064 : POSIX_GUARD_RESULT(s2n_client_psk_recv_binders(conn, extension));
427 : 1064 : }
428 : :
429 : : /* At this point, we have either chosen a PSK or fallen back to a full handshake. */
430 : 1073 : return S2N_SUCCESS;
431 : 1073 : }
|