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