LCOV - code coverage report
Current view: top level - crypto - s2n_hkdf.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 105 158 66.5 %
Date: 2025-08-15 07:28:39 Functions: 8 13 61.5 %
Branches: 71 210 33.8 %

           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_hkdf.h"
      17                 :            : 
      18                 :            : #include "crypto/s2n_fips.h"
      19                 :            : #include "crypto/s2n_hmac.h"
      20                 :            : #include "error/s2n_errno.h"
      21                 :            : #include "stuffer/s2n_stuffer.h"
      22                 :            : #include "utils/s2n_blob.h"
      23                 :            : #include "utils/s2n_mem.h"
      24                 :            : #include "utils/s2n_safety.h"
      25                 :            : 
      26                 :            : #ifdef S2N_LIBCRYPTO_SUPPORTS_HKDF
      27                 :            :     #include <openssl/hkdf.h>
      28                 :            : #endif
      29                 :            : 
      30                 :            : #define MAX_DIGEST_SIZE 64 /* Current highest is SHA512 */
      31                 :            : #define MAX_HKDF_ROUNDS 255
      32                 :            : 
      33                 :            : /* Reference: RFC 5869 */
      34                 :            : 
      35                 :            : struct s2n_hkdf_impl {
      36                 :            :     int (*hkdf)(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt,
      37                 :            :             const struct s2n_blob *key, const struct s2n_blob *info, struct s2n_blob *output);
      38                 :            :     int (*hkdf_extract)(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt,
      39                 :            :             const struct s2n_blob *key, struct s2n_blob *pseudo_rand_key);
      40                 :            :     int (*hkdf_expand)(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *pseudo_rand_key,
      41                 :            :             const struct s2n_blob *info, struct s2n_blob *output);
      42                 :            : };
      43                 :            : 
      44                 :            : static int s2n_custom_hkdf_extract(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt,
      45                 :            :         const struct s2n_blob *key, struct s2n_blob *pseudo_rand_key)
      46                 :      39482 : {
      47                 :      39482 :     uint8_t hmac_size = 0;
      48         [ -  + ]:      39482 :     POSIX_GUARD(s2n_hmac_digest_size(alg, &hmac_size));
      49 [ +  + ][ +  - ]:      39482 :     POSIX_ENSURE(hmac_size <= pseudo_rand_key->size, S2N_ERR_HKDF_OUTPUT_SIZE);
      50                 :      39481 :     pseudo_rand_key->size = hmac_size;
      51                 :            : 
      52         [ -  + ]:      39481 :     POSIX_GUARD(s2n_hmac_init(hmac, alg, salt->data, salt->size));
      53         [ -  + ]:      39481 :     POSIX_GUARD(s2n_hmac_update(hmac, key->data, key->size));
      54         [ -  + ]:      39481 :     POSIX_GUARD(s2n_hmac_digest(hmac, pseudo_rand_key->data, pseudo_rand_key->size));
      55                 :            : 
      56         [ -  + ]:      39481 :     POSIX_GUARD(s2n_hmac_reset(hmac));
      57                 :            : 
      58                 :      39481 :     return S2N_SUCCESS;
      59                 :      39481 : }
      60                 :            : 
      61                 :            : static int s2n_custom_hkdf_expand(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg,
      62                 :            :         const struct s2n_blob *pseudo_rand_key, const struct s2n_blob *info, struct s2n_blob *output)
      63                 :     141500 : {
      64                 :     141500 :     uint8_t prev[MAX_DIGEST_SIZE] = { 0 };
      65                 :            : 
      66                 :     141500 :     uint32_t done_len = 0;
      67                 :     141500 :     uint8_t hash_len = 0;
      68         [ -  + ]:     141500 :     POSIX_GUARD(s2n_hmac_digest_size(alg, &hash_len));
      69 [ -  + ][ #  # ]:     141500 :     POSIX_ENSURE_GT(hash_len, 0);
      70                 :     141500 :     uint32_t total_rounds = output->size / hash_len;
      71         [ +  + ]:     141500 :     if (output->size % hash_len) {
      72                 :      58858 :         total_rounds++;
      73                 :      58858 :     }
      74                 :            : 
      75 [ +  + ][ +  - ]:     141500 :     POSIX_ENSURE(total_rounds > 0, S2N_ERR_HKDF_OUTPUT_SIZE);
      76 [ +  + ][ +  - ]:     141499 :     POSIX_ENSURE(total_rounds <= MAX_HKDF_ROUNDS, S2N_ERR_HKDF_OUTPUT_SIZE);
      77                 :            : 
      78         [ +  + ]:     283159 :     for (uint32_t curr_round = 1; curr_round <= total_rounds; curr_round++) {
      79                 :     141661 :         uint32_t cat_len = 0;
      80         [ -  + ]:     141661 :         POSIX_GUARD(s2n_hmac_init(hmac, alg, pseudo_rand_key->data, pseudo_rand_key->size));
      81         [ +  + ]:     141661 :         if (curr_round != 1) {
      82         [ -  + ]:        163 :             POSIX_GUARD(s2n_hmac_update(hmac, prev, hash_len));
      83                 :        163 :         }
      84         [ -  + ]:     141661 :         POSIX_GUARD(s2n_hmac_update(hmac, info->data, info->size));
      85         [ -  + ]:     141661 :         POSIX_GUARD(s2n_hmac_update(hmac, &curr_round, 1));
      86         [ -  + ]:     141661 :         POSIX_GUARD(s2n_hmac_digest(hmac, prev, hash_len));
      87                 :            : 
      88                 :     141661 :         cat_len = hash_len;
      89         [ +  + ]:     141661 :         if (done_len + hash_len > output->size) {
      90                 :      58857 :             cat_len = output->size - done_len;
      91                 :      58857 :         }
      92                 :            : 
      93 [ -  + ][ #  # ]:     141661 :         POSIX_CHECKED_MEMCPY(output->data + done_len, prev, cat_len);
                 [ +  - ]
      94                 :            : 
      95                 :     141661 :         done_len += cat_len;
      96                 :            : 
      97         [ -  + ]:     141661 :         POSIX_GUARD(s2n_hmac_reset(hmac));
      98                 :     141661 :     }
      99                 :            : 
     100                 :     141498 :     return S2N_SUCCESS;
     101                 :     141498 : }
     102                 :            : 
     103                 :            : static int s2n_custom_hkdf(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt,
     104                 :            :         const struct s2n_blob *key, const struct s2n_blob *info, struct s2n_blob *output)
     105                 :        765 : {
     106                 :        765 :     uint8_t prk_pad[MAX_DIGEST_SIZE] = { 0 };
     107                 :        765 :     struct s2n_blob pseudo_rand_key = { 0 };
     108         [ -  + ]:        765 :     POSIX_GUARD(s2n_blob_init(&pseudo_rand_key, prk_pad, sizeof(prk_pad)));
     109                 :            : 
     110         [ -  + ]:        765 :     POSIX_GUARD(s2n_custom_hkdf_extract(hmac, alg, salt, key, &pseudo_rand_key));
     111         [ +  + ]:        765 :     POSIX_GUARD(s2n_custom_hkdf_expand(hmac, alg, &pseudo_rand_key, info, output));
     112                 :            : 
     113                 :        763 :     return S2N_SUCCESS;
     114                 :        765 : }
     115                 :            : 
     116                 :            : const struct s2n_hkdf_impl s2n_custom_hkdf_impl = {
     117                 :            :     .hkdf = &s2n_custom_hkdf,
     118                 :            :     .hkdf_extract = &s2n_custom_hkdf_extract,
     119                 :            :     .hkdf_expand = &s2n_custom_hkdf_expand,
     120                 :            : };
     121                 :            : 
     122                 :            : #ifdef S2N_LIBCRYPTO_SUPPORTS_HKDF
     123                 :            : static int s2n_libcrypto_hkdf_extract(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt,
     124                 :            :         const struct s2n_blob *key, struct s2n_blob *pseudo_rand_key)
     125                 :            : {
     126                 :            :     const EVP_MD *digest = NULL;
     127                 :            :     POSIX_GUARD_RESULT(s2n_hmac_md_from_alg(alg, &digest));
     128                 :            : 
     129                 :            :     /* The out_len argument of HKDF_extract is set to the number of bytes written to out_key, and
     130                 :            :      * is not used to ensure that out_key is large enough to contain the PRK. Ensure that the PRK
     131                 :            :      * output will fit in the blob.
     132                 :            :      */
     133                 :            :     uint8_t hmac_size = 0;
     134                 :            :     POSIX_GUARD(s2n_hmac_digest_size(alg, &hmac_size));
     135                 :            :     POSIX_ENSURE(hmac_size <= pseudo_rand_key->size, S2N_ERR_HKDF_OUTPUT_SIZE);
     136                 :            : 
     137                 :            :     size_t bytes_written = 0;
     138                 :            :     POSIX_GUARD_OSSL(HKDF_extract(pseudo_rand_key->data, &bytes_written, digest, key->data, key->size,
     139                 :            :                              salt->data, salt->size),
     140                 :            :             S2N_ERR_HKDF);
     141                 :            : 
     142                 :            :     /* HKDF_extract updates the out_len argument based on the digest size. Update the blob's size based on this. */
     143                 :            :     POSIX_ENSURE_LTE(bytes_written, pseudo_rand_key->size);
     144                 :            :     pseudo_rand_key->size = bytes_written;
     145                 :            : 
     146                 :            :     return S2N_SUCCESS;
     147                 :            : }
     148                 :            : 
     149                 :            : static int s2n_libcrypto_hkdf_expand(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg,
     150                 :            :         const struct s2n_blob *pseudo_rand_key, const struct s2n_blob *info, struct s2n_blob *output)
     151                 :            : {
     152                 :            :     POSIX_ENSURE(output->size > 0, S2N_ERR_HKDF_OUTPUT_SIZE);
     153                 :            : 
     154                 :            :     const EVP_MD *digest = NULL;
     155                 :            :     POSIX_GUARD_RESULT(s2n_hmac_md_from_alg(alg, &digest));
     156                 :            : 
     157                 :            :     POSIX_GUARD_OSSL(HKDF_expand(output->data, output->size, digest, pseudo_rand_key->data, pseudo_rand_key->size,
     158                 :            :                              info->data, info->size),
     159                 :            :             S2N_ERR_HKDF);
     160                 :            : 
     161                 :            :     return S2N_SUCCESS;
     162                 :            : }
     163                 :            : 
     164                 :            : static int s2n_libcrypto_hkdf(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt,
     165                 :            :         const struct s2n_blob *key, const struct s2n_blob *info, struct s2n_blob *output)
     166                 :            : {
     167                 :            :     POSIX_ENSURE(output->size > 0, S2N_ERR_HKDF_OUTPUT_SIZE);
     168                 :            : 
     169                 :            :     const EVP_MD *digest = NULL;
     170                 :            :     POSIX_GUARD_RESULT(s2n_hmac_md_from_alg(alg, &digest));
     171                 :            : 
     172                 :            :     POSIX_GUARD_OSSL(HKDF(output->data, output->size, digest, key->data, key->size, salt->data, salt->size,
     173                 :            :                              info->data, info->size),
     174                 :            :             S2N_ERR_HKDF);
     175                 :            : 
     176                 :            :     return S2N_SUCCESS;
     177                 :            : }
     178                 :            : 
     179                 :            : bool s2n_libcrypto_supports_hkdf()
     180                 :            : {
     181                 :            :     return true;
     182                 :            : }
     183                 :            : 
     184                 :            : #elif S2N_OPENSSL_VERSION_AT_LEAST(3, 0, 0)
     185                 :            : 
     186                 :            :     #include "crypto/s2n_kdf.h"
     187                 :            : 
     188                 :            : static S2N_RESULT s2n_hkdf_kdf(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg,
     189                 :            :         const struct s2n_blob *salt, const struct s2n_blob *key, const struct s2n_blob *info,
     190                 :            :         struct s2n_blob *output, int mode)
     191                 :          0 : {
     192                 :            :     /* As an optimization, we should be able to fetch and cache this EVP_KDF*
     193                 :            :      * once when s2n_init is called.
     194                 :            :      */
     195                 :          0 :     DEFER_CLEANUP(EVP_KDF *hkdf_impl = EVP_KDF_fetch(NULL, "HKDF", NULL),
     196                 :          0 :             EVP_KDF_free_pointer);
     197 [ #  # ][ #  # ]:          0 :     RESULT_ENSURE(hkdf_impl, S2N_ERR_PRF_INVALID_ALGORITHM);
     198                 :            : 
     199                 :          0 :     DEFER_CLEANUP(EVP_KDF_CTX *hkdf_ctx = EVP_KDF_CTX_new(hkdf_impl),
     200                 :          0 :             EVP_KDF_CTX_free_pointer);
     201 [ #  # ][ #  # ]:          0 :     RESULT_ENSURE_REF(hkdf_ctx);
     202                 :            : 
     203                 :          0 :     const EVP_MD *digest = NULL;
     204         [ #  # ]:          0 :     RESULT_GUARD(s2n_hmac_md_from_alg(alg, &digest));
     205 [ #  # ][ #  # ]:          0 :     RESULT_ENSURE_REF(digest);
     206                 :          0 :     const char *digest_name = EVP_MD_get0_name(digest);
     207 [ #  # ][ #  # ]:          0 :     RESULT_ENSURE_REF(digest_name);
     208                 :            : 
     209                 :          0 :     OSSL_PARAM params[] = {
     210                 :          0 :         S2N_OSSL_PARAM_INT(OSSL_KDF_PARAM_MODE, mode),
     211                 :          0 :         S2N_OSSL_PARAM_BLOB(OSSL_KDF_PARAM_KEY, key),
     212                 :          0 :         S2N_OSSL_PARAM_BLOB(OSSL_KDF_PARAM_INFO, info),
     213                 :          0 :         S2N_OSSL_PARAM_BLOB(OSSL_KDF_PARAM_SALT, salt),
     214                 :            :         /* Casting away the const is safe because providers are forbidden from
     215                 :            :          * modifying any OSSL_PARAM value other than return_size.
     216                 :            :          * Even the examples in the Openssl documentation cast const strings to
     217                 :            :          * non-const void pointers when setting up OSSL_PARAMs.
     218                 :            :          */
     219                 :          0 :         S2N_OSSL_PARAM_STR(OSSL_KDF_PARAM_DIGEST, (void *) (uintptr_t) digest_name),
     220                 :          0 :         OSSL_PARAM_END,
     221                 :          0 :     };
     222                 :            : 
     223                 :            :     /* From the HKDF docs (https://docs.openssl.org/3.1/man7/EVP_KDF-HKDF/):
     224                 :            :      * > When using EVP_KDF_HKDF_MODE_EXTRACT_ONLY the keylen parameter must equal
     225                 :            :      * > the size of the intermediate fixed-length pseudorandom key otherwise an
     226                 :            :      * > error will occur.
     227                 :            :      */
     228         [ #  # ]:          0 :     if (mode == EVP_KDF_HKDF_MODE_EXTRACT_ONLY) {
     229 [ #  # ][ #  # ]:          0 :         RESULT_GUARD_OSSL(EVP_KDF_CTX_set_params(hkdf_ctx, params), S2N_ERR_HKDF);
     230                 :          0 :         size_t key_size = EVP_KDF_CTX_get_kdf_size(hkdf_ctx);
     231 [ #  # ][ #  # ]:          0 :         RESULT_ENSURE(key_size > 0, S2N_ERR_HKDF_OUTPUT_SIZE);
     232 [ #  # ][ #  # ]:          0 :         RESULT_ENSURE(key_size <= output->size, S2N_ERR_HKDF_OUTPUT_SIZE);
     233                 :          0 :         output->size = key_size;
     234                 :          0 :     }
     235                 :            : 
     236 [ #  # ][ #  # ]:          0 :     RESULT_GUARD_OSSL(EVP_KDF_derive(hkdf_ctx, output->data, output->size, params),
     237                 :          0 :             S2N_ERR_HKDF);
     238                 :          0 :     return S2N_RESULT_OK;
     239                 :          0 : }
     240                 :            : 
     241                 :            : static int s2n_libcrypto_hkdf_extract(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg,
     242                 :            :         const struct s2n_blob *salt, const struct s2n_blob *key, struct s2n_blob *pseudo_rand_key)
     243                 :          0 : {
     244                 :          0 :     struct s2n_blob empty_info = { 0 };
     245         [ #  # ]:          0 :     POSIX_GUARD_RESULT(s2n_hkdf_kdf(hmac, alg, salt, key, &empty_info, pseudo_rand_key,
     246                 :          0 :             EVP_KDF_HKDF_MODE_EXTRACT_ONLY));
     247                 :          0 :     return S2N_SUCCESS;
     248                 :          0 : }
     249                 :            : 
     250                 :            : static int s2n_libcrypto_hkdf_expand(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg,
     251                 :            :         const struct s2n_blob *pseudo_rand_key, const struct s2n_blob *info, struct s2n_blob *output)
     252                 :          0 : {
     253                 :          0 :     struct s2n_blob empty_salt = { 0 };
     254         [ #  # ]:          0 :     POSIX_GUARD_RESULT(s2n_hkdf_kdf(hmac, alg, &empty_salt, pseudo_rand_key, info, output,
     255                 :          0 :             EVP_KDF_HKDF_MODE_EXPAND_ONLY));
     256                 :          0 :     return S2N_SUCCESS;
     257                 :          0 : }
     258                 :            : 
     259                 :            : static int s2n_libcrypto_hkdf(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt,
     260                 :            :         const struct s2n_blob *key, const struct s2n_blob *info, struct s2n_blob *output)
     261                 :          0 : {
     262         [ #  # ]:          0 :     POSIX_GUARD_RESULT(s2n_hkdf_kdf(hmac, alg, salt, key, info, output,
     263                 :          0 :             EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND));
     264                 :          0 :     return S2N_SUCCESS;
     265                 :          0 : }
     266                 :            : 
     267                 :            : bool s2n_libcrypto_supports_hkdf()
     268                 :          0 : {
     269                 :          0 :     return true;
     270                 :          0 : }
     271                 :            : 
     272                 :            : #else
     273                 :            : 
     274                 :            : static int s2n_libcrypto_hkdf_extract(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt,
     275                 :            :         const struct s2n_blob *key, struct s2n_blob *pseudo_rand_key)
     276                 :            : {
     277                 :            :     POSIX_BAIL(S2N_ERR_UNIMPLEMENTED);
     278                 :            : }
     279                 :            : 
     280                 :            : static int s2n_libcrypto_hkdf_expand(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg,
     281                 :            :         const struct s2n_blob *pseudo_rand_key, const struct s2n_blob *info, struct s2n_blob *output)
     282                 :            : {
     283                 :            :     POSIX_BAIL(S2N_ERR_UNIMPLEMENTED);
     284                 :            : }
     285                 :            : 
     286                 :            : static int s2n_libcrypto_hkdf(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt,
     287                 :            :         const struct s2n_blob *key, const struct s2n_blob *info, struct s2n_blob *output)
     288                 :            : {
     289                 :            :     POSIX_BAIL(S2N_ERR_UNIMPLEMENTED);
     290                 :            : }
     291                 :            : 
     292                 :            : bool s2n_libcrypto_supports_hkdf()
     293                 :            : {
     294                 :            :     return false;
     295                 :            : }
     296                 :            : 
     297                 :            : #endif /* S2N_LIBCRYPTO_SUPPORTS_HKDF */
     298                 :            : 
     299                 :            : const struct s2n_hkdf_impl s2n_libcrypto_hkdf_impl = {
     300                 :            :     .hkdf = &s2n_libcrypto_hkdf,
     301                 :            :     .hkdf_extract = &s2n_libcrypto_hkdf_extract,
     302                 :            :     .hkdf_expand = &s2n_libcrypto_hkdf_expand,
     303                 :            : };
     304                 :            : 
     305                 :            : static const struct s2n_hkdf_impl *s2n_get_hkdf_implementation()
     306                 :     180217 : {
     307                 :            :     /* By default, s2n-tls uses a custom HKDF implementation. When operating in FIPS mode, the
     308                 :            :      * FIPS-validated libcrypto implementation is used instead, if an implementation is provided.
     309                 :            :      */
     310 [ -  + ][ #  # ]:     180217 :     if (s2n_is_in_fips_mode() && s2n_libcrypto_supports_hkdf()) {
     311                 :          0 :         return &s2n_libcrypto_hkdf_impl;
     312                 :          0 :     }
     313                 :            : 
     314                 :     180217 :     return &s2n_custom_hkdf_impl;
     315                 :     180217 : }
     316                 :            : 
     317                 :            : int s2n_hkdf_extract(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt,
     318                 :            :         const struct s2n_blob *key, struct s2n_blob *pseudo_rand_key)
     319                 :      38717 : {
     320 [ -  + ][ #  # ]:      38717 :     POSIX_ENSURE_REF(hmac);
     321 [ -  + ][ #  # ]:      38717 :     POSIX_ENSURE_REF(salt);
     322 [ -  + ][ #  # ]:      38717 :     POSIX_ENSURE_REF(key);
     323 [ -  + ][ #  # ]:      38717 :     POSIX_ENSURE_REF(pseudo_rand_key);
     324                 :            : 
     325                 :      38717 :     const struct s2n_hkdf_impl *hkdf_implementation = s2n_get_hkdf_implementation();
     326 [ #  # ][ -  + ]:      38717 :     POSIX_ENSURE_REF(hkdf_implementation);
     327                 :            : 
     328         [ +  + ]:      38717 :     POSIX_GUARD(hkdf_implementation->hkdf_extract(hmac, alg, salt, key, pseudo_rand_key));
     329                 :            : 
     330                 :      38716 :     return S2N_SUCCESS;
     331                 :      38717 : }
     332                 :            : 
     333                 :            : static int s2n_hkdf_expand(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *pseudo_rand_key,
     334                 :            :         const struct s2n_blob *info, struct s2n_blob *output)
     335                 :     140735 : {
     336 [ #  # ][ -  + ]:     140735 :     POSIX_ENSURE_REF(hmac);
     337 [ -  + ][ #  # ]:     140735 :     POSIX_ENSURE_REF(pseudo_rand_key);
     338 [ #  # ][ -  + ]:     140735 :     POSIX_ENSURE_REF(info);
     339 [ -  + ][ #  # ]:     140735 :     POSIX_ENSURE_REF(output);
     340                 :            : 
     341                 :     140735 :     const struct s2n_hkdf_impl *hkdf_implementation = s2n_get_hkdf_implementation();
     342 [ -  + ][ #  # ]:     140735 :     POSIX_ENSURE_REF(hkdf_implementation);
     343                 :            : 
     344         [ -  + ]:     140735 :     POSIX_GUARD(hkdf_implementation->hkdf_expand(hmac, alg, pseudo_rand_key, info, output));
     345                 :            : 
     346                 :     140735 :     return S2N_SUCCESS;
     347                 :     140735 : }
     348                 :            : 
     349                 :            : int s2n_hkdf_expand_label(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *secret, const struct s2n_blob *label,
     350                 :            :         const struct s2n_blob *context, struct s2n_blob *output)
     351                 :     140735 : {
     352 [ #  # ][ -  + ]:     140735 :     POSIX_ENSURE_REF(label);
     353 [ -  + ][ #  # ]:     140735 :     POSIX_ENSURE_REF(context);
     354 [ #  # ][ -  + ]:     140735 :     POSIX_ENSURE_REF(output);
     355                 :            : 
     356                 :            :     /* Per RFC8446: 7.1, a HKDF label is a 2 byte length field, and two 1...255 byte arrays with a one byte length field each. */
     357                 :     140735 :     uint8_t hkdf_label_buf[2 + 256 + 256];
     358                 :     140735 :     struct s2n_blob hkdf_label_blob = { 0 };
     359                 :     140735 :     struct s2n_stuffer hkdf_label = { 0 };
     360                 :            : 
     361 [ -  + ][ #  # ]:     140735 :     POSIX_ENSURE_LTE(label->size, S2N_MAX_HKDF_EXPAND_LABEL_LENGTH);
     362                 :            : 
     363         [ -  + ]:     140735 :     POSIX_GUARD(s2n_blob_init(&hkdf_label_blob, hkdf_label_buf, sizeof(hkdf_label_buf)));
     364         [ -  + ]:     140735 :     POSIX_GUARD(s2n_stuffer_init(&hkdf_label, &hkdf_label_blob));
     365         [ -  + ]:     140735 :     POSIX_GUARD(s2n_stuffer_write_uint16(&hkdf_label, output->size));
     366         [ -  + ]:     140735 :     POSIX_GUARD(s2n_stuffer_write_uint8(&hkdf_label, label->size + sizeof("tls13 ") - 1));
     367         [ -  + ]:     140735 :     POSIX_GUARD(s2n_stuffer_write_str(&hkdf_label, "tls13 "));
     368         [ -  + ]:     140735 :     POSIX_GUARD(s2n_stuffer_write(&hkdf_label, label));
     369         [ -  + ]:     140735 :     POSIX_GUARD(s2n_stuffer_write_uint8(&hkdf_label, context->size));
     370         [ -  + ]:     140735 :     POSIX_GUARD(s2n_stuffer_write(&hkdf_label, context));
     371                 :            : 
     372                 :     140735 :     hkdf_label_blob.size = s2n_stuffer_data_available(&hkdf_label);
     373         [ -  + ]:     140735 :     POSIX_GUARD(s2n_hkdf_expand(hmac, alg, secret, &hkdf_label_blob, output));
     374                 :            : 
     375                 :     140735 :     return S2N_SUCCESS;
     376                 :     140735 : }
     377                 :            : 
     378                 :            : int s2n_hkdf(struct s2n_hmac_state *hmac, s2n_hmac_algorithm alg, const struct s2n_blob *salt,
     379                 :            :         const struct s2n_blob *key, const struct s2n_blob *info, struct s2n_blob *output)
     380                 :        765 : {
     381 [ -  + ][ #  # ]:        765 :     POSIX_ENSURE_REF(hmac);
     382 [ #  # ][ -  + ]:        765 :     POSIX_ENSURE_REF(salt);
     383 [ -  + ][ #  # ]:        765 :     POSIX_ENSURE_REF(key);
     384 [ -  + ][ #  # ]:        765 :     POSIX_ENSURE_REF(info);
     385 [ -  + ][ #  # ]:        765 :     POSIX_ENSURE_REF(output);
     386                 :            : 
     387                 :        765 :     const struct s2n_hkdf_impl *hkdf_implementation = s2n_get_hkdf_implementation();
     388 [ -  + ][ #  # ]:        765 :     POSIX_ENSURE_REF(hkdf_implementation);
     389                 :            : 
     390         [ +  + ]:        765 :     POSIX_GUARD(hkdf_implementation->hkdf(hmac, alg, salt, key, info, output));
     391                 :            : 
     392                 :        763 :     return S2N_SUCCESS;
     393                 :        765 : }

Generated by: LCOV version 1.14