/* * %CopyrightBegin% * * Copyright Ericsson AB 2010-2018. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * %CopyrightEnd% */ /* * Purpose: Dynamically loadable NIF library for cryptography. * Based on OpenSSL. */ #include "common.h" #include "aead.h" #include "aes.h" #include "block.h" #include "bn.h" #include "chacha20.h" #include "cipher.h" #include "cmac.h" #include "dh.h" #include "digest.h" #include "dss.h" #include "ec.h" #include "ecdh.h" #include "eddsa.h" #include "engine.h" #include "evp.h" #include "hash.h" #include "hmac.h" #include "info.h" #include "math.h" #include "pkey.h" #include "poly1305.h" #include "rand.h" #include "rc4.h" #include "rsa.h" #include "srp.h" /* NIF interface declarations */ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info); static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info); static void unload(ErlNifEnv* env, void* priv_data); /* The NIFs: */ static ERL_NIF_TERM info_fips(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM enable_fips_mode(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); /* helpers */ static void init_algorithms_types(ErlNifEnv*); static int library_refc = 0; /* number of users of this dynamic library */ static int library_initialized = 0; static ErlNifFunc nif_funcs[] = { {"info_lib", 0, info_lib}, {"info_fips", 0, info_fips}, {"enable_fips_mode", 1, enable_fips_mode}, {"algorithms", 0, algorithms}, {"hash_nif", 2, hash_nif}, {"hash_init_nif", 1, hash_init_nif}, {"hash_update_nif", 2, hash_update_nif}, {"hash_final_nif", 1, hash_final_nif}, {"hmac_nif", 3, hmac_nif}, {"hmac_nif", 4, hmac_nif}, {"hmac_init_nif", 2, hmac_init_nif}, {"hmac_update_nif", 2, hmac_update_nif}, {"hmac_final_nif", 1, hmac_final_nif}, {"hmac_final_nif", 2, hmac_final_nif}, {"cmac_nif", 3, cmac_nif}, {"block_crypt_nif", 5, block_crypt_nif}, {"block_crypt_nif", 4, block_crypt_nif}, {"aes_ige_crypt_nif", 4, aes_ige_crypt_nif}, {"aes_ctr_stream_init", 2, aes_ctr_stream_init}, {"aes_ctr_stream_encrypt", 2, aes_ctr_stream_encrypt}, {"aes_ctr_stream_decrypt", 2, aes_ctr_stream_encrypt}, {"strong_rand_bytes_nif", 1, strong_rand_bytes_nif}, {"strong_rand_range_nif", 1, strong_rand_range_nif}, {"rand_uniform_nif", 2, rand_uniform_nif}, {"mod_exp_nif", 4, mod_exp_nif}, {"do_exor", 2, do_exor}, {"rc4_set_key", 1, rc4_set_key}, {"rc4_encrypt_with_state", 2, rc4_encrypt_with_state}, {"pkey_sign_nif", 5, pkey_sign_nif}, {"pkey_verify_nif", 6, pkey_verify_nif}, {"pkey_crypt_nif", 6, pkey_crypt_nif}, {"rsa_generate_key_nif", 2, rsa_generate_key_nif}, {"dh_generate_key_nif", 4, dh_generate_key_nif}, {"dh_compute_key_nif", 3, dh_compute_key_nif}, {"evp_compute_key_nif", 3, evp_compute_key_nif}, {"evp_generate_key_nif", 1, evp_generate_key_nif}, {"privkey_to_pubkey_nif", 2, privkey_to_pubkey_nif}, {"srp_value_B_nif", 5, srp_value_B_nif}, {"srp_user_secret_nif", 7, srp_user_secret_nif}, {"srp_host_secret_nif", 5, srp_host_secret_nif}, {"ec_key_generate", 2, ec_key_generate}, {"ecdh_compute_key_nif", 3, ecdh_compute_key_nif}, {"rand_seed_nif", 1, rand_seed_nif}, {"aead_encrypt", 6, aead_encrypt}, {"aead_decrypt", 6, aead_decrypt}, {"chacha20_stream_init", 2, chacha20_stream_init}, {"chacha20_stream_encrypt", 2, chacha20_stream_crypt}, {"chacha20_stream_decrypt", 2, chacha20_stream_crypt}, {"poly1305_nif", 2, poly1305_nif}, {"engine_by_id_nif", 1, engine_by_id_nif}, {"engine_init_nif", 1, engine_init_nif}, {"engine_finish_nif", 1, engine_finish_nif}, {"engine_free_nif", 1, engine_free_nif}, {"engine_load_dynamic_nif", 0, engine_load_dynamic_nif}, {"engine_ctrl_cmd_strings_nif", 3, engine_ctrl_cmd_strings_nif}, {"engine_register_nif", 2, engine_register_nif}, {"engine_unregister_nif", 2, engine_unregister_nif}, {"engine_add_nif", 1, engine_add_nif}, {"engine_remove_nif", 1, engine_remove_nif}, {"engine_get_first_nif", 0, engine_get_first_nif}, {"engine_get_next_nif", 1, engine_get_next_nif}, {"engine_get_id_nif", 1, engine_get_id_nif}, {"engine_get_name_nif", 1, engine_get_name_nif}, {"engine_get_all_methods_nif", 0, engine_get_all_methods_nif} }; ERL_NIF_INIT(crypto,nif_funcs,load,NULL,upgrade,unload) static int verify_lib_version(void) { const unsigned long libv = SSLeay(); const unsigned long hdrv = OPENSSL_VERSION_NUMBER; # define MAJOR_VER(V) ((unsigned long)(V) >> (7*4)) if (MAJOR_VER(libv) != MAJOR_VER(hdrv)) { PRINTF_ERR2("CRYPTO: INCOMPATIBLE SSL VERSION" " lib=%lx header=%lx\n", libv, hdrv); return 0; } return 1; } static int initialize(ErlNifEnv* env, ERL_NIF_TERM load_info) { #ifdef OPENSSL_THREADS ErlNifSysInfo sys_info; #endif get_crypto_callbacks_t* funcp; struct crypto_callbacks* ccb; int nlocks = 0; int tpl_arity; const ERL_NIF_TERM* tpl_array; int vernum; ErlNifBinary lib_bin; char lib_buf[1000]; if (!verify_lib_version()) return __LINE__; /* load_info: {302, <<"/full/path/of/this/library">>,true|false} */ if (!enif_get_tuple(env, load_info, &tpl_arity, &tpl_array) || tpl_arity != 3 || !enif_get_int(env, tpl_array[0], &vernum) || vernum != 302 || !enif_inspect_binary(env, tpl_array[1], &lib_bin)) { PRINTF_ERR1("CRYPTO: Invalid load_info '%T'", load_info); return __LINE__; } hmac_context_rtype = enif_open_resource_type(env, NULL, "hmac_context", (ErlNifResourceDtor*) hmac_context_dtor, ERL_NIF_RT_CREATE|ERL_NIF_RT_TAKEOVER, NULL); if (!hmac_context_rtype) { PRINTF_ERR0("CRYPTO: Could not open resource type 'hmac_context'"); return __LINE__; } #if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0) evp_md_ctx_rtype = enif_open_resource_type(env, NULL, "EVP_MD_CTX", (ErlNifResourceDtor*) evp_md_ctx_dtor, ERL_NIF_RT_CREATE|ERL_NIF_RT_TAKEOVER, NULL); if (!evp_md_ctx_rtype) { PRINTF_ERR0("CRYPTO: Could not open resource type 'EVP_MD_CTX'"); return __LINE__; } #endif #ifdef HAVE_EVP_AES_CTR evp_cipher_ctx_rtype = enif_open_resource_type(env, NULL, "EVP_CIPHER_CTX", (ErlNifResourceDtor*) evp_cipher_ctx_dtor, ERL_NIF_RT_CREATE|ERL_NIF_RT_TAKEOVER, NULL); if (!evp_cipher_ctx_rtype) { PRINTF_ERR0("CRYPTO: Could not open resource type 'EVP_CIPHER_CTX'"); return __LINE__; } #endif #ifdef HAS_ENGINE_SUPPORT engine_ctx_rtype = enif_open_resource_type(env, NULL, "ENGINE_CTX", (ErlNifResourceDtor*) engine_ctx_dtor, ERL_NIF_RT_CREATE|ERL_NIF_RT_TAKEOVER, NULL); if (!engine_ctx_rtype) { PRINTF_ERR0("CRYPTO: Could not open resource type 'ENGINE_CTX'"); return __LINE__; } #endif if (library_initialized) { /* Repeated loading of this library (module upgrade). * Atoms and callbacks are already set, we are done. */ return 0; } if (!init_atoms(env, tpl_array[2], load_info)) { return 0; } #ifdef HAVE_DYNAMIC_CRYPTO_LIB { void* handle; if (!change_basename(&lib_bin, lib_buf, sizeof(lib_buf), crypto_callback_name)) { return __LINE__; } if (!(handle = enif_dlopen(lib_buf, &error_handler, NULL))) { return __LINE__; } if (!(funcp = (get_crypto_callbacks_t*) enif_dlsym(handle, "get_crypto_callbacks", &error_handler, NULL))) { return __LINE__; } } #else /* !HAVE_DYNAMIC_CRYPTO_LIB */ funcp = &get_crypto_callbacks; #endif #ifdef OPENSSL_THREADS enif_system_info(&sys_info, sizeof(sys_info)); if (sys_info.scheduler_threads > 1) { nlocks = CRYPTO_num_locks(); } /* else no need for locks */ #endif ccb = (*funcp)(nlocks); if (!ccb || ccb->sizeof_me != sizeof(*ccb)) { PRINTF_ERR0("Invalid 'crypto_callbacks'"); return __LINE__; } CRYPTO_set_mem_functions(ccb->crypto_alloc, ccb->crypto_realloc, ccb->crypto_free); #ifdef OPENSSL_THREADS if (nlocks > 0) { CRYPTO_set_locking_callback(ccb->locking_function); CRYPTO_set_id_callback(ccb->id_function); CRYPTO_set_dynlock_create_callback(ccb->dyn_create_function); CRYPTO_set_dynlock_lock_callback(ccb->dyn_lock_function); CRYPTO_set_dynlock_destroy_callback(ccb->dyn_destroy_function); } #endif /* OPENSSL_THREADS */ init_digest_types(env); init_cipher_types(env); init_algorithms_types(env); library_initialized = 1; return 0; } static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) { int errline = initialize(env, load_info); if (errline) { return errline; } *priv_data = NULL; library_refc++; return 0; } static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info) { int errline; if (*old_priv_data != NULL) { return __LINE__; /* Don't know how to do that */ } if (*priv_data != NULL) { return __LINE__; /* Don't know how to do that */ } errline = initialize(env, load_info); if (errline) { return errline; } library_refc++; return 0; } static void unload(ErlNifEnv* env, void* priv_data) { --library_refc; } static int algo_hash_cnt, algo_hash_fips_cnt; static ERL_NIF_TERM algo_hash[12]; /* increase when extending the list */ static int algo_pubkey_cnt, algo_pubkey_fips_cnt; static ERL_NIF_TERM algo_pubkey[12]; /* increase when extending the list */ static int algo_cipher_cnt, algo_cipher_fips_cnt; static ERL_NIF_TERM algo_cipher[25]; /* increase when extending the list */ static int algo_mac_cnt, algo_mac_fips_cnt; static ERL_NIF_TERM algo_mac[3]; /* increase when extending the list */ static int algo_curve_cnt, algo_curve_fips_cnt; static ERL_NIF_TERM algo_curve[89]; /* increase when extending the list */ static int algo_rsa_opts_cnt, algo_rsa_opts_fips_cnt; static ERL_NIF_TERM algo_rsa_opts[11]; /* increase when extending the list */ static void init_algorithms_types(ErlNifEnv* env) { // Validated algorithms first algo_hash_cnt = 0; algo_hash[algo_hash_cnt++] = atom_sha; #ifdef HAVE_SHA224 algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha224"); #endif #ifdef HAVE_SHA256 algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha256"); #endif #ifdef HAVE_SHA384 algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha384"); #endif #ifdef HAVE_SHA512 algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha512"); #endif #ifdef HAVE_SHA3_224 algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha3_224"); #endif #ifdef HAVE_SHA3_256 algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha3_256"); #endif #ifdef HAVE_SHA3_384 algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha3_384"); #endif #ifdef HAVE_SHA3_512 algo_hash[algo_hash_cnt++] = enif_make_atom(env, "sha3_512"); #endif // Non-validated algorithms follow algo_hash_fips_cnt = algo_hash_cnt; algo_hash[algo_hash_cnt++] = enif_make_atom(env, "md4"); algo_hash[algo_hash_cnt++] = enif_make_atom(env, "md5"); algo_hash[algo_hash_cnt++] = enif_make_atom(env, "ripemd160"); algo_pubkey_cnt = 0; algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "rsa"); algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "dss"); algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "dh"); #if defined(HAVE_EC) #if !defined(OPENSSL_NO_EC2M) algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "ec_gf2m"); #endif algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "ecdsa"); algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "ecdh"); #endif // Non-validated algorithms follow algo_pubkey_fips_cnt = algo_pubkey_cnt; // Don't know if Edward curves are fips validated #if defined(HAVE_EDDSA) algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "eddsa"); #endif algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "srp"); // Validated algorithms first algo_cipher_cnt = 0; #ifndef OPENSSL_NO_DES algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "des3_cbc"); algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "des_ede3"); #ifdef HAVE_DES_ede3_cfb_encrypt algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "des3_cbf"); algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "des3_cfb"); #endif #endif algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cbc"); algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cbc128"); algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cfb8"); algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cfb128"); algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_cbc256"); algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_ctr"); algo_cipher[algo_cipher_cnt++] = enif_make_atom(env, "aes_ecb"); #if defined(HAVE_GCM) algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"aes_gcm"); #endif #if defined(HAVE_CCM) algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"aes_ccm"); #endif // Non-validated algorithms follow algo_cipher_fips_cnt = algo_cipher_cnt; #ifdef HAVE_AES_IGE algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"aes_ige256"); #endif #ifndef OPENSSL_NO_DES algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"des_cbc"); algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"des_cfb"); algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"des_ecb"); #endif algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"blowfish_cbc"); algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"blowfish_cfb64"); algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"blowfish_ofb64"); algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"blowfish_ecb"); #ifndef OPENSSL_NO_RC2 algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"rc2_cbc"); #endif #ifndef OPENSSL_NO_RC4 algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"rc4"); #endif #if defined(HAVE_CHACHA20_POLY1305) algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"chacha20_poly1305"); #endif #if defined(HAVE_CHACHA20) algo_cipher[algo_cipher_cnt++] = enif_make_atom(env,"chacha20"); #endif // Validated algorithms first algo_mac_cnt = 0; algo_mac[algo_mac_cnt++] = enif_make_atom(env,"hmac"); #ifdef HAVE_CMAC algo_mac[algo_mac_cnt++] = enif_make_atom(env,"cmac"); #endif #ifdef HAVE_POLY1305 algo_mac[algo_mac_cnt++] = enif_make_atom(env,"poly1305"); #endif // Non-validated algorithms follow algo_mac_fips_cnt = algo_mac_cnt; // Validated algorithms first algo_curve_cnt = 0; #if defined(HAVE_EC) algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp160k1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp160r1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp160r2"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp192r1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp192k1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp224k1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp224r1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp256k1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp256r1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp384r1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp521r1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"prime192v1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"prime192v2"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"prime192v3"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"prime239v1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"prime239v2"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"prime239v3"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"prime256v1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls7"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls9"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls12"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP160r1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP160t1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP192r1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP192t1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP224r1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP224t1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP256r1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP256t1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP320r1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP320t1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP384r1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP384t1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP512r1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"brainpoolP512t1"); #if !defined(OPENSSL_NO_EC2M) algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect163k1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect163r1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect163r2"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect193r1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect193r2"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect233k1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect233r1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect239k1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect283k1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect283r1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect409k1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect409r1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect571k1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect571r1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb163v1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb163v2"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb163v3"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb176v1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb191v1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb191v2"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb191v3"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb208w1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb239v1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb239v2"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb239v3"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb272w1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb304w1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb359v1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2pnb368w1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"c2tnb431r1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls3"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls5"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls10"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls11"); #endif #endif // Non-validated algorithms follow algo_curve_fips_cnt = algo_curve_cnt; #if defined(HAVE_EC) algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp112r1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp112r2"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp128r1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"secp128r2"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls6"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls8"); #if !defined(OPENSSL_NO_EC2M) algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect113r1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect113r2"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect131r1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"sect131r2"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls1"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"wtls4"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"ipsec3"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"ipsec4"); #endif #endif //-- #ifdef HAVE_EDDSA algo_curve[algo_curve_cnt++] = enif_make_atom(env,"ed25519"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"ed448"); #endif #ifdef HAVE_ED_CURVE_DH algo_curve[algo_curve_cnt++] = enif_make_atom(env,"x25519"); algo_curve[algo_curve_cnt++] = enif_make_atom(env,"x448"); #endif // Validated algorithms first algo_rsa_opts_cnt = 0; #ifdef HAS_EVP_PKEY_CTX # ifdef HAVE_RSA_PKCS1_PSS_PADDING algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_pkcs1_pss_padding"); algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_pss_saltlen"); # endif # ifdef HAVE_RSA_MGF1_MD algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_mgf1_md"); # endif # ifdef HAVE_RSA_OAEP_PADDING algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_pkcs1_oaep_padding"); # endif # ifdef HAVE_RSA_OAEP_MD algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_oaep_label"); algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_oaep_md"); # endif algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"signature_md"); #endif algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_pkcs1_padding"); algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_x931_padding"); #ifdef HAVE_RSA_SSLV23_PADDING algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_sslv23_padding"); #endif algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_no_padding"); algo_rsa_opts_fips_cnt = algo_rsa_opts_cnt; // Check that the max number of algos is updated ASSERT(algo_hash_cnt <= sizeof(algo_hash)/sizeof(ERL_NIF_TERM)); ASSERT(algo_pubkey_cnt <= sizeof(algo_pubkey)/sizeof(ERL_NIF_TERM)); ASSERT(algo_cipher_cnt <= sizeof(algo_cipher)/sizeof(ERL_NIF_TERM)); ASSERT(algo_mac_cnt <= sizeof(algo_mac)/sizeof(ERL_NIF_TERM)); ASSERT(algo_curve_cnt <= sizeof(algo_curve)/sizeof(ERL_NIF_TERM)); ASSERT(algo_rsa_opts_cnt <= sizeof(algo_rsa_opts)/sizeof(ERL_NIF_TERM)); } static ERL_NIF_TERM algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { #ifdef FIPS_SUPPORT int fips_mode = FIPS_mode(); int hash_cnt = fips_mode ? algo_hash_fips_cnt : algo_hash_cnt; int pubkey_cnt = fips_mode ? algo_pubkey_fips_cnt : algo_pubkey_cnt; int cipher_cnt = fips_mode ? algo_cipher_fips_cnt : algo_cipher_cnt; int mac_cnt = fips_mode ? algo_mac_fips_cnt : algo_mac_cnt; int curve_cnt = fips_mode ? algo_curve_fips_cnt : algo_curve_cnt; int rsa_opts_cnt = fips_mode ? algo_rsa_opts_fips_cnt : algo_rsa_opts_cnt; #else int hash_cnt = algo_hash_cnt; int pubkey_cnt = algo_pubkey_cnt; int cipher_cnt = algo_cipher_cnt; int mac_cnt = algo_mac_cnt; int curve_cnt = algo_curve_cnt; int rsa_opts_cnt = algo_rsa_opts_cnt; #endif return enif_make_tuple6(env, enif_make_list_from_array(env, algo_hash, hash_cnt), enif_make_list_from_array(env, algo_pubkey, pubkey_cnt), enif_make_list_from_array(env, algo_cipher, cipher_cnt), enif_make_list_from_array(env, algo_mac, mac_cnt), enif_make_list_from_array(env, algo_curve, curve_cnt), enif_make_list_from_array(env, algo_rsa_opts, rsa_opts_cnt) ); } static 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 } static ERL_NIF_TERM enable_fips_mode(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Boolean) */ if (argv[0] == 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) { #ifdef FIPS_SUPPORT if (!FIPS_mode_set(0)) { return atom_false; } #endif return atom_true; } else { return enif_make_badarg(env); } }