LCOV - code coverage report
Current view: top level - tls - s2n_psk.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 432 439 98.4 %
Date: 2026-08-22 07:27:53 Functions: 36 36 100.0 %
Branches: 340 602 56.5 %

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

Generated by: LCOV version 1.14