Skip to content

Commit fd330d0

Browse files
authored
[ci]: Use custom library context for rc4 instead of global default context (#3980)
1 parent 405a888 commit fd330d0

File tree

8 files changed

+86
-96
lines changed

8 files changed

+86
-96
lines changed

bindings/rust/s2n-tls-sys/tests/s2n_init.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,8 @@ fn s2n_init_test() {
1010
std::env::set_var("S2N_DONT_MLOCK", "1");
1111

1212
// try to initialize the library
13-
s2n_init();
14-
15-
// make sure it was successful
16-
let error = *s2n_errno_location();
17-
if error != 0 {
13+
if s2n_init() != 0 {
14+
let error = *s2n_errno_location();
1815
let msg = s2n_strerror_name(error);
1916
let msg = std::ffi::CStr::from_ptr(msg);
2017
panic!("s2n did not initialize correctly: {:?}", msg);

crypto/s2n_cipher.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,3 +107,6 @@ extern const struct s2n_cipher s2n_chacha20_poly1305;
107107

108108
extern const struct s2n_cipher s2n_tls13_aes128_gcm;
109109
extern const struct s2n_cipher s2n_tls13_aes256_gcm;
110+
111+
S2N_RESULT s2n_rc4_init();
112+
S2N_RESULT s2n_rc4_cleanup();

crypto/s2n_libcrypto.c

Lines changed: 1 addition & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,13 @@
1717

1818
#include <openssl/crypto.h>
1919
#include <openssl/opensslv.h>
20+
#include <string.h>
2021

2122
#include "crypto/s2n_crypto.h"
2223
#include "crypto/s2n_fips.h"
2324
#include "crypto/s2n_openssl.h"
2425
#include "utils/s2n_safety.h"
2526
#include "utils/s2n_safety_macros.h"
26-
#if S2N_OPENSSL_VERSION_AT_LEAST(3, 0, 0)
27-
#include <openssl/provider.h>
28-
#endif
29-
30-
#include <string.h>
3127

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

152-
S2N_RESULT s2n_libcrypto_init(void)
153-
{
154-
#if S2N_OPENSSL_VERSION_AT_LEAST(3, 0, 0)
155-
RESULT_ENSURE(OSSL_PROVIDER_load(NULL, "default") != NULL, S2N_ERR_OSSL_PROVIDER);
156-
#ifdef S2N_LIBCRYPTO_SUPPORTS_EVP_RC4
157-
/* needed to support RC4 algorithm
158-
* https://www.openssl.org/docs/man3.0/man7/OSSL_PROVIDER-legacy.html
159-
*/
160-
RESULT_ENSURE(OSSL_PROVIDER_load(NULL, "legacy") != NULL, S2N_ERR_OSSL_PROVIDER);
161-
#endif
162-
#endif
163-
164-
return S2N_RESULT_OK;
165-
}
166-
167-
#if S2N_OPENSSL_VERSION_AT_LEAST(3, 0, 0)
168-
int s2n_libcrypto_cleanup_cb(OSSL_PROVIDER *provider, void *cbdata)
169-
{
170-
return OSSL_PROVIDER_unload(provider);
171-
}
172-
173-
S2N_RESULT s2n_libcrypto_cleanup(void)
174-
{
175-
RESULT_GUARD_OSSL(OSSL_PROVIDER_do_all(NULL, *s2n_libcrypto_cleanup_cb, NULL), S2N_ERR_ATEXIT);
176-
177-
return S2N_RESULT_OK;
178-
}
179-
#else
180-
S2N_RESULT s2n_libcrypto_cleanup(void)
181-
{
182-
return S2N_RESULT_OK;
183-
}
184-
#endif
185-
186148
/* Performs various checks to validate that the libcrypto used at compile-time
187149
* is the same libcrypto being used at run-time.
188150
*/

crypto/s2n_libcrypto.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,4 @@
1717

1818
#include "utils/s2n_result.h"
1919

20-
S2N_RESULT s2n_libcrypto_init(void);
2120
S2N_RESULT s2n_libcrypto_validate_runtime(void);
22-
S2N_RESULT s2n_libcrypto_cleanup(void);

crypto/s2n_stream_cipher_rc4.c

Lines changed: 61 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,62 @@
2121
#include "utils/s2n_blob.h"
2222
#include "utils/s2n_safety.h"
2323

24-
static uint8_t s2n_stream_cipher_rc4_available()
24+
#if S2N_OPENSSL_VERSION_AT_LEAST(3, 0, 0)
25+
#include "openssl/provider.h"
26+
DEFINE_POINTER_CLEANUP_FUNC(OSSL_LIB_CTX *, OSSL_LIB_CTX_free);
27+
#endif
28+
29+
static EVP_CIPHER *s2n_rc4_cipher = NULL;
30+
31+
S2N_RESULT s2n_rc4_init()
32+
{
33+
/* In Openssl-3.0, RC4 is only available from the "legacy" provider,
34+
* which is not loaded in the default library context.
35+
*/
36+
#if defined(S2N_LIBCRYPTO_SUPPORTS_EVP_RC4) && S2N_OPENSSL_VERSION_AT_LEAST(3, 0, 0)
37+
DEFER_CLEANUP(OSSL_LIB_CTX *lib_ctx = OSSL_LIB_CTX_new(), OSSL_LIB_CTX_free_pointer);
38+
RESULT_ENSURE_REF(lib_ctx);
39+
RESULT_ENSURE_REF(OSSL_PROVIDER_load(lib_ctx, "legacy"));
40+
s2n_rc4_cipher = EVP_CIPHER_fetch(lib_ctx, "rc4", "provider=legacy");
41+
RESULT_ENSURE_REF(s2n_rc4_cipher);
42+
#endif
43+
return S2N_RESULT_OK;
44+
}
45+
46+
S2N_RESULT s2n_rc4_cleanup()
2547
{
26-
#ifdef S2N_LIBCRYPTO_SUPPORTS_EVP_RC4
48+
#if S2N_OPENSSL_VERSION_AT_LEAST(3, 0, 0)
49+
EVP_CIPHER_free(s2n_rc4_cipher);
50+
#endif
51+
return S2N_RESULT_OK;
52+
}
53+
54+
static S2N_RESULT s2n_get_rc4_cipher(const EVP_CIPHER **cipher)
55+
{
56+
RESULT_ENSURE_REF(cipher);
57+
*cipher = NULL;
2758
if (s2n_is_in_fips_mode()) {
28-
return 0;
59+
*cipher = NULL;
60+
} else if (s2n_rc4_cipher) {
61+
*cipher = s2n_rc4_cipher;
62+
#if S2N_LIBCRYPTO_SUPPORTS_EVP_RC4
2963
} else {
30-
return (EVP_rc4() ? 1 : 0);
64+
*cipher = EVP_rc4();
65+
#endif
66+
}
67+
RESULT_ENSURE(*cipher, S2N_ERR_UNIMPLEMENTED);
68+
return S2N_RESULT_OK;
69+
}
70+
71+
static uint8_t s2n_stream_cipher_rc4_available()
72+
{
73+
const EVP_CIPHER *cipher = NULL;
74+
if (s2n_result_is_ok(s2n_get_rc4_cipher(&cipher)) && cipher) {
75+
return 1;
3176
}
32-
#else
3377
return 0;
34-
#endif /* S2N_LIBCRYPTO_SUPPORTS_EVP_RC4 */
3578
}
3679

37-
#ifdef S2N_LIBCRYPTO_SUPPORTS_EVP_RC4
3880
static int s2n_stream_cipher_rc4_encrypt(struct s2n_session_key *key, struct s2n_blob *in, struct s2n_blob *out)
3981
{
4082
POSIX_ENSURE_GTE(out->size, in->size);
@@ -64,17 +106,25 @@ static int s2n_stream_cipher_rc4_decrypt(struct s2n_session_key *key, struct s2n
64106
static int s2n_stream_cipher_rc4_set_encryption_key(struct s2n_session_key *key, struct s2n_blob *in)
65107
{
66108
POSIX_ENSURE_EQ(in->size, 16);
67-
POSIX_GUARD_OSSL(EVP_EncryptInit_ex(key->evp_cipher_ctx, EVP_rc4(), NULL, in->data, NULL), S2N_ERR_KEY_INIT);
68109

69-
return 0;
110+
const EVP_CIPHER *evp_rc4 = NULL;
111+
POSIX_GUARD_RESULT(s2n_get_rc4_cipher(&evp_rc4));
112+
113+
POSIX_GUARD_OSSL(EVP_EncryptInit_ex(key->evp_cipher_ctx, evp_rc4, NULL, in->data, NULL), S2N_ERR_KEY_INIT);
114+
115+
return S2N_SUCCESS;
70116
}
71117

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

77-
return 0;
122+
const EVP_CIPHER *evp_rc4 = NULL;
123+
POSIX_GUARD_RESULT(s2n_get_rc4_cipher(&evp_rc4));
124+
125+
POSIX_GUARD_OSSL(EVP_DecryptInit_ex(key->evp_cipher_ctx, evp_rc4, NULL, in->data, NULL), S2N_ERR_KEY_INIT);
126+
127+
return S2N_SUCCESS;
78128
}
79129

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

91141
return 0;
92142
}
93-
#else
94-
95-
static int s2n_stream_cipher_rc4_encrypt(struct s2n_session_key *key, struct s2n_blob *in, struct s2n_blob *out)
96-
{
97-
POSIX_BAIL(S2N_ERR_UNIMPLEMENTED);
98-
}
99-
100-
static int s2n_stream_cipher_rc4_decrypt(struct s2n_session_key *key, struct s2n_blob *in, struct s2n_blob *out)
101-
{
102-
POSIX_BAIL(S2N_ERR_UNIMPLEMENTED);
103-
}
104-
105-
static int s2n_stream_cipher_rc4_set_encryption_key(struct s2n_session_key *key, struct s2n_blob *in)
106-
{
107-
POSIX_BAIL(S2N_ERR_UNIMPLEMENTED);
108-
}
109-
110-
static int s2n_stream_cipher_rc4_set_decryption_key(struct s2n_session_key *key, struct s2n_blob *in)
111-
{
112-
POSIX_BAIL(S2N_ERR_UNIMPLEMENTED);
113-
}
114-
115-
static int s2n_stream_cipher_rc4_init(struct s2n_session_key *key)
116-
{
117-
POSIX_BAIL(S2N_ERR_UNIMPLEMENTED);
118-
}
119-
120-
static int s2n_stream_cipher_rc4_destroy_key(struct s2n_session_key *key)
121-
{
122-
POSIX_BAIL(S2N_ERR_UNIMPLEMENTED);
123-
}
124-
125-
#endif /* S2N_LIBCRYPTO_SUPPORTS_EVP_RC4 */
126143

127144
const struct s2n_cipher s2n_rc4 = {
128145
.type = S2N_STREAM,

tests/unit/s2n_rc4_test.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,22 @@ int main(int argc, char **argv)
5555
conn->server = conn->secure;
5656
conn->client = conn->secure;
5757

58+
/* Make sure that RC4 is available when expected */
59+
#if defined(S2N_LIBCRYPTO_SUPPORTS_EVP_RC4)
60+
if (s2n_is_in_fips_mode()) {
61+
EXPECT_FALSE(s2n_rc4.is_available());
62+
} else {
63+
EXPECT_TRUE(s2n_rc4.is_available());
64+
}
65+
#else
66+
EXPECT_FALSE(s2n_rc4.is_available());
67+
#endif
68+
5869
/* test the RC4 cipher with a SHA1 hash */
5970
conn->secure->cipher_suite->record_alg = &s2n_record_alg_rc4_sha;
71+
EXPECT_SUCCESS(conn->secure->cipher_suite->record_alg->cipher->init(&conn->secure->server_key));
72+
EXPECT_SUCCESS(conn->secure->cipher_suite->record_alg->cipher->init(&conn->secure->client_key));
6073
if (conn->secure->cipher_suite->record_alg->cipher->is_available()) {
61-
EXPECT_SUCCESS(conn->secure->cipher_suite->record_alg->cipher->init(&conn->secure->server_key));
62-
EXPECT_SUCCESS(conn->secure->cipher_suite->record_alg->cipher->init(&conn->secure->client_key));
6374
EXPECT_SUCCESS(conn->secure->cipher_suite->record_alg->cipher->set_decryption_key(&conn->secure->client_key, &key_iv));
6475
EXPECT_SUCCESS(conn->secure->cipher_suite->record_alg->cipher->set_encryption_key(&conn->secure->server_key, &key_iv));
6576
EXPECT_SUCCESS(s2n_hmac_init(&conn->secure->client_record_mac, S2N_HMAC_SHA1, mac_key, sizeof(mac_key)));
@@ -119,8 +130,6 @@ int main(int argc, char **argv)
119130
EXPECT_SUCCESS(conn->secure->cipher_suite->record_alg->cipher->destroy_key(&conn->secure->client_key));
120131
EXPECT_SUCCESS(s2n_connection_free(conn));
121132
} else {
122-
EXPECT_FAILURE_WITH_ERRNO(conn->secure->cipher_suite->record_alg->cipher->init(&conn->secure->server_key), S2N_ERR_UNIMPLEMENTED);
123-
EXPECT_FAILURE_WITH_ERRNO(conn->secure->cipher_suite->record_alg->cipher->init(&conn->secure->client_key), S2N_ERR_UNIMPLEMENTED);
124133
EXPECT_FAILURE_WITH_ERRNO(conn->secure->cipher_suite->record_alg->cipher->set_decryption_key(&conn->secure->client_key, &key_iv), S2N_ERR_UNIMPLEMENTED);
125134
EXPECT_FAILURE_WITH_ERRNO(conn->secure->cipher_suite->record_alg->cipher->set_encryption_key(&conn->secure->server_key, &key_iv), S2N_ERR_UNIMPLEMENTED);
126135
}

tls/s2n_cipher_suites.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -971,6 +971,9 @@ int s2n_crypto_disable_init(void)
971971
/* Determines cipher suite availability and selects record algorithms */
972972
int s2n_cipher_suites_init(void)
973973
{
974+
/* RC4 requires some extra setup */
975+
POSIX_GUARD_RESULT(s2n_rc4_init());
976+
974977
const int num_cipher_suites = s2n_array_len(s2n_all_cipher_suites);
975978
for (int i = 0; i < num_cipher_suites; i++) {
976979
struct s2n_cipher_suite *cur_suite = s2n_all_cipher_suites[i];
@@ -1052,6 +1055,9 @@ S2N_RESULT s2n_cipher_suites_cleanup(void)
10521055
#endif
10531056
}
10541057

1058+
/* RC4 requires some extra cleanup */
1059+
RESULT_GUARD(s2n_rc4_cleanup());
1060+
10551061
return S2N_RESULT_OK;
10561062
}
10571063

utils/s2n_init.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ int s2n_init(void)
6666
POSIX_GUARD(s2n_mem_init());
6767
/* Must run before any init method that calls libcrypto methods. */
6868
POSIX_GUARD_RESULT(s2n_locking_init());
69-
POSIX_GUARD_RESULT(s2n_libcrypto_init());
7069
POSIX_GUARD(s2n_fips_init());
7170
POSIX_GUARD_RESULT(s2n_rand_init());
7271
POSIX_GUARD(s2n_cipher_suites_init());
@@ -100,7 +99,6 @@ static bool s2n_cleanup_atexit_impl(void)
10099
bool cleaned_up = s2n_result_is_ok(s2n_cipher_suites_cleanup())
101100
&& s2n_result_is_ok(s2n_rand_cleanup_thread())
102101
&& s2n_result_is_ok(s2n_rand_cleanup())
103-
&& s2n_result_is_ok(s2n_libcrypto_cleanup())
104102
&& s2n_result_is_ok(s2n_locking_cleanup())
105103
&& (s2n_mem_cleanup() == S2N_SUCCESS);
106104

0 commit comments

Comments
 (0)