diff options
Diffstat (limited to 'lib/crypto/c_src/crypto.c')
-rw-r--r-- | lib/crypto/c_src/crypto.c | 698 |
1 files changed, 570 insertions, 128 deletions
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index 6eeebb67a2..07ef60e395 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -148,6 +148,23 @@ # define HAVE_DES_ede3_cfb_encrypt #endif +// SHA3: +#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,1,1) +// An error in beta releases of 1.1.1 fixed in production release +# ifdef NID_sha3_224 +# define HAVE_SHA3_224 +# endif +# ifdef NID_sha3_256 +# define HAVE_SHA3_256 +# endif +#endif +# ifdef NID_sha3_384 +# define HAVE_SHA3_384 +# endif +# ifdef NID_sha3_512 +# define HAVE_SHA3_512 +# endif + #if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION(0,9,8,'o') \ && !defined(OPENSSL_NO_EC) \ && !defined(OPENSSL_NO_ECDH) \ @@ -155,12 +172,11 @@ # define HAVE_EC #endif -// (test for == 1.1.1pre8) -#if OPENSSL_VERSION_NUMBER == (PACKED_OPENSSL_VERSION_PLAIN(1,1,1) - 7) \ +// (test for >= 1.1.1pre8) +#if OPENSSL_VERSION_NUMBER >= (PACKED_OPENSSL_VERSION_PLAIN(1,1,1) - 7) \ && !defined(HAS_LIBRESSL) \ && defined(HAVE_EC) -// EXPERIMENTAL: -# define HAVE_EDDH +# define HAVE_ED_CURVE_DH #endif #if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION(0,9,8,'c') @@ -169,7 +185,9 @@ #if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,1) # define HAVE_EVP_AES_CTR +# define HAVE_AEAD # define HAVE_GCM +# define HAVE_CCM # define HAVE_CMAC # if OPENSSL_VERSION_NUMBER < PACKED_OPENSSL_VERSION(1,0,1,'d') # define HAVE_GCM_EVP_DECRYPT_BUG @@ -178,7 +196,16 @@ #if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,1,0) # ifndef HAS_LIBRESSL +# define HAVE_CHACHA20 # define HAVE_CHACHA20_POLY1305 +# define HAVE_RSA_OAEP_MD +# endif +#endif + +// OPENSSL_VERSION_NUMBER >= 1.1.1-pre8 +#if OPENSSL_VERSION_NUMBER >= (PACKED_OPENSSL_VERSION_PLAIN(1,1,1)-7) +# ifndef HAS_LIBRESSL +# define HAVE_POLY1305 # endif #endif @@ -186,10 +213,14 @@ # define HAVE_ECB_IVEC_BUG #endif -#define HAVE_RSA_SSLV23_PADDING -#if defined(HAS_LIBRESSL) \ - && LIBRESSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(2,6,1) -# undef HAVE_RSA_SSLV23_PADDING +#ifdef RSA_SSLV23_PADDING +# define HAVE_RSA_SSLV23_PADDING +#endif + +#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0) +# ifdef RSA_PKCS1_PSS_PADDING +# define HAVE_RSA_PKCS1_PSS_PADDING +# endif #endif #if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION(0,9,8,'h') \ @@ -514,8 +545,8 @@ static ERL_NIF_TERM evp_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF static ERL_NIF_TERM rand_seed_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM aes_gcm_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM aes_gcm_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM aead_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM aead_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); #ifdef HAVE_GCM_EVP_DECRYPT_BUG static ERL_NIF_TERM aes_gcm_decrypt_NO_EVP(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); #endif @@ -523,6 +554,11 @@ static ERL_NIF_TERM aes_gcm_decrypt_NO_EVP(ErlNifEnv* env, int argc, const ERL_N static ERL_NIF_TERM chacha20_poly1305_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM chacha20_poly1305_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM chacha20_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM chacha20_stream_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); + +static ERL_NIF_TERM poly1305_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); + static ERL_NIF_TERM engine_by_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM engine_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM engine_finish_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); @@ -536,6 +572,7 @@ static ERL_NIF_TERM engine_remove_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE static ERL_NIF_TERM engine_get_first_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM engine_get_next_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM engine_get_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM engine_get_name_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM engine_get_all_methods_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); /* helpers */ @@ -606,12 +643,18 @@ static ErlNifFunc nif_funcs[] = { {"rand_seed_nif", 1, rand_seed_nif}, - {"aes_gcm_encrypt", 5, aes_gcm_encrypt}, - {"aes_gcm_decrypt", 5, aes_gcm_decrypt}, + {"aead_encrypt", 6, aead_encrypt}, + {"aead_decrypt", 6, aead_decrypt}, {"chacha20_poly1305_encrypt", 4, chacha20_poly1305_encrypt}, {"chacha20_poly1305_decrypt", 5, chacha20_poly1305_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}, @@ -625,6 +668,7 @@ static ErlNifFunc nif_funcs[] = { {"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} }; @@ -674,6 +718,12 @@ static ERL_NIF_TERM atom_onbasis; static ERL_NIF_TERM atom_aes_cfb8; static ERL_NIF_TERM atom_aes_cfb128; +#ifdef HAVE_GCM +static ERL_NIF_TERM atom_aes_gcm; +#endif +#ifdef HAVE_CCM +static ERL_NIF_TERM atom_aes_ccm; +#endif #ifdef HAVE_ECB_IVEC_BUG static ERL_NIF_TERM atom_aes_ecb; static ERL_NIF_TERM atom_des_ecb; @@ -684,8 +734,7 @@ static ERL_NIF_TERM atom_rsa; static ERL_NIF_TERM atom_dss; static ERL_NIF_TERM atom_ecdsa; -#ifdef HAVE_EDDH -static ERL_NIF_TERM atom_eddh; +#ifdef HAVE_ED_CURVE_DH static ERL_NIF_TERM atom_x25519; static ERL_NIF_TERM atom_x448; #endif @@ -705,6 +754,10 @@ static ERL_NIF_TERM atom_sha224; static ERL_NIF_TERM atom_sha256; static ERL_NIF_TERM atom_sha384; static ERL_NIF_TERM atom_sha512; +static ERL_NIF_TERM atom_sha3_224; +static ERL_NIF_TERM atom_sha3_256; +static ERL_NIF_TERM atom_sha3_384; +static ERL_NIF_TERM atom_sha3_512; static ERL_NIF_TERM atom_md5; static ERL_NIF_TERM atom_ripemd160; @@ -790,6 +843,35 @@ static struct digest_type_t digest_types[] = {NULL} #endif }, + {{"sha3_224"}, +#ifdef HAVE_SHA3_224 + {&EVP_sha3_224} +#else + {NULL} +#endif + }, + {{"sha3_256"}, +#ifdef HAVE_SHA3_256 + {&EVP_sha3_256} +#else + {NULL} +#endif + }, + {{"sha3_384"}, +#ifdef HAVE_SHA3_384 + {&EVP_sha3_384} +#else + {NULL} +#endif + }, + {{"sha3_512"}, +#ifdef HAVE_SHA3_512 + {&EVP_sha3_512} +#else + {NULL} +#endif + }, + {{NULL}} }; @@ -1082,6 +1164,12 @@ static int initialize(ErlNifEnv* env, ERL_NIF_TERM load_info) #endif atom_aes_cfb8 = enif_make_atom(env, "aes_cfb8"); atom_aes_cfb128 = enif_make_atom(env, "aes_cfb128"); +#ifdef HAVE_GCM + atom_aes_gcm = enif_make_atom(env, "aes_gcm"); +#endif +#ifdef HAVE_CCM + atom_aes_ccm = enif_make_atom(env, "aes_ccm"); +#endif #ifdef HAVE_ECB_IVEC_BUG atom_aes_ecb = enif_make_atom(env, "aes_ecb"); atom_des_ecb = enif_make_atom(env, "des_ecb"); @@ -1097,8 +1185,7 @@ static int initialize(ErlNifEnv* env, ERL_NIF_TERM load_info) atom_rsa = enif_make_atom(env,"rsa"); atom_dss = enif_make_atom(env,"dss"); atom_ecdsa = enif_make_atom(env,"ecdsa"); -#ifdef HAVE_EDDH - atom_eddh = enif_make_atom(env,"eddh"); +#ifdef HAVE_ED_CURVE_DH atom_x25519 = enif_make_atom(env,"x25519"); atom_x448 = enif_make_atom(env,"x448"); #endif @@ -1117,6 +1204,10 @@ static int initialize(ErlNifEnv* env, ERL_NIF_TERM load_info) atom_sha256 = enif_make_atom(env,"sha256"); atom_sha384 = enif_make_atom(env,"sha384"); atom_sha512 = enif_make_atom(env,"sha512"); + atom_sha3_224 = enif_make_atom(env,"sha3_224"); + atom_sha3_256 = enif_make_atom(env,"sha3_256"); + atom_sha3_384 = enif_make_atom(env,"sha3_384"); + atom_sha3_512 = enif_make_atom(env,"sha3_512"); atom_md5 = enif_make_atom(env,"md5"); atom_ripemd160 = enif_make_atom(env,"ripemd160"); @@ -1237,15 +1328,17 @@ static void unload(ErlNifEnv* env, void* priv_data) } static int algo_hash_cnt, algo_hash_fips_cnt; -static ERL_NIF_TERM algo_hash[8]; /* increase when extending the list */ +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[11]; /* increase when extending the list */ static int algo_cipher_cnt, algo_cipher_fips_cnt; -static ERL_NIF_TERM algo_cipher[24]; /* increase when extending the list */ +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[2]; /* increase when extending the list */ +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[87]; /* increase when extending the list */ +static int algo_rsa_opts_cnt, algo_rsa_opts_fips_cnt; +static ERL_NIF_TERM algo_rsa_opts[10]; /* increase when extending the list */ static void init_algorithms_types(ErlNifEnv* env) { @@ -1264,6 +1357,18 @@ static void init_algorithms_types(ErlNifEnv* env) #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"); @@ -1283,9 +1388,6 @@ static void init_algorithms_types(ErlNifEnv* env) #endif // Non-validated algorithms follow algo_pubkey_fips_cnt = algo_pubkey_cnt; -#ifdef HAVE_EDDH - algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "eddh"); -#endif algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "srp"); // Validated algorithms first @@ -1308,6 +1410,9 @@ static void init_algorithms_types(ErlNifEnv* env) #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 @@ -1331,33 +1436,153 @@ static void init_algorithms_types(ErlNifEnv* env) #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_EDDH +#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 + algo_rsa_opts[algo_rsa_opts_cnt++] = enif_make_atom(env,"rsa_mgf1_md"); +# 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[]) @@ -1369,19 +1594,22 @@ static ERL_NIF_TERM algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv 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_tuple5(env, + 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_curve, curve_cnt), + enif_make_list_from_array(env, algo_rsa_opts, rsa_opts_cnt) ); } @@ -1989,6 +2217,62 @@ static ERL_NIF_TERM cmac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] #endif } +/* For OpenSSL >= 1.1.1 the hmac_nif and cmac_nif could be integrated into poly1305 (with 'type' as parameter) */ +static ERL_NIF_TERM poly1305_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* (Key, Text) */ +#ifdef HAVE_POLY1305 + ErlNifBinary key_bin, text, ret_bin; + ERL_NIF_TERM ret = atom_error; + EVP_PKEY *key = NULL; + EVP_MD_CTX *mctx = NULL; + EVP_PKEY_CTX *pctx = NULL; + const EVP_MD *md = NULL; + size_t size; + int type; + + type = EVP_PKEY_POLY1305; + + if (!enif_inspect_binary(env, argv[0], &key_bin) || + !(key_bin.size == 32) ) { + return enif_make_badarg(env); + } + + if (!enif_inspect_binary(env, argv[1], &text) ) { + return enif_make_badarg(env); + } + + key = EVP_PKEY_new_raw_private_key(type, /*engine*/ NULL, key_bin.data, key_bin.size); + + if (!key || + !(mctx = EVP_MD_CTX_new()) || + !EVP_DigestSignInit(mctx, &pctx, md, /*engine*/ NULL, key) || + !EVP_DigestSignUpdate(mctx, text.data, text.size)) { + goto err; + } + + if (!EVP_DigestSignFinal(mctx, NULL, &size) || + !enif_alloc_binary(size, &ret_bin) || + !EVP_DigestSignFinal(mctx, ret_bin.data, &size)) { + goto err; + } + + if ((size != ret_bin.size) && + !enif_realloc_binary(&ret_bin, size)) { + goto err; + } + + ret = enif_make_binary(env, &ret_bin); + + err: + EVP_MD_CTX_free(mctx); + EVP_PKEY_free(key); + return ret; + +#else + return atom_notsup; +#endif +} + static ERL_NIF_TERM block_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Type, Key, Ivec, Text, IsEncrypt) or (Type, Key, Text, IsEncrypt) */ struct cipher_type_t *cipherp = NULL; @@ -2282,66 +2566,95 @@ static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_N } #endif /* !HAVE_EVP_AES_CTR */ -static ERL_NIF_TERM aes_gcm_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Key,Iv,AAD,In) */ -#if defined(HAVE_GCM) +static ERL_NIF_TERM aead_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* (Type,Key,Iv,AAD,In) */ +#if defined(HAVE_AEAD) EVP_CIPHER_CTX *ctx; const EVP_CIPHER *cipher = NULL; ErlNifBinary key, iv, aad, in; unsigned int tag_len; unsigned char *outp, *tagp; - ERL_NIF_TERM out, out_tag; - int len; + ERL_NIF_TERM type, out, out_tag; + int len, ctx_ctrl_set_ivlen, ctx_ctrl_get_tag; - if (!enif_inspect_iolist_as_binary(env, argv[0], &key) - || (key.size != 16 && key.size != 24 && key.size != 32) - || !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0 - || !enif_inspect_iolist_as_binary(env, argv[2], &aad) - || !enif_inspect_iolist_as_binary(env, argv[3], &in) - || !enif_get_uint(env, argv[4], &tag_len) || tag_len < 1 || tag_len > 16) { + type = argv[0]; + + if (!enif_is_atom(env, type) + || !enif_inspect_iolist_as_binary(env, argv[1], &key) + || !enif_inspect_binary(env, argv[2], &iv) + || !enif_inspect_iolist_as_binary(env, argv[3], &aad) + || !enif_inspect_iolist_as_binary(env, argv[4], &in) + || !enif_get_uint(env, argv[5], &tag_len)) { return enif_make_badarg(env); } - if (key.size == 16) - cipher = EVP_aes_128_gcm(); - else if (key.size == 24) - cipher = EVP_aes_192_gcm(); - else if (key.size == 32) - cipher = EVP_aes_256_gcm(); + /* Use cipher_type some day. Must check block_encrypt|decrypt first */ +#if defined(HAVE_GCM) + if ((type == atom_aes_gcm) + && (iv.size > 0) + && (1 <= tag_len && tag_len <= 16)) { + ctx_ctrl_set_ivlen = EVP_CTRL_GCM_SET_IVLEN; + ctx_ctrl_get_tag = EVP_CTRL_GCM_GET_TAG; + if (key.size == 16) cipher = EVP_aes_128_gcm(); + else if (key.size == 24) cipher = EVP_aes_192_gcm(); + else if (key.size == 32) cipher = EVP_aes_256_gcm(); + else + enif_make_badarg(env); + + } else +#endif +#if defined(HAVE_CCM) + if ((type == atom_aes_ccm) + && (7 <= iv.size && iv.size <= 13) + && (4 <= tag_len && tag_len <= 16) + && ((tag_len & 1) == 0) + ) { + ctx_ctrl_set_ivlen = EVP_CTRL_CCM_SET_IVLEN; + ctx_ctrl_get_tag = EVP_CTRL_CCM_GET_TAG; + if (key.size == 16) cipher = EVP_aes_128_ccm(); + else if (key.size == 24) cipher = EVP_aes_192_ccm(); + else if (key.size == 32) cipher = EVP_aes_256_ccm(); + else + enif_make_badarg(env); + } else +#endif + enif_make_badarg(env); + ctx = EVP_CIPHER_CTX_new(); + if (EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1) goto out_err; + if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_set_ivlen, iv.size, NULL) != 1) goto out_err; - if (EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1) - goto out_err; +#if defined(HAVE_GCM) + if (type == atom_aes_gcm) { + if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) goto out_err; + } else +#endif +#if defined(HAVE_CCM) + if (type == atom_aes_ccm) { + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, tag_len, NULL) != 1) goto out_err; + if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) goto out_err; + if (EVP_EncryptUpdate(ctx, NULL, &len, NULL, in.size) != 1) goto out_err; + } else +#endif + goto out_err; - EVP_CIPHER_CTX_set_padding(ctx, 0); - - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv.size, NULL) != 1) - goto out_err; - if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) - goto out_err; - if (EVP_EncryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1) - goto out_err; + if (EVP_EncryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1) goto out_err; outp = enif_make_new_binary(env, in.size, &out); - if (EVP_EncryptUpdate(ctx, outp, &len, in.data, in.size) != 1) - goto out_err; - if (EVP_EncryptFinal_ex(ctx, outp+len, &len) != 1) - goto out_err; + if (EVP_EncryptUpdate(ctx, outp, &len, in.data, in.size) != 1) goto out_err; + if (EVP_EncryptFinal_ex(ctx, outp, &len) != 1) goto out_err; tagp = enif_make_new_binary(env, tag_len, &out_tag); - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, tag_len, tagp) != 1) - goto out_err; + if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_get_tag, tag_len, tagp) != 1) goto out_err; EVP_CIPHER_CTX_free(ctx); - CONSUME_REDS(env, in); - return enif_make_tuple2(env, out, out_tag); -out_err: +out_err: EVP_CIPHER_CTX_free(ctx); return atom_error; @@ -2350,58 +2663,90 @@ out_err: #endif } -static ERL_NIF_TERM aes_gcm_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Key,Iv,AAD,In,Tag) */ -#if defined(HAVE_GCM_EVP_DECRYPT_BUG) - return aes_gcm_decrypt_NO_EVP(env, argc, argv); -#elif defined(HAVE_GCM) +static ERL_NIF_TERM aead_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* (Type,Key,Iv,AAD,In,Tag) */ +#if defined(HAVE_AEAD) EVP_CIPHER_CTX *ctx; const EVP_CIPHER *cipher = NULL; ErlNifBinary key, iv, aad, in, tag; unsigned char *outp; - ERL_NIF_TERM out; - int len; + ERL_NIF_TERM type, out; + int len, ctx_ctrl_set_ivlen; - if (!enif_inspect_iolist_as_binary(env, argv[0], &key) - || (key.size != 16 && key.size != 24 && key.size != 32) - || !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0 - || !enif_inspect_iolist_as_binary(env, argv[2], &aad) - || !enif_inspect_iolist_as_binary(env, argv[3], &in) - || !enif_inspect_iolist_as_binary(env, argv[4], &tag)) { + type = argv[0]; +#if defined(HAVE_GCM_EVP_DECRYPT_BUG) + if (type == atom_aes_gcm) + return aes_gcm_decrypt_NO_EVP(env, argc, argv); +#endif + + if (!enif_is_atom(env, type) + || !enif_inspect_iolist_as_binary(env, argv[1], &key) + || !enif_inspect_binary(env, argv[2], &iv) + || !enif_inspect_iolist_as_binary(env, argv[3], &aad) + || !enif_inspect_iolist_as_binary(env, argv[4], &in) + || !enif_inspect_iolist_as_binary(env, argv[5], &tag)) { return enif_make_badarg(env); } - if (key.size == 16) - cipher = EVP_aes_128_gcm(); - else if (key.size == 24) - cipher = EVP_aes_192_gcm(); - else if (key.size == 32) - cipher = EVP_aes_256_gcm(); + /* Use cipher_type some day. Must check block_encrypt|decrypt first */ +#if defined(HAVE_GCM) + if ((type == atom_aes_gcm) + && (iv.size > 0)) { + ctx_ctrl_set_ivlen = EVP_CTRL_GCM_SET_IVLEN; + if (key.size == 16) cipher = EVP_aes_128_gcm(); + else if (key.size == 24) cipher = EVP_aes_192_gcm(); + else if (key.size == 32) cipher = EVP_aes_256_gcm(); + else + enif_make_badarg(env); - ctx = EVP_CIPHER_CTX_new(); + } else +#endif +#if defined(HAVE_CCM) + if ((type == atom_aes_ccm) + && (iv.size > 0)) { + ctx_ctrl_set_ivlen = EVP_CTRL_CCM_SET_IVLEN; + if (key.size == 16) cipher = EVP_aes_128_ccm(); + else if (key.size == 24) cipher = EVP_aes_192_ccm(); + else if (key.size == 32) cipher = EVP_aes_256_ccm(); + else + enif_make_badarg(env); - if (EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1) - goto out_err; - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv.size, NULL) != 1) - goto out_err; - if (EVP_DecryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) - goto out_err; - if (EVP_DecryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1) - goto out_err; + } else +#endif + enif_make_badarg(env); outp = enif_make_new_binary(env, in.size, &out); - if (EVP_DecryptUpdate(ctx, outp, &len, in.data, in.size) != 1) - goto out_err; - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, tag.size, tag.data) != 1) - goto out_err; - if (EVP_DecryptFinal_ex(ctx, outp+len, &len) != 1) - goto out_err; + ctx = EVP_CIPHER_CTX_new(); + if (EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1) goto out_err; + if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_set_ivlen, iv.size, NULL) != 1) goto out_err; + +#if defined(HAVE_CCM) + if (type == atom_aes_ccm) { + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, tag.size, tag.data) != 1) goto out_err; + } +#endif + + if (EVP_DecryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) goto out_err; + +#if defined(HAVE_CCM) + if (type == atom_aes_ccm) { + if (1 != EVP_DecryptUpdate(ctx, NULL, &len, NULL, in.size)) goto out_err; + } +#endif + if (EVP_DecryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1) goto out_err; + if (EVP_DecryptUpdate(ctx, outp, &len, in.data, in.size) != 1) goto out_err; + +#if defined(HAVE_GCM) + if (type == atom_aes_gcm) { + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, tag.size, tag.data) != 1) goto out_err; + if (EVP_DecryptFinal_ex(ctx, outp+len, &len) != 1) goto out_err; + } +#endif EVP_CIPHER_CTX_free(ctx); CONSUME_REDS(env, in); - return out; out_err: @@ -2414,19 +2759,19 @@ out_err: #ifdef HAVE_GCM_EVP_DECRYPT_BUG static ERL_NIF_TERM aes_gcm_decrypt_NO_EVP(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ +{/* (Type,Key,Iv,AAD,In,Tag) */ GCM128_CONTEXT *ctx; ErlNifBinary key, iv, aad, in, tag; AES_KEY aes_key; unsigned char *outp; ERL_NIF_TERM out; - if (!enif_inspect_iolist_as_binary(env, argv[0], &key) + if (!enif_inspect_iolist_as_binary(env, argv[1], &key) || AES_set_encrypt_key(key.data, key.size*8, &aes_key) != 0 - || !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0 - || !enif_inspect_iolist_as_binary(env, argv[2], &aad) - || !enif_inspect_iolist_as_binary(env, argv[3], &in) - || !enif_inspect_iolist_as_binary(env, argv[4], &tag)) { + || !enif_inspect_binary(env, argv[2], &iv) || iv.size == 0 + || !enif_inspect_iolist_as_binary(env, argv[3], &aad) + || !enif_inspect_iolist_as_binary(env, argv[4], &in) + || !enif_inspect_iolist_as_binary(env, argv[5], &tag)) { return enif_make_badarg(env); } @@ -2573,6 +2918,69 @@ out_err: #endif } + +static ERL_NIF_TERM chacha20_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* (Key, IV) */ +#if defined(HAVE_CHACHA20) + ErlNifBinary key_bin, ivec_bin; + struct evp_cipher_ctx *ctx; + const EVP_CIPHER *cipher; + ERL_NIF_TERM ret; + + if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin) + || !enif_inspect_binary(env, argv[1], &ivec_bin) + || key_bin.size != 32 + || ivec_bin.size != 16) { + return enif_make_badarg(env); + } + + cipher = EVP_chacha20(); + + ctx = enif_alloc_resource(evp_cipher_ctx_rtype, sizeof(struct evp_cipher_ctx)); + ctx->ctx = EVP_CIPHER_CTX_new(); + + + EVP_CipherInit_ex(ctx->ctx, cipher, NULL, + key_bin.data, ivec_bin.data, 1); + EVP_CIPHER_CTX_set_padding(ctx->ctx, 0); + ret = enif_make_resource(env, ctx); + enif_release_resource(ctx); + return ret; +#else + return enif_raise_exception(env, atom_notsup); +#endif +}; + +static ERL_NIF_TERM chacha20_stream_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* (State, Data) */ +#if defined(HAVE_CHACHA20) + struct evp_cipher_ctx *ctx, *new_ctx; + ErlNifBinary data_bin; + ERL_NIF_TERM ret, cipher_term; + unsigned char *out; + int outl = 0; + + if (!enif_get_resource(env, argv[0], evp_cipher_ctx_rtype, (void**)&ctx) + || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) { + return enif_make_badarg(env); + } + new_ctx = enif_alloc_resource(evp_cipher_ctx_rtype, sizeof(struct evp_cipher_ctx)); + new_ctx->ctx = EVP_CIPHER_CTX_new(); + EVP_CIPHER_CTX_copy(new_ctx->ctx, ctx->ctx); + out = enif_make_new_binary(env, data_bin.size, &cipher_term); + EVP_CipherUpdate(new_ctx->ctx, out, &outl, data_bin.data, data_bin.size); + ASSERT(outl == data_bin.size); + + ret = enif_make_tuple2(env, enif_make_resource(env, new_ctx), cipher_term); + enif_release_resource(new_ctx); + CONSUME_REDS(env,data_bin); + return ret; +#else + return enif_raise_exception(env, atom_notsup); +#endif +}; + + static ERL_NIF_TERM strong_rand_bytes_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Bytes) */ unsigned bytes; @@ -3810,7 +4218,7 @@ static ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF int i; EC_GROUP *group; const BIGNUM *priv_key; - EC_POINT *my_ecpoint; + EC_POINT *my_ecpoint = NULL; EC_KEY *other_ecdh = NULL; if (!get_ec_key(env, argv[1], argv[2], atom_undefined, &key)) @@ -3853,11 +4261,10 @@ out_err: #endif } -// EXPERIMENTAL! static ERL_NIF_TERM evp_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) /* (Curve, PeerBin, MyBin) */ { -#ifdef HAVE_EDDH +#ifdef HAVE_ED_CURVE_DH int type; EVP_PKEY_CTX *ctx; ErlNifBinary peer_bin, my_bin, key_bin; @@ -3909,11 +4316,10 @@ static ERL_NIF_TERM evp_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_ #endif } -// EXPERIMENTAL! static ERL_NIF_TERM evp_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) /* (Curve) */ { -#ifdef HAVE_EDDH +#ifdef HAVE_ED_CURVE_DH int type; EVP_PKEY_CTX *ctx; EVP_PKEY *pkey = NULL; @@ -3926,22 +4332,20 @@ static ERL_NIF_TERM evp_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF if (!(ctx = EVP_PKEY_CTX_new_id(type, NULL))) return enif_make_badarg(env); - if (!EVP_PKEY_keygen_init(ctx)) return enif_make_atom(env,"EVP_PKEY_keygen_init failed"); - if (!EVP_PKEY_keygen(ctx, &pkey)) return enif_make_atom(env,"EVP_PKEY_keygen failed"); + if (!EVP_PKEY_keygen_init(ctx)) return atom_error; + if (!EVP_PKEY_keygen(ctx, &pkey)) return atom_error; - if (!EVP_PKEY_get_raw_public_key(pkey, NULL, &key_len)) - return enif_make_atom(env,"EVP_PKEY_get_raw_public_key 1 failed"); + if (!EVP_PKEY_get_raw_public_key(pkey, NULL, &key_len)) return atom_error; if (!EVP_PKEY_get_raw_public_key(pkey, enif_make_new_binary(env, key_len, &ret_pub), &key_len)) - return enif_make_atom(env,"EVP_PKEY_get_raw_public_key 2 failed"); + return atom_error; - if (!EVP_PKEY_get_raw_private_key(pkey, NULL, &key_len)) - return enif_make_atom(env,"EVP_PKEY_get_raw_private_key 1 failed"); + if (!EVP_PKEY_get_raw_private_key(pkey, NULL, &key_len)) return atom_error; if (!EVP_PKEY_get_raw_private_key(pkey, enif_make_new_binary(env, key_len, &ret_prv), &key_len)) - return enif_make_atom(env,"EVP_PKEY_get_raw_private_key 2 failed"); + return atom_error; return enif_make_tuple2(env, ret_pub, ret_prv); #else @@ -4092,7 +4496,7 @@ static int get_pkey_sign_options(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF if (tpl_terms[1] == atom_rsa_pkcs1_padding) { opt->rsa_padding = RSA_PKCS1_PADDING; } else if (tpl_terms[1] == atom_rsa_pkcs1_pss_padding) { -#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0) +#ifdef HAVE_RSA_PKCS1_PSS_PADDING opt->rsa_padding = RSA_PKCS1_PSS_PADDING; if (opt->rsa_mgf1_md == NULL) { opt->rsa_mgf1_md = md; @@ -4381,6 +4785,7 @@ printf("\r\n"); if (argv[0] == atom_rsa) { if (EVP_PKEY_CTX_set_rsa_padding(ctx, sig_opt.rsa_padding) <= 0) goto badarg; +#ifdef HAVE_RSA_PKCS1_PSS_PADDING if (sig_opt.rsa_padding == RSA_PKCS1_PSS_PADDING) { if (sig_opt.rsa_mgf1_md != NULL) { #if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,1) @@ -4395,6 +4800,7 @@ printf("\r\n"); && EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, sig_opt.rsa_pss_saltlen) <= 0) goto badarg; } +#endif } if (EVP_PKEY_sign(ctx, NULL, &siglen, tbs, tbslen) <= 0) goto badarg; @@ -4876,7 +5282,7 @@ static ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM } else { /* non-evp rsa private decrypt */ i = RSA_private_decrypt(in_bin.size, in_bin.data, - out_bin.data, rsa, crypt_opt.rsa_padding); + out_bin.data, rsa, crypt_opt.rsa_padding); if (i > 0) { ERL_VALGRIND_MAKE_MEM_DEFINED(out_bin.data, i); enif_realloc_binary(&out_bin, i); @@ -4894,7 +5300,7 @@ static ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM } else { /* non-evp rsa public decrypt */ i = RSA_public_decrypt(in_bin.size, in_bin.data, - out_bin.data, rsa, crypt_opt.rsa_padding); + out_bin.data, rsa, crypt_opt.rsa_padding); if (i > 0) { ERL_VALGRIND_MAKE_MEM_DEFINED(out_bin.data, i); enif_realloc_binary(&out_bin, i); @@ -4913,7 +5319,10 @@ static ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM unsigned char *p; if (rsa == NULL) goto badarg; tmplen = RSA_size(rsa); - if (!enif_alloc_binary(tmplen, &tmp_bin)) goto badarg; + if (!enif_alloc_binary(tmplen, &tmp_bin)) { + RSA_free(rsa); + goto badarg; + } p = out_bin.data; p++; i = RSA_padding_check_SSLv23(tmp_bin.data, tmplen, p, out_bin.size - 1, tmplen); @@ -4924,6 +5333,7 @@ static ERL_NIF_TERM pkey_crypt_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM tmp_bin = in_bin; i = 1; } + RSA_free(rsa); } #endif } @@ -5012,7 +5422,7 @@ static ERL_NIF_TERM privkey_to_pubkey_nif(ErlNifEnv* env, int argc, const ERL_NI / * Example of result: { Curve = {Field, Prime, Point, Order, CoFactor} = - { + { Field = {prime_field,<<255,...,255>>}, Prime = {<<255,...,252>>, <<90,...,75>>, @@ -5025,9 +5435,9 @@ static ERL_NIF_TERM privkey_to_pubkey_nif(ErlNifEnv* env, int argc, const ERL_NI Key = <<151,...,62>> } or - { + { Curve = - {characteristic_two_field, + {characteristic_two_field, M, Basis = {tpbasis, _} | {ppbasis, k1, k2, k3} @@ -5040,7 +5450,7 @@ static ERL_NIF_TERM privkey_to_pubkey_nif(ErlNifEnv* env, int argc, const ERL_NI */ #endif } - + if (pkey) EVP_PKEY_free(pkey); return enif_make_badarg(env); } @@ -5221,7 +5631,7 @@ static ERL_NIF_TERM engine_ctrl_cmd_strings_nif(ErlNifEnv* env, int argc, const error: for(i = 0; cmds != NULL && cmds[i] != NULL; i++) - enif_free(cmds[i]); + enif_free(cmds[i]); enif_free(cmds); return ret; #else @@ -5539,7 +5949,7 @@ static ERL_NIF_TERM engine_get_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE if (!engine_id) { enif_alloc_binary(0, &engine_id_bin); engine_id_bin.size = 0; - return enif_make_tuple2(env, atom_ok, enif_make_binary(env, &engine_id_bin)); + return enif_make_binary(env, &engine_id_bin); } size = strlen(engine_id); @@ -5547,7 +5957,39 @@ static ERL_NIF_TERM engine_get_id_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE engine_id_bin.size = size; memcpy(engine_id_bin.data, engine_id, size); - return enif_make_tuple2(env, atom_ok, enif_make_binary(env, &engine_id_bin)); + return enif_make_binary(env, &engine_id_bin); +#else + return atom_notsup; +#endif +} + +static ERL_NIF_TERM engine_get_name_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* (Engine) */ +#ifdef HAS_ENGINE_SUPPORT + ErlNifBinary engine_name_bin; + const char *engine_name; + int size; + struct engine_ctx *ctx; + + // Get Engine + if (!enif_get_resource(env, argv[0], engine_ctx_rtype, (void**)&ctx)) { + PRINTF_ERR0("engine_get_id_nif Leaved: Parameter not an engine resource object"); + return enif_make_badarg(env); + } + + engine_name = ENGINE_get_name(ctx->engine); + if (!engine_name) { + enif_alloc_binary(0, &engine_name_bin); + engine_name_bin.size = 0; + return enif_make_binary(env, &engine_name_bin); + } + + size = strlen(engine_name); + enif_alloc_binary(size, &engine_name_bin); + engine_name_bin.size = size; + memcpy(engine_name_bin.data, engine_name, size); + + return enif_make_binary(env, &engine_name_bin); #else return atom_notsup; #endif |