LCOV - code coverage report
Current view: top level - tls - s2n_tls13_secrets.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 401 405 99.0 %
Date: 2025-08-15 07:28:39 Functions: 29 29 100.0 %
Branches: 235 528 44.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 "tls/s2n_tls13_secrets.h"
      17                 :            : 
      18                 :            : #include "tls/s2n_connection.h"
      19                 :            : #include "tls/s2n_key_log.h"
      20                 :            : #include "tls/s2n_tls13_handshake.h"
      21                 :            : #include "utils/s2n_bitmap.h"
      22                 :            : 
      23                 :            : #define S2N_MAX_HASHLEN SHA384_DIGEST_LENGTH
      24                 :            : 
      25                 :      37042 : #define CONN_HMAC_ALG(conn) ((conn)->secure->cipher_suite->prf_alg)
      26                 :     139055 : #define CONN_SECRETS(conn)  ((conn)->secrets.version.tls13)
      27                 :            : #define CONN_HASHES(conn)   ((conn)->handshake.hashes)
      28                 :            : 
      29                 :            : #define CONN_SECRET(conn, secret) ( \
      30                 :            :         (struct s2n_blob){ .data = CONN_SECRETS(conn).secret, .size = s2n_get_hash_len(CONN_HMAC_ALG(conn)) })
      31                 :            : #define CONN_HASH(conn, hash) ( \
      32                 :            :         (struct s2n_blob){ .data = CONN_HASHES(conn)->hash, .size = s2n_get_hash_len(CONN_HMAC_ALG(conn)) })
      33                 :            : #define CONN_FINISHED(conn, mode) ( \
      34                 :            :         (struct s2n_blob){ .data = (conn)->handshake.mode##_finished, .size = s2n_get_hash_len(CONN_HMAC_ALG(conn)) })
      35                 :            : 
      36                 :            : /**
      37                 :            :  *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
      38                 :            :  *# If a given secret is not available, then the 0-value consisting of a
      39                 :            :  *# string of Hash.length bytes set to zeros is used.
      40                 :            :  */
      41                 :            : static uint8_t zero_value_bytes[S2N_MAX_HASHLEN] = { 0 };
      42                 :            : #define ZERO_VALUE(hmac_alg) ( \
      43                 :            :         (const struct s2n_blob){ .data = zero_value_bytes, .size = s2n_get_hash_len(hmac_alg) })
      44                 :            : 
      45                 :            : /**
      46                 :            :  * When an operation doesn't need an actual transcript hash,
      47                 :            :  * it uses an empty transcript hash as an input instead.
      48                 :            :  *
      49                 :            :  *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
      50                 :            :  *# Note that in some cases a zero-
      51                 :            :  *# length Context (indicated by "") is passed to HKDF-Expand-Label
      52                 :            :  */
      53                 :       1090 : #define EMPTY_CONTEXT(hmac_alg) ( \
      54                 :       1090 :         (const struct s2n_blob){ .data = s2n_get_empty_context(hmac_alg), .size = s2n_get_hash_len(hmac_alg) })
      55                 :            : 
      56                 :            : static uint8_t s2n_get_hash_len(s2n_hmac_algorithm hmac_alg)
      57                 :     330213 : {
      58                 :     330213 :     uint8_t hash_size = 0;
      59         [ -  + ]:     330213 :     if (s2n_hmac_digest_size(hmac_alg, &hash_size) != S2N_SUCCESS) {
      60                 :          0 :         return 0;
      61                 :          0 :     }
      62                 :     330213 :     return hash_size;
      63                 :     330213 : }
      64                 :            : 
      65                 :            : static uint8_t *s2n_get_empty_context(s2n_hmac_algorithm hmac_alg)
      66                 :      18509 : {
      67                 :      18509 :     static uint8_t sha256_empty_digest[S2N_MAX_HASHLEN] = { 0 };
      68                 :      18509 :     static uint8_t sha384_empty_digest[S2N_MAX_HASHLEN] = { 0 };
      69                 :            : 
      70                 :      18509 :     switch (hmac_alg) {
      71         [ +  + ]:      17519 :         case S2N_HMAC_SHA256:
      72                 :      17519 :             return sha256_empty_digest;
      73         [ +  + ]:        990 :         case S2N_HMAC_SHA384:
      74                 :        990 :             return sha384_empty_digest;
      75         [ -  + ]:          0 :         default:
      76                 :          0 :             return NULL;
      77                 :      18509 :     }
      78                 :      18509 : }
      79                 :            : 
      80                 :            : static s2n_hmac_algorithm supported_hmacs[] = {
      81                 :            :     S2N_HMAC_SHA256,
      82                 :            :     S2N_HMAC_SHA384
      83                 :            : };
      84                 :            : 
      85                 :            : S2N_RESULT s2n_tls13_empty_transcripts_init()
      86                 :        545 : {
      87                 :        545 :     DEFER_CLEANUP(struct s2n_hash_state hash = { 0 }, s2n_hash_free);
      88         [ -  + ]:        545 :     RESULT_GUARD_POSIX(s2n_hash_new(&hash));
      89                 :            : 
      90                 :        545 :     s2n_hash_algorithm hash_alg = S2N_HASH_NONE;
      91         [ +  + ]:       1635 :     for (size_t i = 0; i < s2n_array_len(supported_hmacs); i++) {
      92                 :       1090 :         s2n_hmac_algorithm hmac_alg = supported_hmacs[i];
      93                 :       1090 :         struct s2n_blob digest = EMPTY_CONTEXT(hmac_alg);
      94                 :            : 
      95         [ -  + ]:       1090 :         RESULT_GUARD_POSIX(s2n_hmac_hash_alg(hmac_alg, &hash_alg));
      96         [ -  + ]:       1090 :         RESULT_GUARD_POSIX(s2n_hash_init(&hash, hash_alg));
      97         [ -  + ]:       1090 :         RESULT_GUARD_POSIX(s2n_hash_digest(&hash, digest.data, digest.size));
      98                 :       1090 :     }
      99                 :            : 
     100                 :        545 :     return S2N_RESULT_OK;
     101                 :        545 : }
     102                 :            : 
     103                 :            : static S2N_RESULT s2n_calculate_transcript_digest(struct s2n_connection *conn)
     104                 :      20404 : {
     105 [ #  # ][ -  + ]:      20404 :     RESULT_ENSURE_REF(conn);
     106 [ #  # ][ -  + ]:      20404 :     RESULT_ENSURE_REF(conn->handshake.hashes);
     107                 :            : 
     108                 :      20404 :     s2n_hash_algorithm hash_algorithm = S2N_HASH_NONE;
     109         [ -  + ]:      20404 :     RESULT_GUARD_POSIX(s2n_hmac_hash_alg(CONN_HMAC_ALG(conn), &hash_algorithm));
     110                 :            : 
     111                 :      20404 :     uint8_t digest_size = 0;
     112         [ -  + ]:      20404 :     RESULT_GUARD_POSIX(s2n_hash_digest_size(hash_algorithm, &digest_size));
     113                 :            : 
     114                 :      20404 :     struct s2n_blob digest = { 0 };
     115         [ -  + ]:      20404 :     RESULT_GUARD_POSIX(s2n_blob_init(&digest, CONN_HASHES(conn)->transcript_hash_digest, digest_size));
     116                 :            : 
     117                 :      20404 :     struct s2n_hash_state *hash_state = &conn->handshake.hashes->hash_workspace;
     118         [ -  + ]:      20404 :     RESULT_GUARD(s2n_handshake_copy_hash_state(conn, hash_algorithm, hash_state));
     119         [ -  + ]:      20404 :     RESULT_GUARD_POSIX(s2n_hash_digest(hash_state, digest.data, digest.size));
     120                 :            : 
     121                 :      20404 :     return S2N_RESULT_OK;
     122                 :      20404 : }
     123                 :            : 
     124                 :            : static S2N_RESULT s2n_extract_secret(s2n_hmac_algorithm hmac_alg,
     125                 :            :         const struct s2n_blob *previous_secret_material, const struct s2n_blob *new_secret_material,
     126                 :            :         struct s2n_blob *output)
     127                 :      25011 : {
     128                 :            :     /*
     129                 :            :      * TODO: We should be able to reuse the prf_work_space rather
     130                 :            :      * than allocating a new HMAC every time.
     131                 :            :      * https://github.com/aws/s2n-tls/issues/3206
     132                 :            :      */
     133                 :      25011 :     DEFER_CLEANUP(struct s2n_hmac_state hmac_state = { 0 }, s2n_hmac_free);
     134         [ -  + ]:      25011 :     RESULT_GUARD_POSIX(s2n_hmac_new(&hmac_state));
     135                 :            : 
     136         [ -  + ]:      25011 :     RESULT_GUARD_POSIX(s2n_hkdf_extract(&hmac_state, hmac_alg,
     137                 :      25011 :             previous_secret_material, new_secret_material, output));
     138                 :      25011 :     return S2N_RESULT_OK;
     139                 :      25011 : }
     140                 :            : 
     141                 :            : /**
     142                 :            :  *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
     143                 :            :  *# Derive-Secret(Secret, Label, Messages) =
     144                 :            :  *#      HKDF-Expand-Label(Secret, Label,
     145                 :            :  *#                        Transcript-Hash(Messages), Hash.length)
     146                 :            :  */
     147                 :            : static S2N_RESULT s2n_derive_secret(s2n_hmac_algorithm hmac_alg,
     148                 :            :         const struct s2n_blob *previous_secret_material, const struct s2n_blob *label, const struct s2n_blob *context,
     149                 :            :         struct s2n_blob *output)
     150                 :      58936 : {
     151                 :            :     /*
     152                 :            :      * TODO: We should be able to reuse the prf_work_space rather
     153                 :            :      * than allocating a new HMAC every time.
     154                 :            :      * https://github.com/aws/s2n-tls/issues/3206
     155                 :            :      */
     156                 :      58936 :     DEFER_CLEANUP(struct s2n_hmac_state hmac_state = { 0 }, s2n_hmac_free);
     157         [ -  + ]:      58936 :     RESULT_GUARD_POSIX(s2n_hmac_new(&hmac_state));
     158                 :            : 
     159                 :      58936 :     output->size = s2n_get_hash_len(hmac_alg);
     160         [ -  + ]:      58936 :     RESULT_GUARD_POSIX(s2n_hkdf_expand_label(&hmac_state, hmac_alg,
     161                 :      58936 :             previous_secret_material, label, context, output));
     162                 :      58936 :     return S2N_RESULT_OK;
     163                 :      58936 : }
     164                 :            : 
     165                 :            : static S2N_RESULT s2n_derive_secret_with_context(struct s2n_connection *conn,
     166                 :            :         s2n_extract_secret_type_t input_secret_type, const struct s2n_blob *label, message_type_t transcript_end_msg,
     167                 :            :         struct s2n_blob *output)
     168                 :      41516 : {
     169 [ #  # ][ -  + ]:      41516 :     RESULT_ENSURE_REF(conn);
     170 [ -  + ][ #  # ]:      41516 :     RESULT_ENSURE_REF(label);
     171 [ -  + ][ #  # ]:      41516 :     RESULT_ENSURE_REF(output);
     172                 :            : 
     173 [ -  + ][ #  # ]:      41516 :     RESULT_ENSURE(conn->secrets.extract_secret_type == input_secret_type, S2N_ERR_SECRET_SCHEDULE_STATE);
     174 [ +  + ][ +  - ]:      41516 :     RESULT_ENSURE(s2n_conn_get_current_message_type(conn) == transcript_end_msg, S2N_ERR_SECRET_SCHEDULE_STATE);
     175         [ -  + ]:      41515 :     RESULT_GUARD(s2n_derive_secret(CONN_HMAC_ALG(conn), &CONN_SECRET(conn, extract_secret),
     176                 :      41515 :             label, &CONN_HASH(conn, transcript_hash_digest), output));
     177                 :      41515 :     return S2N_RESULT_OK;
     178                 :      41515 : }
     179                 :            : 
     180                 :            : static S2N_RESULT s2n_derive_secret_without_context(struct s2n_connection *conn,
     181                 :            :         s2n_extract_secret_type_t input_secret_type, struct s2n_blob *output)
     182                 :      15237 : {
     183 [ -  + ][ #  # ]:      15237 :     RESULT_ENSURE_REF(conn);
     184 [ -  + ][ #  # ]:      15237 :     RESULT_ENSURE_REF(output);
     185                 :            : 
     186 [ -  + ][ #  # ]:      15237 :     RESULT_ENSURE(conn->secrets.extract_secret_type == input_secret_type, S2N_ERR_SECRET_SCHEDULE_STATE);
     187         [ -  + ]:      15237 :     RESULT_GUARD(s2n_derive_secret(CONN_HMAC_ALG(conn), &CONN_SECRET(conn, extract_secret),
     188                 :      15237 :             &s2n_tls13_label_derived_secret, &EMPTY_CONTEXT(CONN_HMAC_ALG(conn)), output));
     189                 :      15237 :     return S2N_RESULT_OK;
     190                 :      15237 : }
     191                 :            : 
     192                 :            : /**
     193                 :            :  *= https://www.rfc-editor.org/rfc/rfc8446#section-4.4.4
     194                 :            :  *# The key used to compute the Finished message is computed from the
     195                 :            :  *# Base Key defined in Section 4.4 using HKDF (see Section 7.1).
     196                 :            :  *# Specifically:
     197                 :            :  *#
     198                 :            :  *# finished_key =
     199                 :            :  *#     HKDF-Expand-Label(BaseKey, "finished", "", Hash.length)
     200                 :            :  **/
     201                 :            : static S2N_RESULT s2n_tls13_compute_finished_key(struct s2n_connection *conn,
     202                 :            :         const struct s2n_blob *base_key, struct s2n_blob *output)
     203                 :      17093 : {
     204 [ -  + ][ #  # ]:      17093 :     RESULT_ENSURE_REF(conn);
     205 [ -  + ][ #  # ]:      17093 :     RESULT_ENSURE_REF(base_key);
     206 [ #  # ][ -  + ]:      17093 :     RESULT_ENSURE_REF(output);
     207                 :            : 
     208         [ -  + ]:      17093 :     RESULT_GUARD(s2n_handshake_set_finished_len(conn, output->size));
     209                 :            : 
     210                 :            :     /*
     211                 :            :      * TODO: We should be able to reuse the prf_work_space rather
     212                 :            :      * than allocating a new HMAC every time.
     213                 :            :      */
     214                 :      17093 :     DEFER_CLEANUP(struct s2n_hmac_state hmac_state = { 0 }, s2n_hmac_free);
     215         [ -  + ]:      17093 :     RESULT_GUARD_POSIX(s2n_hmac_new(&hmac_state));
     216                 :            : 
     217         [ -  + ]:      17093 :     RESULT_GUARD_POSIX(s2n_hkdf_expand_label(&hmac_state, CONN_HMAC_ALG(conn),
     218                 :      17093 :             base_key, &s2n_tls13_label_finished, &(struct s2n_blob){ 0 }, output));
     219                 :      17093 :     return S2N_RESULT_OK;
     220                 :      17093 : }
     221                 :            : 
     222                 :            : static S2N_RESULT s2n_call_secret_callbacks(struct s2n_connection *conn,
     223                 :            :         const struct s2n_blob *secret, s2n_secret_type_t secret_type)
     224                 :      36226 : {
     225 [ #  # ][ -  + ]:      36226 :     RESULT_ENSURE_REF(conn);
     226 [ -  + ][ #  # ]:      36226 :     RESULT_ENSURE_REF(secret);
     227                 :            : 
     228 [ +  + ][ +  - ]:      36226 :     if (conn->secret_cb && (s2n_connection_is_quic_enabled(conn) || s2n_in_unit_test())) {
                 [ #  # ]
     229         [ -  + ]:         10 :         RESULT_GUARD_POSIX(conn->secret_cb(conn->secret_cb_context, conn, secret_type,
     230                 :         10 :                 secret->data, secret->size));
     231                 :         10 :     }
     232                 :      36226 :     s2n_result_ignore(s2n_key_log_tls13_secret(conn, secret, secret_type));
     233                 :      36226 :     return S2N_RESULT_OK;
     234                 :      36226 : }
     235                 :            : 
     236                 :            : static S2N_RESULT s2n_trigger_secret_callbacks(struct s2n_connection *conn,
     237                 :            :         const struct s2n_blob *secret, s2n_extract_secret_type_t secret_type, s2n_mode mode)
     238                 :      30138 : {
     239 [ -  + ][ #  # ]:      30138 :     RESULT_ENSURE_REF(conn);
     240 [ #  # ][ -  + ]:      30138 :     RESULT_ENSURE_REF(secret);
     241                 :            : 
     242                 :      30138 :     static const s2n_secret_type_t conversions[][2] = {
     243                 :      30138 :         [S2N_EARLY_SECRET] = { S2N_CLIENT_EARLY_TRAFFIC_SECRET, S2N_CLIENT_EARLY_TRAFFIC_SECRET },
     244                 :      30138 :         [S2N_HANDSHAKE_SECRET] = { S2N_SERVER_HANDSHAKE_TRAFFIC_SECRET, S2N_CLIENT_HANDSHAKE_TRAFFIC_SECRET },
     245                 :      30138 :         [S2N_MASTER_SECRET] = { S2N_SERVER_APPLICATION_TRAFFIC_SECRET, S2N_CLIENT_APPLICATION_TRAFFIC_SECRET },
     246                 :      30138 :     };
     247                 :      30138 :     s2n_secret_type_t callback_secret_type = conversions[secret_type][mode];
     248                 :            : 
     249         [ -  + ]:      30138 :     RESULT_GUARD(s2n_call_secret_callbacks(conn, secret, callback_secret_type));
     250                 :      30138 :     return S2N_RESULT_OK;
     251                 :      30138 : }
     252                 :            : 
     253                 :            : /**
     254                 :            :  *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
     255                 :            :  *#           0
     256                 :            :  *#           |
     257                 :            :  *#           v
     258                 :            :  *# PSK ->  HKDF-Extract = Early Secret
     259                 :            :  *
     260                 :            :  *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
     261                 :            :  *# There are multiple potential Early Secret values, depending on which
     262                 :            :  *# PSK the server ultimately selects.  The client will need to compute
     263                 :            :  *# one for each potential PSK
     264                 :            :  */
     265                 :            : S2N_RESULT s2n_extract_early_secret(struct s2n_psk *psk)
     266                 :       2185 : {
     267 [ -  + ][ #  # ]:       2185 :     RESULT_ENSURE_REF(psk);
     268         [ -  + ]:       2185 :     RESULT_GUARD_POSIX(s2n_realloc(&psk->early_secret, s2n_get_hash_len(psk->hmac_alg)));
     269         [ -  + ]:       2185 :     RESULT_GUARD(s2n_extract_secret(psk->hmac_alg,
     270                 :       2185 :             &ZERO_VALUE(psk->hmac_alg),
     271                 :       2185 :             &psk->secret,
     272                 :       2185 :             &psk->early_secret));
     273                 :       2185 :     return S2N_RESULT_OK;
     274                 :       2185 : }
     275                 :            : 
     276                 :            : /*
     277                 :            :  * When we require an early secret to derive other secrets,
     278                 :            :  * either retrieve the early secret stored on the chosen / early data PSK
     279                 :            :  * or calculate one using a "zero" PSK.
     280                 :            :  */
     281                 :            : static S2N_RESULT s2n_extract_early_secret_for_schedule(struct s2n_connection *conn)
     282                 :       9232 : {
     283 [ #  # ][ -  + ]:       9232 :     RESULT_ENSURE_REF(conn);
     284                 :            : 
     285                 :       9232 :     struct s2n_psk *psk = conn->psk_params.chosen_psk;
     286                 :       9232 :     s2n_hmac_algorithm hmac_alg = CONN_HMAC_ALG(conn);
     287                 :            : 
     288                 :            :     /*
     289                 :            :      * If the client is sending early data, then the PSK is always assumed
     290                 :            :      * to be the first PSK offered.
     291                 :            :      */
     292 [ +  + ][ +  + ]:       9232 :     if (conn->mode == S2N_CLIENT && conn->early_data_state == S2N_EARLY_DATA_REQUESTED) {
     293         [ -  + ]:        530 :         RESULT_GUARD(s2n_array_get(&conn->psk_params.psk_list, 0, (void **) &psk));
     294 [ #  # ][ -  + ]:        530 :         RESULT_ENSURE_REF(psk);
     295                 :        530 :     }
     296                 :            : 
     297                 :            :     /**
     298                 :            :      *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
     299                 :            :      *# if no PSK is selected, it will then need
     300                 :            :      *# to compute the Early Secret corresponding to the zero PSK.
     301                 :            :      */
     302         [ +  + ]:       9232 :     if (psk == NULL) {
     303         [ -  + ]:       7589 :         RESULT_GUARD(s2n_extract_secret(hmac_alg,
     304                 :       7589 :                 &ZERO_VALUE(hmac_alg),
     305                 :       7589 :                 &ZERO_VALUE(hmac_alg),
     306                 :       7589 :                 &CONN_SECRET(conn, extract_secret)));
     307                 :       7589 :         return S2N_RESULT_OK;
     308                 :       7589 :     }
     309                 :            : 
     310                 :            :     /*
     311                 :            :      * The early secret is required to generate or verify a PSK's binder,
     312                 :            :      * so must have already been calculated if a valid PSK exists.
     313                 :            :      * Use the early secret stored on the PSK.
     314                 :            :      */
     315 [ #  # ][ -  + ]:       1643 :     RESULT_ENSURE_EQ(hmac_alg, psk->hmac_alg);
     316 [ -  + ][ #  # ]:       1643 :     RESULT_CHECKED_MEMCPY(CONN_SECRETS(conn).extract_secret, psk->early_secret.data, psk->early_secret.size);
                 [ +  - ]
     317                 :       1643 :     return S2N_RESULT_OK;
     318                 :       1643 : }
     319                 :            : 
     320                 :            : /**
     321                 :            :  *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
     322                 :            :  *#           |
     323                 :            :  *#           +-----> Derive-Secret(., "ext binder" | "res binder", "")
     324                 :            :  *#           |                     = binder_key
     325                 :            :  */
     326                 :            : S2N_RESULT s2n_derive_binder_key(struct s2n_psk *psk, struct s2n_blob *output)
     327                 :       2183 : {
     328 [ #  # ][ -  + ]:       2183 :     RESULT_ENSURE_REF(psk);
     329 [ #  # ][ -  + ]:       2183 :     RESULT_ENSURE_REF(output);
     330                 :            : 
     331                 :       2183 :     const struct s2n_blob *label = &s2n_tls13_label_resumption_psk_binder_key;
     332         [ +  + ]:       2183 :     if (psk->type == S2N_PSK_TYPE_EXTERNAL) {
     333                 :       1941 :         label = &s2n_tls13_label_external_psk_binder_key;
     334                 :       1941 :     }
     335         [ -  + ]:       2183 :     RESULT_GUARD(s2n_extract_early_secret(psk));
     336         [ -  + ]:       2183 :     RESULT_GUARD(s2n_derive_secret(psk->hmac_alg,
     337                 :       2183 :             &psk->early_secret,
     338                 :       2183 :             label,
     339                 :       2183 :             &EMPTY_CONTEXT(psk->hmac_alg),
     340                 :       2183 :             output));
     341                 :       2183 :     return S2N_RESULT_OK;
     342                 :       2183 : }
     343                 :            : 
     344                 :            : /**
     345                 :            :  *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
     346                 :            :  *#           |
     347                 :            :  *#           +-----> Derive-Secret(., "c e traffic", ClientHello)
     348                 :            :  *#           |                     = client_early_traffic_secret
     349                 :            :  */
     350                 :            : static S2N_RESULT s2n_derive_client_early_traffic_secret(struct s2n_connection *conn, struct s2n_blob *output)
     351                 :        676 : {
     352         [ -  + ]:        676 :     RESULT_GUARD(s2n_derive_secret_with_context(conn,
     353                 :        676 :             S2N_EARLY_SECRET,
     354                 :        676 :             &s2n_tls13_label_client_early_traffic_secret,
     355                 :        676 :             CLIENT_HELLO,
     356                 :        676 :             output));
     357                 :        676 :     return S2N_RESULT_OK;
     358                 :        676 : }
     359                 :            : 
     360                 :            : /**
     361                 :            :  *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
     362                 :            :  *#           |
     363                 :            :  *#           v
     364                 :            :  *#     Derive-Secret(., "derived", "")
     365                 :            :  *#           |
     366                 :            :  *#           v
     367                 :            :  *#     (EC)DHE -> HKDF-Extract = Handshake Secret
     368                 :            :  */
     369                 :            : static S2N_RESULT s2n_extract_handshake_secret(struct s2n_connection *conn)
     370                 :       8860 : {
     371 [ -  + ][ #  # ]:       8860 :     RESULT_ENSURE_REF(conn);
     372                 :            : 
     373                 :       8860 :     struct s2n_blob derived_secret = { 0 };
     374                 :       8860 :     uint8_t derived_secret_bytes[S2N_TLS13_SECRET_MAX_LEN] = { 0 };
     375         [ -  + ]:       8860 :     RESULT_GUARD_POSIX(s2n_blob_init(&derived_secret, derived_secret_bytes, S2N_TLS13_SECRET_MAX_LEN));
     376         [ -  + ]:       8860 :     RESULT_GUARD(s2n_derive_secret_without_context(conn, S2N_EARLY_SECRET, &derived_secret));
     377                 :            : 
     378                 :       8860 :     DEFER_CLEANUP(struct s2n_blob shared_secret = { 0 }, s2n_free_or_wipe);
     379         [ -  + ]:       8860 :     RESULT_GUARD_POSIX(s2n_tls13_compute_shared_secret(conn, &shared_secret));
     380                 :            : 
     381         [ -  + ]:       8860 :     RESULT_GUARD(s2n_extract_secret(CONN_HMAC_ALG(conn),
     382                 :       8860 :             &derived_secret,
     383                 :       8860 :             &shared_secret,
     384                 :       8860 :             &CONN_SECRET(conn, extract_secret)));
     385                 :            : 
     386                 :       8860 :     return S2N_RESULT_OK;
     387                 :       8860 : }
     388                 :            : 
     389                 :            : /**
     390                 :            :  *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
     391                 :            :  *#           |
     392                 :            :  *#           +-----> Derive-Secret(., "c hs traffic",
     393                 :            :  *#           |                     ClientHello...ServerHello)
     394                 :            :  *#           |                     = client_handshake_traffic_secret
     395                 :            :  */
     396                 :            : static S2N_RESULT s2n_derive_client_handshake_traffic_secret(struct s2n_connection *conn, struct s2n_blob *output)
     397                 :       8546 : {
     398 [ -  + ][ #  # ]:       8546 :     RESULT_ENSURE_REF(conn);
     399 [ -  + ][ #  # ]:       8546 :     RESULT_ENSURE_REF(output);
     400                 :            : 
     401         [ -  + ]:       8546 :     RESULT_GUARD(s2n_derive_secret_with_context(conn,
     402                 :       8546 :             S2N_HANDSHAKE_SECRET,
     403                 :       8546 :             &s2n_tls13_label_client_handshake_traffic_secret,
     404                 :       8546 :             SERVER_HELLO,
     405                 :       8546 :             output));
     406                 :            : 
     407                 :            :     /*
     408                 :            :      * The client finished key needs to be calculated using the
     409                 :            :      * same connection state as the client handshake secret.
     410                 :            :      *
     411                 :            :      *= https://www.rfc-editor.org/rfc/rfc8446#section-4.4.4
     412                 :            :      *# The key used to compute the Finished message is computed from the
     413                 :            :      *# Base Key defined in Section 4.4 using HKDF (see Section 7.1).
     414                 :            :      */
     415         [ -  + ]:       8546 :     RESULT_GUARD(s2n_tls13_compute_finished_key(conn,
     416                 :       8546 :             output, &CONN_FINISHED(conn, client)));
     417                 :            : 
     418                 :       8546 :     return S2N_RESULT_OK;
     419                 :       8546 : }
     420                 :            : 
     421                 :            : /**
     422                 :            :  *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
     423                 :            :  *#           |
     424                 :            :  *#           +-----> Derive-Secret(., "s hs traffic",
     425                 :            :  *#           |                     ClientHello...ServerHello)
     426                 :            :  *#           |                     = server_handshake_traffic_secret
     427                 :            :  */
     428                 :            : static S2N_RESULT s2n_derive_server_handshake_traffic_secret(struct s2n_connection *conn, struct s2n_blob *output)
     429                 :       8547 : {
     430 [ -  + ][ #  # ]:       8547 :     RESULT_ENSURE_REF(conn);
     431 [ -  + ][ #  # ]:       8547 :     RESULT_ENSURE_REF(output);
     432                 :            : 
     433         [ -  + ]:       8547 :     RESULT_GUARD(s2n_derive_secret_with_context(conn,
     434                 :       8547 :             S2N_HANDSHAKE_SECRET,
     435                 :       8547 :             &s2n_tls13_label_server_handshake_traffic_secret,
     436                 :       8547 :             SERVER_HELLO,
     437                 :       8547 :             output));
     438                 :            : 
     439                 :            :     /*
     440                 :            :      * The server finished key needs to be calculated using the
     441                 :            :      * same connection state as the server handshake secret.
     442                 :            :      *
     443                 :            :      *= https://www.rfc-editor.org/rfc/rfc8446#section-4.4.4
     444                 :            :      *# The key used to compute the Finished message is computed from the
     445                 :            :      *# Base Key defined in Section 4.4 using HKDF (see Section 7.1).
     446                 :            :      */
     447         [ -  + ]:       8547 :     RESULT_GUARD(s2n_tls13_compute_finished_key(conn,
     448                 :       8547 :             output, &CONN_FINISHED(conn, server)));
     449                 :            : 
     450                 :       8547 :     return S2N_RESULT_OK;
     451                 :       8547 : }
     452                 :            : 
     453                 :            : /**
     454                 :            :  *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
     455                 :            :  *#           v
     456                 :            :  *#     Derive-Secret(., "derived", "")
     457                 :            :  *#           |
     458                 :            :  *#           v
     459                 :            :  *# 0 -> HKDF-Extract = Master Secret
     460                 :            :  */
     461                 :            : static S2N_RESULT s2n_extract_master_secret(struct s2n_connection *conn)
     462                 :       6377 : {
     463 [ -  + ][ #  # ]:       6377 :     RESULT_ENSURE_REF(conn);
     464                 :            : 
     465                 :       6377 :     struct s2n_blob derived_secret = { 0 };
     466                 :       6377 :     uint8_t derived_secret_bytes[S2N_TLS13_SECRET_MAX_LEN] = { 0 };
     467         [ -  + ]:       6377 :     RESULT_GUARD_POSIX(s2n_blob_init(&derived_secret, derived_secret_bytes, S2N_TLS13_SECRET_MAX_LEN));
     468         [ -  + ]:       6377 :     RESULT_GUARD(s2n_derive_secret_without_context(conn, S2N_HANDSHAKE_SECRET, &derived_secret));
     469                 :            : 
     470         [ -  + ]:       6377 :     RESULT_GUARD(s2n_extract_secret(CONN_HMAC_ALG(conn),
     471                 :       6377 :             &derived_secret,
     472                 :       6377 :             &ZERO_VALUE(CONN_HMAC_ALG(conn)),
     473                 :       6377 :             &CONN_SECRET(conn, extract_secret)));
     474                 :       6377 :     return S2N_RESULT_OK;
     475                 :       6377 : }
     476                 :            : 
     477                 :            : /**
     478                 :            :  *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
     479                 :            :  *#           |
     480                 :            :  *#           +-----> Derive-Secret(., "c ap traffic",
     481                 :            :  *#           |                     ClientHello...server Finished)
     482                 :            :  *#           |                     = client_application_traffic_secret_0
     483                 :            :  */
     484                 :            : static S2N_RESULT s2n_derive_client_application_traffic_secret(struct s2n_connection *conn, struct s2n_blob *output)
     485                 :       6184 : {
     486         [ -  + ]:       6184 :     RESULT_GUARD(s2n_derive_secret_with_context(conn,
     487                 :       6184 :             S2N_MASTER_SECRET,
     488                 :       6184 :             &s2n_tls13_label_client_application_traffic_secret,
     489                 :       6184 :             SERVER_FINISHED,
     490                 :       6184 :             output));
     491                 :       6184 :     return S2N_RESULT_OK;
     492                 :       6184 : }
     493                 :            : 
     494                 :            : /**
     495                 :            :  *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
     496                 :            :  *#           |
     497                 :            :  *#           +-----> Derive-Secret(., "s ap traffic",
     498                 :            :  *#           |                     ClientHello...server Finished)
     499                 :            :  *#           |                     = server_application_traffic_secret_0
     500                 :            :  */
     501                 :            : static S2N_RESULT s2n_derive_server_application_traffic_secret(struct s2n_connection *conn, struct s2n_blob *output)
     502                 :       6186 : {
     503         [ +  + ]:       6186 :     RESULT_GUARD(s2n_derive_secret_with_context(conn,
     504                 :       6185 :             S2N_MASTER_SECRET,
     505                 :       6185 :             &s2n_tls13_label_server_application_traffic_secret,
     506                 :       6185 :             SERVER_FINISHED,
     507                 :       6185 :             output));
     508                 :       6185 :     return S2N_RESULT_OK;
     509                 :       6186 : }
     510                 :            : 
     511                 :            : /**
     512                 :            :  *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
     513                 :            :  *#           |
     514                 :            :  *#           +-----> Derive-Secret(., "res master",
     515                 :            :  *#                                 ClientHello...client Finished)
     516                 :            :  *#                                 = resumption_master_secret
     517                 :            :  */
     518                 :            : S2N_RESULT s2n_derive_resumption_master_secret(struct s2n_connection *conn)
     519                 :       5595 : {
     520 [ -  + ][ #  # ]:       5595 :     RESULT_ENSURE_REF(conn);
     521                 :            :     /* Secret derivation requires these fields to be non-null.  */
     522 [ #  # ][ -  + ]:       5595 :     RESULT_ENSURE_REF(conn->secure);
     523 [ -  + ][ #  # ]:       5595 :     RESULT_ENSURE_REF(conn->secure->cipher_suite);
     524                 :            : 
     525         [ -  + ]:       5595 :     RESULT_GUARD(s2n_derive_secret_with_context(conn,
     526                 :       5595 :             S2N_MASTER_SECRET,
     527                 :       5595 :             &s2n_tls13_label_resumption_master_secret,
     528                 :       5595 :             CLIENT_FINISHED,
     529                 :       5595 :             &CONN_SECRET(conn, resumption_master_secret)));
     530                 :       5595 :     return S2N_RESULT_OK;
     531                 :       5595 : }
     532                 :            : 
     533                 :            : /**
     534                 :            :  *= https://www.rfc-editor.org/rfc/rfc8446#section-7.1
     535                 :            :  *#           |
     536                 :            :  *#           +-----> Derive-Secret(., "exp master",
     537                 :            :  *#           |                     ClientHello...server Finished)
     538                 :            :  *#           |                     = exporter_master_secret
     539                 :            :  */
     540                 :            : S2N_RESULT s2n_derive_exporter_master_secret(struct s2n_connection *conn, struct s2n_blob *secret)
     541                 :       6394 : {
     542 [ -  + ][ #  # ]:       6394 :     RESULT_ENSURE_REF(conn);
     543                 :            :     /* Secret derivation requires these fields to be non-null.  */
     544 [ -  + ][ #  # ]:       6394 :     RESULT_ENSURE_REF(conn->secure);
     545 [ #  # ][ -  + ]:       6394 :     RESULT_ENSURE_REF(conn->secure->cipher_suite);
     546                 :            : 
     547         [ -  + ]:       6394 :     RESULT_GUARD(s2n_derive_secret_with_context(conn,
     548                 :       6394 :             S2N_MASTER_SECRET,
     549                 :       6394 :             &s2n_tls13_label_exporter_master_secret,
     550                 :       6394 :             SERVER_FINISHED,
     551                 :       6394 :             secret));
     552                 :            : 
     553         [ -  + ]:       6394 :     RESULT_GUARD(s2n_call_secret_callbacks(conn, secret, S2N_EXPORTER_SECRET));
     554                 :            : 
     555                 :       6394 :     return S2N_RESULT_OK;
     556                 :       6394 : }
     557                 :            : 
     558                 :            : static s2n_result (*extract_methods[])(struct s2n_connection *conn) = {
     559                 :            :     [S2N_EARLY_SECRET] = &s2n_extract_early_secret_for_schedule,
     560                 :            :     [S2N_HANDSHAKE_SECRET] = &s2n_extract_handshake_secret,
     561                 :            :     [S2N_MASTER_SECRET] = &s2n_extract_master_secret,
     562                 :            : };
     563                 :            : 
     564                 :            : S2N_RESULT s2n_tls13_extract_secret(struct s2n_connection *conn, s2n_extract_secret_type_t secret_type)
     565                 :      31977 : {
     566 [ +  + ][ +  - ]:      31977 :     RESULT_ENSURE_REF(conn);
     567 [ +  + ][ +  - ]:      31976 :     RESULT_ENSURE_REF(conn->secure);
     568 [ -  + ][ #  # ]:      31975 :     RESULT_ENSURE_REF(conn->secure->cipher_suite);
     569 [ -  + ][ #  # ]:      31975 :     RESULT_ENSURE_REF(conn->handshake.hashes);
     570 [ #  # ][ -  + ]:      31975 :     RESULT_ENSURE_NE(secret_type, S2N_NONE_SECRET);
     571                 :            : 
     572 [ #  # ][ -  + ]:      31975 :     RESULT_ENSURE_GTE(secret_type, 0);
     573 [ +  - ][ +  + ]:      31975 :     RESULT_ENSURE_LT(secret_type, s2n_array_len(extract_methods));
     574                 :            : 
     575                 :      31970 :     s2n_extract_secret_type_t next_secret_type = conn->secrets.extract_secret_type + 1;
     576         [ +  + ]:      57429 :     for (s2n_extract_secret_type_t i = next_secret_type; i <= secret_type; i++) {
     577 [ -  + ][ #  # ]:      25459 :         RESULT_ENSURE_REF(extract_methods[i]);
     578         [ -  + ]:      25459 :         RESULT_GUARD(extract_methods[i](conn));
     579                 :      25459 :         conn->secrets.extract_secret_type = i;
     580                 :      25459 :     }
     581                 :            : 
     582                 :      31970 :     return S2N_RESULT_OK;
     583                 :      31970 : }
     584                 :            : 
     585                 :            : static s2n_result (*derive_methods[][2])(struct s2n_connection *conn, struct s2n_blob *secret) = {
     586                 :            :     [S2N_EARLY_SECRET] = { &s2n_derive_client_early_traffic_secret, &s2n_derive_client_early_traffic_secret },
     587                 :            :     [S2N_HANDSHAKE_SECRET] = { &s2n_derive_server_handshake_traffic_secret, &s2n_derive_client_handshake_traffic_secret },
     588                 :            :     [S2N_MASTER_SECRET] = { &s2n_derive_server_application_traffic_secret, &s2n_derive_client_application_traffic_secret },
     589                 :            : };
     590                 :            : 
     591                 :            : S2N_RESULT s2n_tls13_derive_secret(struct s2n_connection *conn, s2n_extract_secret_type_t secret_type,
     592                 :            :         s2n_mode mode, struct s2n_blob *secret)
     593                 :      31530 : {
     594 [ +  + ][ +  - ]:      31530 :     RESULT_ENSURE_REF(conn);
     595 [ +  - ][ +  + ]:      31529 :     RESULT_ENSURE_REF(secret);
     596 [ +  + ][ +  - ]:      31528 :     RESULT_ENSURE_REF(conn->secure);
     597 [ -  + ][ #  # ]:      31527 :     RESULT_ENSURE_REF(conn->secure->cipher_suite);
     598 [ #  # ][ -  + ]:      31527 :     RESULT_ENSURE_REF(conn->handshake.hashes);
     599 [ -  + ][ #  # ]:      31527 :     RESULT_ENSURE_NE(secret_type, S2N_NONE_SECRET);
     600                 :            : 
     601         [ +  + ]:      31527 :     RESULT_GUARD(s2n_tls13_extract_secret(conn, secret_type));
     602                 :            : 
     603 [ -  + ][ #  # ]:      31525 :     RESULT_ENSURE_GTE(secret_type, 0);
     604 [ -  + ][ #  # ]:      31525 :     RESULT_ENSURE_LT(secret_type, s2n_array_len(derive_methods));
     605 [ -  + ][ #  # ]:      31525 :     RESULT_ENSURE_REF(derive_methods[secret_type][mode]);
     606         [ +  + ]:      31525 :     RESULT_GUARD(derive_methods[secret_type][mode](conn, secret));
     607                 :            : 
     608         [ -  + ]:      31524 :     RESULT_GUARD(s2n_trigger_secret_callbacks(conn, secret, secret_type, mode));
     609                 :      31524 :     return S2N_RESULT_OK;
     610                 :      31524 : }
     611                 :            : 
     612                 :            : S2N_RESULT s2n_tls13_secrets_clean(struct s2n_connection *conn)
     613                 :       7942 : {
     614 [ +  + ][ +  - ]:       7942 :     RESULT_ENSURE_REF(conn);
     615                 :            :     /* Secret clean requires these fields to be non-null.  */
     616 [ #  # ][ -  + ]:       7941 :     RESULT_ENSURE_REF(conn->secure);
     617 [ #  # ][ -  + ]:       7941 :     RESULT_ENSURE_REF(conn->secure->cipher_suite);
     618                 :            : 
     619         [ +  + ]:       7941 :     if (conn->actual_protocol_version < S2N_TLS13) {
     620                 :       2660 :         return S2N_RESULT_OK;
     621                 :       2660 :     }
     622                 :            : 
     623                 :            :     /*
     624                 :            :      * Wipe base secrets.
     625                 :            :      * Not strictly necessary, but probably safer than leaving them.
     626                 :            :      * A compromised secret additionally compromises all secrets derived from it,
     627                 :            :      * so these are the most sensitive secrets.
     628                 :            :      */
     629         [ -  + ]:       5281 :     RESULT_GUARD_POSIX(s2n_blob_zero(&CONN_SECRET(conn, extract_secret)));
     630                 :       5281 :     conn->secrets.extract_secret_type = S2N_NONE_SECRET;
     631                 :            : 
     632                 :            :     /* Wipe other secrets no longer needed */
     633         [ -  + ]:       5281 :     RESULT_GUARD_POSIX(s2n_blob_zero(&CONN_SECRET(conn, client_early_secret)));
     634         [ -  + ]:       5281 :     RESULT_GUARD_POSIX(s2n_blob_zero(&CONN_SECRET(conn, client_handshake_secret)));
     635         [ -  + ]:       5281 :     RESULT_GUARD_POSIX(s2n_blob_zero(&CONN_SECRET(conn, server_handshake_secret)));
     636                 :            : 
     637                 :       5281 :     return S2N_RESULT_OK;
     638                 :       5281 : }
     639                 :            : 
     640                 :            : S2N_RESULT s2n_tls13_secrets_update(struct s2n_connection *conn)
     641                 :      94243 : {
     642 [ +  + ][ +  - ]:      94243 :     RESULT_ENSURE_REF(conn);
     643         [ +  + ]:      94242 :     if (s2n_connection_get_protocol_version(conn) < S2N_TLS13) {
     644                 :      34514 :         return S2N_RESULT_OK;
     645                 :      34514 :     }
     646                 :            : 
     647                 :            :     /* Secret update requires these fields to be non-null.  */
     648 [ -  + ][ #  # ]:      59728 :     RESULT_ENSURE_REF(conn->secure);
     649 [ -  + ][ #  # ]:      59728 :     RESULT_ENSURE_REF(conn->secure->cipher_suite);
     650                 :            : 
     651                 :      59728 :     message_type_t message_type = s2n_conn_get_current_message_type(conn);
     652                 :      59728 :     switch (message_type) {
     653         [ +  + ]:      10579 :         case CLIENT_HELLO:
     654         [ +  + ]:      10579 :             if (conn->early_data_state == S2N_EARLY_DATA_REQUESTED
     655         [ +  + ]:      10579 :                     || conn->early_data_state == S2N_EARLY_DATA_ACCEPTED) {
     656         [ -  + ]:        739 :                 RESULT_GUARD(s2n_calculate_transcript_digest(conn));
     657         [ -  + ]:        739 :                 RESULT_GUARD(s2n_tls13_derive_secret(conn, S2N_EARLY_SECRET,
     658                 :        739 :                         S2N_CLIENT, &CONN_SECRET(conn, client_early_secret)));
     659                 :        739 :             }
     660                 :      10579 :             break;
     661         [ +  + ]:      10579 :         case SERVER_HELLO:
     662         [ -  + ]:       8760 :             RESULT_GUARD(s2n_calculate_transcript_digest(conn));
     663         [ -  + ]:       8760 :             RESULT_GUARD(s2n_tls13_derive_secret(conn, S2N_HANDSHAKE_SECRET,
     664                 :       8760 :                     S2N_CLIENT, &CONN_SECRET(conn, client_handshake_secret)));
     665         [ -  + ]:       8760 :             RESULT_GUARD(s2n_tls13_derive_secret(conn, S2N_HANDSHAKE_SECRET,
     666                 :       8760 :                     S2N_SERVER, &CONN_SECRET(conn, server_handshake_secret)));
     667                 :       8760 :             break;
     668         [ +  + ]:       8760 :         case SERVER_FINISHED:
     669         [ -  + ]:       6392 :             RESULT_GUARD(s2n_calculate_transcript_digest(conn));
     670         [ -  + ]:       6392 :             RESULT_GUARD(s2n_tls13_derive_secret(conn, S2N_MASTER_SECRET,
     671                 :       6392 :                     S2N_CLIENT, &CONN_SECRET(conn, client_app_secret)));
     672         [ -  + ]:       6392 :             RESULT_GUARD(s2n_tls13_derive_secret(conn, S2N_MASTER_SECRET,
     673                 :       6392 :                     S2N_SERVER, &CONN_SECRET(conn, server_app_secret)));
     674         [ -  + ]:       6392 :             RESULT_GUARD(s2n_derive_exporter_master_secret(conn,
     675                 :       6392 :                     &CONN_SECRET(conn, exporter_master_secret)));
     676                 :       6392 :             break;
     677         [ +  + ]:       6392 :         case CLIENT_FINISHED:
     678         [ -  + ]:       5593 :             RESULT_GUARD(s2n_calculate_transcript_digest(conn));
     679         [ -  + ]:       5593 :             RESULT_GUARD(s2n_derive_resumption_master_secret(conn));
     680                 :       5593 :             break;
     681         [ +  + ]:      28404 :         default:
     682                 :      28404 :             break;
     683                 :      59728 :     }
     684                 :      59728 :     return S2N_RESULT_OK;
     685                 :      59728 : }
     686                 :            : 
     687                 :            : S2N_RESULT s2n_tls13_secrets_get(struct s2n_connection *conn, s2n_extract_secret_type_t secret_type,
     688                 :            :         s2n_mode mode, struct s2n_blob *secret)
     689                 :      27819 : {
     690 [ +  + ][ +  - ]:      27819 :     RESULT_ENSURE_REF(conn);
     691 [ +  + ][ +  - ]:      27818 :     RESULT_ENSURE_REF(secret);
     692                 :            :     /* Getting secrets requires these fields to be non-null.  */
     693 [ +  + ][ +  - ]:      27817 :     RESULT_ENSURE_REF(conn->secure);
     694 [ +  + ][ +  - ]:      27816 :     RESULT_ENSURE_REF(conn->secure->cipher_suite);
     695                 :            : 
     696         [ +  + ]:      27815 :     bool is_available = (secret_type <= conn->secrets.extract_secret_type)
     697                 :            :             /* Unlike the other secrets, we don't wipe the master / app secrets */
     698 [ +  + ][ +  - ]:      27815 :             || (secret_type == S2N_MASTER_SECRET && s2n_handshake_is_complete(conn));
     699 [ +  + ][ +  - ]:      27815 :     RESULT_ENSURE(is_available, S2N_ERR_SAFETY);
     700                 :            : 
     701                 :      27811 :     uint8_t *secrets[][2] = {
     702                 :      27811 :         [S2N_EARLY_SECRET] = { NULL, CONN_SECRETS(conn).client_early_secret },
     703                 :      27811 :         [S2N_HANDSHAKE_SECRET] = { CONN_SECRETS(conn).server_handshake_secret, CONN_SECRETS(conn).client_handshake_secret },
     704                 :      27811 :         [S2N_MASTER_SECRET] = { CONN_SECRETS(conn).server_app_secret, CONN_SECRETS(conn).client_app_secret },
     705                 :      27811 :     };
     706 [ +  - ][ +  + ]:      27811 :     RESULT_ENSURE_GT(secret_type, S2N_NONE_SECRET);
     707 [ -  + ][ #  # ]:      27810 :     RESULT_ENSURE_LT(secret_type, s2n_array_len(secrets));
     708 [ #  # ][ -  + ]:      27810 :     RESULT_ENSURE_REF(secrets[secret_type][mode]);
     709                 :            : 
     710                 :      27810 :     secret->size = s2n_get_hash_len(CONN_HMAC_ALG(conn));
     711 [ -  + ][ #  # ]:      27810 :     RESULT_CHECKED_MEMCPY(secret->data, secrets[secret_type][mode], secret->size);
                 [ +  - ]
     712 [ -  + ][ #  # ]:      27810 :     RESULT_ENSURE_GT(secret->size, 0);
     713                 :      27810 :     return S2N_RESULT_OK;
     714                 :      27810 : }
     715                 :            : 
     716                 :            : /*
     717                 :            :  *= https://www.rfc-editor.org/rfc/rfc8446#section-7.5
     718                 :            :  *# The exporter value is computed as:
     719                 :            :  *#
     720                 :            :  *# TLS-Exporter(label, context_value, key_length) =
     721                 :            :  *#     HKDF-Expand-Label(Derive-Secret(Secret, label, ""),
     722                 :            :  *#                       "exporter", Hash(context_value), key_length)
     723                 :            :  */
     724                 :            : int s2n_connection_tls_exporter(struct s2n_connection *conn,
     725                 :            :         const uint8_t *label_in, uint32_t label_length,
     726                 :            :         const uint8_t *context, uint32_t context_length,
     727                 :            :         uint8_t *output_in, uint32_t output_length)
     728                 :          1 : {
     729 [ -  + ][ #  # ]:          1 :     POSIX_ENSURE_REF(conn);
     730 [ -  + ][ #  # ]:          1 :     POSIX_ENSURE_REF(output_in);
     731 [ -  + ][ #  # ]:          1 :     POSIX_ENSURE_REF(label_in);
     732 [ -  + ][ #  # ]:          1 :     POSIX_ENSURE_REF(context);
     733 [ #  # ][ -  + ]:          1 :     POSIX_ENSURE(s2n_connection_get_protocol_version(conn) == S2N_TLS13, S2N_ERR_INVALID_STATE);
     734                 :            : 
     735 [ -  + ][ #  # ]:          1 :     POSIX_ENSURE(is_handshake_complete(conn), S2N_ERR_HANDSHAKE_NOT_COMPLETE);
     736 [ -  + ][ #  # ]:          1 :     POSIX_ENSURE_REF(conn->secure);
     737 [ -  + ][ #  # ]:          1 :     POSIX_ENSURE_REF(conn->secure->cipher_suite);
     738                 :          1 :     s2n_hmac_algorithm hmac_alg = conn->secure->cipher_suite->prf_alg;
     739                 :            : 
     740                 :          1 :     uint8_t label_bytes[S2N_MAX_HKDF_EXPAND_LABEL_LENGTH] = { 0 };
     741                 :          1 :     struct s2n_blob label = { 0 };
     742 [ -  + ][ #  # ]:          1 :     POSIX_ENSURE_LTE(label_length, sizeof(label_bytes));
     743 [ -  + ][ #  # ]:          1 :     POSIX_CHECKED_MEMCPY(label_bytes, label_in, label_length);
                 [ +  - ]
     744         [ -  + ]:          1 :     POSIX_GUARD(s2n_blob_init(&label, label_bytes, label_length));
     745                 :            : 
     746                 :          1 :     uint8_t derived_secret_bytes[S2N_MAX_DIGEST_LEN] = { 0 };
     747                 :          1 :     struct s2n_blob derived_secret = { 0 };
     748 [ -  + ][ #  # ]:          1 :     POSIX_ENSURE_LTE(s2n_get_hash_len(CONN_HMAC_ALG(conn)), S2N_MAX_DIGEST_LEN);
     749         [ -  + ]:          1 :     POSIX_GUARD(s2n_blob_init(&derived_secret,
     750                 :          1 :             derived_secret_bytes, s2n_get_hash_len(CONN_HMAC_ALG(conn))));
     751         [ -  + ]:          1 :     POSIX_GUARD_RESULT(s2n_derive_secret(hmac_alg, &CONN_SECRET(conn, exporter_master_secret),
     752                 :          1 :             &label, &EMPTY_CONTEXT(hmac_alg), &derived_secret));
     753                 :            : 
     754                 :          1 :     DEFER_CLEANUP(struct s2n_hmac_state hmac_state = { 0 }, s2n_hmac_free);
     755         [ -  + ]:          1 :     POSIX_GUARD(s2n_hmac_new(&hmac_state));
     756                 :            : 
     757                 :          1 :     DEFER_CLEANUP(struct s2n_hash_state hash = { 0 }, s2n_hash_free);
     758         [ -  + ]:          1 :     POSIX_GUARD(s2n_hash_new(&hash));
     759                 :            : 
     760                 :          1 :     s2n_hash_algorithm hash_alg = { 0 };
     761         [ -  + ]:          1 :     POSIX_GUARD(s2n_hmac_hash_alg(hmac_alg, &hash_alg));
     762                 :          1 :     uint8_t digest_bytes[S2N_MAX_DIGEST_LEN] = { 0 };
     763                 :          1 :     struct s2n_blob digest = { 0 };
     764 [ -  + ][ #  # ]:          1 :     POSIX_ENSURE_LTE(s2n_get_hash_len(CONN_HMAC_ALG(conn)), S2N_MAX_DIGEST_LEN);
     765         [ -  + ]:          1 :     POSIX_GUARD(s2n_blob_init(&digest, digest_bytes, s2n_get_hash_len(CONN_HMAC_ALG(conn))));
     766                 :            : 
     767         [ -  + ]:          1 :     POSIX_GUARD(s2n_hash_init(&hash, hash_alg));
     768         [ -  + ]:          1 :     POSIX_GUARD(s2n_hash_update(&hash, context, context_length));
     769         [ -  + ]:          1 :     POSIX_GUARD(s2n_hash_digest(&hash, digest.data, digest.size));
     770                 :            : 
     771                 :          1 :     struct s2n_blob output = { 0 };
     772         [ -  + ]:          1 :     POSIX_GUARD(s2n_blob_init(&output, output_in, output_length));
     773         [ -  + ]:          1 :     POSIX_GUARD(s2n_hkdf_expand_label(&hmac_state, hmac_alg,
     774                 :          1 :             &derived_secret, &s2n_tls13_label_exporter, &digest, &output));
     775                 :            : 
     776                 :          1 :     return S2N_SUCCESS;
     777                 :          1 : }

Generated by: LCOV version 1.14