LCOV - code coverage report
Current view: top level - crypto - s2n_pkey_evp.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 160 201 79.6 %
Date: 2025-08-15 07:28:39 Functions: 12 15 80.0 %
Branches: 101 350 28.9 %

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

Generated by: LCOV version 1.14