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_pkey_evp.h"
17 : :
18 : : #include <openssl/evp.h>
19 : : #include <openssl/rsa.h>
20 : :
21 : : #include "crypto/s2n_evp.h"
22 : : #include "crypto/s2n_libcrypto.h"
23 : : #include "crypto/s2n_pkey.h"
24 : : #include "crypto/s2n_rsa_pss.h"
25 : : #include "error/s2n_errno.h"
26 : : #include "tls/s2n_signature_algorithms.h"
27 : : #include "utils/s2n_random.h"
28 : : #include "utils/s2n_safety.h"
29 : :
30 : : DEFINE_POINTER_CLEANUP_FUNC(EVP_PKEY_CTX *, EVP_PKEY_CTX_free);
31 : :
32 : : static S2N_RESULT s2n_evp_md_ctx_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx)
33 : 0 : {
34 : 0 : #ifdef S2N_LIBCRYPTO_SUPPORTS_EVP_MD_CTX_SET_PKEY_CTX
35 : 0 : EVP_MD_CTX_set_pkey_ctx(ctx, pctx);
36 : 0 : return S2N_RESULT_OK;
37 : : #else
38 : : RESULT_BAIL(S2N_ERR_UNIMPLEMENTED);
39 : : #endif
40 : 0 : }
41 : :
42 : : static S2N_RESULT s2n_evp_pkey_set_rsa_pss_saltlen(EVP_PKEY_CTX *pctx)
43 : 4882 : {
44 : 4882 : #if defined(S2N_LIBCRYPTO_SUPPORTS_RSA_PSS_SIGNING)
45 [ # # ][ - + ]: 4882 : RESULT_GUARD_OSSL(EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, RSA_PSS_SALTLEN_DIGEST), S2N_ERR_PKEY_CTX_INIT);
46 : 4882 : return S2N_RESULT_OK;
47 : : #else
48 : : RESULT_BAIL(S2N_ERR_RSA_PSS_NOT_SUPPORTED);
49 : : #endif
50 : 4882 : }
51 : :
52 : : static S2N_RESULT s2n_pkey_evp_validate_sig_alg(const struct s2n_pkey *key, s2n_signature_algorithm sig_alg)
53 : 3646 : {
54 [ # # ][ - + ]: 3646 : RESULT_ENSURE_REF(key);
55 : :
56 : : /* Ensure that the signature algorithm type matches the key type. */
57 : 3646 : s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN;
58 [ - + ]: 3646 : RESULT_GUARD(s2n_pkey_get_type(key->pkey, &pkey_type));
59 : 3646 : s2n_pkey_type sig_alg_type = S2N_PKEY_TYPE_UNKNOWN;
60 [ - + ]: 3646 : RESULT_GUARD(s2n_signature_algorithm_get_pkey_type(sig_alg, &sig_alg_type));
61 [ + + ][ + - ]: 3646 : RESULT_ENSURE(pkey_type == sig_alg_type, S2N_ERR_INVALID_SIGNATURE_ALGORITHM);
62 : :
63 : 3637 : return S2N_RESULT_OK;
64 : 3646 : }
65 : :
66 : : static EVP_PKEY_CTX *s2n_evp_pkey_ctx_new(EVP_PKEY *pkey, s2n_hash_algorithm hash_alg)
67 : 8056 : {
68 [ - + ][ # # ]: 8056 : PTR_ENSURE_REF(pkey);
69 : 8056 : switch (hash_alg) {
70 : 0 : #if S2N_LIBCRYPTO_SUPPORTS_PROVIDERS
71 : : /* For openssl-3.0, pkey methods will do an implicit fetch for the signing
72 : : * algorithm, which includes the hash algorithm. If using a legacy hash
73 : : * algorithm, specify the non-fips version.
74 : : */
75 [ - + ]: 0 : case S2N_HASH_MD5:
76 [ + + ]: 415 : case S2N_HASH_MD5_SHA1:
77 [ + + ]: 724 : case S2N_HASH_SHA1:
78 : 724 : return EVP_PKEY_CTX_new_from_pkey(NULL, pkey, "-fips");
79 : 0 : #endif
80 [ + + ]: 7332 : default:
81 : 7332 : return EVP_PKEY_CTX_new(pkey, NULL);
82 : 8056 : }
83 : 8056 : }
84 : :
85 : : /* Our "digest-and-sign" EVP signing logic is intended to support FIPS 140-3.
86 : : * FIPS 140-3 does not allow signing or verifying externally calculated digests
87 : : * for RSA and ECDSA verify.
88 : : * See https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/Digital-Signatures,
89 : : * and note that "component" tests only exist for ECDSA sign.
90 : : *
91 : : * In order to avoid signing externally calculated digests, we naively would
92 : : * need access to the full message to be signed at the time of signing. That's
93 : : * a problem for TLS1.2, where the client cert verify message requires signing
94 : : * every handshake message sent or received before the client cert verify message.
95 : : * To avoid storing every single handshake message in its entirety, we instead
96 : : * keep a running hash of the messages in an EVP hash state. Then, instead of
97 : : * digesting that hash state, we pass it unmodified to EVP_DigestSignFinal.
98 : : * That would normally not be allowed, since the hash state was initialized without
99 : : * a key using EVP_DigestInit instead of with a key using EVP_DigestSignInit.
100 : : * We make it work by using the EVP_MD_CTX_set_pkey_ctx method to attach a key
101 : : * to an existing hash state.
102 : : *
103 : : * All that means that "digest-and-sign" requires two things:
104 : : * - A single EVP hash state to sign. So we must not use a custom MD5_SHA1 hash,
105 : : * which doesn't produce a single hash state.
106 : : * - EVP_MD_CTX_set_pkey_ctx to exist and to behave as expected. Existence
107 : : * alone is not sufficient: the method exists in openssl-3.0-fips, but
108 : : * it cannot be used to setup a hash state for EVP_DigestSignFinal.
109 : : *
110 : : * Currently only awslc-fips meets both these requirements. New libcryptos
111 : : * should be assumed not to meet these requirements until proven otherwise.
112 : : */
113 : : static int s2n_pkey_evp_digest_and_sign(EVP_PKEY_CTX *pctx, s2n_signature_algorithm sig_alg,
114 : : struct s2n_hash_state *hash_state, struct s2n_blob *signature)
115 : 0 : {
116 [ # # ][ # # ]: 0 : POSIX_ENSURE_REF(pctx);
117 [ # # ][ # # ]: 0 : POSIX_ENSURE_REF(hash_state);
118 [ # # ][ # # ]: 0 : POSIX_ENSURE_REF(signature);
119 : :
120 : : /* Custom MD5_SHA1 involves combining separate MD5 and SHA1 hashes.
121 : : * That involves two hash states instead of the single hash state this
122 : : * method requires.
123 : : */
124 [ # # ][ # # ]: 0 : POSIX_ENSURE(!s2n_hash_use_custom_md5_sha1(), S2N_ERR_SAFETY);
125 : :
126 : : /* Not all implementations of EVP_MD_CTX_set_pkey_ctx behave as required
127 : : * by this method. Using EVP_MD_CTX_set_pkey_ctx to convert a hash initialized
128 : : * with EVP_DigestInit to one that can be finalized with EVP_DigestSignFinal
129 : : * is not entirely standard.
130 : : *
131 : : * However, this behavior is known to work with awslc-fips.
132 : : */
133 [ # # ][ # # ]: 0 : POSIX_ENSURE(s2n_libcrypto_is_awslc_fips(), S2N_ERR_SAFETY);
134 : :
135 : 0 : EVP_MD_CTX *ctx = hash_state->digest.high_level.evp.ctx;
136 [ # # ][ # # ]: 0 : POSIX_ENSURE_REF(ctx);
137 [ # # ]: 0 : POSIX_GUARD_RESULT(s2n_evp_md_ctx_set_pkey_ctx(ctx, pctx));
138 : :
139 : 0 : size_t signature_size = signature->size;
140 [ # # ][ # # ]: 0 : POSIX_GUARD_OSSL(EVP_DigestSignFinal(ctx, signature->data, &signature_size), S2N_ERR_SIGN);
141 [ # # ][ # # ]: 0 : POSIX_ENSURE(signature_size <= signature->size, S2N_ERR_SIZE_MISMATCH);
142 : 0 : signature->size = signature_size;
143 [ # # ]: 0 : POSIX_GUARD_RESULT(s2n_evp_md_ctx_set_pkey_ctx(ctx, NULL));
144 : :
145 : 0 : return S2N_SUCCESS;
146 : 0 : }
147 : :
148 : : /* See s2n_evp_digest_and_sign for more information */
149 : : static bool s2n_pkey_evp_digest_and_sign_is_required(s2n_signature_algorithm sig_alg)
150 : 8056 : {
151 [ - + ]: 8056 : if (sig_alg == S2N_SIGNATURE_MLDSA) {
152 : : /* The FIPS restrictions do not apply to ML-DSA */
153 : 0 : return false;
154 : 0 : }
155 : 8056 : return s2n_libcrypto_is_awslc_fips();
156 : 8056 : }
157 : :
158 : : /* "digest-then-sign" means that we calculate the digest for a hash state,
159 : : * then sign the digest bytes. That is not allowed by FIPS 140-3, but is allowed
160 : : * in all other cases.
161 : : */
162 : : static int s2n_pkey_evp_digest_then_sign(EVP_PKEY_CTX *pctx,
163 : : struct s2n_hash_state *hash_state, struct s2n_blob *signature)
164 : 4419 : {
165 [ # # ][ - + ]: 4419 : POSIX_ENSURE_REF(pctx);
166 [ # # ][ - + ]: 4419 : POSIX_ENSURE_REF(hash_state);
167 [ - + ][ # # ]: 4419 : POSIX_ENSURE_REF(signature);
168 : :
169 : 4419 : uint8_t digest_length = 0;
170 [ - + ]: 4419 : POSIX_GUARD(s2n_hash_digest_size(hash_state->alg, &digest_length));
171 [ - + ][ # # ]: 4419 : POSIX_ENSURE_LTE(digest_length, S2N_MAX_DIGEST_LEN);
172 : :
173 : 4419 : uint8_t digest_out[S2N_MAX_DIGEST_LEN] = { 0 };
174 [ - + ]: 4419 : POSIX_GUARD(s2n_hash_digest(hash_state, digest_out, digest_length));
175 : :
176 : 4419 : size_t signature_size = signature->size;
177 [ # # ][ - + ]: 4419 : POSIX_GUARD_OSSL(EVP_PKEY_sign(pctx, signature->data, &signature_size,
178 : 4419 : digest_out, digest_length),
179 : 4419 : S2N_ERR_SIGN);
180 [ - + ][ # # ]: 4419 : POSIX_ENSURE(signature_size <= signature->size, S2N_ERR_SIZE_MISMATCH);
181 : 4419 : signature->size = signature_size;
182 : :
183 : 4419 : return S2N_SUCCESS;
184 : 4419 : }
185 : :
186 : : int s2n_pkey_evp_sign(const struct s2n_pkey *priv, s2n_signature_algorithm sig_alg,
187 : : struct s2n_hash_state *hash_state, struct s2n_blob *signature)
188 : 4419 : {
189 [ - + ][ # # ]: 4419 : POSIX_ENSURE_REF(priv);
190 [ # # ][ - + ]: 4419 : POSIX_ENSURE_REF(hash_state);
191 : :
192 : 4419 : DEFER_CLEANUP(EVP_PKEY_CTX *pctx = s2n_evp_pkey_ctx_new(priv->pkey, hash_state->alg), EVP_PKEY_CTX_free_pointer);
193 [ # # ][ - + ]: 4419 : POSIX_ENSURE_REF(pctx);
194 [ # # ][ - + ]: 4419 : POSIX_GUARD_OSSL(EVP_PKEY_sign_init(pctx), S2N_ERR_PKEY_CTX_INIT);
195 : :
196 [ + - ]: 4419 : if (sig_alg != S2N_SIGNATURE_MLDSA) {
197 [ # # ][ - + ]: 4419 : POSIX_GUARD_OSSL(S2N_EVP_PKEY_CTX_set_signature_md(pctx, s2n_hash_alg_to_evp_md(hash_state->alg)), S2N_ERR_PKEY_CTX_INIT);
198 : 4419 : }
199 : :
200 [ + + ][ + + ]: 4419 : if (sig_alg == S2N_SIGNATURE_RSA_PSS_RSAE || sig_alg == S2N_SIGNATURE_RSA_PSS_PSS) {
201 [ - + ][ # # ]: 2844 : POSIX_GUARD_OSSL(EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING), S2N_ERR_PKEY_CTX_INIT);
202 [ - + ]: 2844 : POSIX_GUARD_RESULT(s2n_evp_pkey_set_rsa_pss_saltlen(pctx));
203 : 2844 : }
204 : :
205 [ - + ]: 4419 : if (s2n_pkey_evp_digest_and_sign_is_required(sig_alg)) {
206 [ # # ]: 0 : POSIX_GUARD(s2n_pkey_evp_digest_and_sign(pctx, sig_alg, hash_state, signature));
207 : 4419 : } else {
208 [ - + ]: 4419 : POSIX_GUARD(s2n_pkey_evp_digest_then_sign(pctx, hash_state, signature));
209 : 4419 : }
210 : :
211 : 4419 : return S2N_SUCCESS;
212 : 4419 : }
213 : :
214 : : /* See s2n_evp_digest_and_sign for more information */
215 : : static int s2n_pkey_evp_digest_and_verify(EVP_PKEY_CTX *pctx, s2n_signature_algorithm sig_alg,
216 : : struct s2n_hash_state *hash_state, struct s2n_blob *signature)
217 : 0 : {
218 [ # # ][ # # ]: 0 : POSIX_ENSURE_REF(pctx);
219 [ # # ][ # # ]: 0 : POSIX_ENSURE_REF(hash_state);
220 [ # # ][ # # ]: 0 : POSIX_ENSURE_REF(signature);
221 : :
222 : : /* See digest-and-sign requirements */
223 [ # # ][ # # ]: 0 : POSIX_ENSURE(!s2n_hash_use_custom_md5_sha1(), S2N_ERR_SAFETY);
224 [ # # ][ # # ]: 0 : POSIX_ENSURE(s2n_libcrypto_is_awslc_fips(), S2N_ERR_SAFETY);
225 : :
226 : 0 : EVP_MD_CTX *ctx = hash_state->digest.high_level.evp.ctx;
227 [ # # ][ # # ]: 0 : POSIX_ENSURE_REF(ctx);
228 [ # # ]: 0 : POSIX_GUARD_RESULT(s2n_evp_md_ctx_set_pkey_ctx(ctx, pctx));
229 : :
230 [ # # ][ # # ]: 0 : POSIX_GUARD_OSSL(EVP_DigestVerifyFinal(ctx, signature->data, signature->size), S2N_ERR_VERIFY_SIGNATURE);
231 [ # # ]: 0 : POSIX_GUARD_RESULT(s2n_evp_md_ctx_set_pkey_ctx(ctx, NULL));
232 : :
233 : 0 : return S2N_SUCCESS;
234 : 0 : }
235 : :
236 : : /* See s2n_evp_digest_then_sign for more information */
237 : : static int s2n_pkey_evp_digest_then_verify(EVP_PKEY_CTX *pctx,
238 : : struct s2n_hash_state *hash_state, struct s2n_blob *signature)
239 : 3637 : {
240 [ - + ][ # # ]: 3637 : POSIX_ENSURE_REF(pctx);
241 [ # # ][ - + ]: 3637 : POSIX_ENSURE_REF(hash_state);
242 [ - + ][ # # ]: 3637 : POSIX_ENSURE_REF(signature);
243 : :
244 : 3637 : uint8_t digest_length = 0;
245 [ - + ]: 3637 : POSIX_GUARD(s2n_hash_digest_size(hash_state->alg, &digest_length));
246 [ # # ][ - + ]: 3637 : POSIX_ENSURE_LTE(digest_length, S2N_MAX_DIGEST_LEN);
247 : :
248 : 3637 : uint8_t digest_out[S2N_MAX_DIGEST_LEN] = { 0 };
249 [ - + ]: 3637 : POSIX_GUARD(s2n_hash_digest(hash_state, digest_out, digest_length));
250 : :
251 [ + + ][ + - ]: 3637 : POSIX_GUARD_OSSL(EVP_PKEY_verify(pctx, signature->data, signature->size,
252 : 3600 : digest_out, digest_length),
253 : 3600 : S2N_ERR_VERIFY_SIGNATURE);
254 : 3600 : return S2N_SUCCESS;
255 : 3637 : }
256 : :
257 : : int s2n_pkey_evp_verify(const struct s2n_pkey *pub, s2n_signature_algorithm sig_alg,
258 : : struct s2n_hash_state *hash_state, struct s2n_blob *signature)
259 : 3646 : {
260 [ - + ][ # # ]: 3646 : POSIX_ENSURE_REF(pub);
261 [ - + ][ # # ]: 3646 : POSIX_ENSURE_REF(hash_state);
262 [ # # ][ - + ]: 3646 : POSIX_ENSURE_REF(signature);
263 [ + + ]: 3646 : POSIX_GUARD_RESULT(s2n_pkey_evp_validate_sig_alg(pub, sig_alg));
264 : :
265 : 3637 : DEFER_CLEANUP(EVP_PKEY_CTX *pctx = s2n_evp_pkey_ctx_new(pub->pkey, hash_state->alg), EVP_PKEY_CTX_free_pointer);
266 [ - + ][ # # ]: 3637 : POSIX_ENSURE_REF(pctx);
267 [ - + ][ # # ]: 3637 : POSIX_GUARD_OSSL(EVP_PKEY_verify_init(pctx), S2N_ERR_PKEY_CTX_INIT);
268 : :
269 [ + - ]: 3637 : if (sig_alg != S2N_SIGNATURE_MLDSA) {
270 [ - + ][ # # ]: 3637 : POSIX_GUARD_OSSL(S2N_EVP_PKEY_CTX_set_signature_md(pctx, s2n_hash_alg_to_evp_md(hash_state->alg)), S2N_ERR_PKEY_CTX_INIT);
271 : 3637 : }
272 : :
273 [ + + ][ + + ]: 3637 : if (sig_alg == S2N_SIGNATURE_RSA_PSS_RSAE || sig_alg == S2N_SIGNATURE_RSA_PSS_PSS) {
274 [ # # ][ - + ]: 2038 : POSIX_GUARD_OSSL(EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING), S2N_ERR_PKEY_CTX_INIT);
275 [ - + ]: 2038 : POSIX_GUARD_RESULT(s2n_evp_pkey_set_rsa_pss_saltlen(pctx));
276 : 2038 : }
277 : :
278 [ - + ]: 3637 : if (s2n_pkey_evp_digest_and_sign_is_required(sig_alg)) {
279 [ # # ]: 0 : POSIX_GUARD(s2n_pkey_evp_digest_and_verify(pctx, sig_alg, hash_state, signature));
280 : 3637 : } else {
281 [ + + ]: 3637 : POSIX_GUARD(s2n_pkey_evp_digest_then_verify(pctx, hash_state, signature));
282 : 3637 : }
283 : :
284 : 3600 : return S2N_SUCCESS;
285 : 3637 : }
286 : :
287 : : S2N_RESULT s2n_pkey_evp_size(const struct s2n_pkey *pkey, uint32_t *size_out)
288 : 7561 : {
289 [ - + ][ # # ]: 7561 : RESULT_ENSURE_REF(pkey);
290 [ - + ][ # # ]: 7561 : RESULT_ENSURE_REF(pkey->pkey);
291 [ - + ][ # # ]: 7561 : RESULT_ENSURE_REF(size_out);
292 : :
293 : 7561 : const int size = EVP_PKEY_size(pkey->pkey);
294 [ - + ][ # # ]: 7561 : RESULT_ENSURE_GT(size, 0);
295 : 7561 : *size_out = size;
296 : :
297 : 7561 : return S2N_RESULT_OK;
298 : 7561 : }
299 : :
300 : : int s2n_pkey_evp_encrypt(const struct s2n_pkey *key, struct s2n_blob *in, struct s2n_blob *out)
301 : 247 : {
302 [ - + ][ # # ]: 247 : POSIX_ENSURE_REF(key);
303 [ - + ][ # # ]: 247 : POSIX_ENSURE_REF(in);
304 [ - + ][ # # ]: 247 : POSIX_ENSURE_REF(out);
305 [ # # ][ - + ]: 247 : POSIX_ENSURE_REF(key->pkey);
306 : :
307 : 247 : s2n_pkey_type type = 0;
308 [ - + ]: 247 : POSIX_GUARD_RESULT(s2n_pkey_get_type(key->pkey, &type));
309 [ + + ][ + - ]: 247 : POSIX_ENSURE(type == S2N_PKEY_TYPE_RSA, S2N_ERR_UNIMPLEMENTED);
310 : :
311 : 245 : DEFER_CLEANUP(EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(key->pkey, NULL), EVP_PKEY_CTX_free_pointer);
312 [ - + ][ # # ]: 245 : POSIX_ENSURE_REF(pctx);
313 [ - + ][ # # ]: 245 : POSIX_GUARD_OSSL(EVP_PKEY_encrypt_init(pctx), S2N_ERR_PKEY_CTX_INIT);
314 [ - + ][ # # ]: 245 : POSIX_GUARD_OSSL(EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PADDING), S2N_ERR_PKEY_CTX_INIT);
315 : :
316 : 245 : size_t out_size = out->size;
317 [ - + ][ # # ]: 245 : POSIX_GUARD_OSSL(EVP_PKEY_encrypt(pctx, out->data, &out_size, in->data, in->size), S2N_ERR_ENCRYPT);
318 [ - + ][ # # ]: 245 : POSIX_ENSURE(out_size == out->size, S2N_ERR_SIZE_MISMATCH);
319 : :
320 : 245 : return S2N_SUCCESS;
321 : 245 : }
322 : :
323 : : int s2n_pkey_evp_decrypt(const struct s2n_pkey *key, struct s2n_blob *in, struct s2n_blob *out)
324 : 1709 : {
325 [ - + ][ # # ]: 1709 : POSIX_ENSURE_REF(key);
326 [ - + ][ # # ]: 1709 : POSIX_ENSURE_REF(in);
327 [ # # ][ - + ]: 1709 : POSIX_ENSURE_REF(out);
328 [ - + ][ # # ]: 1709 : POSIX_ENSURE_REF(key->pkey);
329 : :
330 : 1709 : s2n_pkey_type type = 0;
331 [ - + ]: 1709 : POSIX_GUARD_RESULT(s2n_pkey_get_type(key->pkey, &type));
332 [ + - ][ + + ]: 1709 : POSIX_ENSURE(type == S2N_PKEY_TYPE_RSA, S2N_ERR_UNIMPLEMENTED);
333 : :
334 : 1707 : uint32_t expected_size = 0;
335 [ - + ]: 1707 : POSIX_GUARD_RESULT(s2n_pkey_size(key, &expected_size));
336 : :
337 : : /* RSA decryption requires more output memory than the size of the final decrypted message */
338 : 1707 : struct s2n_blob buffer = { 0 };
339 : 1707 : uint8_t buffer_bytes[4096] = { 0 };
340 [ - + ]: 1707 : POSIX_GUARD(s2n_blob_init(&buffer, buffer_bytes, sizeof(buffer_bytes)));
341 [ - + ][ # # ]: 1707 : POSIX_ENSURE(out->size <= buffer.size, S2N_ERR_NOMEM);
342 [ # # ][ - + ]: 1707 : POSIX_ENSURE(expected_size <= buffer.size, S2N_ERR_NOMEM);
343 : :
344 : 1707 : DEFER_CLEANUP(EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(key->pkey, NULL), EVP_PKEY_CTX_free_pointer);
345 [ - + ][ # # ]: 1707 : POSIX_ENSURE_REF(pctx);
346 [ - + ][ # # ]: 1707 : POSIX_GUARD_OSSL(EVP_PKEY_decrypt_init(pctx), S2N_ERR_PKEY_CTX_INIT);
347 : : /* The padding is actually RSA_PKCS1_PADDING, but we'll handle the padding later */
348 [ - + ][ # # ]: 1707 : POSIX_GUARD_OSSL(EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_NO_PADDING), S2N_ERR_PKEY_CTX_INIT);
349 : :
350 : 1707 : size_t out_size = buffer.size;
351 [ - + ][ # # ]: 1707 : POSIX_GUARD_OSSL(EVP_PKEY_decrypt(pctx, buffer.data, &out_size, in->data, in->size), S2N_ERR_DECRYPT);
352 [ - + ][ # # ]: 1707 : POSIX_ENSURE(out_size == expected_size, S2N_ERR_SIZE_MISMATCH);
353 : :
354 : : /* Handle padding in constant time to avoid Bleichenbacher oracles.
355 : : * If the padding is wrong, we return random output rather than failing.
356 : : * That ensures that padding failures are treated the same as wrong outputs.
357 : : */
358 [ - + ]: 1707 : POSIX_GUARD_RESULT(s2n_get_public_random_data(out));
359 : 1707 : s2n_constant_time_pkcs1_unpad_or_dont(out->data, buffer.data, out_size, out->size);
360 : :
361 : 1707 : return S2N_SUCCESS;
362 : 1707 : }
363 : :
364 : : S2N_RESULT s2n_pkey_evp_init(struct s2n_pkey *pkey)
365 : 10786 : {
366 [ - + ][ # # ]: 10786 : RESULT_ENSURE_REF(pkey);
367 : 10786 : pkey->size = &s2n_pkey_evp_size;
368 : 10786 : pkey->sign = &s2n_pkey_evp_sign;
369 : 10786 : pkey->verify = &s2n_pkey_evp_verify;
370 : 10786 : pkey->encrypt = s2n_pkey_evp_encrypt;
371 : 10786 : pkey->decrypt = s2n_pkey_evp_decrypt;
372 : 10786 : return S2N_RESULT_OK;
373 : 10786 : }
|