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 : }
|