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