LCOV - code coverage report
Current view: top level - crypto - s2n_libcrypto.c (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 53 82 64.6 %
Date: 2025-08-15 07:28:39 Functions: 12 16 75.0 %
Branches: 12 54 22.2 %

           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_libcrypto.h"
      17                 :            : 
      18                 :            : #include <openssl/crypto.h>
      19                 :            : #include <openssl/opensslv.h>
      20                 :            : #include <string.h>
      21                 :            : 
      22                 :            : #include "crypto/s2n_crypto.h"
      23                 :            : #include "crypto/s2n_fips.h"
      24                 :            : #include "crypto/s2n_openssl.h"
      25                 :            : #include "utils/s2n_safety.h"
      26                 :            : #include "utils/s2n_safety_macros.h"
      27                 :            : 
      28                 :            : /* Note: OpenSSL 1.0.2 -> 1.1.0 implemented a new API to get the version number
      29                 :            :  * and version name. We have to handle that by using old functions
      30                 :            :  * (named "SSLea*"). Newer version of OpenSSL luckily define these symbols to
      31                 :            :  * the new API. When dropping OpenSSL 1.0.2 support, we can move to the new API.
      32                 :            :  */
      33                 :            : 
      34                 :            : /* The result of SSLeay_version(SSLEAY_VERSION) for OpenSSL and AWS-LC depends on the
      35                 :            :  * version. AWS-LC and BoringSSL have consistent prefixes that can be statically asserted.
      36                 :            :  *
      37                 :            :  * https://github.com/awslabs/aws-lc/commit/8f184f5d69604cc4645bafec47c2d6d9929cb50f
      38                 :            :  * has not been pushed to the fips branch of AWS-LC. In addition, we can't
      39                 :            :  * distinguish AWS-LC fips and non-fips at pre-processing time since AWS-LC
      40                 :            :  * doesn't distribute fips-specific header files.
      41                 :            :  */
      42                 :          0 : #define EXPECTED_AWSLC_VERSION_PREFIX_OLD "BoringSSL"
      43                 :          0 : #define EXPECTED_AWSLC_VERSION_PREFIX_NEW "AWS-LC"
      44                 :            : #define EXPECTED_BORINGSSL_VERSION_PREFIX "BoringSSL"
      45                 :            : 
      46                 :            : /* https://www.openssl.org/docs/man{1.0.2, 1.1.1, 3.0}/man3/OPENSSL_VERSION_NUMBER.html
      47                 :            :  * OPENSSL_VERSION_NUMBER in hex is: MNNFFPPS major minor fix patch status.
      48                 :            :  * Bitwise: MMMMNNNNNNNNFFFFFFFFPPPPPPPPSSSS
      49                 :            :  * To not be overly restrictive, we only care about the major version.
      50                 :            :  * From OpenSSL 3.0 the "fix" part is also deprecated and is always a flat 0x00.
      51                 :            :  */
      52                 :       1090 : #define VERSION_NUMBER_MASK 0xF0000000L
      53                 :            : 
      54                 :            : /* Returns the version name of the libcrypto containing the definition that the
      55                 :            :  * symbol OpenSSL_version binded to at link-time. This can be used as
      56                 :            :  * verification at run-time that s2n linked against the expected libcrypto.
      57                 :            :  */
      58                 :            : const char *s2n_libcrypto_get_version_name(void)
      59                 :          0 : {
      60                 :          0 :     return SSLeay_version(SSLEAY_VERSION);
      61                 :          0 : }
      62                 :            : 
      63                 :            : static S2N_RESULT s2n_libcrypto_validate_expected_version_prefix(const char *expected_name_prefix)
      64                 :          0 : {
      65 [ #  # ][ #  # ]:          0 :     RESULT_ENSURE_REF(expected_name_prefix);
      66 [ #  # ][ #  # ]:          0 :     RESULT_ENSURE_REF(s2n_libcrypto_get_version_name());
      67 [ #  # ][ #  # ]:          0 :     RESULT_ENSURE_LTE(strlen(expected_name_prefix), strlen(s2n_libcrypto_get_version_name()));
      68 [ #  # ][ #  # ]:          0 :     RESULT_ENSURE(s2n_constant_time_equals((const uint8_t *) expected_name_prefix, (const uint8_t *) s2n_libcrypto_get_version_name(), (const uint32_t) strlen(expected_name_prefix)), S2N_ERR_LIBCRYPTO_VERSION_NAME_MISMATCH);
      69                 :            : 
      70                 :          0 :     return S2N_RESULT_OK;
      71                 :          0 : }
      72                 :            : 
      73                 :            : /* Compare compile-time version number with the version number of the libcrypto
      74                 :            :  * containing the definition that the symbol OpenSSL_version_num binded to at
      75                 :            :  * link-time.
      76                 :            :  *
      77                 :            :  * This is an imperfect check for AWS-LC and BoringSSL, since their version
      78                 :            :  * number is basically never incremented. However, for these we have a strong
      79                 :            :  * check through s2n_libcrypto_validate_expected_version_name(), so it is not
      80                 :            :  * of great importance.
      81                 :            :  */
      82                 :            : static S2N_RESULT s2n_libcrypto_validate_expected_version_number(void)
      83                 :        545 : {
      84                 :            : /* We mutate the version number in s2n_openssl.h when detecting Libressl. This
      85                 :            :  * value is cached by s2n_get_openssl_version(). Hence, for libressl, the
      86                 :            :  * run-time version number will always be different from what
      87                 :            :  * s2n_get_openssl_version() returns. We cater for this here by just getting
      88                 :            :  * what ever we cached instead of asking Libressl libcrypto.
      89                 :            :  */
      90                 :            : #if defined(LIBRESSL_VERSION_NUMBER)
      91                 :            :     unsigned long run_time_version_number = s2n_get_openssl_version() & VERSION_NUMBER_MASK;
      92                 :            : #else
      93                 :        545 :     unsigned long run_time_version_number = SSLeay() & VERSION_NUMBER_MASK;
      94                 :        545 : #endif
      95                 :        545 :     unsigned long compile_time_version_number = s2n_get_openssl_version() & VERSION_NUMBER_MASK;
      96 [ -  + ][ #  # ]:        545 :     RESULT_ENSURE(compile_time_version_number == run_time_version_number, S2N_ERR_LIBCRYPTO_VERSION_NUMBER_MISMATCH);
      97                 :            : 
      98                 :        545 :     return S2N_RESULT_OK;
      99                 :        545 : }
     100                 :            : 
     101                 :            : /* s2n_libcrypto_is_*() encodes the libcrypto version used at build-time.
     102                 :            :  *
     103                 :            :  * When a libcrypto-dependent branch is required, we prefer these functions
     104                 :            :  * where possible to reduce #ifs and avoid potential bugs where the header
     105                 :            :  * containing the #define is not included.
     106                 :            :  */
     107                 :            : 
     108                 :            : #if defined(OPENSSL_IS_AWSLC) && defined(OPENSSL_IS_BORINGSSL)
     109                 :            :     #error "Both OPENSSL_IS_AWSLC and OPENSSL_IS_BORINGSSL are defined at the same time!"
     110                 :            : #endif
     111                 :            : 
     112                 :            : /* Attempt to detect if the libcrypto is OpenSSL.
     113                 :            :  *
     114                 :            :  * This check should be updated if s2n-tls adds support for a new libcrypto.
     115                 :            :  *
     116                 :            :  * Since several libcrypto implementations (such as BoringSSL and AWS-LC) are
     117                 :            :  * ABI compatible forks of OpenSSL, detecting OpenSSL is done by checking the
     118                 :            :  * absence of other known libcrypto variants.
     119                 :            :  */
     120                 :            : bool s2n_libcrypto_is_openssl(void)
     121                 :       3870 : {
     122                 :       3870 :     bool is_other_libcrypto_variant =
     123 [ -  + ][ -  + ]:       3870 :             s2n_libcrypto_is_boringssl() || s2n_libcrypto_is_libressl() || s2n_libcrypto_is_awslc();
                 [ -  + ]
     124                 :            : 
     125                 :       3870 :     return !is_other_libcrypto_variant;
     126                 :       3870 : }
     127                 :            : 
     128                 :            : bool s2n_libcrypto_is_openssl_fips(void)
     129                 :       2366 : {
     130 [ +  - ][ -  + ]:       2366 :     return s2n_libcrypto_is_openssl() && s2n_is_in_fips_mode();
     131                 :       2366 : }
     132                 :            : 
     133                 :            : bool s2n_libcrypto_is_awslc()
     134                 :      12657 : {
     135                 :            : #if defined(OPENSSL_IS_AWSLC)
     136                 :            :     return true;
     137                 :            : #else
     138                 :      12657 :     return false;
     139                 :      12657 : #endif
     140                 :      12657 : }
     141                 :            : 
     142                 :            : bool s2n_libcrypto_is_awslc_fips(void)
     143                 :       8056 : {
     144 [ -  + ][ #  # ]:       8056 :     return s2n_libcrypto_is_awslc() && s2n_is_in_fips_mode();
     145                 :       8056 : }
     146                 :            : 
     147                 :            : uint64_t s2n_libcrypto_awslc_api_version(void)
     148                 :          1 : {
     149                 :            : #if defined(OPENSSL_IS_AWSLC)
     150                 :            :     return AWSLC_API_VERSION;
     151                 :            : #else
     152                 :          1 :     return 0;
     153                 :          1 : #endif
     154                 :          1 : }
     155                 :            : 
     156                 :            : bool s2n_libcrypto_is_boringssl()
     157                 :       4960 : {
     158                 :            : #if defined(OPENSSL_IS_BORINGSSL)
     159                 :            :     return true;
     160                 :            : #else
     161                 :       4960 :     return false;
     162                 :       4960 : #endif
     163                 :       4960 : }
     164                 :            : 
     165                 :            : bool s2n_libcrypto_is_libressl()
     166                 :       3872 : {
     167                 :            : #if defined(LIBRESSL_VERSION_NUMBER)
     168                 :            :     return true;
     169                 :            : #else
     170                 :       3872 :     return false;
     171                 :       3872 : #endif
     172                 :       3872 : }
     173                 :            : 
     174                 :            : /* Performs various checks to validate that the libcrypto used at compile-time
     175                 :            :  * is the same libcrypto being used at run-time.
     176                 :            :  */
     177                 :            : S2N_RESULT s2n_libcrypto_validate_runtime(void)
     178                 :        545 : {
     179                 :            :     /* Sanity check that we don't think we built against AWS-LC and BoringSSL at
     180                 :            :      * the same time.
     181                 :            :      */
     182 [ #  # ][ -  + ]:        545 :     RESULT_ENSURE_EQ(s2n_libcrypto_is_boringssl() && s2n_libcrypto_is_awslc(), false);
         [ #  # ][ -  + ]
     183                 :            : 
     184                 :            :     /* If we know the expected version name, we can validate it. */
     185         [ -  + ]:        545 :     if (s2n_libcrypto_is_awslc()) {
     186                 :          0 :         const char *expected_awslc_name_prefix = NULL;
     187                 :            :         /* For backwards compatability, also check the AWS-LC API version see
     188                 :            :          * https://github.com/awslabs/aws-lc/pull/467. When we are confident we
     189                 :            :          * don't meet anymore "old" AWS-LC libcrypto's, this API version check
     190                 :            :          * can be removed.
     191                 :            :          */
     192         [ #  # ]:          0 :         if (s2n_libcrypto_awslc_api_version() < 17) {
     193                 :          0 :             expected_awslc_name_prefix = EXPECTED_AWSLC_VERSION_PREFIX_OLD;
     194                 :          0 :         } else {
     195                 :          0 :             expected_awslc_name_prefix = EXPECTED_AWSLC_VERSION_PREFIX_NEW;
     196                 :          0 :         }
     197         [ #  # ]:          0 :         RESULT_GUARD(s2n_libcrypto_validate_expected_version_prefix(expected_awslc_name_prefix));
     198         [ -  + ]:        545 :     } else if (s2n_libcrypto_is_boringssl()) {
     199         [ #  # ]:          0 :         RESULT_GUARD(s2n_libcrypto_validate_expected_version_prefix(EXPECTED_BORINGSSL_VERSION_PREFIX));
     200                 :          0 :     }
     201                 :            : 
     202         [ -  + ]:        545 :     RESULT_GUARD(s2n_libcrypto_validate_expected_version_number());
     203                 :            : 
     204                 :        545 :     return S2N_RESULT_OK;
     205                 :        545 : }
     206                 :            : 
     207                 :            : bool s2n_libcrypto_is_interned(void)
     208                 :          0 : {
     209                 :            : #if defined(S2N_INTERN_LIBCRYPTO)
     210                 :            :     return true;
     211                 :            : #else
     212                 :          0 :     return false;
     213                 :          0 : #endif
     214                 :          0 : }
     215                 :            : 
     216                 :            : unsigned long s2n_get_openssl_version(void)
     217                 :        545 : {
     218                 :        545 :     return OPENSSL_VERSION_NUMBER;
     219                 :        545 : }
     220                 :            : 
     221                 :            : bool s2n_libcrypto_supports_flag_no_check_time()
     222                 :          8 : {
     223                 :          8 : #ifdef S2N_LIBCRYPTO_SUPPORTS_FLAG_NO_CHECK_TIME
     224                 :          8 :     return true;
     225                 :            : #else
     226                 :            :     return false;
     227                 :            : #endif
     228                 :          8 : }
     229                 :            : 
     230                 :            : bool s2n_libcrypto_supports_providers(void)
     231                 :          0 : {
     232                 :          0 : #if S2N_LIBCRYPTO_SUPPORTS_PROVIDERS
     233                 :          0 :     return true;
     234                 :            : #else
     235                 :            :     return false;
     236                 :            : #endif
     237                 :          0 : }
     238                 :            : 
     239                 :            : bool s2n_libcrypto_supports_custom_oid(void)
     240                 :          2 : {
     241                 :            : #if S2N_LIBCRYPTO_SUPPORTS_CUSTOM_OID
     242                 :            :     return true;
     243                 :            : #else
     244                 :          2 :     return false;
     245                 :          2 : #endif
     246                 :          2 : }

Generated by: LCOV version 1.14