Skip to content

Commit

Permalink
[ci]: Use custom library context for rc4 instead of global default co…
Browse files Browse the repository at this point in the history
…ntext (#3980)
  • Loading branch information
lrstewart committed May 5, 2023
1 parent 405a888 commit fd330d0
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 96 deletions.
7 changes: 2 additions & 5 deletions bindings/rust/s2n-tls-sys/tests/s2n_init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,8 @@ fn s2n_init_test() {
std::env::set_var("S2N_DONT_MLOCK", "1");

// try to initialize the library
s2n_init();

// make sure it was successful
let error = *s2n_errno_location();
if error != 0 {
if s2n_init() != 0 {
let error = *s2n_errno_location();
let msg = s2n_strerror_name(error);
let msg = std::ffi::CStr::from_ptr(msg);
panic!("s2n did not initialize correctly: {:?}", msg);
Expand Down
3 changes: 3 additions & 0 deletions crypto/s2n_cipher.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,6 @@ extern const struct s2n_cipher s2n_chacha20_poly1305;

extern const struct s2n_cipher s2n_tls13_aes128_gcm;
extern const struct s2n_cipher s2n_tls13_aes256_gcm;

S2N_RESULT s2n_rc4_init();
S2N_RESULT s2n_rc4_cleanup();
40 changes: 1 addition & 39 deletions crypto/s2n_libcrypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,13 @@

#include <openssl/crypto.h>
#include <openssl/opensslv.h>
#include <string.h>

#include "crypto/s2n_crypto.h"
#include "crypto/s2n_fips.h"
#include "crypto/s2n_openssl.h"
#include "utils/s2n_safety.h"
#include "utils/s2n_safety_macros.h"
#if S2N_OPENSSL_VERSION_AT_LEAST(3, 0, 0)
#include <openssl/provider.h>
#endif

#include <string.h>

/* Note: OpenSSL 1.0.2 -> 1.1.0 implemented a new API to get the version number
* and version name. We have to handle that by using old functions
Expand Down Expand Up @@ -149,40 +145,6 @@ bool s2n_libcrypto_is_libressl()
#endif
}

S2N_RESULT s2n_libcrypto_init(void)
{
#if S2N_OPENSSL_VERSION_AT_LEAST(3, 0, 0)
RESULT_ENSURE(OSSL_PROVIDER_load(NULL, "default") != NULL, S2N_ERR_OSSL_PROVIDER);
#ifdef S2N_LIBCRYPTO_SUPPORTS_EVP_RC4
/* needed to support RC4 algorithm
* https://www.openssl.org/docs/man3.0/man7/OSSL_PROVIDER-legacy.html
*/
RESULT_ENSURE(OSSL_PROVIDER_load(NULL, "legacy") != NULL, S2N_ERR_OSSL_PROVIDER);
#endif
#endif

return S2N_RESULT_OK;
}

#if S2N_OPENSSL_VERSION_AT_LEAST(3, 0, 0)
int s2n_libcrypto_cleanup_cb(OSSL_PROVIDER *provider, void *cbdata)
{
return OSSL_PROVIDER_unload(provider);
}

S2N_RESULT s2n_libcrypto_cleanup(void)
{
RESULT_GUARD_OSSL(OSSL_PROVIDER_do_all(NULL, *s2n_libcrypto_cleanup_cb, NULL), S2N_ERR_ATEXIT);

return S2N_RESULT_OK;
}
#else
S2N_RESULT s2n_libcrypto_cleanup(void)
{
return S2N_RESULT_OK;
}
#endif

/* Performs various checks to validate that the libcrypto used at compile-time
* is the same libcrypto being used at run-time.
*/
Expand Down
2 changes: 0 additions & 2 deletions crypto/s2n_libcrypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,4 @@

#include "utils/s2n_result.h"

S2N_RESULT s2n_libcrypto_init(void);
S2N_RESULT s2n_libcrypto_validate_runtime(void);
S2N_RESULT s2n_libcrypto_cleanup(void);
105 changes: 61 additions & 44 deletions crypto/s2n_stream_cipher_rc4.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,62 @@
#include "utils/s2n_blob.h"
#include "utils/s2n_safety.h"

static uint8_t s2n_stream_cipher_rc4_available()
#if S2N_OPENSSL_VERSION_AT_LEAST(3, 0, 0)
#include "openssl/provider.h"
DEFINE_POINTER_CLEANUP_FUNC(OSSL_LIB_CTX *, OSSL_LIB_CTX_free);
#endif

static EVP_CIPHER *s2n_rc4_cipher = NULL;

S2N_RESULT s2n_rc4_init()
{
/* In Openssl-3.0, RC4 is only available from the "legacy" provider,
* which is not loaded in the default library context.
*/
#if defined(S2N_LIBCRYPTO_SUPPORTS_EVP_RC4) && S2N_OPENSSL_VERSION_AT_LEAST(3, 0, 0)
DEFER_CLEANUP(OSSL_LIB_CTX *lib_ctx = OSSL_LIB_CTX_new(), OSSL_LIB_CTX_free_pointer);
RESULT_ENSURE_REF(lib_ctx);
RESULT_ENSURE_REF(OSSL_PROVIDER_load(lib_ctx, "legacy"));
s2n_rc4_cipher = EVP_CIPHER_fetch(lib_ctx, "rc4", "provider=legacy");
RESULT_ENSURE_REF(s2n_rc4_cipher);
#endif
return S2N_RESULT_OK;
}

S2N_RESULT s2n_rc4_cleanup()
{
#ifdef S2N_LIBCRYPTO_SUPPORTS_EVP_RC4
#if S2N_OPENSSL_VERSION_AT_LEAST(3, 0, 0)
EVP_CIPHER_free(s2n_rc4_cipher);
#endif
return S2N_RESULT_OK;
}

static S2N_RESULT s2n_get_rc4_cipher(const EVP_CIPHER **cipher)
{
RESULT_ENSURE_REF(cipher);
*cipher = NULL;
if (s2n_is_in_fips_mode()) {
return 0;
*cipher = NULL;
} else if (s2n_rc4_cipher) {
*cipher = s2n_rc4_cipher;
#if S2N_LIBCRYPTO_SUPPORTS_EVP_RC4
} else {
return (EVP_rc4() ? 1 : 0);
*cipher = EVP_rc4();
#endif
}
RESULT_ENSURE(*cipher, S2N_ERR_UNIMPLEMENTED);
return S2N_RESULT_OK;
}

static uint8_t s2n_stream_cipher_rc4_available()
{
const EVP_CIPHER *cipher = NULL;
if (s2n_result_is_ok(s2n_get_rc4_cipher(&cipher)) && cipher) {
return 1;
}
#else
return 0;
#endif /* S2N_LIBCRYPTO_SUPPORTS_EVP_RC4 */
}

#ifdef S2N_LIBCRYPTO_SUPPORTS_EVP_RC4
static int s2n_stream_cipher_rc4_encrypt(struct s2n_session_key *key, struct s2n_blob *in, struct s2n_blob *out)
{
POSIX_ENSURE_GTE(out->size, in->size);
Expand Down Expand Up @@ -64,17 +106,25 @@ static int s2n_stream_cipher_rc4_decrypt(struct s2n_session_key *key, struct s2n
static int s2n_stream_cipher_rc4_set_encryption_key(struct s2n_session_key *key, struct s2n_blob *in)
{
POSIX_ENSURE_EQ(in->size, 16);
POSIX_GUARD_OSSL(EVP_EncryptInit_ex(key->evp_cipher_ctx, EVP_rc4(), NULL, in->data, NULL), S2N_ERR_KEY_INIT);

return 0;
const EVP_CIPHER *evp_rc4 = NULL;
POSIX_GUARD_RESULT(s2n_get_rc4_cipher(&evp_rc4));

POSIX_GUARD_OSSL(EVP_EncryptInit_ex(key->evp_cipher_ctx, evp_rc4, NULL, in->data, NULL), S2N_ERR_KEY_INIT);

return S2N_SUCCESS;
}

static int s2n_stream_cipher_rc4_set_decryption_key(struct s2n_session_key *key, struct s2n_blob *in)
{
POSIX_ENSURE_EQ(in->size, 16);
POSIX_GUARD_OSSL(EVP_DecryptInit_ex(key->evp_cipher_ctx, EVP_rc4(), NULL, in->data, NULL), S2N_ERR_KEY_INIT);

return 0;
const EVP_CIPHER *evp_rc4 = NULL;
POSIX_GUARD_RESULT(s2n_get_rc4_cipher(&evp_rc4));

POSIX_GUARD_OSSL(EVP_DecryptInit_ex(key->evp_cipher_ctx, evp_rc4, NULL, in->data, NULL), S2N_ERR_KEY_INIT);

return S2N_SUCCESS;
}

static int s2n_stream_cipher_rc4_init(struct s2n_session_key *key)
Expand All @@ -90,39 +140,6 @@ static int s2n_stream_cipher_rc4_destroy_key(struct s2n_session_key *key)

return 0;
}
#else

static int s2n_stream_cipher_rc4_encrypt(struct s2n_session_key *key, struct s2n_blob *in, struct s2n_blob *out)
{
POSIX_BAIL(S2N_ERR_UNIMPLEMENTED);
}

static int s2n_stream_cipher_rc4_decrypt(struct s2n_session_key *key, struct s2n_blob *in, struct s2n_blob *out)
{
POSIX_BAIL(S2N_ERR_UNIMPLEMENTED);
}

static int s2n_stream_cipher_rc4_set_encryption_key(struct s2n_session_key *key, struct s2n_blob *in)
{
POSIX_BAIL(S2N_ERR_UNIMPLEMENTED);
}

static int s2n_stream_cipher_rc4_set_decryption_key(struct s2n_session_key *key, struct s2n_blob *in)
{
POSIX_BAIL(S2N_ERR_UNIMPLEMENTED);
}

static int s2n_stream_cipher_rc4_init(struct s2n_session_key *key)
{
POSIX_BAIL(S2N_ERR_UNIMPLEMENTED);
}

static int s2n_stream_cipher_rc4_destroy_key(struct s2n_session_key *key)
{
POSIX_BAIL(S2N_ERR_UNIMPLEMENTED);
}

#endif /* S2N_LIBCRYPTO_SUPPORTS_EVP_RC4 */

const struct s2n_cipher s2n_rc4 = {
.type = S2N_STREAM,
Expand Down
17 changes: 13 additions & 4 deletions tests/unit/s2n_rc4_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,22 @@ int main(int argc, char **argv)
conn->server = conn->secure;
conn->client = conn->secure;

/* Make sure that RC4 is available when expected */
#if defined(S2N_LIBCRYPTO_SUPPORTS_EVP_RC4)
if (s2n_is_in_fips_mode()) {
EXPECT_FALSE(s2n_rc4.is_available());
} else {
EXPECT_TRUE(s2n_rc4.is_available());
}
#else
EXPECT_FALSE(s2n_rc4.is_available());
#endif

/* test the RC4 cipher with a SHA1 hash */
conn->secure->cipher_suite->record_alg = &s2n_record_alg_rc4_sha;
EXPECT_SUCCESS(conn->secure->cipher_suite->record_alg->cipher->init(&conn->secure->server_key));
EXPECT_SUCCESS(conn->secure->cipher_suite->record_alg->cipher->init(&conn->secure->client_key));
if (conn->secure->cipher_suite->record_alg->cipher->is_available()) {
EXPECT_SUCCESS(conn->secure->cipher_suite->record_alg->cipher->init(&conn->secure->server_key));
EXPECT_SUCCESS(conn->secure->cipher_suite->record_alg->cipher->init(&conn->secure->client_key));
EXPECT_SUCCESS(conn->secure->cipher_suite->record_alg->cipher->set_decryption_key(&conn->secure->client_key, &key_iv));
EXPECT_SUCCESS(conn->secure->cipher_suite->record_alg->cipher->set_encryption_key(&conn->secure->server_key, &key_iv));
EXPECT_SUCCESS(s2n_hmac_init(&conn->secure->client_record_mac, S2N_HMAC_SHA1, mac_key, sizeof(mac_key)));
Expand Down Expand Up @@ -119,8 +130,6 @@ int main(int argc, char **argv)
EXPECT_SUCCESS(conn->secure->cipher_suite->record_alg->cipher->destroy_key(&conn->secure->client_key));
EXPECT_SUCCESS(s2n_connection_free(conn));
} else {
EXPECT_FAILURE_WITH_ERRNO(conn->secure->cipher_suite->record_alg->cipher->init(&conn->secure->server_key), S2N_ERR_UNIMPLEMENTED);
EXPECT_FAILURE_WITH_ERRNO(conn->secure->cipher_suite->record_alg->cipher->init(&conn->secure->client_key), S2N_ERR_UNIMPLEMENTED);
EXPECT_FAILURE_WITH_ERRNO(conn->secure->cipher_suite->record_alg->cipher->set_decryption_key(&conn->secure->client_key, &key_iv), S2N_ERR_UNIMPLEMENTED);
EXPECT_FAILURE_WITH_ERRNO(conn->secure->cipher_suite->record_alg->cipher->set_encryption_key(&conn->secure->server_key, &key_iv), S2N_ERR_UNIMPLEMENTED);
}
Expand Down
6 changes: 6 additions & 0 deletions tls/s2n_cipher_suites.c
Original file line number Diff line number Diff line change
Expand Up @@ -971,6 +971,9 @@ int s2n_crypto_disable_init(void)
/* Determines cipher suite availability and selects record algorithms */
int s2n_cipher_suites_init(void)
{
/* RC4 requires some extra setup */
POSIX_GUARD_RESULT(s2n_rc4_init());

const int num_cipher_suites = s2n_array_len(s2n_all_cipher_suites);
for (int i = 0; i < num_cipher_suites; i++) {
struct s2n_cipher_suite *cur_suite = s2n_all_cipher_suites[i];
Expand Down Expand Up @@ -1052,6 +1055,9 @@ S2N_RESULT s2n_cipher_suites_cleanup(void)
#endif
}

/* RC4 requires some extra cleanup */
RESULT_GUARD(s2n_rc4_cleanup());

return S2N_RESULT_OK;
}

Expand Down
2 changes: 0 additions & 2 deletions utils/s2n_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ int s2n_init(void)
POSIX_GUARD(s2n_mem_init());
/* Must run before any init method that calls libcrypto methods. */
POSIX_GUARD_RESULT(s2n_locking_init());
POSIX_GUARD_RESULT(s2n_libcrypto_init());
POSIX_GUARD(s2n_fips_init());
POSIX_GUARD_RESULT(s2n_rand_init());
POSIX_GUARD(s2n_cipher_suites_init());
Expand Down Expand Up @@ -100,7 +99,6 @@ static bool s2n_cleanup_atexit_impl(void)
bool cleaned_up = s2n_result_is_ok(s2n_cipher_suites_cleanup())
&& s2n_result_is_ok(s2n_rand_cleanup_thread())
&& s2n_result_is_ok(s2n_rand_cleanup())
&& s2n_result_is_ok(s2n_libcrypto_cleanup())
&& s2n_result_is_ok(s2n_locking_cleanup())
&& (s2n_mem_cleanup() == S2N_SUCCESS);

Expand Down

0 comments on commit fd330d0

Please sign in to comment.