LCOV - code coverage report
Current view: top level - tls - s2n_tls13_key_schedule.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 142 144 98.6 %
Date: 2025-08-15 07:28:39 Functions: 8 8 100.0 %
Branches: 86 168 51.2 %

           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_prf.h"
      17                 :            : #include "tls/s2n_tls13_handshake.h"
      18                 :            : #include "utils/s2n_result.h"
      19                 :            : 
      20                 :            : /* The state machine refers to the "master" secret as the "application" secret.
      21                 :            :  * Let's use that terminology here to match.
      22                 :            :  */
      23                 :            : #define S2N_APPLICATION_SECRET S2N_MASTER_SECRET
      24                 :            : 
      25                 :            : /**
      26                 :            :  *= https://www.rfc-editor.org/rfc/rfc8446#appendix-A
      27                 :            :  *# The notation "K_{send,recv} = foo" means "set
      28                 :            :  *# the send/recv key to the given key".
      29                 :            :  */
      30                 :      14187 : #define K_send(conn, secret_type) RESULT_GUARD(s2n_tls13_key_schedule_set_key(conn, secret_type, (conn)->mode))
      31                 :      13609 : #define K_recv(conn, secret_type) RESULT_GUARD(s2n_tls13_key_schedule_set_key(conn, secret_type, S2N_PEER_MODE((conn)->mode)))
      32                 :            : 
      33                 :            : static const struct s2n_blob s2n_zero_length_context = { 0 };
      34                 :            : 
      35                 :            : static S2N_RESULT s2n_zero_sequence_number(struct s2n_connection *conn, s2n_mode mode)
      36                 :      27808 : {
      37 [ -  + ][ #  # ]:      27808 :     RESULT_ENSURE_REF(conn);
      38 [ #  # ][ -  + ]:      27808 :     RESULT_ENSURE_REF(conn->secure);
      39                 :      27808 :     struct s2n_blob sequence_number = { 0 };
      40         [ -  + ]:      27808 :     RESULT_GUARD(s2n_connection_get_sequence_number(conn, mode, &sequence_number));
      41         [ -  + ]:      27808 :     RESULT_GUARD_POSIX(s2n_blob_zero(&sequence_number));
      42                 :      27808 :     return S2N_RESULT_OK;
      43                 :      27808 : }
      44                 :            : 
      45                 :            : static S2N_RESULT s2n_tls13_key_schedule_get_keying_material(
      46                 :            :         struct s2n_connection *conn, s2n_extract_secret_type_t secret_type,
      47                 :            :         s2n_mode mode, struct s2n_blob *iv, struct s2n_blob *key)
      48                 :      27809 : {
      49 [ -  + ][ #  # ]:      27809 :     RESULT_ENSURE_REF(conn);
      50 [ -  + ][ #  # ]:      27809 :     RESULT_ENSURE_REF(iv);
      51 [ -  + ][ #  # ]:      27809 :     RESULT_ENSURE_REF(key);
      52 [ -  + ][ #  # ]:      27809 :     RESULT_ENSURE_REF(conn->secure);
      53                 :            : 
      54                 :      27809 :     const struct s2n_cipher_suite *cipher_suite = conn->secure->cipher_suite;
      55 [ #  # ][ -  + ]:      27809 :     RESULT_ENSURE_REF(cipher_suite);
      56                 :            : 
      57                 :      27809 :     const struct s2n_cipher *cipher = NULL;
      58         [ -  + ]:      27809 :     RESULT_GUARD(s2n_connection_get_secure_cipher(conn, &cipher));
      59 [ -  + ][ #  # ]:      27809 :     RESULT_ENSURE_REF(cipher);
      60                 :            : 
      61                 :            :     /**
      62                 :            :      *= https://www.rfc-editor.org/rfc/rfc8446#section-7.3
      63                 :            :      *# The traffic keying material is generated from the following input
      64                 :            :      *# values:
      65                 :            :      *#
      66                 :            :      *# -  A secret value
      67                 :            :      **/
      68                 :      27809 :     struct s2n_blob secret = { 0 };
      69                 :      27809 :     uint8_t secret_bytes[S2N_TLS13_SECRET_MAX_LEN] = { 0 };
      70         [ -  + ]:      27809 :     RESULT_GUARD_POSIX(s2n_blob_init(&secret, secret_bytes, S2N_TLS13_SECRET_MAX_LEN));
      71         [ -  + ]:      27809 :     RESULT_GUARD(s2n_tls13_secrets_get(conn, secret_type, mode, &secret));
      72                 :            : 
      73                 :            :     /**
      74                 :            :      *= https://www.rfc-editor.org/rfc/rfc8446#section-7.3
      75                 :            :      *#
      76                 :            :      *# -  A purpose value indicating the specific value being generated
      77                 :            :      **/
      78                 :      27809 :     const struct s2n_blob *key_purpose = &s2n_tls13_label_traffic_secret_key;
      79                 :      27809 :     const struct s2n_blob *iv_purpose = &s2n_tls13_label_traffic_secret_iv;
      80                 :            : 
      81                 :            :     /**
      82                 :            :      *= https://www.rfc-editor.org/rfc/rfc8446#section-7.3
      83                 :            :      *#
      84                 :            :      *# -  The length of the key being generated
      85                 :            :      **/
      86                 :      27809 :     const uint32_t key_size = cipher->key_material_size;
      87                 :      27809 :     const uint32_t iv_size = S2N_TLS13_FIXED_IV_LEN;
      88                 :            : 
      89                 :            :     /*
      90                 :            :      * TODO: We should be able to reuse the prf_work_space rather
      91                 :            :      * than allocating a new HMAC every time.
      92                 :            :      * https://github.com/aws/s2n-tls/issues/3206
      93                 :            :      */
      94                 :      27809 :     s2n_hmac_algorithm hmac_alg = cipher_suite->prf_alg;
      95                 :      27809 :     DEFER_CLEANUP(struct s2n_hmac_state hmac = { 0 }, s2n_hmac_free);
      96         [ -  + ]:      27809 :     RESULT_GUARD_POSIX(s2n_hmac_new(&hmac));
      97                 :            : 
      98                 :            :     /**
      99                 :            :      *= https://www.rfc-editor.org/rfc/rfc8446#section-7.3
     100                 :            :      *#
     101                 :            :      *# The traffic keying material is generated from an input traffic secret
     102                 :            :      *# value using:
     103                 :            :      *#
     104                 :            :      *# [sender]_write_key = HKDF-Expand-Label(Secret, "key", "", key_length)
     105                 :            :      **/
     106 [ #  # ][ -  + ]:      27809 :     RESULT_ENSURE_LTE(key_size, key->size);
     107                 :      27809 :     key->size = key_size;
     108         [ -  + ]:      27809 :     RESULT_GUARD_POSIX(s2n_hkdf_expand_label(&hmac, hmac_alg,
     109                 :      27809 :             &secret, key_purpose, &s2n_zero_length_context, key));
     110                 :            :     /**
     111                 :            :      *= https://www.rfc-editor.org/rfc/rfc8446#section-7.3
     112                 :            :      *# [sender]_write_iv  = HKDF-Expand-Label(Secret, "iv", "", iv_length)
     113                 :            :      **/
     114 [ -  + ][ #  # ]:      27809 :     RESULT_ENSURE_LTE(iv_size, iv->size);
     115                 :      27809 :     iv->size = iv_size;
     116         [ -  + ]:      27809 :     RESULT_GUARD_POSIX(s2n_hkdf_expand_label(&hmac, hmac_alg,
     117                 :      27809 :             &secret, iv_purpose, &s2n_zero_length_context, iv));
     118                 :            : 
     119                 :      27809 :     return S2N_RESULT_OK;
     120                 :      27809 : }
     121                 :            : 
     122                 :            : S2N_RESULT s2n_tls13_key_schedule_set_key(struct s2n_connection *conn, s2n_extract_secret_type_t secret_type, s2n_mode mode)
     123                 :      27810 : {
     124 [ #  # ][ -  + ]:      27810 :     RESULT_ENSURE_REF(conn);
     125 [ +  + ][ +  - ]:      27810 :     RESULT_ENSURE_REF(conn->secure);
     126                 :            : 
     127                 :      27808 :     uint8_t *implicit_iv_data = NULL;
     128                 :      27808 :     struct s2n_session_key *session_key = NULL;
     129                 :      27808 :     uint8_t key_bytes[S2N_TLS13_SECRET_MAX_LEN] = { 0 };
     130         [ +  + ]:      27808 :     if (mode == S2N_CLIENT) {
     131                 :      12652 :         implicit_iv_data = conn->secure->client_implicit_iv;
     132                 :      12652 :         session_key = &conn->secure->client_key;
     133                 :      12652 :         conn->client = conn->secure;
     134                 :      15156 :     } else {
     135                 :      15156 :         implicit_iv_data = conn->secure->server_implicit_iv;
     136                 :      15156 :         session_key = &conn->secure->server_key;
     137                 :      15156 :         conn->server = conn->secure;
     138                 :      15156 :     }
     139                 :            : 
     140                 :      27808 :     struct s2n_blob iv = { 0 };
     141                 :      27808 :     struct s2n_blob key = { 0 };
     142         [ -  + ]:      27808 :     RESULT_GUARD_POSIX(s2n_blob_init(&iv, implicit_iv_data, S2N_TLS13_FIXED_IV_LEN));
     143         [ -  + ]:      27808 :     RESULT_GUARD_POSIX(s2n_blob_init(&key, key_bytes, sizeof(key_bytes)));
     144         [ -  + ]:      27808 :     RESULT_GUARD(s2n_tls13_key_schedule_get_keying_material(
     145                 :      27808 :             conn, secret_type, mode, &iv, &key));
     146                 :            : 
     147                 :      27808 :     const struct s2n_cipher *cipher = NULL;
     148         [ -  + ]:      27808 :     RESULT_GUARD(s2n_connection_get_secure_cipher(conn, &cipher));
     149 [ -  + ][ #  # ]:      27808 :     RESULT_ENSURE_REF(cipher);
     150                 :            : 
     151                 :      27808 :     bool is_sending_secret = (mode == conn->mode);
     152         [ +  + ]:      27808 :     if (is_sending_secret) {
     153         [ -  + ]:      14192 :         RESULT_GUARD(cipher->set_encryption_key(session_key, &key));
     154                 :      14192 :     } else {
     155         [ -  + ]:      13616 :         RESULT_GUARD(cipher->set_decryption_key(session_key, &key));
     156                 :      13616 :     }
     157                 :            : 
     158                 :            :     /**
     159                 :            :      *= https://www.rfc-editor.org/rfc/rfc8446#section-5.3
     160                 :            :      *# Each sequence number is
     161                 :            :      *# set to zero at the beginning of a connection and whenever the key is
     162                 :            :      *# changed; the first record transmitted under a particular traffic key
     163                 :            :      *# MUST use sequence number 0.
     164                 :            :      */
     165         [ -  + ]:      27808 :     RESULT_GUARD(s2n_zero_sequence_number(conn, mode));
     166                 :            : 
     167                 :      27808 :     return S2N_RESULT_OK;
     168                 :      27808 : }
     169                 :            : 
     170                 :            : static S2N_RESULT s2n_client_key_schedule(struct s2n_connection *conn)
     171                 :      28086 : {
     172 [ -  + ][ #  # ]:      28086 :     RESULT_ENSURE_REF(conn);
     173                 :            : 
     174                 :      28086 :     message_type_t message_type = s2n_conn_get_current_message_type(conn);
     175                 :            : 
     176                 :            :     /**
     177                 :            :      * How client keys are set varies depending on early data state.
     178                 :            :      *
     179                 :            :      *= https://www.rfc-editor.org/rfc/rfc8446#appendix-A
     180                 :            :      *# Actions which are taken only in certain circumstances
     181                 :            :      *# are indicated in [].
     182                 :            :      */
     183                 :            : 
     184                 :            :     /**
     185                 :            :      *= https://www.rfc-editor.org/rfc/rfc8446#appendix-A.1
     186                 :            :      *#                              START <----+
     187                 :            :      *#               Send ClientHello |        | Recv HelloRetryRequest
     188                 :            :      *#          [K_send = early data] |        |
     189                 :            :      */
     190         [ +  + ]:      28086 :     if (message_type == CLIENT_HELLO
     191         [ +  + ]:      28086 :             && conn->early_data_state == S2N_EARLY_DATA_REQUESTED) {
     192         [ +  + ]:        613 :         K_send(conn, S2N_EARLY_SECRET);
     193                 :        613 :     }
     194                 :            :     /**
     195                 :            :      *= https://www.rfc-editor.org/rfc/rfc8446#appendix-A.1
     196                 :            :      *#                                v        |
     197                 :            :      *#           /                 WAIT_SH ----+
     198                 :            :      *#           |                    | Recv ServerHello
     199                 :            :      *#           |                    | K_recv = handshake
     200                 :            :      */
     201         [ +  + ]:      28085 :     if (message_type == SERVER_HELLO) {
     202         [ -  + ]:       4377 :         K_recv(conn, S2N_HANDSHAKE_SECRET);
     203                 :       4377 :     }
     204                 :            :     /**
     205                 :            :      *= https://www.rfc-editor.org/rfc/rfc8446#appendix-A.1
     206                 :            :      *#       Can |                    V
     207                 :            :      *#      send |                 WAIT_EE
     208                 :            :      *#     early |                    | Recv EncryptedExtensions
     209                 :            :      *#      data |           +--------+--------+
     210                 :            :      *#           |     Using |                 | Using certificate
     211                 :            :      *#           |       PSK |                 v
     212                 :            :      *#           |           |            WAIT_CERT_CR
     213                 :            :      *#           |           |        Recv |       | Recv CertificateRequest
     214                 :            :      *#           |           | Certificate |       v
     215                 :            :      *#           |           |             |    WAIT_CERT
     216                 :            :      *#           |           |             |       | Recv Certificate
     217                 :            :      *#           |           |             v       v
     218                 :            :      *#           |           |              WAIT_CV
     219                 :            :      *#           |           |                 | Recv CertificateVerify
     220                 :            :      *#           |           +> WAIT_FINISHED <+
     221                 :            :      *#           |                  | Recv Finished
     222                 :            :      *#           \                  | [Send EndOfEarlyData]
     223                 :            :      *#                              | K_send = handshake
     224                 :            :      */
     225 [ +  + ][ +  + ]:      28085 :     if ((message_type == SERVER_FINISHED && !WITH_EARLY_DATA(conn))
     226         [ +  + ]:      28085 :             || (message_type == END_OF_EARLY_DATA)) {
     227         [ -  + ]:       2801 :         K_send(conn, S2N_HANDSHAKE_SECRET);
     228                 :       2801 :     }
     229                 :            :     /**
     230                 :            :      *= https://www.rfc-editor.org/rfc/rfc8446#appendix-A.1
     231                 :            :      *#                              | [Send Certificate [+ CertificateVerify]]
     232                 :            :      *#    Can send                  | Send Finished
     233                 :            :      *#    app data   -->            | K_send = K_recv = application
     234                 :            :      */
     235         [ +  + ]:      28085 :     if (message_type == CLIENT_FINISHED) {
     236         [ -  + ]:       2798 :         K_send(conn, S2N_APPLICATION_SECRET);
     237         [ -  + ]:       2798 :         K_recv(conn, S2N_APPLICATION_SECRET);
     238                 :       2798 :     }
     239                 :            :     /**
     240                 :            :      *= https://www.rfc-editor.org/rfc/rfc8446#appendix-A.1
     241                 :            :      *#    after here                v
     242                 :            :      *#                          CONNECTED
     243                 :            :      */
     244                 :      28085 :     return S2N_RESULT_OK;
     245                 :      28085 : }
     246                 :            : 
     247                 :            : static S2N_RESULT s2n_server_key_schedule(struct s2n_connection *conn)
     248                 :      31645 : {
     249 [ -  + ][ #  # ]:      31645 :     RESULT_ENSURE_REF(conn);
     250                 :            : 
     251                 :      31645 :     message_type_t message_type = s2n_conn_get_current_message_type(conn);
     252                 :            : 
     253                 :            :     /**
     254                 :            :      *= https://www.rfc-editor.org/rfc/rfc8446#appendix-A.2
     255                 :            :      *#                              START <-----+
     256                 :            :      *#               Recv ClientHello |         | Send HelloRetryRequest
     257                 :            :      *#                                v         |
     258                 :            :      *#                             RECVD_CH ----+
     259                 :            :      *#                                | Select parameters
     260                 :            :      *#                                v
     261                 :            :      *#                             NEGOTIATED
     262                 :            :      *#                                | Send ServerHello
     263                 :            :      *#                                | K_send = handshake
     264                 :            :      */
     265         [ +  + ]:      31645 :     if (message_type == SERVER_HELLO) {
     266         [ +  + ]:       4384 :         K_send(conn, S2N_HANDSHAKE_SECRET);
     267                 :       4384 :     }
     268                 :            :     /**
     269                 :            :      *= https://www.rfc-editor.org/rfc/rfc8446#appendix-A.2
     270                 :            :      *#                                | Send EncryptedExtensions
     271                 :            :      *#                                | [Send CertificateRequest]
     272                 :            :      *# Can send                       | [Send Certificate + CertificateVerify]
     273                 :            :      *# app data                       | Send Finished
     274                 :            :      *# after   -->                    | K_send = application
     275                 :            :      */
     276         [ +  + ]:      31644 :     if (message_type == SERVER_FINISHED) {
     277         [ -  + ]:       3591 :         K_send(conn, S2N_APPLICATION_SECRET);
     278                 :            :         /* clang-format off */
     279                 :            :     /**
     280                 :            :      *= https://www.rfc-editor.org/rfc/rfc8446#appendix-A.2
     281                 :            :      *# here                  +--------+--------+
     282                 :            :      *#              No 0-RTT |                 | 0-RTT
     283                 :            :      *#                       |                 |
     284                 :            :      *#   K_recv = handshake  |                 | K_recv = early data
     285                 :            :      */
     286                 :            :         /* clang-format on */
     287         [ +  + ]:       3591 :         if (WITH_EARLY_DATA(conn)) {
     288         [ -  + ]:         55 :             K_recv(conn, S2N_EARLY_SECRET);
     289                 :       3536 :         } else {
     290         [ -  + ]:       3536 :             K_recv(conn, S2N_HANDSHAKE_SECRET);
     291                 :       3536 :         }
     292                 :       3591 :     }
     293                 :            :     /**
     294                 :            :      *= https://www.rfc-editor.org/rfc/rfc8446#appendix-A.2
     295                 :            :      *# [Skip decrypt errors] |    +------> WAIT_EOED -+
     296                 :            :      *#                       |    |       Recv |      | Recv EndOfEarlyData
     297                 :            :      *#                       |    | early data |      | K_recv = handshake
     298                 :            :      *#                       |    +------------+      |
     299                 :            :      */
     300         [ +  + ]:      31644 :     if (message_type == END_OF_EARLY_DATA) {
     301         [ -  + ]:         46 :         K_recv(conn, S2N_HANDSHAKE_SECRET);
     302                 :         46 :     }
     303                 :            :     /**
     304                 :            :      *= https://www.rfc-editor.org/rfc/rfc8446#appendix-A.2
     305                 :            :      *#                       |                        |
     306                 :            :      *#                       +> WAIT_FLIGHT2 <--------+
     307                 :            :      *#                                |
     308                 :            :      *#                       +--------+--------+
     309                 :            :      *#               No auth |                 | Client auth
     310                 :            :      *#                       |                 |
     311                 :            :      *#                       |                 v
     312                 :            :      *#                       |             WAIT_CERT
     313                 :            :      *#                       |        Recv |       | Recv Certificate
     314                 :            :      *#                       |       empty |       v
     315                 :            :      *#                       | Certificate |    WAIT_CV
     316                 :            :      *#                       |             |       | Recv
     317                 :            :      *#                       |             v       | CertificateVerify
     318                 :            :      *#                       +-> WAIT_FINISHED <---+
     319                 :            :      *#                                | Recv Finished
     320                 :            :      *#                                | K_recv = application
     321                 :            :      */
     322         [ +  + ]:      31644 :     if (message_type == CLIENT_FINISHED) {
     323         [ -  + ]:       2797 :         K_recv(conn, S2N_APPLICATION_SECRET);
     324                 :       2797 :     }
     325                 :            :     /**
     326                 :            :      *= https://www.rfc-editor.org/rfc/rfc8446#appendix-A.2
     327                 :            :      *#                                v
     328                 :            :      *#                            CONNECTED
     329                 :            :      */
     330                 :      31644 :     return S2N_RESULT_OK;
     331                 :      31644 : }
     332                 :            : 
     333                 :            : s2n_result (*key_schedules[])(struct s2n_connection *) = {
     334                 :            :     [S2N_CLIENT] = &s2n_client_key_schedule,
     335                 :            :     [S2N_SERVER] = &s2n_server_key_schedule,
     336                 :            : };
     337                 :            : 
     338                 :            : S2N_RESULT s2n_tls13_key_schedule_update(struct s2n_connection *conn)
     339                 :      94248 : {
     340 [ +  + ][ +  - ]:      94248 :     RESULT_ENSURE_REF(conn);
     341         [ +  + ]:      94247 :     if (s2n_connection_get_protocol_version(conn) < S2N_TLS13) {
     342                 :      34516 :         return S2N_RESULT_OK;
     343                 :      34516 :     }
     344 [ -  + ][ #  # ]:      59731 :     RESULT_ENSURE_REF(key_schedules[conn->mode]);
     345         [ +  + ]:      59731 :     RESULT_GUARD(key_schedules[conn->mode](conn));
     346                 :      59729 :     return S2N_RESULT_OK;
     347                 :      59731 : }
     348                 :            : 
     349                 :            : S2N_RESULT s2n_tls13_key_schedule_reset(struct s2n_connection *conn)
     350                 :       1060 : {
     351 [ #  # ][ -  + ]:       1060 :     RESULT_ENSURE_REF(conn);
     352 [ -  + ][ #  # ]:       1060 :     RESULT_ENSURE_REF(conn->initial);
     353                 :       1060 :     conn->client = conn->initial;
     354                 :       1060 :     conn->server = conn->initial;
     355                 :       1060 :     conn->secrets.extract_secret_type = S2N_NONE_SECRET;
     356                 :       1060 :     return S2N_RESULT_OK;
     357                 :       1060 : }
     358                 :            : 
     359                 :            : S2N_RESULT s2n_tls13_key_schedule_generate_key_material(struct s2n_connection *conn,
     360                 :            :         s2n_mode sender, struct s2n_key_material *key_material)
     361                 :          1 : {
     362         [ -  + ]:          1 :     RESULT_GUARD(s2n_key_material_init(key_material, conn));
     363         [ -  + ]:          1 :     if (sender == S2N_CLIENT) {
     364         [ #  # ]:          0 :         RESULT_GUARD(s2n_tls13_key_schedule_get_keying_material(conn, S2N_MASTER_SECRET,
     365                 :          0 :                 sender, &key_material->client_iv, &key_material->client_key));
     366                 :          1 :     } else {
     367         [ -  + ]:          1 :         RESULT_GUARD(s2n_tls13_key_schedule_get_keying_material(conn, S2N_MASTER_SECRET,
     368                 :          1 :                 sender, &key_material->server_iv, &key_material->server_key));
     369                 :          1 :     }
     370                 :          1 :     return S2N_RESULT_OK;
     371                 :          1 : }

Generated by: LCOV version 1.14