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: 2026-07-04 07:27:58 Functions: 36 36 100.0 %
Branches: 337 598 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 "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                 :    6970933 : {
     133 [ +  - ][ +  + ]:    6970933 :     RESULT_ENSURE_REF(params);
     134 [ -  + ][ #  # ]:    6970932 :     RESULT_CHECKED_MEMSET(params, 0, sizeof(struct s2n_psk_parameters));
                 [ +  - ]
     135         [ -  + ]:    6970932 :     RESULT_GUARD(s2n_array_init(&params->psk_list, sizeof(struct s2n_psk)));
     136                 :    6970932 :     return S2N_RESULT_OK;
     137                 :    6970932 : }
     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                 :    3548931 : {
     176 [ +  + ][ +  - ]:    3548931 :     RESULT_ENSURE_REF(params);
     177                 :            : 
     178         [ +  + ]:    3551736 :     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         [ -  + ]:    3548930 :     RESULT_GUARD_POSIX(s2n_free(&params->psk_list.mem));
     184         [ -  + ]:    3548930 :     RESULT_GUARD(s2n_psk_parameters_init(params));
     185                 :            : 
     186                 :    3548930 :     return S2N_RESULT_OK;
     187                 :    3548930 : }
     188                 :            : 
     189                 :            : S2N_CLEANUP_RESULT s2n_psk_parameters_wipe_secrets(struct s2n_psk_parameters *params)
     190                 :       9477 : {
     191 [ +  + ][ +  - ]:       9477 :     RESULT_ENSURE_REF(params);
     192                 :            : 
     193         [ +  + ]:      10710 :     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                 :       9476 :     return S2N_RESULT_OK;
     202                 :       9476 : }
     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                 :        142 : {
     319 [ +  + ][ +  - ]:        142 :     POSIX_ENSURE_REF(psk_list);
     320 [ #  # ][ -  + ]:        141 :     POSIX_ENSURE_REF(psk_list->conn);
     321                 :            : 
     322                 :        141 :     struct s2n_psk_parameters *psk_params = &psk_list->conn->psk_params;
     323                 :        141 :     struct s2n_stuffer ticket_stuffer = { 0 };
     324                 :            : 
     325         [ +  + ]:        141 :     if (!psk) {
     326                 :          1 :         psk_params->chosen_psk = NULL;
     327                 :          1 :         return S2N_SUCCESS;
     328                 :          1 :     }
     329                 :            : 
     330 [ +  + ][ +  + ]:        140 :     if (psk_params->type == S2N_PSK_TYPE_RESUMPTION && psk_list->conn->config->use_tickets) {
     331         [ -  + ]:        126 :         POSIX_GUARD(s2n_stuffer_init(&ticket_stuffer, &psk->identity));
     332         [ -  + ]:        126 :         POSIX_GUARD(s2n_stuffer_skip_write(&ticket_stuffer, psk->identity.size));
     333                 :            : 
     334                 :            :         /* s2n_resume_decrypt_session appends a new PSK with the decrypted values. */
     335         [ +  + ]:        126 :         POSIX_GUARD_RESULT(s2n_resume_decrypt_session(psk_list->conn, &ticket_stuffer));
     336                 :        126 :     }
     337                 :            : 
     338                 :        130 :     struct s2n_psk *chosen_psk = NULL;
     339         [ -  + ]:        130 :     POSIX_GUARD_RESULT(s2n_match_psk_identity(&psk_params->psk_list, &psk->identity, &chosen_psk));
     340 [ +  + ][ +  - ]:        130 :     POSIX_ENSURE_REF(chosen_psk);
     341         [ +  + ]:        122 :     POSIX_GUARD_RESULT(s2n_validate_ticket_lifetime(psk_list->conn, psk->obfuscated_ticket_age, chosen_psk->ticket_age_add));
     342                 :        120 :     psk_params->chosen_psk = chosen_psk;
     343                 :        120 :     psk_params->chosen_psk_wire_index = psk->wire_index;
     344                 :            : 
     345                 :        120 :     return S2N_SUCCESS;
     346                 :        122 : }
     347                 :            : 
     348                 :            : struct s2n_offered_psk *s2n_offered_psk_new()
     349                 :          4 : {
     350                 :          4 :     DEFER_CLEANUP(struct s2n_blob mem = { 0 }, s2n_free);
     351         [ -  + ]:          4 :     PTR_GUARD_POSIX(s2n_alloc(&mem, sizeof(struct s2n_offered_psk)));
     352         [ -  + ]:          4 :     PTR_GUARD_POSIX(s2n_blob_zero(&mem));
     353                 :            : 
     354                 :          4 :     struct s2n_offered_psk *psk = (struct s2n_offered_psk *) (void *) mem.data;
     355                 :            : 
     356                 :          4 :     ZERO_TO_DISABLE_DEFER_CLEANUP(mem);
     357                 :          4 :     return psk;
     358                 :          4 : }
     359                 :            : 
     360                 :            : int s2n_offered_psk_free(struct s2n_offered_psk **psk)
     361                 :          5 : {
     362         [ +  + ]:          5 :     if (psk == NULL) {
     363                 :          1 :         return S2N_SUCCESS;
     364                 :          1 :     }
     365                 :          4 :     return s2n_free_object((uint8_t **) psk, sizeof(struct s2n_offered_psk));
     366                 :          5 : }
     367                 :            : 
     368                 :            : int s2n_offered_psk_get_identity(struct s2n_offered_psk *psk, uint8_t **identity, uint16_t *size)
     369                 :          8 : {
     370 [ +  - ][ +  + ]:          8 :     POSIX_ENSURE_REF(psk);
     371 [ +  - ][ +  + ]:          7 :     POSIX_ENSURE_REF(psk->identity.data);
     372 [ -  + ][ #  # ]:          4 :     POSIX_ENSURE_REF(identity);
     373 [ -  + ][ #  # ]:          4 :     POSIX_ENSURE_REF(size);
     374                 :          4 :     *identity = psk->identity.data;
     375                 :          4 :     *size = psk->identity.size;
     376                 :          4 :     return S2N_SUCCESS;
     377                 :          4 : }
     378                 :            : 
     379                 :            : /* The binder hash is computed by hashing the concatenation of the current transcript
     380                 :            :  * and a partial ClientHello that does not include the binders themselves.
     381                 :            :  */
     382                 :            : int s2n_psk_calculate_binder_hash(struct s2n_connection *conn, s2n_hmac_algorithm hmac_alg,
     383                 :            :         const struct s2n_blob *partial_client_hello, struct s2n_blob *output_binder_hash)
     384                 :       2162 : {
     385 [ #  # ][ -  + ]:       2162 :     POSIX_ENSURE_REF(conn);
     386 [ #  # ][ -  + ]:       2162 :     POSIX_ENSURE_REF(partial_client_hello);
     387 [ #  # ][ -  + ]:       2162 :     POSIX_ENSURE_REF(output_binder_hash);
     388                 :       2162 :     struct s2n_handshake_hashes *hashes = conn->handshake.hashes;
     389 [ -  + ][ #  # ]:       2162 :     POSIX_ENSURE_REF(hashes);
     390                 :            : 
     391                 :            :     /* Retrieve the current transcript.
     392                 :            :      * The current transcript will be empty unless this handshake included a HelloRetryRequest. */
     393                 :       2162 :     s2n_hash_algorithm hash_alg = S2N_HASH_NONE;
     394                 :       2162 :     struct s2n_hash_state *hash_state = &hashes->hash_workspace;
     395         [ -  + ]:       2162 :     POSIX_GUARD(s2n_hmac_hash_alg(hmac_alg, &hash_alg));
     396         [ -  + ]:       2162 :     POSIX_GUARD_RESULT(s2n_handshake_copy_hash_state(conn, hash_alg, hash_state));
     397                 :            : 
     398                 :            :     /* Add the partial client hello to the transcript. */
     399         [ -  + ]:       2162 :     POSIX_GUARD(s2n_hash_update(hash_state, partial_client_hello->data, partial_client_hello->size));
     400                 :            : 
     401                 :            :     /* Get the transcript digest */
     402         [ -  + ]:       2162 :     POSIX_GUARD(s2n_hash_digest(hash_state, output_binder_hash->data, output_binder_hash->size));
     403                 :            : 
     404                 :       2162 :     return S2N_SUCCESS;
     405                 :       2162 : }
     406                 :            : 
     407                 :            : /* The binder is computed in the same way as the Finished message
     408                 :            :  * (https://tools.ietf.org/html/rfc8446#section-4.4.4) but with the BaseKey being the binder_key
     409                 :            :  * derived via the key schedule from the corresponding PSK which is being offered
     410                 :            :  * (https://tools.ietf.org/html/rfc8446#section-7.1)
     411                 :            :  */
     412                 :            : int s2n_psk_calculate_binder(struct s2n_psk *psk, const struct s2n_blob *binder_hash,
     413                 :            :         struct s2n_blob *output_binder)
     414                 :       2183 : {
     415 [ -  + ][ #  # ]:       2183 :     POSIX_ENSURE_REF(psk);
     416 [ -  + ][ #  # ]:       2183 :     POSIX_ENSURE_REF(binder_hash);
     417 [ -  + ][ #  # ]:       2183 :     POSIX_ENSURE_REF(output_binder);
     418                 :            : 
     419                 :       2183 :     DEFER_CLEANUP(struct s2n_tls13_keys psk_keys, s2n_tls13_keys_free);
     420         [ -  + ]:       2183 :     POSIX_GUARD(s2n_tls13_keys_init(&psk_keys, psk->hmac_alg));
     421 [ -  + ][ #  # ]:       2183 :     POSIX_ENSURE_EQ(binder_hash->size, psk_keys.size);
     422 [ #  # ][ -  + ]:       2183 :     POSIX_ENSURE_EQ(output_binder->size, psk_keys.size);
     423                 :            : 
     424                 :            :     /* Derive the binder key */
     425         [ -  + ]:       2183 :     POSIX_GUARD_RESULT(s2n_derive_binder_key(psk, &psk_keys.derive_secret));
     426         [ -  + ]:       2183 :     POSIX_GUARD(s2n_blob_init(&psk_keys.extract_secret, psk->early_secret.data, psk_keys.size));
     427                 :       2183 :     struct s2n_blob *binder_key = &psk_keys.derive_secret;
     428                 :            : 
     429                 :            :     /* Expand the binder key into the finished key */
     430 [ -  + ][ #  # ]:       2183 :     s2n_tls13_key_blob(finished_key, psk_keys.size);
                 [ -  + ]
     431         [ -  + ]:       2183 :     POSIX_GUARD(s2n_tls13_derive_finished_key(&psk_keys, binder_key, &finished_key));
     432                 :            : 
     433                 :            :     /* HMAC the binder hash with the binder finished key */
     434         [ -  + ]:       2183 :     POSIX_GUARD(s2n_hkdf_extract(&psk_keys.hmac, psk_keys.hmac_algorithm, &finished_key, binder_hash, output_binder));
     435                 :            : 
     436                 :       2183 :     return S2N_SUCCESS;
     437                 :       2183 : }
     438                 :            : 
     439                 :            : int s2n_psk_verify_binder(struct s2n_connection *conn, struct s2n_psk *psk,
     440                 :            :         const struct s2n_blob *partial_client_hello, struct s2n_blob *binder_to_verify)
     441                 :       1073 : {
     442 [ +  - ][ +  + ]:       1073 :     POSIX_ENSURE_REF(psk);
     443 [ #  # ][ -  + ]:       1072 :     POSIX_ENSURE_REF(binder_to_verify);
     444                 :            : 
     445                 :       1072 :     DEFER_CLEANUP(struct s2n_tls13_keys psk_keys, s2n_tls13_keys_free);
     446         [ -  + ]:       1072 :     POSIX_GUARD(s2n_tls13_keys_init(&psk_keys, psk->hmac_alg));
     447 [ +  - ][ +  + ]:       1072 :     POSIX_ENSURE_EQ(binder_to_verify->size, psk_keys.size);
     448                 :            : 
     449                 :            :     /* Calculate the binder hash from the transcript */
     450 [ #  # ][ -  + ]:       2142 :     s2n_tls13_key_blob(binder_hash, psk_keys.size);
                 [ -  + ]
     451         [ -  + ]:       1071 :     POSIX_GUARD(s2n_psk_calculate_binder_hash(conn, psk->hmac_alg, partial_client_hello, &binder_hash));
     452                 :            : 
     453                 :            :     /* Calculate the expected binder from the binder hash */
     454 [ -  + ][ #  # ]:       2142 :     s2n_tls13_key_blob(expected_binder, psk_keys.size);
                 [ -  + ]
     455         [ -  + ]:       1071 :     POSIX_GUARD(s2n_psk_calculate_binder(psk, &binder_hash, &expected_binder));
     456                 :            : 
     457                 :            :     /* Verify the expected binder matches the given binder.
     458                 :            :      * This operation must be constant time. */
     459         [ +  + ]:       1071 :     POSIX_GUARD(s2n_tls13_mac_verify(&psk_keys, &expected_binder, binder_to_verify));
     460                 :            : 
     461                 :       1069 :     return S2N_SUCCESS;
     462                 :       1071 : }
     463                 :            : 
     464                 :            : static S2N_RESULT s2n_psk_write_binder(struct s2n_connection *conn, struct s2n_psk *psk,
     465                 :            :         const struct s2n_blob *binder_hash, struct s2n_stuffer *out)
     466                 :       1097 : {
     467 [ #  # ][ -  + ]:       1097 :     RESULT_ENSURE_REF(binder_hash);
     468                 :            : 
     469                 :       1097 :     struct s2n_blob binder = { 0 };
     470                 :       1097 :     uint8_t binder_data[S2N_TLS13_SECRET_MAX_LEN] = { 0 };
     471         [ -  + ]:       1097 :     RESULT_GUARD_POSIX(s2n_blob_init(&binder, binder_data, binder_hash->size));
     472                 :            : 
     473         [ -  + ]:       1097 :     RESULT_GUARD_POSIX(s2n_psk_calculate_binder(psk, binder_hash, &binder));
     474         [ -  + ]:       1097 :     RESULT_GUARD_POSIX(s2n_stuffer_write_uint8(out, binder.size));
     475         [ -  + ]:       1097 :     RESULT_GUARD_POSIX(s2n_stuffer_write(out, &binder));
     476                 :            : 
     477                 :       1097 :     return S2N_RESULT_OK;
     478                 :       1097 : }
     479                 :            : 
     480                 :            : static S2N_RESULT s2n_psk_write_binder_list(struct s2n_connection *conn, const struct s2n_blob *partial_client_hello,
     481                 :            :         struct s2n_stuffer *out)
     482                 :       1081 : {
     483 [ -  + ][ #  # ]:       1081 :     RESULT_ENSURE_REF(conn);
     484 [ #  # ][ -  + ]:       1081 :     RESULT_ENSURE_REF(partial_client_hello);
     485 [ -  + ][ #  # ]:       1081 :     RESULT_ENSURE_REF(conn->secure);
     486                 :            : 
     487                 :       1081 :     struct s2n_psk_parameters *psk_params = &conn->psk_params;
     488                 :       1081 :     struct s2n_array *psk_list = &psk_params->psk_list;
     489                 :            : 
     490                 :            :     /* Setup memory to hold the binder hashes. We potentially need one for
     491                 :            :      * every hash algorithm. */
     492                 :       1081 :     uint8_t binder_hashes_data[S2N_HASH_ALGS_COUNT][S2N_TLS13_SECRET_MAX_LEN] = { 0 };
     493                 :       1081 :     struct s2n_blob binder_hashes[S2N_HASH_ALGS_COUNT] = { 0 };
     494                 :            : 
     495                 :       1081 :     struct s2n_stuffer_reservation binder_list_size = { 0 };
     496         [ -  + ]:       1081 :     RESULT_GUARD_POSIX(s2n_stuffer_reserve_uint16(out, &binder_list_size));
     497                 :            : 
     498                 :            :     /* Write binder for every psk */
     499         [ +  + ]:       2178 :     for (size_t i = 0; i < psk_list->len; i++) {
     500                 :       1097 :         struct s2n_psk *psk = NULL;
     501         [ -  + ]:       1097 :         RESULT_GUARD(s2n_array_get(psk_list, i, (void **) &psk));
     502 [ -  + ][ #  # ]:       1097 :         RESULT_ENSURE_REF(psk);
     503                 :            : 
     504                 :            :         /**
     505                 :            :          *= https://www.rfc-editor.org/rfc/rfc8446#section-4.1.4
     506                 :            :          *# In addition, in its updated ClientHello, the client SHOULD NOT offer
     507                 :            :          *# any pre-shared keys associated with a hash other than that of the
     508                 :            :          *# selected cipher suite.  This allows the client to avoid having to
     509                 :            :          *# compute partial hash transcripts for multiple hashes in the second
     510                 :            :          *# ClientHello.
     511                 :            :          */
     512 [ +  + ][ -  + ]:       1097 :         if (s2n_is_hello_retry_handshake(conn) && conn->secure->cipher_suite->prf_alg != psk->hmac_alg) {
     513                 :          0 :             continue;
     514                 :          0 :         }
     515                 :            : 
     516                 :            :         /* Retrieve or calculate the binder hash. */
     517                 :       1097 :         struct s2n_blob *binder_hash = &binder_hashes[psk->hmac_alg];
     518         [ +  + ]:       1097 :         if (binder_hash->size == 0) {
     519                 :       1082 :             uint8_t hash_size = 0;
     520         [ -  + ]:       1082 :             RESULT_GUARD_POSIX(s2n_hmac_digest_size(psk->hmac_alg, &hash_size));
     521         [ -  + ]:       1082 :             RESULT_GUARD_POSIX(s2n_blob_init(binder_hash, binder_hashes_data[psk->hmac_alg], hash_size));
     522         [ -  + ]:       1082 :             RESULT_GUARD_POSIX(s2n_psk_calculate_binder_hash(conn, psk->hmac_alg, partial_client_hello, binder_hash));
     523                 :       1082 :         }
     524                 :            : 
     525         [ -  + ]:       1097 :         RESULT_GUARD(s2n_psk_write_binder(conn, psk, binder_hash, out));
     526                 :       1097 :     }
     527         [ -  + ]:       1081 :     RESULT_GUARD_POSIX(s2n_stuffer_write_vector_size(&binder_list_size));
     528                 :            : 
     529                 :       1081 :     return S2N_RESULT_OK;
     530                 :       1081 : }
     531                 :            : 
     532                 :            : S2N_RESULT s2n_finish_psk_extension(struct s2n_connection *conn)
     533                 :       7721 : {
     534 [ -  + ][ #  # ]:       7721 :     RESULT_ENSURE_REF(conn);
     535                 :            : 
     536         [ +  + ]:       7721 :     if (!conn->psk_params.binder_list_size) {
     537                 :       6639 :         return S2N_RESULT_OK;
     538                 :       6639 :     }
     539                 :            : 
     540                 :       1082 :     struct s2n_stuffer *client_hello = &conn->handshake.io;
     541                 :       1082 :     struct s2n_psk_parameters *psk_params = &conn->psk_params;
     542                 :            : 
     543                 :            :     /* Fill in the correct message size. */
     544         [ -  + ]:       1082 :     RESULT_GUARD_POSIX(s2n_handshake_finish_header(client_hello));
     545                 :            : 
     546                 :            :     /* Remove the empty space allocated for the binder list.
     547                 :            :      * It was originally added to ensure the extension / extension list / message sizes
     548                 :            :      * were properly calculated. */
     549         [ -  + ]:       1082 :     RESULT_GUARD_POSIX(s2n_stuffer_wipe_n(client_hello, psk_params->binder_list_size));
     550                 :            : 
     551                 :            :     /* Store the partial client hello for use in calculating the binder hash. */
     552                 :       1082 :     struct s2n_blob partial_client_hello = { 0 };
     553         [ -  + ]:       1082 :     RESULT_GUARD_POSIX(s2n_blob_init(&partial_client_hello, client_hello->blob.data,
     554                 :       1082 :             s2n_stuffer_data_available(client_hello)));
     555                 :            : 
     556         [ -  + ]:       1082 :     RESULT_GUARD(s2n_psk_write_binder_list(conn, &partial_client_hello, client_hello));
     557                 :            : 
     558                 :            :     /* Reset binder list size.
     559                 :            :      * This is important because the psk extension can be removed during a retry.
     560                 :            :      */
     561                 :       1082 :     conn->psk_params.binder_list_size = 0;
     562                 :            : 
     563                 :       1082 :     return S2N_RESULT_OK;
     564                 :       1082 : }
     565                 :            : 
     566                 :            : int s2n_psk_set_hmac(struct s2n_psk *psk, s2n_psk_hmac hmac)
     567                 :         48 : {
     568 [ +  - ][ +  + ]:         48 :     POSIX_ENSURE_REF(psk);
     569                 :         47 :     switch (hmac) {
     570         [ +  + ]:         34 :         case S2N_PSK_HMAC_SHA256:
     571                 :         34 :             psk->hmac_alg = S2N_HMAC_SHA256;
     572                 :         34 :             break;
     573         [ +  + ]:         12 :         case S2N_PSK_HMAC_SHA384:
     574                 :         12 :             psk->hmac_alg = S2N_HMAC_SHA384;
     575                 :         12 :             break;
     576         [ +  + ]:          1 :         default:
     577         [ +  - ]:          1 :             POSIX_BAIL(S2N_ERR_HMAC_INVALID_ALGORITHM);
     578                 :         47 :     }
     579                 :         46 :     return S2N_SUCCESS;
     580                 :         47 : }
     581                 :            : 
     582                 :            : S2N_RESULT s2n_connection_set_psk_type(struct s2n_connection *conn, s2n_psk_type type)
     583                 :    3562938 : {
     584 [ -  + ][ #  # ]:    3562938 :     RESULT_ENSURE_REF(conn);
     585         [ +  + ]:    3562938 :     if (conn->psk_params.psk_list.len != 0) {
     586 [ +  + ][ +  - ]:         45 :         RESULT_ENSURE(conn->psk_params.type == type, S2N_ERR_PSK_MODE);
     587                 :         45 :     }
     588                 :    3562934 :     conn->psk_params.type = type;
     589                 :    3562934 :     return S2N_RESULT_OK;
     590                 :    3562938 : }
     591                 :            : 
     592                 :            : int s2n_connection_append_psk(struct s2n_connection *conn, struct s2n_psk *input_psk)
     593                 :       1344 : {
     594 [ +  + ][ +  - ]:       1344 :     POSIX_ENSURE_REF(conn);
     595 [ +  + ][ +  - ]:       1343 :     POSIX_ENSURE_REF(input_psk);
     596         [ +  + ]:       1342 :     POSIX_GUARD_RESULT(s2n_connection_set_psk_type(conn, input_psk->type));
     597                 :            : 
     598                 :       1340 :     struct s2n_array *psk_list = &conn->psk_params.psk_list;
     599                 :            : 
     600                 :            :     /* Check for duplicate identities */
     601         [ +  + ]:       4000 :     for (uint32_t j = 0; j < psk_list->len; j++) {
     602                 :       2661 :         struct s2n_psk *existing_psk = NULL;
     603         [ -  + ]:       2661 :         POSIX_GUARD_RESULT(s2n_array_get(psk_list, j, (void **) &existing_psk));
     604 [ -  + ][ #  # ]:       2661 :         POSIX_ENSURE_REF(existing_psk);
     605                 :            : 
     606         [ +  + ]:       2661 :         bool duplicate = existing_psk->identity.size == input_psk->identity.size
     607         [ +  + ]:       2661 :                 && memcmp(existing_psk->identity.data, input_psk->identity.data, existing_psk->identity.size) == 0;
     608 [ +  + ][ +  - ]:       2661 :         POSIX_ENSURE(!duplicate, S2N_ERR_DUPLICATE_PSK_IDENTITIES);
     609                 :       2661 :     }
     610                 :            : 
     611                 :            :     /* Verify the PSK list will fit in the ClientHello pre_shared_key extension */
     612         [ +  + ]:       1339 :     if (conn->mode == S2N_CLIENT) {
     613                 :        680 :         uint32_t list_size = 0;
     614         [ -  + ]:        680 :         POSIX_GUARD_RESULT(s2n_psk_parameters_offered_psks_size(&conn->psk_params, &list_size));
     615                 :            : 
     616                 :        680 :         uint32_t psk_size = 0;
     617         [ -  + ]:        680 :         POSIX_GUARD_RESULT(s2n_psk_offered_psk_size(input_psk, &psk_size));
     618                 :            : 
     619 [ +  + ][ +  - ]:        680 :         POSIX_ENSURE(list_size + psk_size + S2N_EXTENSION_HEADER_LENGTH <= UINT16_MAX, S2N_ERR_OFFERED_PSKS_TOO_LONG);
     620                 :        680 :     }
     621                 :            : 
     622                 :       1337 :     DEFER_CLEANUP(struct s2n_psk new_psk = { 0 }, s2n_psk_wipe);
     623 [ +  + ][ +  - ]:       1337 :     POSIX_ENSURE(s2n_result_is_ok(s2n_psk_clone(&new_psk, input_psk)), S2N_ERR_INVALID_ARGUMENT);
     624         [ -  + ]:       1335 :     POSIX_GUARD_RESULT(s2n_array_insert_and_copy(psk_list, psk_list->len, &new_psk));
     625                 :            : 
     626                 :       1335 :     ZERO_TO_DISABLE_DEFER_CLEANUP(new_psk);
     627                 :       1335 :     return S2N_SUCCESS;
     628                 :       1335 : }
     629                 :            : 
     630                 :            : int s2n_config_set_psk_mode(struct s2n_config *config, s2n_psk_mode mode)
     631                 :          3 : {
     632 [ +  - ][ +  + ]:          3 :     POSIX_ENSURE_REF(config);
     633                 :          2 :     config->psk_mode = mode;
     634                 :          2 :     return S2N_SUCCESS;
     635                 :          3 : }
     636                 :            : 
     637                 :            : int s2n_connection_set_psk_mode(struct s2n_connection *conn, s2n_psk_mode mode)
     638                 :    3561341 : {
     639 [ +  - ][ +  + ]:    3561341 :     POSIX_ENSURE_REF(conn);
     640                 :    3561340 :     s2n_psk_type type = 0;
     641                 :    3561340 :     switch (mode) {
     642         [ +  + ]:    3561338 :         case S2N_PSK_MODE_RESUMPTION:
     643                 :    3561338 :             type = S2N_PSK_TYPE_RESUMPTION;
     644                 :    3561338 :             break;
     645         [ +  + ]:          2 :         case S2N_PSK_MODE_EXTERNAL:
     646                 :          2 :             type = S2N_PSK_TYPE_EXTERNAL;
     647                 :          2 :             break;
     648         [ -  + ]:          0 :         default:
     649         [ #  # ]:          0 :             POSIX_BAIL(S2N_ERR_INVALID_ARGUMENT);
     650                 :          0 :             break;
     651                 :    3561340 :     }
     652         [ +  + ]:    3561340 :     POSIX_GUARD_RESULT(s2n_connection_set_psk_type(conn, type));
     653                 :    3561339 :     conn->psk_mode_overridden = true;
     654                 :    3561339 :     return S2N_SUCCESS;
     655                 :    3561340 : }
     656                 :            : 
     657                 :            : int s2n_connection_get_negotiated_psk_identity_length(struct s2n_connection *conn, uint16_t *identity_length)
     658                 :          5 : {
     659 [ +  - ][ +  + ]:          5 :     POSIX_ENSURE_REF(conn);
     660 [ +  + ][ +  - ]:          4 :     POSIX_ENSURE_REF(identity_length);
     661                 :            : 
     662                 :          3 :     struct s2n_psk *chosen_psk = conn->psk_params.chosen_psk;
     663                 :            : 
     664         [ +  + ]:          3 :     if (chosen_psk == NULL) {
     665                 :          1 :         *identity_length = 0;
     666                 :          2 :     } else {
     667                 :          2 :         *identity_length = chosen_psk->identity.size;
     668                 :          2 :     }
     669                 :            : 
     670                 :          3 :     return S2N_SUCCESS;
     671                 :          4 : }
     672                 :            : 
     673                 :            : int s2n_connection_get_negotiated_psk_identity(struct s2n_connection *conn, uint8_t *identity,
     674                 :            :         uint16_t max_identity_length)
     675                 :          5 : {
     676 [ +  + ][ +  - ]:          5 :     POSIX_ENSURE_REF(conn);
     677 [ +  + ][ +  - ]:          4 :     POSIX_ENSURE_REF(identity);
     678                 :            : 
     679                 :          3 :     struct s2n_psk *chosen_psk = conn->psk_params.chosen_psk;
     680                 :            : 
     681         [ +  + ]:          3 :     if (chosen_psk == NULL) {
     682                 :          1 :         return S2N_SUCCESS;
     683                 :          1 :     }
     684                 :            : 
     685 [ +  - ][ +  + ]:          2 :     POSIX_ENSURE(chosen_psk->identity.size <= max_identity_length, S2N_ERR_INSUFFICIENT_MEM_SIZE);
     686 [ #  # ][ -  + ]:          1 :     POSIX_CHECKED_MEMCPY(identity, chosen_psk->identity.data, chosen_psk->identity.size);
                 [ +  - ]
     687                 :            : 
     688                 :          1 :     return S2N_SUCCESS;
     689                 :          1 : }
     690                 :            : 
     691                 :            : S2N_RESULT s2n_psk_validate_keying_material(struct s2n_connection *conn)
     692                 :        428 : {
     693 [ +  + ][ +  - ]:        428 :     RESULT_ENSURE_REF(conn);
     694                 :            : 
     695                 :        427 :     struct s2n_psk *chosen_psk = conn->psk_params.chosen_psk;
     696 [ +  + ][ +  + ]:        427 :     if (!chosen_psk || chosen_psk->type != S2N_PSK_TYPE_RESUMPTION) {
     697                 :        147 :         return S2N_RESULT_OK;
     698                 :        147 :     }
     699                 :            : 
     700                 :            :     /*
     701                 :            :      * The minimum ticket lifetime is 1s, because ticket_lifetime is given
     702                 :            :      * in seconds and 0 indicates that the ticket should be immediately discarded.
     703                 :            :      */
     704                 :        280 :     uint32_t min_lifetime = ONE_SEC_IN_NANOS;
     705                 :            : 
     706                 :        280 :     uint64_t current_time = 0;
     707         [ -  + ]:        280 :     RESULT_GUARD(s2n_config_wall_clock(conn->config, &current_time));
     708 [ +  - ][ +  + ]:        280 :     RESULT_ENSURE(chosen_psk->keying_material_expiration > current_time + min_lifetime, S2N_ERR_KEYING_MATERIAL_EXPIRED);
     709                 :            : 
     710                 :        274 :     return S2N_RESULT_OK;
     711                 :        280 : }

Generated by: LCOV version 1.14