LCOV - code coverage report
Current view: top level - crypto - s2n_hash.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 221 261 84.7 %
Date: 2025-08-15 07:28:39 Functions: 25 25 100.0 %
Branches: 142 354 40.1 %

           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_hash.h"
      17                 :            : 
      18                 :            : #include "crypto/s2n_fips.h"
      19                 :            : #include "crypto/s2n_hmac.h"
      20                 :            : #include "error/s2n_errno.h"
      21                 :            : #include "utils/s2n_safety.h"
      22                 :            : 
      23                 :            : #if S2N_LIBCRYPTO_SUPPORTS_PROVIDERS
      24                 :            : static EVP_MD *s2n_evp_mds[S2N_HASH_ALGS_COUNT] = { 0 };
      25                 :            : #else
      26                 :            : static const EVP_MD *s2n_evp_mds[S2N_HASH_ALGS_COUNT] = { 0 };
      27                 :            : #endif
      28                 :            : 
      29                 :            : bool s2n_hash_use_custom_md5_sha1()
      30                 :   15344691 : {
      31                 :   15344691 : #if defined(S2N_LIBCRYPTO_SUPPORTS_EVP_MD5_SHA1_HASH)
      32                 :   15344691 :     return false;
      33                 :            : #else
      34                 :            :     return true;
      35                 :            : #endif
      36                 :   15344691 : }
      37                 :            : 
      38                 :            : bool s2n_hash_supports_shake()
      39                 :          3 : {
      40                 :          3 : #if S2N_LIBCRYPTO_SUPPORTS_SHAKE
      41                 :          3 :     return true;
      42                 :            : #else
      43                 :            :     return false;
      44                 :            : #endif
      45                 :          3 : }
      46                 :            : 
      47                 :            : S2N_RESULT s2n_hash_algorithms_init()
      48                 :        545 : {
      49                 :        545 : #if S2N_LIBCRYPTO_SUPPORTS_PROVIDERS
      50                 :            :     /* openssl-3.0 introduced the concept of providers.
      51                 :            :      * After openssl-3.0, the old EVP_sha256()-style methods will still work,
      52                 :            :      * but may be inefficient. See
      53                 :            :      * https://docs.openssl.org/3.4/man7/ossl-guide-libcrypto-introduction/#performance
      54                 :            :      *
      55                 :            :      * Additionally, the old style methods do not support property query strings
      56                 :            :      * to guide which provider to fetch from. This is important for FIPS, where
      57                 :            :      * the default query string of "fips=yes" will need to be overridden for
      58                 :            :      * legacy algorithms.
      59                 :            :      */
      60                 :        545 :     s2n_evp_mds[S2N_HASH_MD5] = EVP_MD_fetch(NULL, "MD5", "-fips");
      61                 :        545 :     s2n_evp_mds[S2N_HASH_MD5_SHA1] = EVP_MD_fetch(NULL, "MD5-SHA1", "-fips");
      62                 :        545 :     s2n_evp_mds[S2N_HASH_SHA1] = EVP_MD_fetch(NULL, "SHA1", NULL);
      63                 :        545 :     s2n_evp_mds[S2N_HASH_SHA224] = EVP_MD_fetch(NULL, "SHA224", NULL);
      64                 :        545 :     s2n_evp_mds[S2N_HASH_SHA256] = EVP_MD_fetch(NULL, "SHA256", NULL);
      65                 :        545 :     s2n_evp_mds[S2N_HASH_SHA384] = EVP_MD_fetch(NULL, "SHA384", NULL);
      66                 :        545 :     s2n_evp_mds[S2N_HASH_SHA512] = EVP_MD_fetch(NULL, "SHA512", NULL);
      67                 :        545 :     s2n_evp_mds[S2N_HASH_SHAKE256_64] = EVP_MD_fetch(NULL, "SHAKE256", NULL);
      68                 :            : #else
      69                 :            :     s2n_evp_mds[S2N_HASH_MD5] = EVP_md5();
      70                 :            :     s2n_evp_mds[S2N_HASH_SHA1] = EVP_sha1();
      71                 :            :     s2n_evp_mds[S2N_HASH_SHA224] = EVP_sha224();
      72                 :            :     s2n_evp_mds[S2N_HASH_SHA256] = EVP_sha256();
      73                 :            :     s2n_evp_mds[S2N_HASH_SHA384] = EVP_sha384();
      74                 :            :     s2n_evp_mds[S2N_HASH_SHA512] = EVP_sha512();
      75                 :            :     #if S2N_LIBCRYPTO_SUPPORTS_SHAKE
      76                 :            :     s2n_evp_mds[S2N_HASH_SHAKE256_64] = EVP_shake256();
      77                 :            :     #endif
      78                 :            :     /* Very old libcryptos like openssl-1.0.2 do not support EVP_MD_md5_sha1().
      79                 :            :      * We work around that by manually combining MD5 and SHA1, rather than
      80                 :            :      * using the composite algorithm.
      81                 :            :      */
      82                 :            :     #if defined(S2N_LIBCRYPTO_SUPPORTS_EVP_MD5_SHA1_HASH)
      83                 :            :     s2n_evp_mds[S2N_HASH_MD5_SHA1] = EVP_md5_sha1();
      84                 :            :     #endif
      85                 :            : #endif
      86                 :        545 :     return S2N_RESULT_OK;
      87                 :        545 : }
      88                 :            : 
      89                 :            : S2N_RESULT s2n_hash_algorithms_cleanup()
      90                 :        576 : {
      91                 :        576 : #if S2N_LIBCRYPTO_SUPPORTS_PROVIDERS
      92         [ +  + ]:       5760 :     for (size_t i = 0; i < S2N_HASH_ALGS_COUNT; i++) {
      93                 :            :         /* https://docs.openssl.org/3.4/man3/EVP_DigestInit/
      94                 :            :          * > Decrements the reference count for the fetched EVP_MD structure.
      95                 :            :          * > If the reference count drops to 0 then the structure is freed.
      96                 :            :          * > If the argument is NULL, nothing is done.
      97                 :            :          */
      98                 :       5184 :         EVP_MD_free(s2n_evp_mds[i]);
      99                 :       5184 :         s2n_evp_mds[i] = NULL;
     100                 :       5184 :     }
     101                 :        576 : #endif
     102                 :        576 :     return S2N_RESULT_OK;
     103                 :        576 : }
     104                 :            : 
     105                 :            : const EVP_MD *s2n_hash_alg_to_evp_md(s2n_hash_algorithm alg)
     106                 :   25709225 : {
     107 [ -  + ][ #  # ]:   25709225 :     PTR_ENSURE_GTE(alg, 0);
     108 [ #  # ][ -  + ]:   25709225 :     PTR_ENSURE_LT(alg, S2N_HASH_ALGS_COUNT);
     109                 :   25709225 :     return s2n_evp_mds[alg];
     110                 :   25709225 : }
     111                 :            : 
     112                 :            : int s2n_hash_digest_size(s2n_hash_algorithm alg, uint8_t *out)
     113                 :   20434654 : {
     114 [ #  # ][ +  - ]:   20434654 :     POSIX_ENSURE(S2N_MEM_IS_WRITABLE_CHECK(out, sizeof(*out)), S2N_ERR_PRECONDITION_VIOLATION);
     115                 :            :     /* clang-format off */
     116                 :   20434654 :     switch (alg) {
     117         [ +  + ]:   17631419 :         case S2N_HASH_NONE:     *out = 0;                    break;
     118         [ +  + ]:      31470 :         case S2N_HASH_MD5:      *out = MD5_DIGEST_LENGTH;    break;
     119         [ +  + ]:     516578 :         case S2N_HASH_SHA1:     *out = SHA_DIGEST_LENGTH;    break;
     120         [ +  + ]:         47 :         case S2N_HASH_SHA224:   *out = SHA224_DIGEST_LENGTH; break;
     121         [ +  + ]:    2208244 :         case S2N_HASH_SHA256:   *out = SHA256_DIGEST_LENGTH; break;
     122         [ +  + ]:      45915 :         case S2N_HASH_SHA384:   *out = SHA384_DIGEST_LENGTH; break;
     123         [ +  + ]:        134 :         case S2N_HASH_SHA512:   *out = SHA512_DIGEST_LENGTH; break;
     124         [ +  + ]:        841 :         case S2N_HASH_MD5_SHA1: *out = MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH; break;
     125                 :            :         /* SHAKE digests can be variable sized, but for now we only support
     126                 :            :          * 64-byte digests to match the behavior of our existing SHA hashes.
     127                 :            :          */
     128         [ +  + ]:          6 :         case S2N_HASH_SHAKE256_64: *out = 64; break;
     129         [ -  + ]:          0 :         default:
     130         [ #  # ]:          0 :             POSIX_BAIL(S2N_ERR_HASH_INVALID_ALGORITHM);
     131                 :   20434654 :     }
     132                 :            :     /* clang-format on */
     133                 :   20434654 :     return S2N_SUCCESS;
     134                 :   20434654 : }
     135                 :            : 
     136                 :            : /* Return true if hash algorithm is available, false otherwise. */
     137                 :            : bool s2n_hash_is_available(s2n_hash_algorithm alg)
     138                 :   84509115 : {
     139         [ -  + ]:   84509115 :     switch (alg) {
     140         [ +  + ]:    3557364 :         case S2N_HASH_MD5:
     141         [ +  + ]:    7103872 :         case S2N_HASH_MD5_SHA1:
     142         [ +  + ]:   65911805 :         case S2N_HASH_NONE:
     143         [ +  + ]:   69509389 :         case S2N_HASH_SHA1:
     144         [ +  + ]:   73055500 :         case S2N_HASH_SHA224:
     145         [ +  + ]:   77391406 :         case S2N_HASH_SHA256:
     146         [ +  + ]:   80962915 :         case S2N_HASH_SHA384:
     147         [ +  + ]:   84509112 :         case S2N_HASH_SHA512:
     148                 :   84509112 :             return true;
     149         [ +  + ]:          3 :         case S2N_HASH_SHAKE256_64:
     150                 :          3 :             return s2n_hash_supports_shake();
     151         [ -  + ]:          0 :         case S2N_HASH_ALGS_COUNT:
     152                 :          0 :             return false;
     153                 :   84509115 :     }
     154                 :          0 :     return false;
     155                 :   84509115 : }
     156                 :            : 
     157                 :            : int s2n_hash_is_ready_for_input(struct s2n_hash_state *state)
     158                 :         41 : {
     159 [ -  + ][ +  - ]:         41 :     POSIX_PRECONDITION(s2n_hash_state_validate(state));
     160                 :         41 :     return state->is_ready_for_input;
     161                 :         41 : }
     162                 :            : 
     163                 :            : static int s2n_evp_hash_new(struct s2n_hash_state *state)
     164                 :    4166024 : {
     165 [ #  # ][ -  + ]:    4166024 :     POSIX_ENSURE_REF(state->digest.high_level.evp.ctx = S2N_EVP_MD_CTX_NEW());
     166         [ -  + ]:    4166024 :     if (s2n_hash_use_custom_md5_sha1()) {
     167 [ #  # ][ #  # ]:          0 :         POSIX_ENSURE_REF(state->digest.high_level.evp_md5_secondary.ctx = S2N_EVP_MD_CTX_NEW());
     168                 :          0 :     }
     169                 :    4166024 :     return S2N_SUCCESS;
     170                 :    4166024 : }
     171                 :            : 
     172                 :            : static int s2n_evp_hash_init(struct s2n_hash_state *state, s2n_hash_algorithm alg)
     173                 :   84509100 : {
     174 [ #  # ][ -  + ]:   84509100 :     POSIX_ENSURE_REF(state->digest.high_level.evp.ctx);
     175                 :            : 
     176         [ +  + ]:   84509100 :     if (alg == S2N_HASH_NONE) {
     177                 :   58807932 :         return S2N_SUCCESS;
     178                 :   58807932 :     }
     179                 :            : 
     180 [ +  + ][ -  + ]:   25701168 :     if (alg == S2N_HASH_MD5_SHA1 && s2n_hash_use_custom_md5_sha1()) {
     181 [ #  # ][ #  # ]:          0 :         POSIX_ENSURE_REF(state->digest.high_level.evp_md5_secondary.ctx);
     182 [ #  # ][ #  # ]:          0 :         POSIX_GUARD_OSSL(EVP_DigestInit_ex(state->digest.high_level.evp.ctx,
     183                 :          0 :                                  s2n_hash_alg_to_evp_md(S2N_HASH_SHA1), NULL),
     184                 :          0 :                 S2N_ERR_HASH_INIT_FAILED);
     185 [ #  # ][ #  # ]:          0 :         POSIX_GUARD_OSSL(EVP_DigestInit_ex(state->digest.high_level.evp_md5_secondary.ctx,
     186                 :          0 :                                  s2n_hash_alg_to_evp_md(S2N_HASH_MD5), NULL),
     187                 :          0 :                 S2N_ERR_HASH_INIT_FAILED);
     188                 :          0 :         return S2N_SUCCESS;
     189                 :          0 :     }
     190                 :            : 
     191                 :   25701168 :     const EVP_MD *md = s2n_hash_alg_to_evp_md(alg);
     192 [ -  + ][ #  # ]:   25701168 :     POSIX_ENSURE(md, S2N_ERR_HASH_INVALID_ALGORITHM);
     193 [ -  + ][ #  # ]:   25701168 :     POSIX_GUARD_OSSL(EVP_DigestInit_ex(state->digest.high_level.evp.ctx, md, NULL),
     194                 :   25701168 :             S2N_ERR_HASH_INIT_FAILED);
     195                 :            : 
     196                 :   25701168 :     return S2N_SUCCESS;
     197                 :   25701168 : }
     198                 :            : 
     199                 :            : static int s2n_evp_hash_update(struct s2n_hash_state *state, const void *data, uint32_t size)
     200                 :   30312858 : {
     201         [ +  + ]:   30312858 :     if (state->alg == S2N_HASH_NONE) {
     202                 :   27833695 :         return S2N_SUCCESS;
     203                 :   27833695 :     }
     204                 :            : 
     205 [ -  + ][ #  # ]:    2479163 :     POSIX_ENSURE_REF(EVP_MD_CTX_md(state->digest.high_level.evp.ctx));
     206 [ #  # ][ -  + ]:    2479163 :     POSIX_GUARD_OSSL(EVP_DigestUpdate(state->digest.high_level.evp.ctx, data, size), S2N_ERR_HASH_UPDATE_FAILED);
     207                 :            : 
     208 [ +  + ][ -  + ]:    2479163 :     if (state->alg == S2N_HASH_MD5_SHA1 && s2n_hash_use_custom_md5_sha1()) {
     209 [ #  # ][ #  # ]:          0 :         POSIX_ENSURE_REF(EVP_MD_CTX_md(state->digest.high_level.evp_md5_secondary.ctx));
     210 [ #  # ][ #  # ]:          0 :         POSIX_GUARD_OSSL(EVP_DigestUpdate(state->digest.high_level.evp_md5_secondary.ctx, data, size), S2N_ERR_HASH_UPDATE_FAILED);
     211                 :          0 :     }
     212                 :            : 
     213                 :    2479163 :     return S2N_SUCCESS;
     214                 :    2479163 : }
     215                 :            : 
     216                 :            : static int s2n_evp_hash_digest(struct s2n_hash_state *state, void *out, uint32_t size)
     217                 :    1039249 : {
     218                 :    1039249 :     unsigned int digest_size = size;
     219                 :    1039249 :     uint8_t expected_digest_size = 0;
     220         [ -  + ]:    1039249 :     POSIX_GUARD(s2n_hash_digest_size(state->alg, &expected_digest_size));
     221 [ -  + ][ #  # ]:    1039249 :     POSIX_ENSURE_EQ(digest_size, expected_digest_size);
     222                 :            : 
     223         [ +  + ]:    1039249 :     if (state->alg == S2N_HASH_NONE) {
     224                 :     100704 :         return S2N_SUCCESS;
     225                 :     100704 :     }
     226                 :            : 
     227 [ #  # ][ -  + ]:     938545 :     POSIX_ENSURE_REF(EVP_MD_CTX_md(state->digest.high_level.evp.ctx));
     228                 :            : 
     229 [ +  + ][ -  + ]:     938545 :     if (state->alg == S2N_HASH_MD5_SHA1 && s2n_hash_use_custom_md5_sha1()) {
     230 [ #  # ][ #  # ]:          0 :         POSIX_ENSURE_REF(EVP_MD_CTX_md(state->digest.high_level.evp_md5_secondary.ctx));
     231                 :            : 
     232                 :          0 :         uint8_t sha1_digest_size = 0;
     233         [ #  # ]:          0 :         POSIX_GUARD(s2n_hash_digest_size(S2N_HASH_SHA1, &sha1_digest_size));
     234                 :            : 
     235                 :          0 :         unsigned int sha1_primary_digest_size = sha1_digest_size;
     236                 :          0 :         unsigned int md5_secondary_digest_size = digest_size - sha1_primary_digest_size;
     237                 :            : 
     238 [ #  # ][ #  # ]:          0 :         POSIX_ENSURE(EVP_MD_CTX_size(state->digest.high_level.evp.ctx) <= sha1_digest_size, S2N_ERR_HASH_DIGEST_FAILED);
     239 [ #  # ][ #  # ]:          0 :         POSIX_ENSURE((size_t) EVP_MD_CTX_size(state->digest.high_level.evp_md5_secondary.ctx) <= md5_secondary_digest_size, S2N_ERR_HASH_DIGEST_FAILED);
     240                 :            : 
     241 [ #  # ][ #  # ]:          0 :         POSIX_GUARD_OSSL(EVP_DigestFinal_ex(state->digest.high_level.evp.ctx, ((uint8_t *) out) + MD5_DIGEST_LENGTH, &sha1_primary_digest_size), S2N_ERR_HASH_DIGEST_FAILED);
     242 [ #  # ][ #  # ]:          0 :         POSIX_GUARD_OSSL(EVP_DigestFinal_ex(state->digest.high_level.evp_md5_secondary.ctx, out, &md5_secondary_digest_size), S2N_ERR_HASH_DIGEST_FAILED);
     243                 :          0 :         return S2N_SUCCESS;
     244                 :          0 :     }
     245                 :            : 
     246         [ +  + ]:     938545 :     if (state->alg == S2N_HASH_SHAKE256_64) {
     247                 :          4 : #if S2N_LIBCRYPTO_SUPPORTS_SHAKE
     248                 :            :         /* "XOF" stands for "extendable-output functions", and indicates a hash algorithm
     249                 :            :          * like SHAKE that can produce digests of any size. When using an XOF algorithm,
     250                 :            :          * EVP_DigestFinalXOF should be used instead of EVP_DigestFinal_ex.
     251                 :            :          * Calling the wrong digest method will error.
     252                 :            :          */
     253 [ #  # ][ -  + ]:          4 :         POSIX_GUARD_OSSL(EVP_DigestFinalXOF(state->digest.high_level.evp.ctx, out, digest_size),
     254                 :          4 :                 S2N_ERR_HASH_DIGEST_FAILED);
     255                 :          4 :         return S2N_SUCCESS;
     256                 :            : #else
     257                 :            :         POSIX_BAIL(S2N_ERR_HASH_INVALID_ALGORITHM);
     258                 :            : #endif
     259                 :          4 :     }
     260                 :            : 
     261 [ -  + ][ #  # ]:     938541 :     POSIX_ENSURE((size_t) EVP_MD_CTX_size(state->digest.high_level.evp.ctx) <= digest_size, S2N_ERR_HASH_DIGEST_FAILED);
     262 [ -  + ][ #  # ]:     938541 :     POSIX_GUARD_OSSL(EVP_DigestFinal_ex(state->digest.high_level.evp.ctx, out, &digest_size), S2N_ERR_HASH_DIGEST_FAILED);
     263                 :     938541 :     return S2N_SUCCESS;
     264                 :     938541 : }
     265                 :            : 
     266                 :            : static int s2n_evp_hash_copy(struct s2n_hash_state *to, struct s2n_hash_state *from)
     267                 :   18483535 : {
     268         [ +  + ]:   18483535 :     if (from->alg == S2N_HASH_NONE) {
     269                 :   17345731 :         return S2N_SUCCESS;
     270                 :   17345731 :     }
     271                 :            : 
     272 [ #  # ][ -  + ]:    1137804 :     POSIX_ENSURE_REF(to->digest.high_level.evp.ctx);
     273 [ #  # ][ -  + ]:    1137804 :     POSIX_GUARD_OSSL(EVP_MD_CTX_copy_ex(to->digest.high_level.evp.ctx, from->digest.high_level.evp.ctx), S2N_ERR_HASH_COPY_FAILED);
     274                 :            : 
     275 [ +  + ][ -  + ]:    1137804 :     if (from->alg == S2N_HASH_MD5_SHA1 && s2n_hash_use_custom_md5_sha1()) {
     276 [ #  # ][ #  # ]:          0 :         POSIX_ENSURE_REF(to->digest.high_level.evp_md5_secondary.ctx);
     277 [ #  # ][ #  # ]:          0 :         POSIX_GUARD_OSSL(EVP_MD_CTX_copy_ex(to->digest.high_level.evp_md5_secondary.ctx, from->digest.high_level.evp_md5_secondary.ctx), S2N_ERR_HASH_COPY_FAILED);
     278                 :          0 :     }
     279                 :            : 
     280                 :    1137804 :     return S2N_SUCCESS;
     281                 :    1137804 : }
     282                 :            : 
     283                 :            : static int s2n_evp_hash_reset(struct s2n_hash_state *state)
     284                 :   27409471 : {
     285 [ #  # ][ -  + ]:   27409471 :     POSIX_GUARD_OSSL(S2N_EVP_MD_CTX_RESET(state->digest.high_level.evp.ctx), S2N_ERR_HASH_WIPE_FAILED);
     286 [ +  + ][ -  + ]:   27409471 :     if (state->alg == S2N_HASH_MD5_SHA1 && s2n_hash_use_custom_md5_sha1()) {
     287 [ #  # ][ #  # ]:          0 :         POSIX_GUARD_OSSL(S2N_EVP_MD_CTX_RESET(state->digest.high_level.evp_md5_secondary.ctx), S2N_ERR_HASH_WIPE_FAILED);
     288                 :          0 :     }
     289                 :   27409471 :     return S2N_SUCCESS;
     290                 :   27409471 : }
     291                 :            : 
     292                 :            : static int s2n_evp_hash_free(struct s2n_hash_state *state)
     293                 :    4166022 : {
     294                 :    4166022 :     S2N_EVP_MD_CTX_FREE(state->digest.high_level.evp.ctx);
     295                 :    4166022 :     state->digest.high_level.evp.ctx = NULL;
     296         [ -  + ]:    4166022 :     if (s2n_hash_use_custom_md5_sha1()) {
     297                 :          0 :         S2N_EVP_MD_CTX_FREE(state->digest.high_level.evp_md5_secondary.ctx);
     298                 :          0 :         state->digest.high_level.evp_md5_secondary.ctx = NULL;
     299                 :          0 :     }
     300                 :    4166022 :     return S2N_SUCCESS;
     301                 :    4166022 : }
     302                 :            : 
     303                 :            : static const struct s2n_hash s2n_evp_hash = {
     304                 :            :     .alloc = &s2n_evp_hash_new,
     305                 :            :     .init = &s2n_evp_hash_init,
     306                 :            :     .update = &s2n_evp_hash_update,
     307                 :            :     .digest = &s2n_evp_hash_digest,
     308                 :            :     .copy = &s2n_evp_hash_copy,
     309                 :            :     .reset = &s2n_evp_hash_reset,
     310                 :            :     .free = &s2n_evp_hash_free,
     311                 :            : };
     312                 :            : 
     313                 :            : /* This method looks unnecessary, but our CBMC proofs are
     314                 :            :  * dependent on it. Search for:
     315                 :            :  * __CPROVER_file_local_s2n_hash_c_s2n_hash_set_evp_impl
     316                 :            :  */
     317                 :            : static void s2n_hash_set_evp_impl(struct s2n_hash_state *state)
     318                 :    4166024 : {
     319                 :    4166024 :     state->hash_impl = &s2n_evp_hash;
     320                 :    4166024 : }
     321                 :            : 
     322                 :            : int s2n_hash_new(struct s2n_hash_state *state)
     323                 :    4166024 : {
     324 [ -  + ][ #  # ]:    4166024 :     POSIX_ENSURE_REF(state);
     325                 :            : 
     326                 :    4166024 :     s2n_hash_set_evp_impl(state);
     327 [ -  + ][ #  # ]:    4166024 :     POSIX_ENSURE_REF(state->hash_impl->alloc);
     328         [ -  + ]:    4166024 :     POSIX_GUARD(state->hash_impl->alloc(state));
     329                 :            : 
     330                 :    4166024 :     state->alg = S2N_HASH_NONE;
     331                 :    4166024 :     state->is_ready_for_input = 0;
     332                 :    4166024 :     state->currently_in_hash = 0;
     333                 :    4166024 :     return S2N_SUCCESS;
     334                 :    4166024 : }
     335                 :            : 
     336                 :            : S2N_RESULT s2n_hash_state_validate(struct s2n_hash_state *state)
     337                 :  168573024 : {
     338 [ -  + ][ #  # ]:  168573024 :     RESULT_ENSURE_REF(state);
     339                 :  168573024 :     return S2N_RESULT_OK;
     340                 :  168573024 : }
     341                 :            : 
     342                 :            : int s2n_hash_init(struct s2n_hash_state *state, s2n_hash_algorithm alg)
     343                 :   84509101 : {
     344 [ -  + ][ #  # ]:   84509101 :     POSIX_ENSURE_REF(state);
     345 [ #  # ][ -  + ]:   84509101 :     POSIX_ENSURE(s2n_hash_is_available(alg), S2N_ERR_HASH_INVALID_ALGORITHM);
     346                 :            : 
     347 [ -  + ][ #  # ]:   84509101 :     POSIX_ENSURE_REF(state->hash_impl);
     348 [ #  # ][ -  + ]:   84509101 :     POSIX_ENSURE_REF(state->hash_impl->init);
     349         [ -  + ]:   84509101 :     POSIX_GUARD(state->hash_impl->init(state, alg));
     350                 :            : 
     351                 :   84509101 :     state->alg = alg;
     352                 :   84509101 :     state->is_ready_for_input = 1;
     353                 :   84509101 :     state->currently_in_hash = 0;
     354                 :   84509101 :     return S2N_SUCCESS;
     355                 :   84509101 : }
     356                 :            : 
     357                 :            : int s2n_hash_update(struct s2n_hash_state *state, const void *data, uint32_t size)
     358                 :   30312857 : {
     359 [ -  + ][ +  - ]:   30312857 :     POSIX_PRECONDITION(s2n_hash_state_validate(state));
     360 [ #  # ][ +  - ]:   30312857 :     POSIX_ENSURE(S2N_MEM_IS_READABLE(data, size), S2N_ERR_PRECONDITION_VIOLATION);
                 [ +  + ]
     361 [ -  + ][ #  # ]:   30312857 :     POSIX_ENSURE(state->is_ready_for_input, S2N_ERR_HASH_NOT_READY);
     362                 :            : 
     363 [ -  + ][ #  # ]:   30312857 :     POSIX_ENSURE_REF(state->hash_impl);
     364 [ -  + ][ #  # ]:   30312857 :     POSIX_ENSURE_REF(state->hash_impl->update);
     365         [ -  + ]:   30312857 :     POSIX_GUARD(state->hash_impl->update(state, data, size));
     366                 :            : 
     367 [ #  # ][ -  + ]:   30312857 :     POSIX_ENSURE(size <= (UINT64_MAX - state->currently_in_hash), S2N_ERR_INTEGER_OVERFLOW);
     368                 :   30312857 :     state->currently_in_hash += size;
     369                 :   30312857 :     return S2N_SUCCESS;
     370                 :   30312857 : }
     371                 :            : 
     372                 :            : int s2n_hash_digest(struct s2n_hash_state *state, void *out, uint32_t size)
     373                 :    1039257 : {
     374 [ -  + ][ +  - ]:    1039257 :     POSIX_PRECONDITION(s2n_hash_state_validate(state));
     375 [ #  # ][ +  - ]:    1039257 :     POSIX_ENSURE(S2N_MEM_IS_READABLE(out, size), S2N_ERR_PRECONDITION_VIOLATION);
                 [ +  + ]
     376 [ +  - ][ +  + ]:    1039257 :     POSIX_ENSURE(state->is_ready_for_input, S2N_ERR_HASH_NOT_READY);
     377                 :            : 
     378 [ #  # ][ -  + ]:    1039249 :     POSIX_ENSURE_REF(state->hash_impl);
     379 [ #  # ][ -  + ]:    1039249 :     POSIX_ENSURE_REF(state->hash_impl->digest);
     380         [ -  + ]:    1039249 :     POSIX_GUARD(state->hash_impl->digest(state, out, size));
     381                 :            : 
     382                 :    1039249 :     state->currently_in_hash = 0;
     383                 :    1039249 :     state->is_ready_for_input = 0;
     384                 :    1039249 :     return S2N_SUCCESS;
     385                 :    1039249 : }
     386                 :            : 
     387                 :            : int s2n_hash_copy(struct s2n_hash_state *to, struct s2n_hash_state *from)
     388                 :   18483534 : {
     389 [ -  + ][ +  + ]:   18483534 :     POSIX_PRECONDITION(s2n_hash_state_validate(to));
     390 [ -  + ][ +  + ]:   18483534 :     POSIX_PRECONDITION(s2n_hash_state_validate(from));
     391                 :            : 
     392 [ #  # ][ -  + ]:   18483534 :     POSIX_ENSURE_REF(from->hash_impl);
     393 [ -  + ][ #  # ]:   18483534 :     POSIX_ENSURE_REF(from->hash_impl->copy);
     394         [ -  + ]:   18483534 :     POSIX_GUARD(from->hash_impl->copy(to, from));
     395                 :            : 
     396                 :   18483534 :     to->hash_impl = from->hash_impl;
     397                 :   18483534 :     to->alg = from->alg;
     398                 :   18483534 :     to->is_ready_for_input = from->is_ready_for_input;
     399                 :   18483534 :     to->currently_in_hash = from->currently_in_hash;
     400                 :   18483534 :     return S2N_SUCCESS;
     401                 :   18483534 : }
     402                 :            : 
     403                 :            : int s2n_hash_reset(struct s2n_hash_state *state)
     404                 :   27409471 : {
     405 [ -  + ][ #  # ]:   27409471 :     POSIX_ENSURE_REF(state);
     406 [ -  + ][ #  # ]:   27409471 :     POSIX_ENSURE_REF(state->hash_impl);
     407 [ -  + ][ #  # ]:   27409471 :     POSIX_ENSURE_REF(state->hash_impl->reset);
     408         [ -  + ]:   27409471 :     POSIX_GUARD(state->hash_impl->reset(state));
     409         [ -  + ]:   27409471 :     POSIX_GUARD(s2n_hash_init(state, state->alg));
     410                 :   27409471 :     return S2N_SUCCESS;
     411                 :   27409471 : }
     412                 :            : 
     413                 :            : int s2n_hash_free(struct s2n_hash_state *state)
     414                 :    4166022 : {
     415         [ -  + ]:    4166022 :     if (state == NULL) {
     416                 :          0 :         return S2N_SUCCESS;
     417                 :          0 :     }
     418                 :            : 
     419 [ #  # ][ -  + ]:    4166022 :     POSIX_ENSURE_REF(state->hash_impl);
     420 [ #  # ][ -  + ]:    4166022 :     POSIX_ENSURE_REF(state->hash_impl->free);
     421         [ -  + ]:    4166022 :     POSIX_GUARD(state->hash_impl->free(state));
     422                 :            : 
     423                 :    4166022 :     state->alg = S2N_HASH_NONE;
     424                 :    4166022 :     state->is_ready_for_input = 0;
     425                 :    4166022 :     state->currently_in_hash = 0;
     426                 :    4166022 :     return S2N_SUCCESS;
     427                 :    4166022 : }
     428                 :            : 
     429                 :            : int s2n_hash_get_currently_in_hash_total(struct s2n_hash_state *state, uint64_t *out)
     430                 :   17957311 : {
     431 [ -  + ][ +  - ]:   17957311 :     POSIX_PRECONDITION(s2n_hash_state_validate(state));
     432 [ #  # ][ +  - ]:   17957311 :     POSIX_ENSURE(S2N_MEM_IS_WRITABLE_CHECK(out, sizeof(*out)), S2N_ERR_PRECONDITION_VIOLATION);
     433 [ +  + ][ +  - ]:   17957311 :     POSIX_ENSURE(state->is_ready_for_input, S2N_ERR_HASH_NOT_READY);
     434                 :   17957296 :     *out = state->currently_in_hash;
     435                 :   17957296 :     return S2N_SUCCESS;
     436                 :   17957311 : }

Generated by: LCOV version 1.14