LCOV - code coverage report
Current view: top level - tls - s2n_psk.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 431 438 98.4 %
Date: 2025-08-15 07:28:39 Functions: 36 36 100.0 %
Branches: 336 596 56.4 %

           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(&params->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(&params->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(&params->psk_list, i, (void **) &psk));
     183         [ -  + ]:       2804 :         RESULT_GUARD(s2n_psk_wipe(psk));
     184                 :       2804 :     }
     185         [ -  + ]:    3546067 :     RESULT_GUARD_POSIX(s2n_free(&params->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(&params->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, &current_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 : }

Generated by: LCOV version 1.14