Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add s2n_libcrypto_is_openssl helper, docs, fix test #4930

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions crypto/s2n_fips.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,24 @@

static bool s2n_fips_mode_enabled = false;

/* FIPS mode can be checked if OpenSSL was configured and built for FIPS which then defines OPENSSL_FIPS.
/* Check if the linked libcrypto has FIPS mode enabled.
*
* AWS-LC always defines FIPS_mode() that you can call and check what the library was built with. It does not define
* a public OPENSSL_FIPS/AWSLC_FIPS macro that we can (or need to) check here
* This method indicates the state of the libcrypto, NOT the state
* of s2n-tls and should ONLY be called during library initialization (i.e.
* s2n_init()). For example, if s2n-tls is using Openssl and FIPS_mode_set(1)
* is called after s2n_init() is called, then this method will return true
* while s2n_is_in_fips_mode() will return false and s2n-tls will not operate
* in FIPS mode.
*
* Safeguard with macro's, for example because Libressl dosn't define
* FIPS_mode() by default.
* For AWS-LC, the FIPS_mode() method is always defined. If AWS-LC was built to
* support FIPS, FIPS_mode() always returns 1.
*
* Note: FIPS_mode() does not change the FIPS state of libcrypto. This only returns the current state. Applications
* using s2n must call FIPS_mode_set(1) prior to s2n_init.
* */
* For OpenSSL, OPENSSL_FIPS is defined if the libcrypto was built to support
* FIPS. The FIPS_mode() method is only present if OPENSSL_FIPS is defined, and
* only returns 1 if FIPS_mode_set(1) was used to enable FIPS mode.
* Applications wanting to enable FIPS mode with OpenSSL must call
* FIPS_mode_set(1) prior to calling s2n_init().
*/
bool s2n_libcrypto_is_fips(void)
{
#if defined(OPENSSL_FIPS) || defined(OPENSSL_IS_AWSLC)
Expand Down
1 change: 0 additions & 1 deletion crypto/s2n_fips.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@

int s2n_fips_init(void);
bool s2n_is_in_fips_mode(void);
bool s2n_libcrypto_is_fips(void);

struct s2n_cipher_suite;
S2N_RESULT s2n_fips_validate_cipher_suite(const struct s2n_cipher_suite *cipher_suite, bool *valid);
Expand Down
24 changes: 20 additions & 4 deletions crypto/s2n_libcrypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,16 +99,32 @@ static S2N_RESULT s2n_libcrypto_validate_expected_version_number(void)
}

/* s2n_libcrypto_is_*() encodes the libcrypto version used at build-time.
* Currently only captures AWS-LC and BoringSSL. When a libcrypto-dependent
* branch is required, we prefer these functions where possible to reduce
# #ifs and avoid potential bugs where the header containing the #define is not
* included.
*
* When a libcrypto-dependent branch is required, we prefer these functions
* where possible to reduce #ifs and avoid potential bugs where the header
* containing the #define is not included.
*/

#if defined(OPENSSL_IS_AWSLC) && defined(OPENSSL_IS_BORINGSSL)
#error "Both OPENSSL_IS_AWSLC and OPENSSL_IS_BORINGSSL are defined at the same time!"
#endif

/* Attempt to detect if the libcrypto is OpenSSL.
*
* This check should be updated if s2n-tls adds support for a new libcrypto.
*
* Since several libcrypto implementations (such as BoringSSL and AWS-LC) are
* ABI compatible forks of OpenSSL, detecting OpenSSL is done by checking the
* absence of other known libcrypto variants.
*/
bool s2n_libcrypto_is_openssl()
{
bool is_other_libcrypto_variant =
s2n_libcrypto_is_boringssl() || s2n_libcrypto_is_libressl() || s2n_libcrypto_is_awslc();

return !is_other_libcrypto_variant;
}

bool s2n_libcrypto_is_awslc()
{
#if defined(OPENSSL_IS_AWSLC)
Expand Down
1 change: 1 addition & 0 deletions crypto/s2n_openssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
#define S2N_LIBCRYPTO_SUPPORTS_CUSTOM_RAND 0
#endif

bool s2n_libcrypto_is_openssl();
bool s2n_libcrypto_is_awslc();
bool s2n_libcrypto_is_boringssl();
bool s2n_libcrypto_is_libressl();
46 changes: 46 additions & 0 deletions tests/unit/s2n_build_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,43 @@ S2N_RESULT s2n_test_lowercase_copy(const char *input, char *destination, size_t
return S2N_RESULT_OK;
}

S2N_RESULT s2n_check_supported_libcrypto(const char *s2n_libcrypto)
{
RESULT_ENSURE_REF(s2n_libcrypto);

/* List of supported libcrypto variants we test with */
const struct {
const char *libcrypto;
bool is_openssl;
} supported_libcrypto[] = {
{ .libcrypto = "awslc", .is_openssl = false },
{ .libcrypto = "awslc-fips", .is_openssl = false },
{ .libcrypto = "awslc-fips-2022", .is_openssl = false },
{ .libcrypto = "boringssl", .is_openssl = false },
{ .libcrypto = "libressl", .is_openssl = false },
{ .libcrypto = "openssl-1.0.2", .is_openssl = true },
{ .libcrypto = "openssl-1.0.2-fips", .is_openssl = true },
{ .libcrypto = "openssl-1.1.1", .is_openssl = true },
{ .libcrypto = "openssl-3.0", .is_openssl = true },
};

for (size_t i = 0; i < s2n_array_len(supported_libcrypto); i++) {
/* The linked libcryto is one of the known supported libcrypto variants */
if (strcmp(s2n_libcrypto, supported_libcrypto[i].libcrypto) == 0) {
if (supported_libcrypto[i].is_openssl) {
EXPECT_TRUE(s2n_libcrypto_is_openssl());
} else {
EXPECT_FALSE(s2n_libcrypto_is_openssl());
}

return S2N_RESULT_OK;
}
}

/* Testing with an unexpected libcrypto. */
return S2N_RESULT_ERROR;
}

int main()
{
BEGIN_TEST();
Expand Down Expand Up @@ -131,6 +168,15 @@ int main()
}
};

/* Ensure we are testing with supported libcryto variants.
*
* We need to update s2n_libcrypto_is_openssl() when adding support
* for a new libcrypto.
*/
{
EXPECT_OK(s2n_check_supported_libcrypto(s2n_libcrypto));
};

END_TEST();
return 0;
}
24 changes: 20 additions & 4 deletions tests/unit/s2n_openssl_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,31 @@ int main(int argc, char** argv)
END_TEST();
}

if (strcmp(env_libcrypto, "boringssl") == 0) {
/* Confirm "S2N_LIBCRYPTO" env variable matches the linked libcrypto. */
if (strstr(env_libcrypto, "awslc") != NULL) {
EXPECT_TRUE(s2n_libcrypto_is_awslc());
EXPECT_FALSE(s2n_libcrypto_is_boringssl());
EXPECT_FALSE(s2n_libcrypto_is_libressl());
EXPECT_FALSE(s2n_libcrypto_is_openssl());
} else if (strcmp(env_libcrypto, "boringssl") == 0) {
EXPECT_FALSE(s2n_libcrypto_is_awslc());
EXPECT_TRUE(s2n_libcrypto_is_boringssl());
} else if (strstr(env_libcrypto, "awslc") != NULL) {
EXPECT_TRUE(s2n_libcrypto_is_awslc());
EXPECT_FALSE(s2n_libcrypto_is_libressl());
EXPECT_FALSE(s2n_libcrypto_is_openssl());
} else if (strcmp(env_libcrypto, "libressl") == 0) {
EXPECT_FALSE(s2n_libcrypto_is_awslc());
EXPECT_FALSE(s2n_libcrypto_is_boringssl());
} else {
EXPECT_TRUE(s2n_libcrypto_is_libressl());
EXPECT_FALSE(s2n_libcrypto_is_openssl());
} else if (strstr(env_libcrypto, "openssl") != NULL) {
EXPECT_FALSE(s2n_libcrypto_is_awslc());
EXPECT_FALSE(s2n_libcrypto_is_boringssl());
EXPECT_FALSE(s2n_libcrypto_is_libressl());
EXPECT_TRUE(s2n_libcrypto_is_openssl());
} else if (strcmp(env_libcrypto, "default") == 0) {
/* running with the default libcrypto on path */
} else {
FAIL_MSG("Testing with an unexpected libcrypto.");
}

END_TEST();
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/s2n_pq_kem_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ int main()

#if defined(OPENSSL_IS_AWSLC) && defined(AWSLC_API_VERSION)
/* If using non-FIPS AWS-LC >= v1.6 (API vers. 21), expect Kyber512 KEM from AWS-LC */
if (!s2n_libcrypto_is_fips() && AWSLC_API_VERSION >= 21) {
if (!s2n_is_in_fips_mode() && AWSLC_API_VERSION >= 21) {
EXPECT_TRUE(s2n_libcrypto_supports_evp_kem());
}
#endif
Expand Down
3 changes: 3 additions & 0 deletions utils/s2n_random.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@
#include <errno.h>
#include <limits.h>
#include <openssl/engine.h>
/* LibreSSL requires <openssl/rand.h> include.
* https://github.com/aws/s2n-tls/issues/153#issuecomment-129651643
*/
#include <openssl/rand.h>
#include <pthread.h>
#include <stdint.h>
Expand Down
Loading