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 <sys/param.h>
17 : :
18 : : #include "crypto/s2n_tls13_keys.h"
19 : : #include "tls/extensions/s2n_extension_type.h"
20 : : #include "tls/s2n_handshake.h"
21 : : #include "tls/s2n_tls.h"
22 : : #include "tls/s2n_tls13_handshake.h"
23 : : #include "tls/s2n_tls13_secrets.h"
24 : : #include "utils/s2n_array.h"
25 : : #include "utils/s2n_mem.h"
26 : : #include "utils/s2n_safety.h"
27 : :
28 : : S2N_RESULT s2n_psk_init(struct s2n_psk *psk, s2n_psk_type type)
29 : 1815 : {
30 [ + + ][ + - ]: 1815 : RESULT_ENSURE_MUT(psk);
31 : :
32 [ - + ][ # # ]: 1814 : RESULT_CHECKED_MEMSET(psk, 0, sizeof(struct s2n_psk));
[ + - ]
33 : 1814 : psk->hmac_alg = S2N_HMAC_SHA256;
34 : 1814 : psk->type = type;
35 : :
36 : 1814 : return S2N_RESULT_OK;
37 : 1814 : }
38 : :
39 : : struct s2n_psk *s2n_external_psk_new()
40 : 163 : {
41 : 163 : DEFER_CLEANUP(struct s2n_blob mem = { 0 }, s2n_free);
42 [ - + ]: 163 : PTR_GUARD_POSIX(s2n_alloc(&mem, sizeof(struct s2n_psk)));
43 : :
44 : 163 : struct s2n_psk *psk = (struct s2n_psk *) (void *) mem.data;
45 [ - + ]: 163 : PTR_GUARD_RESULT(s2n_psk_init(psk, S2N_PSK_TYPE_EXTERNAL));
46 : :
47 : 163 : ZERO_TO_DISABLE_DEFER_CLEANUP(mem);
48 : 163 : return psk;
49 : 163 : }
50 : :
51 : : int s2n_psk_set_identity(struct s2n_psk *psk, const uint8_t *identity, uint16_t identity_size)
52 : 3192 : {
53 [ + + ][ + - ]: 3192 : POSIX_ENSURE_REF(psk);
54 [ + + ][ + - ]: 3191 : POSIX_ENSURE_REF(identity);
55 [ + + ][ + - ]: 3189 : POSIX_ENSURE(identity_size != 0, S2N_ERR_INVALID_ARGUMENT);
56 : :
57 [ - + ]: 3188 : POSIX_GUARD(s2n_realloc(&psk->identity, identity_size));
58 [ - + ][ # # ]: 3188 : POSIX_CHECKED_MEMCPY(psk->identity.data, identity, identity_size);
[ + - ]
59 : :
60 : 3188 : return S2N_SUCCESS;
61 : 3188 : }
62 : :
63 : : int s2n_psk_set_secret(struct s2n_psk *psk, const uint8_t *secret, uint16_t secret_size)
64 : 1808 : {
65 [ + - ][ + + ]: 1808 : POSIX_ENSURE_REF(psk);
66 [ + - ][ + + ]: 1807 : POSIX_ENSURE_REF(secret);
67 [ + + ][ + - ]: 1805 : POSIX_ENSURE(secret_size != 0, S2N_ERR_INVALID_ARGUMENT);
68 : :
69 : : /* There are a number of application level errors that might result in an
70 : : * all-zero secret accidentally getting used. Error if that happens.
71 : : */
72 : 1804 : bool secret_is_all_zero = true;
73 [ + + ]: 33452 : for (uint16_t i = 0; i < secret_size; i++) {
74 [ + + ][ + + ]: 31648 : secret_is_all_zero = secret_is_all_zero && secret[i] == 0;
75 : 31648 : }
76 [ + - ][ + + ]: 1804 : POSIX_ENSURE(!secret_is_all_zero, S2N_ERR_INVALID_ARGUMENT);
77 : :
78 [ - + ]: 1803 : POSIX_GUARD(s2n_realloc(&psk->secret, secret_size));
79 [ - + ][ # # ]: 1803 : POSIX_CHECKED_MEMCPY(psk->secret.data, secret, secret_size);
[ + - ]
80 : :
81 : 1803 : return S2N_SUCCESS;
82 : 1803 : }
83 : :
84 : : S2N_RESULT s2n_psk_clone(struct s2n_psk *new_psk, struct s2n_psk *original_psk)
85 : 1339 : {
86 [ - + ]: 1339 : if (original_psk == NULL) {
87 : 0 : return S2N_RESULT_OK;
88 : 0 : }
89 [ - + ][ # # ]: 1339 : RESULT_ENSURE_REF(new_psk);
90 : :
91 : 1339 : struct s2n_psk psk_copy = *new_psk;
92 : :
93 : : /* Copy all fields from the old_config EXCEPT the blobs, which we need to reallocate. */
94 : 1339 : *new_psk = *original_psk;
95 : 1339 : new_psk->identity = psk_copy.identity;
96 : 1339 : new_psk->secret = psk_copy.secret;
97 : 1339 : new_psk->early_secret = psk_copy.early_secret;
98 : 1339 : new_psk->early_data_config = psk_copy.early_data_config;
99 : :
100 : : /* Clone / realloc blobs */
101 [ + + ]: 1339 : RESULT_GUARD_POSIX(s2n_psk_set_identity(new_psk, original_psk->identity.data, original_psk->identity.size));
102 [ + + ]: 1338 : RESULT_GUARD_POSIX(s2n_psk_set_secret(new_psk, original_psk->secret.data, original_psk->secret.size));
103 [ - + ]: 1337 : RESULT_GUARD_POSIX(s2n_realloc(&new_psk->early_secret, original_psk->early_secret.size));
104 [ - + ][ # # ]: 1337 : RESULT_CHECKED_MEMCPY(new_psk->early_secret.data, original_psk->early_secret.data, original_psk->early_secret.size);
[ + + ]
105 [ - + ]: 1337 : RESULT_GUARD(s2n_early_data_config_clone(new_psk, &original_psk->early_data_config));
106 : :
107 : 1337 : return S2N_RESULT_OK;
108 : 1337 : }
109 : :
110 : : S2N_CLEANUP_RESULT s2n_psk_wipe(struct s2n_psk *psk)
111 : 4655 : {
112 [ + + ]: 4655 : if (psk == NULL) {
113 : 90 : return S2N_RESULT_OK;
114 : 90 : }
115 : :
116 [ - + ]: 4565 : RESULT_GUARD_POSIX(s2n_free(&psk->early_secret));
117 [ - + ]: 4565 : RESULT_GUARD_POSIX(s2n_free(&psk->identity));
118 [ - + ]: 4565 : RESULT_GUARD_POSIX(s2n_free(&psk->secret));
119 [ - + ]: 4565 : RESULT_GUARD(s2n_early_data_config_free(&psk->early_data_config));
120 : :
121 : 4565 : return S2N_RESULT_OK;
122 : 4565 : }
123 : :
124 : : int s2n_psk_free(struct s2n_psk **psk)
125 : 254 : {
126 [ + + ]: 254 : if (psk == NULL) {
127 : 1 : return S2N_SUCCESS;
128 : 1 : }
129 [ - + ]: 253 : POSIX_GUARD_RESULT(s2n_psk_wipe(*psk));
130 : 253 : return s2n_free_object((uint8_t **) psk, sizeof(struct s2n_psk));
131 : 253 : }
132 : :
133 : : S2N_RESULT s2n_psk_parameters_init(struct s2n_psk_parameters *params)
134 : 6966659 : {
135 [ + - ][ + + ]: 6966659 : RESULT_ENSURE_REF(params);
136 [ - + ][ # # ]: 6966658 : RESULT_CHECKED_MEMSET(params, 0, sizeof(struct s2n_psk_parameters));
[ + - ]
137 [ - + ]: 6966658 : RESULT_GUARD(s2n_array_init(¶ms->psk_list, sizeof(struct s2n_psk)));
138 : 6966658 : return S2N_RESULT_OK;
139 : 6966658 : }
140 : :
141 : : static S2N_RESULT s2n_psk_offered_psk_size(struct s2n_psk *psk, uint32_t *size)
142 : 691 : {
143 : 691 : *size = sizeof(uint16_t) /* identity size */
144 : 691 : + sizeof(uint32_t) /* obfuscated ticket age */
145 : 691 : + sizeof(uint8_t); /* binder size */
146 : :
147 [ - + ]: 691 : RESULT_GUARD_POSIX(s2n_add_overflow(*size, psk->identity.size, size));
148 : :
149 : 691 : uint8_t binder_size = 0;
150 [ - + ]: 691 : RESULT_GUARD_POSIX(s2n_hmac_digest_size(psk->hmac_alg, &binder_size));
151 [ - + ]: 691 : RESULT_GUARD_POSIX(s2n_add_overflow(*size, binder_size, size));
152 : :
153 : 691 : return S2N_RESULT_OK;
154 : 691 : }
155 : :
156 : : S2N_RESULT s2n_psk_parameters_offered_psks_size(struct s2n_psk_parameters *params, uint32_t *size)
157 : 1994 : {
158 [ - + ][ # # ]: 1994 : RESULT_ENSURE_REF(params);
159 [ - + ][ # # ]: 1994 : RESULT_ENSURE_REF(size);
160 : :
161 : 1994 : *size = sizeof(uint16_t) /* identity list size */
162 : 1994 : + sizeof(uint16_t) /* binder list size */;
163 : :
164 [ + + ]: 864654 : for (uint32_t i = 0; i < params->psk_list.len; i++) {
165 : 862660 : struct s2n_psk *psk = NULL;
166 [ - + ]: 862660 : RESULT_GUARD(s2n_array_get(¶ms->psk_list, i, (void **) &psk));
167 [ # # ][ - + ]: 862660 : RESULT_ENSURE_REF(psk);
168 : :
169 : 862660 : uint32_t psk_size = 0;
170 [ - + ]: 862660 : RESULT_GUARD(s2n_psk_offered_psk_size(psk, &psk_size));
171 [ - + ]: 862660 : RESULT_GUARD_POSIX(s2n_add_overflow(*size, psk_size, size));
172 : 862660 : }
173 : 1994 : return S2N_RESULT_OK;
174 : 1994 : }
175 : :
176 : : S2N_CLEANUP_RESULT s2n_psk_parameters_wipe(struct s2n_psk_parameters *params)
177 : 3546068 : {
178 [ + + ][ + - ]: 3546068 : RESULT_ENSURE_REF(params);
179 : :
180 [ + + ]: 3548871 : for (size_t i = 0; i < params->psk_list.len; i++) {
181 : 2804 : struct s2n_psk *psk = NULL;
182 [ - + ]: 2804 : RESULT_GUARD(s2n_array_get(¶ms->psk_list, i, (void **) &psk));
183 [ - + ]: 2804 : RESULT_GUARD(s2n_psk_wipe(psk));
184 : 2804 : }
185 [ - + ]: 3546067 : RESULT_GUARD_POSIX(s2n_free(¶ms->psk_list.mem));
186 [ - + ]: 3546067 : RESULT_GUARD(s2n_psk_parameters_init(params));
187 : :
188 : 3546067 : return S2N_RESULT_OK;
189 : 3546067 : }
190 : :
191 : : S2N_CLEANUP_RESULT s2n_psk_parameters_wipe_secrets(struct s2n_psk_parameters *params)
192 : 8903 : {
193 [ + + ][ + - ]: 8903 : RESULT_ENSURE_REF(params);
194 : :
195 [ + + ]: 10136 : for (size_t i = 0; i < params->psk_list.len; i++) {
196 : 1234 : struct s2n_psk *psk = NULL;
197 [ - + ]: 1234 : RESULT_GUARD(s2n_array_get(¶ms->psk_list, i, (void **) &psk));
198 [ - + ][ # # ]: 1234 : RESULT_ENSURE_REF(psk);
199 [ - + ]: 1234 : RESULT_GUARD_POSIX(s2n_free(&psk->early_secret));
200 [ - + ]: 1234 : RESULT_GUARD_POSIX(s2n_free(&psk->secret));
201 : 1234 : }
202 : :
203 : 8902 : return S2N_RESULT_OK;
204 : 8902 : }
205 : :
206 : : bool s2n_offered_psk_list_has_next(struct s2n_offered_psk_list *psk_list)
207 : 3640 : {
208 [ + + ][ + + ]: 3640 : return psk_list != NULL && s2n_stuffer_data_available(&psk_list->wire_data) > 0;
209 : 3640 : }
210 : :
211 : : S2N_RESULT s2n_offered_psk_list_read_next(struct s2n_offered_psk_list *psk_list, struct s2n_offered_psk *psk)
212 : 1299 : {
213 [ + + ][ + - ]: 1299 : RESULT_ENSURE_REF(psk_list);
214 [ + + ][ + - ]: 1298 : RESULT_ENSURE_REF(psk_list->conn);
215 [ - + ][ # # ]: 1295 : RESULT_ENSURE_MUT(psk);
216 : :
217 : 1295 : uint16_t identity_size = 0;
218 [ - + ]: 1295 : RESULT_GUARD_POSIX(s2n_stuffer_read_uint16(&psk_list->wire_data, &identity_size));
219 [ - + ][ # # ]: 1295 : RESULT_ENSURE_GT(identity_size, 0);
220 : :
221 : 1295 : uint8_t *identity_data = NULL;
222 : 1295 : identity_data = s2n_stuffer_raw_read(&psk_list->wire_data, identity_size);
223 [ # # ][ - + ]: 1295 : RESULT_ENSURE_REF(identity_data);
224 : :
225 : : /**
226 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-4.2.11
227 : : *# For identities established externally, an obfuscated_ticket_age of 0 SHOULD be
228 : : *# used, and servers MUST ignore the value.
229 : : */
230 [ + + ]: 1295 : if (psk_list->conn->psk_params.type == S2N_PSK_TYPE_EXTERNAL) {
231 [ - + ]: 1159 : RESULT_GUARD_POSIX(s2n_stuffer_skip_read(&psk_list->wire_data, sizeof(uint32_t)));
232 : 1159 : } else {
233 [ - + ]: 136 : RESULT_GUARD_POSIX(s2n_stuffer_read_uint32(&psk_list->wire_data, &psk->obfuscated_ticket_age));
234 : 136 : }
235 : :
236 [ - + ]: 1295 : RESULT_GUARD_POSIX(s2n_blob_init(&psk->identity, identity_data, identity_size));
237 : 1295 : psk->wire_index = psk_list->wire_index;
238 : :
239 [ - + ][ # # ]: 1295 : RESULT_ENSURE(psk_list->wire_index < UINT16_MAX, S2N_ERR_INTEGER_OVERFLOW);
240 : 1295 : psk_list->wire_index++;
241 : 1295 : return S2N_RESULT_OK;
242 : 1295 : }
243 : :
244 : : int s2n_offered_psk_list_next(struct s2n_offered_psk_list *psk_list, struct s2n_offered_psk *psk)
245 : 1303 : {
246 [ + + ][ + - ]: 1303 : POSIX_ENSURE_REF(psk_list);
247 [ + - ][ + + ]: 1302 : POSIX_ENSURE_REF(psk);
248 : 1301 : *psk = (struct s2n_offered_psk){ 0 };
249 [ + - ][ + + ]: 1301 : POSIX_ENSURE(s2n_offered_psk_list_has_next(psk_list), S2N_ERR_STUFFER_OUT_OF_DATA);
250 [ + + ][ + - ]: 1295 : POSIX_ENSURE(s2n_result_is_ok(s2n_offered_psk_list_read_next(psk_list, psk)), S2N_ERR_BAD_MESSAGE);
251 : 1293 : return S2N_SUCCESS;
252 : 1295 : }
253 : :
254 : : int s2n_offered_psk_list_reread(struct s2n_offered_psk_list *psk_list)
255 : 1041 : {
256 [ + + ][ + - ]: 1041 : POSIX_ENSURE_REF(psk_list);
257 : 1040 : psk_list->wire_index = 0;
258 : 1040 : return s2n_stuffer_reread(&psk_list->wire_data);
259 : 1041 : }
260 : :
261 : : /* Match a PSK identity received from the client against the server's known PSK identities.
262 : : * This method compares a single client identity to all server identities.
263 : : *
264 : : * While both the client's offered identities and whether a match was found are public, we should make an attempt
265 : : * to keep the server's known identities a secret. We will make comparisons to the server's identities constant
266 : : * time (to hide partial matches) and not end the search early when a match is found (to hide the ordering).
267 : : *
268 : : * Keeping these comparisons constant time is not high priority. There's no known attack using these timings,
269 : : * and an attacker could probably guess the server's known identities just by observing the public identities
270 : : * sent by clients.
271 : : */
272 : : static S2N_RESULT s2n_match_psk_identity(struct s2n_array *known_psks, const struct s2n_blob *wire_identity,
273 : : struct s2n_psk **match)
274 : 121 : {
275 [ - + ][ # # ]: 121 : RESULT_ENSURE_REF(match);
276 [ - + ][ # # ]: 121 : RESULT_ENSURE_REF(wire_identity);
277 [ # # ][ - + ]: 121 : RESULT_ENSURE_REF(known_psks);
278 : 121 : *match = NULL;
279 [ + + ]: 240 : for (size_t i = 0; i < known_psks->len; i++) {
280 : 119 : struct s2n_psk *psk = NULL;
281 [ - + ]: 119 : RESULT_GUARD(s2n_array_get(known_psks, i, (void **) &psk));
282 [ - + ][ # # ]: 119 : RESULT_ENSURE_REF(psk);
283 [ - + ][ # # ]: 119 : RESULT_ENSURE_REF(psk->identity.data);
284 [ # # ][ - + ]: 119 : RESULT_ENSURE_REF(wire_identity->data);
285 : 119 : uint32_t compare_size = MIN(wire_identity->size, psk->identity.size);
286 [ + + ]: 119 : if (s2n_constant_time_equals(psk->identity.data, wire_identity->data, compare_size)
287 : 119 : & (psk->identity.size == wire_identity->size) & (!*match)) {
288 : 116 : *match = psk;
289 : 116 : }
290 : 119 : }
291 : 121 : return S2N_RESULT_OK;
292 : 121 : }
293 : :
294 : : /**
295 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-4.2.10
296 : : *# For PSKs provisioned via NewSessionTicket, a server MUST validate
297 : : *# that the ticket age for the selected PSK identity (computed by
298 : : *# subtracting ticket_age_add from PskIdentity.obfuscated_ticket_age
299 : : *# modulo 2^32) is within a small tolerance of the time since the ticket
300 : : *# was issued (see Section 8).
301 : : **/
302 : : static S2N_RESULT s2n_validate_ticket_lifetime(struct s2n_connection *conn, uint32_t obfuscated_ticket_age, uint32_t ticket_age_add)
303 : 116 : {
304 [ # # ][ - + ]: 116 : RESULT_ENSURE_REF(conn);
305 : :
306 [ + + ]: 116 : if (conn->psk_params.type == S2N_PSK_TYPE_EXTERNAL) {
307 : 2 : return S2N_RESULT_OK;
308 : 2 : }
309 : :
310 : : /* Subtract the ticket_age_add value from the ticket age in milliseconds. The resulting uint32_t value
311 : : * may wrap, resulting in the modulo 2^32 operation. */
312 : 114 : uint32_t ticket_age_in_millis = obfuscated_ticket_age - ticket_age_add;
313 : 114 : uint32_t session_lifetime_in_millis = conn->config->session_state_lifetime_in_nanos / ONE_MILLISEC_IN_NANOS;
314 [ + - ][ + + ]: 114 : RESULT_ENSURE(ticket_age_in_millis < session_lifetime_in_millis, S2N_ERR_INVALID_SESSION_TICKET);
315 : :
316 : 113 : return S2N_RESULT_OK;
317 : 114 : }
318 : :
319 : : int s2n_offered_psk_list_choose_psk(struct s2n_offered_psk_list *psk_list, struct s2n_offered_psk *psk)
320 : 142 : {
321 [ + + ][ + - ]: 142 : POSIX_ENSURE_REF(psk_list);
322 [ # # ][ - + ]: 141 : POSIX_ENSURE_REF(psk_list->conn);
323 : :
324 : 141 : struct s2n_psk_parameters *psk_params = &psk_list->conn->psk_params;
325 : 141 : struct s2n_stuffer ticket_stuffer = { 0 };
326 : :
327 [ + + ]: 141 : if (!psk) {
328 : 1 : psk_params->chosen_psk = NULL;
329 : 1 : return S2N_SUCCESS;
330 : 1 : }
331 : :
332 [ + + ][ + + ]: 140 : if (psk_params->type == S2N_PSK_TYPE_RESUMPTION && psk_list->conn->config->use_tickets) {
333 [ - + ]: 126 : POSIX_GUARD(s2n_stuffer_init(&ticket_stuffer, &psk->identity));
334 [ - + ]: 126 : POSIX_GUARD(s2n_stuffer_skip_write(&ticket_stuffer, psk->identity.size));
335 : :
336 : : /* s2n_resume_decrypt_session appends a new PSK with the decrypted values. */
337 [ + + ]: 126 : POSIX_GUARD_RESULT(s2n_resume_decrypt_session(psk_list->conn, &ticket_stuffer));
338 : 126 : }
339 : :
340 : 130 : struct s2n_psk *chosen_psk = NULL;
341 [ - + ]: 130 : POSIX_GUARD_RESULT(s2n_match_psk_identity(&psk_params->psk_list, &psk->identity, &chosen_psk));
342 [ + - ][ + + ]: 130 : POSIX_ENSURE_REF(chosen_psk);
343 [ + + ]: 122 : POSIX_GUARD_RESULT(s2n_validate_ticket_lifetime(psk_list->conn, psk->obfuscated_ticket_age, chosen_psk->ticket_age_add));
344 : 120 : psk_params->chosen_psk = chosen_psk;
345 : 120 : psk_params->chosen_psk_wire_index = psk->wire_index;
346 : :
347 : 120 : return S2N_SUCCESS;
348 : 122 : }
349 : :
350 : : struct s2n_offered_psk *s2n_offered_psk_new()
351 : 4 : {
352 : 4 : DEFER_CLEANUP(struct s2n_blob mem = { 0 }, s2n_free);
353 [ - + ]: 4 : PTR_GUARD_POSIX(s2n_alloc(&mem, sizeof(struct s2n_offered_psk)));
354 [ - + ]: 4 : PTR_GUARD_POSIX(s2n_blob_zero(&mem));
355 : :
356 : 4 : struct s2n_offered_psk *psk = (struct s2n_offered_psk *) (void *) mem.data;
357 : :
358 : 4 : ZERO_TO_DISABLE_DEFER_CLEANUP(mem);
359 : 4 : return psk;
360 : 4 : }
361 : :
362 : : int s2n_offered_psk_free(struct s2n_offered_psk **psk)
363 : 5 : {
364 [ + + ]: 5 : if (psk == NULL) {
365 : 1 : return S2N_SUCCESS;
366 : 1 : }
367 : 4 : return s2n_free_object((uint8_t **) psk, sizeof(struct s2n_offered_psk));
368 : 5 : }
369 : :
370 : : int s2n_offered_psk_get_identity(struct s2n_offered_psk *psk, uint8_t **identity, uint16_t *size)
371 : 8 : {
372 [ + + ][ + - ]: 8 : POSIX_ENSURE_REF(psk);
373 [ + + ][ + - ]: 7 : POSIX_ENSURE_REF(psk->identity.data);
374 [ - + ][ # # ]: 4 : POSIX_ENSURE_REF(identity);
375 [ # # ][ - + ]: 4 : POSIX_ENSURE_REF(size);
376 : 4 : *identity = psk->identity.data;
377 : 4 : *size = psk->identity.size;
378 : 4 : return S2N_SUCCESS;
379 : 4 : }
380 : :
381 : : /* The binder hash is computed by hashing the concatenation of the current transcript
382 : : * and a partial ClientHello that does not include the binders themselves.
383 : : */
384 : : int s2n_psk_calculate_binder_hash(struct s2n_connection *conn, s2n_hmac_algorithm hmac_alg,
385 : : const struct s2n_blob *partial_client_hello, struct s2n_blob *output_binder_hash)
386 : 2160 : {
387 [ # # ][ - + ]: 2160 : POSIX_ENSURE_REF(conn);
388 [ - + ][ # # ]: 2160 : POSIX_ENSURE_REF(partial_client_hello);
389 [ # # ][ - + ]: 2160 : POSIX_ENSURE_REF(output_binder_hash);
390 : 2160 : struct s2n_handshake_hashes *hashes = conn->handshake.hashes;
391 [ - + ][ # # ]: 2160 : POSIX_ENSURE_REF(hashes);
392 : :
393 : : /* Retrieve the current transcript.
394 : : * The current transcript will be empty unless this handshake included a HelloRetryRequest. */
395 : 2160 : s2n_hash_algorithm hash_alg = S2N_HASH_NONE;
396 : 2160 : struct s2n_hash_state *hash_state = &hashes->hash_workspace;
397 [ - + ]: 2160 : POSIX_GUARD(s2n_hmac_hash_alg(hmac_alg, &hash_alg));
398 [ - + ]: 2160 : POSIX_GUARD_RESULT(s2n_handshake_copy_hash_state(conn, hash_alg, hash_state));
399 : :
400 : : /* Add the partial client hello to the transcript. */
401 [ - + ]: 2160 : POSIX_GUARD(s2n_hash_update(hash_state, partial_client_hello->data, partial_client_hello->size));
402 : :
403 : : /* Get the transcript digest */
404 [ - + ]: 2160 : POSIX_GUARD(s2n_hash_digest(hash_state, output_binder_hash->data, output_binder_hash->size));
405 : :
406 : 2160 : return S2N_SUCCESS;
407 : 2160 : }
408 : :
409 : : /* The binder is computed in the same way as the Finished message
410 : : * (https://tools.ietf.org/html/rfc8446#section-4.4.4) but with the BaseKey being the binder_key
411 : : * derived via the key schedule from the corresponding PSK which is being offered
412 : : * (https://tools.ietf.org/html/rfc8446#section-7.1)
413 : : */
414 : : int s2n_psk_calculate_binder(struct s2n_psk *psk, const struct s2n_blob *binder_hash,
415 : : struct s2n_blob *output_binder)
416 : 2181 : {
417 [ - + ][ # # ]: 2181 : POSIX_ENSURE_REF(psk);
418 [ - + ][ # # ]: 2181 : POSIX_ENSURE_REF(binder_hash);
419 [ - + ][ # # ]: 2181 : POSIX_ENSURE_REF(output_binder);
420 : :
421 : 2181 : DEFER_CLEANUP(struct s2n_tls13_keys psk_keys, s2n_tls13_keys_free);
422 [ - + ]: 2181 : POSIX_GUARD(s2n_tls13_keys_init(&psk_keys, psk->hmac_alg));
423 [ - + ][ # # ]: 2181 : POSIX_ENSURE_EQ(binder_hash->size, psk_keys.size);
424 [ # # ][ - + ]: 2181 : POSIX_ENSURE_EQ(output_binder->size, psk_keys.size);
425 : :
426 : : /* Derive the binder key */
427 [ - + ]: 2181 : POSIX_GUARD_RESULT(s2n_derive_binder_key(psk, &psk_keys.derive_secret));
428 [ - + ]: 2181 : POSIX_GUARD(s2n_blob_init(&psk_keys.extract_secret, psk->early_secret.data, psk_keys.size));
429 : 2181 : struct s2n_blob *binder_key = &psk_keys.derive_secret;
430 : :
431 : : /* Expand the binder key into the finished key */
432 [ - + ][ # # ]: 2181 : s2n_tls13_key_blob(finished_key, psk_keys.size);
[ - + ]
433 [ - + ]: 2181 : POSIX_GUARD(s2n_tls13_derive_finished_key(&psk_keys, binder_key, &finished_key));
434 : :
435 : : /* HMAC the binder hash with the binder finished key */
436 [ - + ]: 2181 : POSIX_GUARD(s2n_hkdf_extract(&psk_keys.hmac, psk_keys.hmac_algorithm, &finished_key, binder_hash, output_binder));
437 : :
438 : 2181 : return S2N_SUCCESS;
439 : 2181 : }
440 : :
441 : : int s2n_psk_verify_binder(struct s2n_connection *conn, struct s2n_psk *psk,
442 : : const struct s2n_blob *partial_client_hello, struct s2n_blob *binder_to_verify)
443 : 1072 : {
444 [ + - ][ + + ]: 1072 : POSIX_ENSURE_REF(psk);
445 [ - + ][ # # ]: 1071 : POSIX_ENSURE_REF(binder_to_verify);
446 : :
447 : 1071 : DEFER_CLEANUP(struct s2n_tls13_keys psk_keys, s2n_tls13_keys_free);
448 [ - + ]: 1071 : POSIX_GUARD(s2n_tls13_keys_init(&psk_keys, psk->hmac_alg));
449 [ + + ][ + - ]: 1071 : POSIX_ENSURE_EQ(binder_to_verify->size, psk_keys.size);
450 : :
451 : : /* Calculate the binder hash from the transcript */
452 [ # # ][ - + ]: 2140 : s2n_tls13_key_blob(binder_hash, psk_keys.size);
[ - + ]
453 [ - + ]: 1070 : POSIX_GUARD(s2n_psk_calculate_binder_hash(conn, psk->hmac_alg, partial_client_hello, &binder_hash));
454 : :
455 : : /* Calculate the expected binder from the binder hash */
456 [ - + ][ - + ]: 2140 : s2n_tls13_key_blob(expected_binder, psk_keys.size);
[ # # ]
457 [ - + ]: 1070 : POSIX_GUARD(s2n_psk_calculate_binder(psk, &binder_hash, &expected_binder));
458 : :
459 : : /* Verify the expected binder matches the given binder.
460 : : * This operation must be constant time. */
461 [ + + ]: 1070 : POSIX_GUARD(s2n_tls13_mac_verify(&psk_keys, &expected_binder, binder_to_verify));
462 : :
463 : 1068 : return S2N_SUCCESS;
464 : 1070 : }
465 : :
466 : : static S2N_RESULT s2n_psk_write_binder(struct s2n_connection *conn, struct s2n_psk *psk,
467 : : const struct s2n_blob *binder_hash, struct s2n_stuffer *out)
468 : 1096 : {
469 [ - + ][ # # ]: 1096 : RESULT_ENSURE_REF(binder_hash);
470 : :
471 : 1096 : struct s2n_blob binder = { 0 };
472 : 1096 : uint8_t binder_data[S2N_TLS13_SECRET_MAX_LEN] = { 0 };
473 [ - + ]: 1096 : RESULT_GUARD_POSIX(s2n_blob_init(&binder, binder_data, binder_hash->size));
474 : :
475 [ - + ]: 1096 : RESULT_GUARD_POSIX(s2n_psk_calculate_binder(psk, binder_hash, &binder));
476 [ - + ]: 1096 : RESULT_GUARD_POSIX(s2n_stuffer_write_uint8(out, binder.size));
477 [ - + ]: 1096 : RESULT_GUARD_POSIX(s2n_stuffer_write(out, &binder));
478 : :
479 : 1096 : return S2N_RESULT_OK;
480 : 1096 : }
481 : :
482 : : static S2N_RESULT s2n_psk_write_binder_list(struct s2n_connection *conn, const struct s2n_blob *partial_client_hello,
483 : : struct s2n_stuffer *out)
484 : 1080 : {
485 [ - + ][ # # ]: 1080 : RESULT_ENSURE_REF(conn);
486 [ # # ][ - + ]: 1080 : RESULT_ENSURE_REF(partial_client_hello);
487 [ - + ][ # # ]: 1080 : RESULT_ENSURE_REF(conn->secure);
488 : :
489 : 1080 : struct s2n_psk_parameters *psk_params = &conn->psk_params;
490 : 1080 : struct s2n_array *psk_list = &psk_params->psk_list;
491 : :
492 : : /* Setup memory to hold the binder hashes. We potentially need one for
493 : : * every hash algorithm. */
494 : 1080 : uint8_t binder_hashes_data[S2N_HASH_ALGS_COUNT][S2N_TLS13_SECRET_MAX_LEN] = { 0 };
495 : 1080 : struct s2n_blob binder_hashes[S2N_HASH_ALGS_COUNT] = { 0 };
496 : :
497 : 1080 : struct s2n_stuffer_reservation binder_list_size = { 0 };
498 [ - + ]: 1080 : RESULT_GUARD_POSIX(s2n_stuffer_reserve_uint16(out, &binder_list_size));
499 : :
500 : : /* Write binder for every psk */
501 [ + + ]: 2176 : for (size_t i = 0; i < psk_list->len; i++) {
502 : 1096 : struct s2n_psk *psk = NULL;
503 [ - + ]: 1096 : RESULT_GUARD(s2n_array_get(psk_list, i, (void **) &psk));
504 [ - + ][ # # ]: 1096 : RESULT_ENSURE_REF(psk);
505 : :
506 : : /**
507 : : *= https://www.rfc-editor.org/rfc/rfc8446#section-4.1.4
508 : : *# In addition, in its updated ClientHello, the client SHOULD NOT offer
509 : : *# any pre-shared keys associated with a hash other than that of the
510 : : *# selected cipher suite. This allows the client to avoid having to
511 : : *# compute partial hash transcripts for multiple hashes in the second
512 : : *# ClientHello.
513 : : */
514 [ + + ][ - + ]: 1096 : if (s2n_is_hello_retry_handshake(conn) && conn->secure->cipher_suite->prf_alg != psk->hmac_alg) {
515 : 0 : continue;
516 : 0 : }
517 : :
518 : : /* Retrieve or calculate the binder hash. */
519 : 1096 : struct s2n_blob *binder_hash = &binder_hashes[psk->hmac_alg];
520 [ + + ]: 1096 : if (binder_hash->size == 0) {
521 : 1081 : uint8_t hash_size = 0;
522 [ - + ]: 1081 : RESULT_GUARD_POSIX(s2n_hmac_digest_size(psk->hmac_alg, &hash_size));
523 [ - + ]: 1081 : RESULT_GUARD_POSIX(s2n_blob_init(binder_hash, binder_hashes_data[psk->hmac_alg], hash_size));
524 [ - + ]: 1081 : RESULT_GUARD_POSIX(s2n_psk_calculate_binder_hash(conn, psk->hmac_alg, partial_client_hello, binder_hash));
525 : 1081 : }
526 : :
527 [ - + ]: 1096 : RESULT_GUARD(s2n_psk_write_binder(conn, psk, binder_hash, out));
528 : 1096 : }
529 [ - + ]: 1080 : RESULT_GUARD_POSIX(s2n_stuffer_write_vector_size(&binder_list_size));
530 : :
531 : 1080 : return S2N_RESULT_OK;
532 : 1080 : }
533 : :
534 : : S2N_RESULT s2n_finish_psk_extension(struct s2n_connection *conn)
535 : 7351 : {
536 [ - + ][ # # ]: 7351 : RESULT_ENSURE_REF(conn);
537 : :
538 [ + + ]: 7351 : if (!conn->psk_params.binder_list_size) {
539 : 6270 : return S2N_RESULT_OK;
540 : 6270 : }
541 : :
542 : 1081 : struct s2n_stuffer *client_hello = &conn->handshake.io;
543 : 1081 : struct s2n_psk_parameters *psk_params = &conn->psk_params;
544 : :
545 : : /* Fill in the correct message size. */
546 [ - + ]: 1081 : RESULT_GUARD_POSIX(s2n_handshake_finish_header(client_hello));
547 : :
548 : : /* Remove the empty space allocated for the binder list.
549 : : * It was originally added to ensure the extension / extension list / message sizes
550 : : * were properly calculated. */
551 [ - + ]: 1081 : RESULT_GUARD_POSIX(s2n_stuffer_wipe_n(client_hello, psk_params->binder_list_size));
552 : :
553 : : /* Store the partial client hello for use in calculating the binder hash. */
554 : 1081 : struct s2n_blob partial_client_hello = { 0 };
555 [ - + ]: 1081 : RESULT_GUARD_POSIX(s2n_blob_init(&partial_client_hello, client_hello->blob.data,
556 : 1081 : s2n_stuffer_data_available(client_hello)));
557 : :
558 [ - + ]: 1081 : RESULT_GUARD(s2n_psk_write_binder_list(conn, &partial_client_hello, client_hello));
559 : :
560 : : /* Reset binder list size.
561 : : * This is important because the psk extension can be removed during a retry.
562 : : */
563 : 1081 : conn->psk_params.binder_list_size = 0;
564 : :
565 : 1081 : return S2N_RESULT_OK;
566 : 1081 : }
567 : :
568 : : int s2n_psk_set_hmac(struct s2n_psk *psk, s2n_psk_hmac hmac)
569 : 48 : {
570 [ + - ][ + + ]: 48 : POSIX_ENSURE_REF(psk);
571 : 47 : switch (hmac) {
572 [ + + ]: 34 : case S2N_PSK_HMAC_SHA256:
573 : 34 : psk->hmac_alg = S2N_HMAC_SHA256;
574 : 34 : break;
575 [ + + ]: 12 : case S2N_PSK_HMAC_SHA384:
576 : 12 : psk->hmac_alg = S2N_HMAC_SHA384;
577 : 12 : break;
578 [ + + ]: 1 : default:
579 [ + - ]: 1 : POSIX_BAIL(S2N_ERR_HMAC_INVALID_ALGORITHM);
580 : 47 : }
581 : 46 : return S2N_SUCCESS;
582 : 47 : }
583 : :
584 : : S2N_RESULT s2n_connection_set_psk_type(struct s2n_connection *conn, s2n_psk_type type)
585 : 3559314 : {
586 [ - + ][ # # ]: 3559314 : RESULT_ENSURE_REF(conn);
587 [ + + ]: 3559314 : if (conn->psk_params.psk_list.len != 0) {
588 [ + + ][ + - ]: 45 : RESULT_ENSURE(conn->psk_params.type == type, S2N_ERR_PSK_MODE);
589 : 45 : }
590 : 3559310 : conn->psk_params.type = type;
591 : 3559310 : return S2N_RESULT_OK;
592 : 3559314 : }
593 : :
594 : : int s2n_connection_append_psk(struct s2n_connection *conn, struct s2n_psk *input_psk)
595 : 1344 : {
596 [ + + ][ + - ]: 1344 : POSIX_ENSURE_REF(conn);
597 [ + + ][ + - ]: 1343 : POSIX_ENSURE_REF(input_psk);
598 [ + + ]: 1342 : POSIX_GUARD_RESULT(s2n_connection_set_psk_type(conn, input_psk->type));
599 : :
600 : 1340 : struct s2n_array *psk_list = &conn->psk_params.psk_list;
601 : :
602 : : /* Check for duplicate identities */
603 [ + + ]: 4000 : for (uint32_t j = 0; j < psk_list->len; j++) {
604 : 2661 : struct s2n_psk *existing_psk = NULL;
605 [ - + ]: 2661 : POSIX_GUARD_RESULT(s2n_array_get(psk_list, j, (void **) &existing_psk));
606 [ # # ][ - + ]: 2661 : POSIX_ENSURE_REF(existing_psk);
607 : :
608 [ + + ]: 2661 : bool duplicate = existing_psk->identity.size == input_psk->identity.size
609 [ + + ]: 2661 : && memcmp(existing_psk->identity.data, input_psk->identity.data, existing_psk->identity.size) == 0;
610 [ + + ][ + - ]: 2661 : POSIX_ENSURE(!duplicate, S2N_ERR_DUPLICATE_PSK_IDENTITIES);
611 : 2661 : }
612 : :
613 : : /* Verify the PSK list will fit in the ClientHello pre_shared_key extension */
614 [ + + ]: 1339 : if (conn->mode == S2N_CLIENT) {
615 : 680 : uint32_t list_size = 0;
616 [ - + ]: 680 : POSIX_GUARD_RESULT(s2n_psk_parameters_offered_psks_size(&conn->psk_params, &list_size));
617 : :
618 : 680 : uint32_t psk_size = 0;
619 [ - + ]: 680 : POSIX_GUARD_RESULT(s2n_psk_offered_psk_size(input_psk, &psk_size));
620 : :
621 [ + + ][ + - ]: 680 : POSIX_ENSURE(list_size + psk_size + S2N_EXTENSION_HEADER_LENGTH <= UINT16_MAX, S2N_ERR_OFFERED_PSKS_TOO_LONG);
622 : 680 : }
623 : :
624 : 1337 : DEFER_CLEANUP(struct s2n_psk new_psk = { 0 }, s2n_psk_wipe);
625 [ + - ][ + + ]: 1337 : POSIX_ENSURE(s2n_result_is_ok(s2n_psk_clone(&new_psk, input_psk)), S2N_ERR_INVALID_ARGUMENT);
626 [ - + ]: 1335 : POSIX_GUARD_RESULT(s2n_array_insert_and_copy(psk_list, psk_list->len, &new_psk));
627 : :
628 : 1335 : ZERO_TO_DISABLE_DEFER_CLEANUP(new_psk);
629 : 1335 : return S2N_SUCCESS;
630 : 1335 : }
631 : :
632 : : int s2n_config_set_psk_mode(struct s2n_config *config, s2n_psk_mode mode)
633 : 3 : {
634 [ + - ][ + + ]: 3 : POSIX_ENSURE_REF(config);
635 : 2 : config->psk_mode = mode;
636 : 2 : return S2N_SUCCESS;
637 : 3 : }
638 : :
639 : : int s2n_connection_set_psk_mode(struct s2n_connection *conn, s2n_psk_mode mode)
640 : 3557718 : {
641 [ + + ][ + - ]: 3557718 : POSIX_ENSURE_REF(conn);
642 : 3557717 : s2n_psk_type type = 0;
643 : 3557717 : switch (mode) {
644 [ + + ]: 3557715 : case S2N_PSK_MODE_RESUMPTION:
645 : 3557715 : type = S2N_PSK_TYPE_RESUMPTION;
646 : 3557715 : break;
647 [ + + ]: 2 : case S2N_PSK_MODE_EXTERNAL:
648 : 2 : type = S2N_PSK_TYPE_EXTERNAL;
649 : 2 : break;
650 [ - + ]: 0 : default:
651 [ # # ]: 0 : POSIX_BAIL(S2N_ERR_INVALID_ARGUMENT);
652 : 0 : break;
653 : 3557717 : }
654 [ + + ]: 3557717 : POSIX_GUARD_RESULT(s2n_connection_set_psk_type(conn, type));
655 : 3557716 : conn->psk_mode_overridden = true;
656 : 3557716 : return S2N_SUCCESS;
657 : 3557717 : }
658 : :
659 : : int s2n_connection_get_negotiated_psk_identity_length(struct s2n_connection *conn, uint16_t *identity_length)
660 : 5 : {
661 [ + - ][ + + ]: 5 : POSIX_ENSURE_REF(conn);
662 [ + + ][ + - ]: 4 : POSIX_ENSURE_REF(identity_length);
663 : :
664 : 3 : struct s2n_psk *chosen_psk = conn->psk_params.chosen_psk;
665 : :
666 [ + + ]: 3 : if (chosen_psk == NULL) {
667 : 1 : *identity_length = 0;
668 : 2 : } else {
669 : 2 : *identity_length = chosen_psk->identity.size;
670 : 2 : }
671 : :
672 : 3 : return S2N_SUCCESS;
673 : 4 : }
674 : :
675 : : int s2n_connection_get_negotiated_psk_identity(struct s2n_connection *conn, uint8_t *identity,
676 : : uint16_t max_identity_length)
677 : 5 : {
678 [ + - ][ + + ]: 5 : POSIX_ENSURE_REF(conn);
679 [ + + ][ + - ]: 4 : POSIX_ENSURE_REF(identity);
680 : :
681 : 3 : struct s2n_psk *chosen_psk = conn->psk_params.chosen_psk;
682 : :
683 [ + + ]: 3 : if (chosen_psk == NULL) {
684 : 1 : return S2N_SUCCESS;
685 : 1 : }
686 : :
687 [ + - ][ + + ]: 2 : POSIX_ENSURE(chosen_psk->identity.size <= max_identity_length, S2N_ERR_INSUFFICIENT_MEM_SIZE);
688 [ - + ][ # # ]: 1 : POSIX_CHECKED_MEMCPY(identity, chosen_psk->identity.data, chosen_psk->identity.size);
[ + - ]
689 : :
690 : 1 : return S2N_SUCCESS;
691 : 1 : }
692 : :
693 : : S2N_RESULT s2n_psk_validate_keying_material(struct s2n_connection *conn)
694 : 428 : {
695 [ + + ][ + - ]: 428 : RESULT_ENSURE_REF(conn);
696 : :
697 : 427 : struct s2n_psk *chosen_psk = conn->psk_params.chosen_psk;
698 [ + + ][ + + ]: 427 : if (!chosen_psk || chosen_psk->type != S2N_PSK_TYPE_RESUMPTION) {
699 : 147 : return S2N_RESULT_OK;
700 : 147 : }
701 : :
702 : : /*
703 : : * The minimum ticket lifetime is 1s, because ticket_lifetime is given
704 : : * in seconds and 0 indicates that the ticket should be immediately discarded.
705 : : */
706 : 280 : uint32_t min_lifetime = ONE_SEC_IN_NANOS;
707 : :
708 : 280 : uint64_t current_time = 0;
709 [ - + ]: 280 : RESULT_GUARD(s2n_config_wall_clock(conn->config, ¤t_time));
710 [ + + ][ + - ]: 280 : RESULT_ENSURE(chosen_psk->keying_material_expiration > current_time + min_lifetime, S2N_ERR_KEYING_MATERIAL_EXPIRED);
711 : :
712 : 274 : return S2N_RESULT_OK;
713 : 280 : }
|