diff options
author | Hans Nilsson <hans@erlang.org> | 2021-10-25 13:06:27 +0200 |
---|---|---|
committer | Hans Nilsson <hans@erlang.org> | 2022-01-24 13:37:52 +0100 |
commit | 5660f1b9da05ce61382454f0fce4a96ee2473f13 (patch) | |
tree | fe10961ca93baa6161ae08848868e3bd6b18776d | |
parent | 7e5932f8be51d40e7b8a54ceeff202b39b8f2f0e (diff) | |
download | erlang-5660f1b9da05ce61382454f0fce4a96ee2473f13.tar.gz |
crypto: FIPS - Framework
Only one function to enable/disable fips mode.
There where two (of which one was really displaced) depending of
whether the enable was due to an env or a function call.
-rw-r--r-- | lib/crypto/c_src/atoms.c | 16 | ||||
-rw-r--r-- | lib/crypto/c_src/atoms.h | 2 | ||||
-rw-r--r-- | lib/crypto/c_src/crypto.c | 28 | ||||
-rw-r--r-- | lib/crypto/c_src/fips.c | 14 | ||||
-rw-r--r-- | lib/crypto/c_src/fips.h | 2 | ||||
-rw-r--r-- | lib/crypto/c_src/info.c | 8 | ||||
-rw-r--r-- | lib/crypto/c_src/openssl_config.h | 17 | ||||
-rw-r--r-- | lib/crypto/test/crypto_SUITE.erl | 4 |
8 files changed, 62 insertions, 29 deletions
diff --git a/lib/crypto/c_src/atoms.c b/lib/crypto/c_src/atoms.c index b6a190bf09..c7c6aca9dc 100644 --- a/lib/crypto/c_src/atoms.c +++ b/lib/crypto/c_src/atoms.c @@ -144,23 +144,9 @@ ERL_NIF_TERM atom_key_id; ERL_NIF_TERM atom_password; #endif -int init_atoms(ErlNifEnv *env, const ERL_NIF_TERM fips_mode, const ERL_NIF_TERM load_info) { +int init_atoms(ErlNifEnv *env) { atom_true = enif_make_atom(env,"true"); atom_false = enif_make_atom(env,"false"); - /* Enter FIPS mode */ - if (fips_mode == atom_true) { -#ifdef FIPS_SUPPORT - if (!FIPS_mode_set(1)) { -#else - { -#endif - PRINTF_ERR0("CRYPTO: Could not setup FIPS mode"); - return 0; - } - } else if (fips_mode != atom_false) { - PRINTF_ERR1("CRYPTO: Invalid load_info '%T'", load_info); - return 0; - } atom_sha = enif_make_atom(env,"sha"); atom_error = enif_make_atom(env,"error"); diff --git a/lib/crypto/c_src/atoms.h b/lib/crypto/c_src/atoms.h index 7bedf799b6..05a24e21b3 100644 --- a/lib/crypto/c_src/atoms.h +++ b/lib/crypto/c_src/atoms.h @@ -143,6 +143,6 @@ extern ERL_NIF_TERM atom_key_id; extern ERL_NIF_TERM atom_password; #endif -int init_atoms(ErlNifEnv *env, const ERL_NIF_TERM fips_mode, const ERL_NIF_TERM load_info); +int init_atoms(ErlNifEnv *env); #endif /* E_ATOMS_H__ */ diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index a2b230528c..5d1c1b306e 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -128,6 +128,11 @@ static ErlNifFunc nif_funcs[] = { {"engine_get_all_methods_nif", 0, engine_get_all_methods_nif, 0} }; +#ifdef HAS_3_0_API +OSSL_PROVIDER *prov[MAX_NUM_PROVIDERS]; +int prov_cnt; +#endif + ERL_NIF_INIT(crypto,nif_funcs,load,NULL,upgrade,unload) @@ -151,6 +156,7 @@ static int verify_lib_version(void) return 1; } + static int initialize(ErlNifEnv* env, ERL_NIF_TERM load_info) { #if OPENSSL_VERSION_NUMBER < PACKED_OPENSSL_VERSION_PLAIN(1,1,0) @@ -204,6 +210,16 @@ static int initialize(ErlNifEnv* env, ERL_NIF_TERM load_info) return __LINE__; } +#ifdef HAS_3_0_API + prov_cnt = 0; +# ifdef FIPS_SUPPORT + if ((prov_cnt<MAX_NUM_PROVIDERS) && !(prov[prov_cnt++] = OSSL_PROVIDER_load(NULL, "fips"))) return __LINE__; +#endif + if ((prov_cnt<MAX_NUM_PROVIDERS) && !(prov[prov_cnt++] = OSSL_PROVIDER_load(NULL, "default"))) return __LINE__; + if ((prov_cnt<MAX_NUM_PROVIDERS) && !(prov[prov_cnt++] = OSSL_PROVIDER_load(NULL, "base"))) return __LINE__; + if ((prov_cnt<MAX_NUM_PROVIDERS) && !(prov[prov_cnt++] = OSSL_PROVIDER_load(NULL, "legacy"))) return __LINE__; +#endif + if (library_initialized) { /* Repeated loading of this library (module upgrade). * Atoms and callbacks are already set, we are done. @@ -211,10 +227,14 @@ static int initialize(ErlNifEnv* env, ERL_NIF_TERM load_info) return 0; } - if (!init_atoms(env, tpl_array[2], load_info)) { + if (!init_atoms(env)) { return __LINE__; } + /* Check if enter FIPS mode at module load (happening now) */ + if (enable_fips_mode(env, tpl_array[2]) != atom_true) + return __LINE__; + #ifdef HAVE_DYNAMIC_CRYPTO_LIB if (!change_basename(&lib_bin, lib_buf, sizeof(lib_buf), crypto_callback_name)) return __LINE__; @@ -305,4 +325,10 @@ static void unload(ErlNifEnv* env, void* priv_data) { if (--library_refc == 0) cleanup_algorithms_types(env); + +#ifdef HAS_3_0_API + while (prov_cnt>0) + OSSL_PROVIDER_unload(prov[--prov_cnt]); +#endif + } diff --git a/lib/crypto/c_src/fips.c b/lib/crypto/c_src/fips.c index d1468d085d..12028ea75b 100644 --- a/lib/crypto/c_src/fips.c +++ b/lib/crypto/c_src/fips.c @@ -24,22 +24,26 @@ ERL_NIF_TERM info_fips(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { #ifdef FIPS_SUPPORT return FIPS_MODE() ? atom_enabled : atom_not_enabled; -#else - return atom_not_supported; #endif + return atom_not_supported; } ERL_NIF_TERM enable_fips_mode_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Boolean) */ - if (argv[0] == atom_true) { + return enable_fips_mode(env, argv[0]); +} + + +ERL_NIF_TERM enable_fips_mode(ErlNifEnv* env, ERL_NIF_TERM fips_mode) +{ + if (fips_mode == atom_true) { #ifdef FIPS_SUPPORT if (FIPS_mode_set(1)) { return atom_true; } #endif - PRINTF_ERR0("CRYPTO: Could not setup FIPS mode"); return atom_false; - } else if (argv[0] == atom_false) { + } else if (fips_mode == atom_false) { #ifdef FIPS_SUPPORT if (!FIPS_mode_set(0)) { return atom_false; diff --git a/lib/crypto/c_src/fips.h b/lib/crypto/c_src/fips.h index 6f592cf9c2..ea7aad59cd 100644 --- a/lib/crypto/c_src/fips.h +++ b/lib/crypto/c_src/fips.h @@ -26,4 +26,6 @@ ERL_NIF_TERM info_fips(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); ERL_NIF_TERM enable_fips_mode_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +ERL_NIF_TERM enable_fips_mode(ErlNifEnv* env, ERL_NIF_TERM fips_mode); + #endif /* E_FIPS_H__ */ diff --git a/lib/crypto/c_src/info.c b/lib/crypto/c_src/info.c index 57525400dd..3021c3d71b 100644 --- a/lib/crypto/c_src/info.c +++ b/lib/crypto/c_src/info.c @@ -113,6 +113,14 @@ ERL_NIF_TERM info_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) enif_make_atom(env, "cryptolib_version_linked"), enif_make_string(env, SSLeay_version(SSLEAY_VERSION), ERL_NIF_LATIN1), &ret); + +#ifdef HAS_3_0_API + enif_make_map_put(env, ret, + enif_make_atom(env, "fips_provider_available"), + OSSL_PROVIDER_available(NULL, "fips") ? atom_true : atom_false, + &ret); +#endif + return ret; } diff --git a/lib/crypto/c_src/openssl_config.h b/lib/crypto/c_src/openssl_config.h index 3125d25028..9e228c62d1 100644 --- a/lib/crypto/c_src/openssl_config.h +++ b/lib/crypto/c_src/openssl_config.h @@ -23,6 +23,7 @@ #define OPENSSL_THREAD_DEFINES #include <openssl/opensslconf.h> +#include "openssl_version.h" #include <openssl/crypto.h> #include <openssl/des.h> @@ -49,10 +50,10 @@ #include <openssl/evp.h> #include <openssl/hmac.h> #include <openssl/err.h> -#include "openssl_version.h" #if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(3,0,0) # define HAS_3_0_API +# include <openssl/provider.h> #endif /* LibreSSL was cloned from OpenSSL 1.0.1g and claims to be API and BPI compatible @@ -410,6 +411,10 @@ /* Current value is: erlang:system_info(context_reductions) * 10 */ #define MAX_BYTES_TO_NIF 20000 +#ifdef HAS_3_0_API +# define MAX_NUM_PROVIDERS 10 +#endif + #define CONSUME_REDS(NifEnv, Ibin) \ do { \ size_t _cost = (Ibin).size; \ @@ -449,13 +454,15 @@ do { \ #endif -/* This is not the final FIPS adaptation for 3.0, just making it compilable */ -#ifdef HAS_3_0_API -# undef FIPS_SUPPORT +#if defined(FIPS_SUPPORT) && \ + defined(HAS_3_0_API) +# define FIPS_mode() EVP_default_properties_is_fips_enabled(NULL) +# define FIPS_mode_set(enable) EVP_default_properties_enable_fips(NULL, enable) #endif + #if defined(FIPS_SUPPORT) -# define FIPS_MODE() (FIPS_mode() ? 1 : 0) +# define FIPS_MODE() (FIPS_mode() ? 1 : 0) #else # define FIPS_MODE() 0 #endif diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl index a3ea7fd0a7..2b3112f604 100644 --- a/lib/crypto/test/crypto_SUITE.erl +++ b/lib/crypto/test/crypto_SUITE.erl @@ -498,8 +498,8 @@ init_per_group(non_fips, Config) -> NonFIPSConfig = [{fips, false} | Config], case crypto:info_fips() of enabled -> - true = crypto:enable_fips_mode(false), - not_enabled = crypto:info_fips(), + %% true = crypto:enable_fips_mode(false), + %% not_enabled = crypto:info_fips(), NonFIPSConfig; _NotEnabled -> NonFIPSConfig |