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
3880static 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
64106static 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
72118static 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
80130static 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
127144const struct s2n_cipher s2n_rc4 = {
128145 .type = S2N_STREAM ,
0 commit comments