aboutsummaryrefslogtreecommitdiffstats
path: root/lib/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'lib/crypto')
-rw-r--r--lib/crypto/c_src/Makefile.in60
-rw-r--r--lib/crypto/c_src/crypto.c292
-rw-r--r--lib/crypto/configure.in780
-rw-r--r--lib/crypto/doc/src/crypto.xml283
-rw-r--r--lib/crypto/doc/src/engine_load.xml31
-rw-r--r--lib/crypto/src/crypto.erl220
-rw-r--r--lib/crypto/src/crypto_ec_curves.erl36
-rw-r--r--lib/crypto/test/crypto_SUITE.erl197
-rw-r--r--lib/crypto/test/engine_SUITE.erl278
9 files changed, 1973 insertions, 204 deletions
diff --git a/lib/crypto/c_src/Makefile.in b/lib/crypto/c_src/Makefile.in
index 31124ba477..cd0e5442e9 100644
--- a/lib/crypto/c_src/Makefile.in
+++ b/lib/crypto/c_src/Makefile.in
@@ -19,7 +19,6 @@
#
include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
-include $(ERL_TOP)/make/$(TARGET)/otp_ded.mk
# ----------------------------------------------------
# Application version
@@ -31,23 +30,20 @@ VSN=$(CRYPTO_VSN)
# The following variables differ between systems.
# Set by configure.
# ----------------------------------------------------
-CC = $(DED_CC)
-LD = $(DED_LD)
+CC = @DED_CC@
+LD = @DED_LD@
SHELL = /bin/sh
-LIBS = $(DED_LIBS)
-LDFLAGS += $(DED_LDFLAGS)
-CFLAGS = $(DED_CFLAGS)
+LIBS = @DED_LIBS@
+LDFLAGS += @DED_LDFLAGS@
+CFLAGS = @DED_CFLAGS@ @SSL_FLAGS@
# From erts/configure
SSL_LIBDIR = @SSL_LIBDIR@
SSL_INCLUDE = @SSL_INCLUDE@
SSL_CRYPTO_LIBNAME = @SSL_CRYPTO_LIBNAME@
SSL_SSL_LIBNAME = @SSL_SSL_LIBNAME@
-SSL_FLAGS = @SSL_FLAGS@
-
-INCLUDES = $(SSL_INCLUDE) $(DED_INCLUDES)
-CFLAGS += $(SSL_FLAGS)
+INCLUDES = $(SSL_INCLUDE) @DED_INCLUDE@
ifeq ($(TYPE),debug)
TYPEMARKER = .debug
@@ -70,6 +66,11 @@ RELSYSDIR = $(RELEASE_PATH)/lib/crypto-$(VSN)
# ----------------------------------------------------
# Misc Macros
# ----------------------------------------------------
+
+PRIVDIR = ../priv
+OBJDIR = $(PRIVDIR)/obj/$(TARGET)
+LIBDIR = $(PRIVDIR)/lib/$(TARGET)
+
CRYPTO_OBJS = $(OBJDIR)/crypto$(TYPEMARKER).o
CALLBACK_OBJS = $(OBJDIR)/crypto_callback$(TYPEMARKER).o
NIF_MAKEFILE = $(PRIVDIR)/Makefile
@@ -80,19 +81,10 @@ NIF_ARCHIVE = $(LIBDIR)/crypto$(TYPEMARKER).a
TEST_ENGINE_OBJS = $(OBJDIR)/otp_test_engine$(TYPEMARKER).o
-ifeq ($(findstring win32,$(TARGET)), win32)
-NIF_LIB = $(LIBDIR)/crypto$(TYPEMARKER).dll
-CALLBACK_LIB = $(LIBDIR)/crypto_callback$(TYPEMARKER).dll
-TEST_ENGINE_LIB = $(LIBDIR)/otp_test_engine$(TYPEMARKER).dll
-else
-NIF_LIB = $(LIBDIR)/crypto$(TYPEMARKER).so
-CALLBACK_LIB = $(LIBDIR)/crypto_callback$(TYPEMARKER).so
-TEST_ENGINE_LIB = $(LIBDIR)/otp_test_engine$(TYPEMARKER).so
-endif
+NIF_LIB = $(LIBDIR)/crypto$(TYPEMARKER).@DED_EXT@
+CALLBACK_LIB = $(LIBDIR)/crypto_callback$(TYPEMARKER).@DED_EXT@
+TEST_ENGINE_LIB = $(LIBDIR)/otp_test_engine$(TYPEMARKER).@DED_EXT@
-ifeq ($(HOST_OS),)
-HOST_OS := $(shell $(ERL_TOP)/erts/autoconf/config.guess)
-endif
DYNAMIC_CRYPTO_LIB=@SSL_DYNAMIC_ONLY@
ifeq ($(DYNAMIC_CRYPTO_LIB),yes)
@@ -125,7 +117,7 @@ RANLIB=true
endif
ALL_CFLAGS = $(TYPE_FLAGS) $(EXTRA_FLAGS) $(INCLUDES)
-ALL_STATIC_CFLAGS = $(DED_STATIC_CFLAGS) $(INCLUDES)
+ALL_STATIC_CFLAGS = @DED_STATIC_CFLAGS@ $(INCLUDES)
# ----------------------------------------------------
# Targets
@@ -181,21 +173,13 @@ endif
clean:
-ifeq ($(findstring win32,$(TARGET)), win32)
- rm -f $(LIBDIR)/crypto.dll
- rm -f $(LIBDIR)/crypto.debug.dll
- rm -f $(LIBDIR)/crypto_callback.dll
- rm -f $(LIBDIR)/crypto_callback.debug.dll
- rm -f $(LIBDIR)/otp_test_engine.dll
-else
- rm -f $(LIBDIR)/crypto.so
- rm -f $(LIBDIR)/crypto.debug.so
- rm -f $(LIBDIR)/crypto.valgrind.so
- rm -f $(LIBDIR)/crypto_callback.so
- rm -f $(LIBDIR)/crypto_callback.debug.so
- rm -f $(LIBDIR)/crypto_callback.valgrind.so
- rm -f $(LIBDIR)/otp_test_engine.so
-endif
+ rm -f $(LIBDIR)/crypto.@DED_EXT@
+ rm -f $(LIBDIR)/crypto.debug.@DED_EXT@
+ rm -f $(LIBDIR)/crypto.valgrind.@DED_EXT@
+ rm -f $(LIBDIR)/crypto_callback.@DED_EXT@
+ rm -f $(LIBDIR)/crypto_callback.debug.@DED_EXT@
+ rm -f $(LIBDIR)/crypto_callback.valgrind.@DED_EXT@
+ rm -f $(LIBDIR)/otp_test_engine.@DED_EXT@
rm -f $(OBJDIR)/crypto.o
rm -f $(OBJDIR)/crypto_static.o
rm -f $(OBJDIR)/crypto.debug.o
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index a9fef65e03..d409ea7dcf 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -178,11 +178,19 @@
#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
+
#if OPENSSL_VERSION_NUMBER <= PACKED_OPENSSL_VERSION(0,9,8,'l')
# define HAVE_ECB_IVEC_BUG
#endif
@@ -524,6 +532,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[]);
@@ -537,6 +550,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 */
@@ -613,6 +627,12 @@ static ErlNifFunc nif_funcs[] = {
{"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},
@@ -626,6 +646,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}
};
@@ -1244,7 +1265,7 @@ 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 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 */
@@ -1332,21 +1353,117 @@ 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
algo_curve[algo_curve_cnt++] = enif_make_atom(env,"x25519");
@@ -1990,6 +2107,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;
@@ -2574,6 +2747,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;
@@ -4877,7 +5113,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);
@@ -4895,7 +5131,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);
@@ -5013,7 +5249,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>>,
@@ -5026,9 +5262,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}
@@ -5041,7 +5277,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);
}
@@ -5222,7 +5458,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
@@ -5540,7 +5776,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);
@@ -5548,7 +5784,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
diff --git a/lib/crypto/configure.in b/lib/crypto/configure.in
new file mode 100644
index 0000000000..3e54371198
--- /dev/null
+++ b/lib/crypto/configure.in
@@ -0,0 +1,780 @@
+dnl Process this file with autoconf to produce a configure script. -*-m4-*-
+dnl
+dnl %CopyrightBegin%
+dnl
+dnl Copyright Ericsson AB 2018. All Rights Reserved.
+dnl
+dnl Licensed under the Apache License, Version 2.0 (the "License");
+dnl you may not use this file except in compliance with the License.
+dnl You may obtain a copy of the License at
+dnl
+dnl http://www.apache.org/licenses/LICENSE-2.0
+dnl
+dnl Unless required by applicable law or agreed to in writing, software
+dnl distributed under the License is distributed on an "AS IS" BASIS,
+dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+dnl See the License for the specific language governing permissions and
+dnl limitations under the License.
+dnl
+dnl %CopyrightEnd%
+dnl
+
+dnl define([AC_CACHE_LOAD], )dnl
+dnl define([AC_CACHE_SAVE], )dnl
+
+
+AC_INIT(vsn.mk)
+
+if test -z "$ERL_TOP" || test ! -d "$ERL_TOP" ; then
+ AC_CONFIG_AUX_DIRS(autoconf)
+else
+ erl_top=${ERL_TOP}
+ AC_CONFIG_AUX_DIRS($erl_top/erts/autoconf)
+fi
+
+if test "X$host" != "Xfree_source" -a "X$host" != "Xwin32"; then
+ AC_CANONICAL_HOST
+else
+ host_os=win32
+fi
+
+LM_PRECIOUS_VARS
+
+if test "$cross_compiling" = "yes"; then
+ CROSS_COMPILING=yes
+else
+ CROSS_COMPILING=no
+fi
+AC_SUBST(CROSS_COMPILING)
+
+ERL_XCOMP_SYSROOT_INIT
+
+AC_PROG_CC
+LM_WINDOWS_ENVIRONMENT
+
+ERL_DED
+
+dnl
+dnl SSL, SSH and CRYPTO need the OpenSSL libraries
+dnl
+dnl Check flags --with-ssl, --without-ssl --with-ssl=PATH.
+dnl If no option is given or --with-ssl is set without a path then we
+dnl search for OpenSSL libraries and header files in the standard locations.
+dnl If set to --without-ssl we disable the use of SSL, SSH and CRYPTO.
+dnl If set to --with-ssl=PATH we use that path as the prefix, i.e. we
+dnl use "PATH/include" and "PATH/lib".
+
+AC_CHECK_SIZEOF(void *)
+
+CC=$DED_CC
+CFLAGS=$DED_BASIC_CFLAGS
+LD=$DED_LD
+LDFLAGS=$DED_LDFLAGS
+
+std_ssl_locations="/usr/local /usr/sfw /usr /opt/local /usr/pkg /usr/local/openssl /usr/lib/openssl /usr/openssl /usr/local/ssl /usr/lib/ssl /usr/ssl /"
+
+AC_ARG_WITH(ssl-zlib,
+AS_HELP_STRING([--with-ssl-zlib=PATH],
+ [specify location of ZLib to be used by OpenSSL])
+AS_HELP_STRING([--with-ssl-zlib],
+ [link SSL with Zlib (default if found)])
+AS_HELP_STRING([--without-ssl-zlib],
+ [don't link SSL with ZLib]))
+
+if test "x$with_ssl_zlib" = "xno"; then
+ SSL_LINK_WITH_ZLIB=no
+ STATIC_ZLIB_LIBS=
+elif test "x$with_ssl_zlib" = "xyes" || test "x$with_ssl_zlib" = "x"; then
+ if test $erl_xcomp_without_sysroot = yes; then
+ AC_MSG_WARN([Cannot search for zlib; missing cross system root (erl_xcomp_sysroot).])
+ SSL_LINK_WITH_ZLIB=no
+ STATIC_ZLIB_LIBS=
+ elif test "x$MIXED_CYGWIN" = "xyes" -o "x$MIXED_MSYS" = "xyes"; then
+ SSL_LINK_WITH_ZLIB=no
+ STATIC_ZLIB_LIBS=
+ else
+ SSL_LINK_WITH_ZLIB=no
+ STATIC_ZLIB_LIBS=
+ AC_MSG_CHECKING(for static ZLib to be used by SSL in standard locations)
+ for rdir in $std_ssl_locations; do
+ dir="$erl_xcomp_sysroot$rdir"
+ if test "x$ac_cv_sizeof_void_p" = "x8"; then
+ if test -f "$dir/lib64/libz.a"; then
+ SSL_LINK_WITH_ZLIB=yes
+ STATIC_ZLIB_LIBS="$dir/lib64/libz.a"
+ break
+ elif test -f "$dir/lib/64/libz.a"; then
+ SSL_LINK_WITH_ZLIB=yes
+ STATIC_ZLIB_LIBS="$dir/lib/64/libz.a"
+ break
+ fi
+ fi
+ if test -f "$dir/lib/libz.a"; then
+ SSL_LINK_WITH_ZLIB=yes
+ STATIC_ZLIB_LIBS="$dir/lib/libz.a"
+ break
+ fi
+ done
+ if test "x$SSL_LINK_WITH_ZLIB" = "xno"; then
+ AC_MSG_RESULT([no])
+ else
+ AC_MSG_RESULT([$STATIC_ZLIB_LIBS])
+ fi
+ fi
+else
+ SSL_LINK_WITH_ZLIB=no
+ STATIC_ZLIB_LIBS=
+ if test -f "$with_ssl_zlib/libz.a"; then
+ SSL_LINK_WITH_ZLIB=yes
+ STATIC_ZLIB_LIBS=$with_ssl_zlib/libz.a
+ elif test -f "$with_ssl_zlib/lib/libz.a"; then
+ SSL_LINK_WITH_ZLIB=yes
+ STATIC_ZLIB_LIBS=$with_ssl_zlib/lib/libz.a
+ fi
+ if test "x$ac_cv_sizeof_void_p" = "x8"; then
+ if test -f "$with_ssl_zlib/lib64/libz.a"; then
+ SSL_LINK_WITH_ZLIB=yes
+ STATIC_ZLIB_LIBS=$with_ssl_zlib/lib64/libz.a
+ elif test -f "$with_ssl_zlib/lib/64/libz.a"; then
+ SSL_LINK_WITH_ZLIB=yes
+ STATIC_ZLIB_LIBS=$with_ssl_zlib/lib/64/libz.a
+ fi
+ fi
+ if test "x$SSL_LINK_WITH_ZLIB" = "xno"; then
+ AC_MSG_ERROR(Invalid path to option --with-ssl-zlib=PATH)
+ fi
+fi
+
+
+AC_ARG_WITH(ssl,
+AS_HELP_STRING([--with-ssl=PATH], [specify location of OpenSSL include and lib])
+AS_HELP_STRING([--with-ssl], [use SSL (default)])
+AS_HELP_STRING([--without-ssl], [don't use SSL]))
+
+AC_ARG_WITH(ssl-incl,
+AS_HELP_STRING([--with-ssl-incl=PATH], [location of OpenSSL include dir, if different than specified by --with-ssl=PATH]),
+[
+case X$with_ssl in
+ X | Xyes | Xno) AC_MSG_ERROR([--with-ssl-incl=PATH set without --with-ssl=PATH]);;
+esac
+],
+[with_ssl_incl=$with_ssl]) #default
+
+AC_ARG_WITH(ssl-rpath,
+AS_HELP_STRING([--with-ssl-rpath=yes|no|PATHS],
+ [runtime library path for OpenSSL. Default is "yes", which equates to a
+ number of standard locations. If "no", then no runtime
+ library paths will be used. Anything else should be a
+ comma separated list of paths.]),
+[
+case X$with_ssl in
+ Xno) AC_MSG_ERROR([--with-ssl-rpath set without --with-ssl]);;
+esac
+],
+[with_ssl_rpath=yes]) #default
+
+
+AC_ARG_ENABLE(dynamic-ssl-lib,
+AS_HELP_STRING([--disable-dynamic-ssl-lib],
+ [disable using dynamic openssl libraries]),
+[ case "$enableval" in
+ no) enable_dynamic_ssl=no ;;
+ *) enable_dynamic_ssl=yes ;;
+ esac ], enable_dynamic_ssl=yes)
+
+#----------------------------------------------------------------------
+# We actually might do the SSL tests twice due to late discovery of
+# kerberos problems with static linking, in case we redo it all trying
+# dynamic SSL libraries instead.
+#----------------------------------------------------------------------
+
+ssl_done=no
+
+while test "x$ssl_done" != "xyes"; do
+
+ssl_done=yes # Default only one run
+
+# Remove all SKIP files from previous runs
+for a in ssl crypto ssh; do
+ rm -f "$ERL_TOP/lib/$a/SKIP"
+done
+
+SSL_DYNAMIC_ONLY=$enable_dynamic_ssl
+SSL_STATIC_ONLY=no
+
+case "$erl_xcomp_without_sysroot-$with_ssl" in
+ yes-* | no-no)
+ SSL_APP=
+ CRYPTO_APP=
+ SSH_APP=
+ if test "$with_ssl" = "no"; then
+ skip="User gave --without-ssl option"
+ else
+ skip="Cannot search for ssl; missing cross system root (erl_xcomp_sysroot)."
+ fi
+ for a in ssl crypto ssh; do
+ echo "$skip" > $ERL_TOP/lib/$a/SKIP
+ done
+ ;;
+ no-yes | no- )
+ # On windows, we could try to find the installation
+ # of Shining Light OpenSSL, which can be found by poking in
+ # the uninstall section in the registry, it's worth a try...
+ extra_dir=""
+ if test "x$MIXED_CYGWIN" = "xyes"; then
+ AC_CHECK_PROG(REGTOOL, regtool, regtool, false)
+ if test "$ac_cv_prog_REGTOOL" != false; then
+ wrp="/machine/software/microsoft/windows/currentversion/"
+ if test "x$ac_cv_sizeof_void_p" = "x8"; then
+ urp="uninstall/openssl (64-bit)_is1/inno setup: app path"
+ regtool_subsystem=-w
+ else
+ urp="uninstall/openssl (32-bit)_is1/inno setup: app path"
+ regtool_subsystem=-W
+ fi
+ rp="$wrp$urp"
+ if regtool -q $regtool_subsystem get "$rp" > /dev/null; then
+ true
+ else
+ # Fallback to unspecified wordlength
+ urp="uninstall/openssl_is1/inno setup: app path"
+ rp="$wrp$urp"
+ fi
+ if regtool -q $regtool_subsystem get "$rp" > /dev/null; then
+ ssl_install_dir=`regtool -q $regtool_subsystem get "$rp"`
+ # Try hard to get rid of spaces...
+ if cygpath -d "$ssl_install_dir" > /dev/null 2>&1; then
+ ssl_install_dir=`cygpath -d "$ssl_install_dir"`
+ fi
+ extra_dir=`cygpath $ssl_install_dir`
+ fi
+ fi
+ elif test "x$MIXED_MSYS" = "xyes"; then
+ AC_CHECK_PROG(REGTOOL, reg_query.sh, reg_query.sh, false)
+ if test "$ac_cv_prog_REGTOOL" != false; then
+ if test "x$ac_cv_sizeof_void_p" = "x8"; then
+ rp="HKLM/SOFTWARE/Microsoft/Windows/CurrentVersion/Uninstall/OpenSSL (64-bit)_is1"
+ else
+ rp="HKLM/SOFTWARE/Microsoft/Windows/CurrentVersion/Uninstall/OpenSSL_is1"
+ fi
+ key="Inno Setup: App Path"
+ if "$ac_cv_prog_REGTOOL" "$rp" "$key" > /dev/null; then
+ ssl_install_dir=`"$ac_cv_prog_REGTOOL" "$rp" "$key"`
+ extra_dir=`win2msys_path.sh "$ssl_install_dir"`
+ fi
+ fi
+ fi
+ # We search for OpenSSL in the common OS standard locations.
+ SSL_APP=ssl
+ CRYPTO_APP=crypto
+ SSH_APP=ssh
+
+ SSL_CRYPTO_LIBNAME=crypto
+ SSL_SSL_LIBNAME=ssl
+
+ if test "x$MIXED_CYGWIN" = "xyes" -o "x$MIXED_MSYS" = "xyes"; then
+ if test "x$ac_cv_sizeof_void_p" = "x8"; then
+ std_win_ssl_locations="/cygdrive/c/OpenSSL-Win64 /c/OpenSSL-Win64 /opt/local64/pgm/OpenSSL"
+ else
+ std_win_ssl_locations="/cygdrive/c/OpenSSL-Win32 /c/OpenSSL-Win32 /cygdrive/c/OpenSSL /c/OpenSSL /opt/local/pgm/OpenSSL"
+ fi
+ else
+ std_win_ssl_locations=""
+ fi
+
+
+ AC_MSG_CHECKING(for OpenSSL >= 0.9.8c in standard locations)
+ for rdir in $extra_dir $std_win_ssl_locations $std_ssl_locations; do
+ dir="$erl_xcomp_sysroot$rdir"
+ if test -f "$erl_xcomp_isysroot$rdir/include/openssl/opensslv.h"; then
+ is_real_ssl=yes
+ SSL_INCDIR="$dir"
+ if test "x$MIXED_CYGWIN" = "xyes" -o "x$MIXED_MSYS" = "xyes"; then
+ if test -f "$dir/lib/VC/libeay32.lib"; then
+ SSL_RUNTIME_LIBDIR="$rdir/lib/VC"
+ SSL_LIBDIR="$dir/lib/VC"
+ SSL_CRYPTO_LIBNAME=libeay32
+ SSL_SSL_LIBNAME=ssleay32
+ elif test -f "$dir/lib/VC/openssl.lib"; then
+ SSL_RUNTIME_LIBDIR="$rdir/lib/VC"
+ SSL_LIBDIR="$dir/lib/VC"
+ elif test -f $dir/lib/VC/libeay32MD.lib; then
+ SSL_CRYPTO_LIBNAME=libeay32MD
+ SSL_SSL_LIBNAME=ssleay32MD
+ if test "x$enable_dynamic_ssl" = "xno" && \
+ test -f $dir/lib/VC/static/libeay32MD.lib; then
+ SSL_RUNTIME_LIBDIR="$rdir/lib/VC/static"
+ SSL_LIBDIR="$dir/lib/VC/static"
+ else
+ SSL_RUNTIME_LIBDIR="$rdir/lib/VC"
+ SSL_LIBDIR="$dir/lib/VC"
+ fi
+ elif test -f "$dir/lib/libeay32.lib"; then
+ SSL_RUNTIME_LIBDIR="$rdir/lib"
+ SSL_LIBDIR="$dir/lib"
+ SSL_CRYPTO_LIBNAME=libeay32
+ SSL_SSL_LIBNAME=ssleay32
+ elif test -f "$dir/lib/openssl.lib"; then
+ SSL_RUNTIME_LIBDIR="$rdir/lib"
+ SSL_LIBDIR="$dir/lib"
+ else
+ is_real_ssl=no
+ fi
+ elif test -f "$dir/lib/powerpc/libsslcrypto.a"; then
+ SSL_CRYPTO_LIBNAME=sslcrypto
+ SSL_LIBDIR="$dir/lib/powerpc/"
+ SSL_RUNTIME_LIBDIR="$rdir/lib/powerpc/"
+ else
+ if test "x$ac_cv_sizeof_void_p" = "x8"; then
+ if test -f "$dir/lib64/libcrypto.a"; then
+ SSL_RUNTIME_LIBDIR="$rdir/lib64"
+ SSL_LIBDIR="$dir/lib64"
+ elif test -f "$dir/lib/64/libcrypto.a"; then
+ SSL_RUNTIME_LIBDIR="$rdir/lib/64"
+ SSL_LIBDIR="$dir/lib/64"
+ elif test -f "$dir/lib64/libcrypto.so"; then
+ SSL_RUNTIME_LIBDIR="$rdir/lib64"
+ SSL_LIBDIR="$dir/lib64"
+ elif test -f "$dir/lib/64/libcrypto.so"; then
+ SSL_RUNTIME_LIBDIR="$rdir/lib/64"
+ SSL_LIBDIR="$dir/lib/64"
+ else
+ SSL_RUNTIME_LIBDIR="$rdir/lib"
+ SSL_LIBDIR="$dir/lib"
+ fi
+ else
+ SSL_RUNTIME_LIBDIR="$rdir/lib"
+ SSL_LIBDIR="$dir/lib"
+ fi
+ fi
+ if test '!' -f "$SSL_LIBDIR/lib${SSL_CRYPTO_LIBNAME}.a"; then
+ SSL_DYNAMIC_ONLY=yes
+ elif test '!' -f "$SSL_LIBDIR/lib${SSL_CRYPTO_LIBNAME}.so" -a '!' -f "$SSL_LIBDIR/lib${SSL_CRYPTO_LIBNAME}.dylib"; then
+ SSL_STATIC_ONLY=yes
+ fi
+ SSL_BINDIR="$rdir/bin"
+ if test "x$is_real_ssl" = "xyes" ; then
+ SSL_INCLUDE="-I$dir/include"
+ old_CPPFLAGS=$CPPFLAGS
+ CPPFLAGS=$SSL_INCLUDE
+ AC_EGREP_CPP(^yes$,[
+#include <openssl/opensslv.h>
+#if OPENSSL_VERSION_NUMBER >= 0x0090803fL
+yes
+#endif
+ ],[
+ ssl_found=yes
+ ],[
+ SSL_APP=
+ ssl_found=no
+ ])
+ CPPFLAGS=$old_CPPFLAGS
+ if test "x$ssl_found" = "xyes"; then
+ if test "x$MIXED_CYGWIN" = "xyes" -o "x$MIXED_MSYS" = "xyes"; then
+ ssl_linkable=yes
+ elif test "x${SSL_CRYPTO_LIBNAME}" = "xsslcrypto"; then
+ # This should only be triggered seen OSE
+ ssl_linkable=yes
+ else
+ saveCFLAGS="$CFLAGS"
+ saveLDFLAGS="$LDFLAGS"
+ saveLIBS="$LIBS"
+ CFLAGS="$CFLAGS $SSL_INCLUDE"
+ if test "x$SSL_STATIC_ONLY" = "xyes"; then
+ LIBS="${SSL_LIBDIR}/lib${SSL_CRYPTO_LIBNAME}.a"
+ else
+ LDFLAGS="$LDFLAGS -L$SSL_LIBDIR"
+ LIBS="$LIBS -l${SSL_CRYPTO_LIBNAME}"
+ fi
+ AC_TRY_LINK([
+ #include <stdio.h>
+ #include <openssl/hmac.h>],
+ [
+ HMAC(0, 0, 0, 0, 0, 0, 0);
+ ],
+ [ssl_linkable=yes],
+ [ssl_linkable=no])
+ CFLAGS="$saveCFLAGS"
+ LDFLAGS="$saveLDFLAGS"
+ LIBS="$saveLIBS"
+ fi
+ fi
+ if test "x$ssl_found" = "xyes" && test "x$ssl_linkable" = "xyes"; then
+ AC_MSG_RESULT([$dir])
+ break;
+ fi
+ fi
+ fi
+ done
+
+ if test "x$ssl_found" != "xyes" ; then
+ dnl
+ dnl If no SSL found above, check whether we are running on OpenBSD.
+ dnl
+ case $host_os in
+ openbsd*)
+ if test -f "$erl_xcomp_isysroot/usr/include/openssl/opensslv.h"; then
+ # Trust OpenBSD to have everything the in the correct locations.
+ ssl_found=yes
+ ssl_linkable=yes
+ SSL_INCDIR="$erl_xcomp_sysroot/usr"
+ AC_MSG_RESULT([$SSL_INCDIR])
+ SSL_RUNTIME_LIB="/usr/lib"
+ SSL_LIB="$erl_xcomp_sysroot/usr/lib"
+ SSL_BINDIR="/usr/sbin"
+ dnl OpenBSD requires us to link with -L and -l
+ SSL_DYNAMIC_ONLY="yes"
+ fi
+ ;;
+ esac
+ fi
+dnl Now, certain linuxes have a 64bit libcrypto
+dnl that cannot build shared libraries (i.e. not PIC)
+dnl One could argue that this is wrong, but
+dnl so it is - be adoptable
+ if test "$ssl_found" = "yes" && test "$ssl_linkable" = "yes" && test "$SSL_DYNAMIC_ONLY" != "yes"; then
+ case $host_os in
+ linux*)
+ saveCFLAGS="$CFLAGS"
+ saveLDFLAGS="$LDFLAGS"
+ saveLIBS="$LIBS"
+ CFLAGS="$DED_CFLAGS $SSL_INCLUDE"
+ LDFLAGS="$DED_LDFLAGS"
+ LIBS="$SSL_LIBDIR/libcrypto.a $STATIC_ZLIB_LIBS"
+ AC_TRY_LINK([
+ #include <stdio.h>
+ #include <openssl/hmac.h>],
+ [
+ HMAC(0, 0, 0, 0, 0, 0, 0);
+ ],
+ [ssl_dyn_linkable=yes],
+ [ssl_dyn_linkable=no])
+ CFLAGS="$saveCFLAGS"
+ LDFLAGS="$saveLDFLAGS"
+ LIBS="$saveLIBS"
+ if test "x$ssl_dyn_linkable" != "xyes"; then
+ SSL_DYNAMIC_ONLY=yes
+ AC_MSG_WARN([SSL will be linked against dynamic lib as static lib is not purely relocatable])
+ fi
+ ;;
+ esac
+ fi
+
+
+
+
+ if test "x$ssl_found" != "xyes" || test "x$ssl_linkable" != "xyes"; then
+ if test "x$ssl_found" = "xyes"; then
+ AC_MSG_RESULT([found; but not usable])
+ else
+ AC_MSG_RESULT([no])
+ fi
+ SSL_APP=
+ CRYPTO_APP=
+ SSH_APP=
+ AC_MSG_WARN([No (usable) OpenSSL found, skipping ssl, ssh and crypto applications])
+
+ for a in ssl crypto ssh; do
+ echo "No usable OpenSSL found" > $ERL_TOP/lib/$a/SKIP
+ done
+ fi
+ ;;
+ *)
+ # Option given with PATH to package
+ if test ! -d "$with_ssl" ; then
+ AC_MSG_ERROR(Invalid path to option --with-ssl=PATH)
+ fi
+ if test ! -d "$with_ssl_incl" ; then
+ AC_MSG_ERROR(Invalid path to option --with-ssl-incl=PATH)
+ fi
+ SSL_INCDIR="$with_ssl_incl"
+ SSL_CRYPTO_LIBNAME=crypto
+ SSL_SSL_LIBNAME=ssl
+ if test "x$MIXED_CYGWIN" = "xyes" -o "x$MIXED_MSYS" = "xyes" && test -d "$with_ssl/lib/VC"; then
+ if test -f "$with_ssl/lib/VC/libeay32.lib"; then
+ SSL_LIBDIR="$with_ssl/lib/VC"
+ SSL_CRYPTO_LIBNAME=libeay32
+ SSL_SSL_LIBNAME=ssleay32
+ elif test -f "$with_ssl/lib/VC/openssl.lib"; then
+ SSL_LIBDIR="$with_ssl/lib/VC"
+ elif test -f $with_ssl/lib/VC/libeay32MD.lib; then
+ SSL_CRYPTO_LIBNAME=libeay32MD
+ SSL_SSL_LIBNAME=ssleay32MD
+ if test "x$enable_dynamic_ssl" = "xno" && \
+ test -f $with_ssl/lib/VC/static/libeay32MD.lib; then
+ SSL_LIBDIR="$with_ssl/lib/VC/static"
+ else
+ SSL_LIBDIR="$with_ssl/lib/VC"
+ fi
+ elif test -f "$with_ssl/lib/libeay32.lib"; then
+ SSL_LIBDIR="$with_ssl/lib"
+ SSL_CRYPTO_LIBNAME=libeay32
+ SSL_SSL_LIBNAME=ssleay32
+ else
+ # This probably wont work, but that's what the user said, so...
+ SSL_LIBDIR="$with_ssl/lib"
+ fi
+ elif test -f "$dir/lib/powerpc/libsslcrypto.a"; then
+ SSL_CRYPTO_LIBNAME=sslcrypto
+ SSL_LIBDIR="$with_ssl/lib/powerpc/"
+ elif test "x$ac_cv_sizeof_void_p" = "x8"; then
+ if test -f "$with_ssl/lib64/libcrypto.a"; then
+ SSL_LIBDIR="$with_ssl/lib64"
+ elif test -f "$with_ssl/lib/64/libcrypto.a"; then
+ SSL_LIBDIR="$with_ssl/lib/64"
+ elif test -f "$with_ssl/lib64/libcrypto.so"; then
+ SSL_LIBDIR="$with_ssl/lib64"
+ elif test -f "$with_ssl/lib/64/libcrypto.so"; then
+ SSL_LIBDIR="$with_ssl/lib/64"
+ else
+ SSL_LIBDIR="$with_ssl/lib"
+ fi
+ else
+ SSL_LIBDIR="$with_ssl/lib"
+ fi
+ if test '!' -f "${SSL_LIBDIR}/lib${SSL_CRYPTO_LIBNAME}.a"; then
+ SSL_DYNAMIC_ONLY=yes
+ elif test '!' -f ${SSL_LIBDIR}/lib${SSL_CRYPTO_LIBNAME}.so -a '!' -f "$SSL_LIBDIR/lib${SSL_CRYPTO_LIBNAME}.dylib"; then
+ SSL_STATIC_ONLY=yes
+ fi
+ SSL_INCLUDE="-I$with_ssl_incl/include"
+ SSL_APP=ssl
+ CRYPTO_APP=crypto
+ SSH_APP=ssh
+ if test "$cross_compiling" = "yes"; then
+ SSL_RUNTIME_LIBDIR=`echo "$SSL_LIBDIR" | sed -n "s|^$erl_xcomp_sysroot\(/*\)\(.*\)\$|/\2|p"`
+ else
+ SSL_RUNTIME_LIBDIR="$SSL_LIBDIR"
+ fi
+esac
+
+if test "x$SSL_APP" != "x" ; then
+ dnl We found openssl, now check if we use kerberos 5 support
+ dnl FIXME: Do we still support platforms that have Kerberos?
+ AC_MSG_CHECKING(for OpenSSL kerberos 5 support)
+ old_CPPFLAGS=$CPPFLAGS
+ CPPFLAGS=$SSL_INCLUDE
+ AC_EGREP_CPP(^yes$,[
+#include <openssl/opensslv.h>
+#include <openssl/opensslconf.h>
+#if OPENSSL_VERSION_NUMBER < 0x1010000fL && !defined(OPENSSL_NO_KRB5)
+yes
+#endif
+ ],[
+ AC_MSG_RESULT([yes])
+ ssl_krb5_enabled=yes
+ if test "x$SSL_DYNAMIC_ONLY" != "xyes"; then
+ if test -f "$SSL_LIBDIR/libkrb5.a"; then
+ SSL_LINK_WITH_KERBEROS=yes
+ STATIC_KERBEROS_LIBS="$SSL_LIBDIR/libkrb5.a"
+ if test -f "$SSL_LIBDIR/libkrb5support.a"; then
+ STATIC_KERBEROS_LIBS="$STATIC_KERBEROS_LIBS $SSL_LIBDIR/libkrb5support.a"
+ fi
+ if test -f "$SSL_LIBDIR/libk5crypto.a"; then
+ STATIC_KERBEROS_LIBS="$STATIC_KERBEROS_LIBS $SSL_LIBDIR/libk5crypto.a"
+ fi
+ if test -f "$SSL_LIBDIR/libresolv.a"; then
+ STATIC_KERBEROS_LIBS="$STATIC_KERBEROS_LIBS $SSL_LIBDIR/libresolv.a"
+ fi
+ if test -f "$SSL_LIBDIR/libcom_err.a"; then
+ STATIC_KERBEROS_LIBS="$STATIC_KERBEROS_LIBS $SSL_LIBDIR/libcom_err.a"
+ fi
+ else
+ AC_MSG_WARN([Kerberos needed but no kerberos static libraries found])
+ AC_MSG_WARN([Rescanning for dynamic SSL libraries])
+ enable_dynamic_ssl=yes
+ ssl_done=no
+ SSL_LINK_WITH_KERBEROS=no
+ STATIC_KERBEROS_LIBS=""
+ ssl_krb5_enabled=no
+ SSL_WITH_KERBEROS=no
+ fi
+ else
+ SSL_LINK_WITH_KERBEROS=no
+ STATIC_KERBEROS_LIBS=""
+ fi
+ ],[
+ AC_MSG_RESULT([no])
+ ssl_krb5_enabled=no
+ SSL_WITH_KERBEROS=no
+ ])
+ CPPFLAGS=$old_CPPFLAGS
+ SSL_KRB5_INCLUDE=
+ if test "x$ssl_krb5_enabled" = "xyes" ; then
+ AC_MSG_CHECKING(for krb5.h in standard locations)
+ for dir in $extra_dir "$SSL_INCDIR/include" "$SSL_INCDIR/include/openssl" \
+ "$SSL_INCDIR/include/kerberos" \
+ "$erl_xcomp_isysroot/cygdrive/c/kerberos/include" \
+ "$erl_xcomp_isysroot/usr/local/kerberos/include" \
+ "$erl_xcomp_isysroot/usr/kerberos/include" \
+ "$erl_xcomp_isysroot/usr/include"
+ do
+ if test -f "$dir/krb5.h" ; then
+ SSL_KRB5_INCLUDE="$dir"
+ break
+ fi
+ done
+ if test "x$SSL_KRB5_INCLUDE" = "x" ; then
+ AC_MSG_RESULT([not found])
+ SSL_APP=
+ CRYPTO_APP=
+ SSH_APP=
+ AC_MSG_WARN([OpenSSL is configured for kerberos but no krb5.h found])
+ for a in ssl crypto ssh ; do
+ echo "OpenSSL is configured for kerberos but no krb5.h found" > $ERL_TOP/lib/$a/SKIP
+ done
+ else
+ AC_MSG_RESULT([found in $SSL_KRB5_INCLUDE])
+ SSL_INCLUDE="$SSL_INCLUDE -I$SSL_KRB5_INCLUDE"
+ fi
+ fi
+fi
+
+done # while test ssl_done != yes
+
+SSL_DED_LD_RUNTIME_LIBRARY_PATH=
+ded_ld_rflg="$DED_LD_FLAG_RUNTIME_LIBRARY_PATH"
+
+
+case "$with_ssl_rpath" in
+
+yes) # Use standard lib locations for ssl runtime library path
+
+ if test "$SSL_APP" != "" && test "$SSL_DYNAMIC_ONLY" = "yes" && test "$ded_ld_rflg" != ""; then
+
+ AC_MSG_CHECKING(for ssl runtime library path to use)
+
+ libdirs="/lib"
+
+ if test "$ac_cv_sizeof_void_p" = "8"; then
+ dir_lib64=no
+ dir_lib_64=no
+
+ case "$SSL_RUNTIME_LIBDIR" in
+ */lib/64 | */lib/64/ ) dir_lib_64=yes;;
+ */lib64 | */lib64/ ) dir_lib64=yes;;
+ *) ;;
+ esac
+
+ for dir in $std_ssl_locations; do
+ test $dir_lib_64 = no &&
+ test -d "$erl_xcomp_sysroot$dir/lib/64" &&
+ dir_lib_64=yes
+ test $dir_lib64 = no &&
+ test -d "$erl_xcomp_sysroot$dir/lib64" &&
+ dir_lib64=yes
+ done
+
+ test $dir_lib_64 = yes && libdirs="/lib/64 $libdirs"
+ test $dir_lib64 = yes && libdirs="/lib64 $libdirs"
+ fi
+
+ for type in std x_std curr; do
+
+ ded_ld_rpath="$ded_ld_rflg$SSL_RUNTIME_LIBDIR"
+ rpath="$SSL_RUNTIME_LIBDIR"
+
+ if test $type != curr; then
+ for ldir in $libdirs; do
+ for dir in $std_ssl_locations; do
+ test "$SSL_LIBDIR" != "$dir$ldir" || continue
+ test $type != x_std || test -d "$dir$ldir" || continue
+ if test "$dir" = "/"; then
+ libdir="$ldir"
+ else
+ libdir="$dir$ldir"
+ fi
+ ded_ld_rpath="$ded_ld_rpath $ded_ld_rflg$libdir"
+ rpath="$rpath:$libdir"
+ done
+ done
+ fi
+
+ saveCFLAGS="$CFLAGS"
+ saveLDFLAGS="$LDFLAGS"
+ saveLIBS="$LIBS"
+ CFLAGS="$CFLAGS $SSL_INCLUDE"
+ LDFLAGS="$LDFLAGS $ld_rpath -L$SSL_LIBDIR"
+ LIBS="-lcrypto"
+ AC_TRY_LINK([
+ #include <stdio.h>
+ #include <openssl/hmac.h>
+ ],
+ [
+ HMAC(0, 0, 0, 0, 0, 0, 0);
+ ],
+ [rpath_success=yes],
+ [rpath_success=no])
+ CFLAGS="$saveCFLAGS"
+ LDFLAGS="$saveLDFLAGS"
+ LIBS="$saveLIBS"
+
+ test "$rpath_success" = "yes" && break
+ done
+
+ test "$rpath_success" = "yes" || { ded_ld_rpath=; rpath=; }
+
+ SSL_DED_LD_RUNTIME_LIBRARY_PATH="$ded_ld_rpath"
+
+ AC_MSG_RESULT([$rpath])
+ test "$rpath" != "" || AC_MSG_WARN([Cannot set run path during linking])
+ fi
+ ;;
+
+no) # Use no ssl runtime library path
+ SSL_DED_LD_RUNTIME_LIBRARY_PATH=
+ ;;
+
+*) # Use ssl runtime library paths set by --with-ssl-rpath (without any check)
+ ded_ld_rpath=
+ delimit=
+ for dir in `echo $with_ssl_rpath | sed "s/,/ /g"`; do
+ ded_ld_rpath="$ded_ld_rpath$delimit$ded_ld_rflg$dir"
+ delimit=" "
+ done
+ SSL_DED_LD_RUNTIME_LIBRARY_PATH="$ded_ld_rpath"
+ ;;
+
+esac
+
+
+AC_ARG_ENABLE(fips,
+AS_HELP_STRING([--enable-fips], [enable OpenSSL FIPS mode support])
+AS_HELP_STRING([--disable-fips], [disable OpenSSL FIPS mode support (default)]),
+[ case "$enableval" in
+ yes) enable_fips_support=yes ;;
+ *) enable_fips_support=no ;;
+ esac ], enable_fips_support=no)
+
+if test "x$enable_fips_support" = "xyes" && test "$CRYPTO_APP" != ""; then
+ saveCFLAGS="$CFLAGS"
+ saveLDFLAGS="$LDFLAGS"
+ saveLIBS="$LIBS"
+ CFLAGS="$CFLAGS $SSL_INCLUDE"
+ LDFLAGS="$LDFLAGS $ded_ld_rpath -L$SSL_LIBDIR"
+ LIBS="-lcrypto"
+ AC_CHECK_FUNC([FIPS_mode_set],
+ [SSL_FLAGS="-DFIPS_SUPPORT"],
+ [SSL_FLAGS=])
+ CFLAGS="$saveCFLAGS"
+ LDFLAGS="$saveLDFLAGS"
+ LIBS="$saveLIBS"
+else
+ SSL_FLAGS=
+fi
+
+AC_SUBST(SSL_INCLUDE)
+AC_SUBST(SSL_INCDIR)
+AC_SUBST(SSL_LIBDIR)
+AC_SUBST(SSL_FLAGS)
+AC_SUBST(SSL_CRYPTO_LIBNAME)
+AC_SUBST(SSL_SSL_LIBNAME)
+AC_SUBST(SSL_DED_LD_RUNTIME_LIBRARY_PATH)
+AC_SUBST(SSL_DYNAMIC_ONLY)
+AC_SUBST(SSL_LINK_WITH_KERBEROS)
+AC_SUBST(STATIC_KERBEROS_LIBS)
+AC_SUBST(SSL_LINK_WITH_ZLIB)
+AC_SUBST(STATIC_ZLIB_LIBS)
+
+AC_OUTPUT(c_src/$host/Makefile:c_src/Makefile.in)
+
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index 85d5ccaa34..38cc93a476 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -143,7 +143,7 @@
password => password()}</code>
<code>engine_ref() = term()</code>
- <p>The result of a call to <seealso marker="#engine_load-3">engine_load/3</seealso>.
+ <p>The result of a call to for example <seealso marker="#engine_load-3">engine_load/3</seealso>.
</p>
<code>key_id() = string() | binary()</code>
@@ -155,7 +155,7 @@
<p>The key's password
</p>
- <code>stream_cipher() = rc4 | aes_ctr </code>
+ <code>stream_cipher() = rc4 | aes_ctr | chacha20 </code>
<code>block_cipher() = aes_cbc | aes_cfb8 | aes_cfb128 | aes_ige256 | blowfish_cbc |
blowfish_cfb64 | des_cbc | des_cfb | des3_cbc | des3_cfb | des_ede3 | rc2_cbc </code>
@@ -193,9 +193,9 @@
Note that both md4 and md5 are recommended only for compatibility with existing applications.
</p>
<code> cipher_algorithms() = aes_cbc | aes_cfb8 | aes_cfb128 | aes_ctr | aes_gcm |
- aes_ige256 | blowfish_cbc | blowfish_cfb64 | chacha20_poly1305 | des_cbc |
+ aes_ige256 | blowfish_cbc | blowfish_cfb64 | chacha20 | chacha20_poly1305 | des_cbc |
des_cfb | des3_cbc | des3_cfb | des_ede3 | rc2_cbc | rc4 </code>
- <code> mac_algorithms() = hmac | cmac</code>
+ <code> mac_algorithms() = hmac | cmac | poly1305</code>
<code> public_key_algorithms() = rsa |dss | ecdsa | dh | ecdh | ec_gf2m</code>
<p>Note that ec_gf2m is not strictly a public key algorithm, but a restriction on what curves are supported
with ecdsa and ecdh.
@@ -598,6 +598,20 @@
</func>
<func>
+ <name>poly1305(Key, Data) -> Mac</name>
+ <fsummary></fsummary>
+ <type>
+ <v>Key = iodata()</v>
+ <v>Data = iodata()</v>
+ <v>Mac = binary()</v>
+ </type>
+ <desc>
+ <p>Computes a POLY1305 message authentication code (<c>Mac</c>) from <c>Data</c> using
+ <c>Key</c> as the authentication key.</p>
+ </desc>
+ </func>
+
+ <func>
<name>private_decrypt(Type, CipherText, PrivateKey, Padding) -> PlainText</name>
<fsummary>Decrypts CipherText using the private Key.</fsummary>
<type>
@@ -629,7 +643,7 @@
<desc>
<p>Fetches the corresponding public key from a private key stored in an Engine.
The key must be of the type indicated by the Type parameter.
- </p>
+ </p>
</desc>
</func>
@@ -958,7 +972,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<name>stream_init(Type, Key, IVec) -> State</name>
<fsummary></fsummary>
<type>
- <v>Type = aes_ctr </v>
+ <v>Type = aes_ctr | chacha20</v>
<v>State = opaque() </v>
<v>Key = iodata()</v>
<v>IVec = binary()</v>
@@ -1075,8 +1089,8 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<p>
Returns a list of all possible engine methods.
</p>
- <p>
- May throw exception notsup in case there is
+ <p>
+ May throw exception notsup in case there is
no engine support in the underlying OpenSSL implementation.
</p>
<p>
@@ -1092,18 +1106,18 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<type>
<v>EngineId = unicode:chardata()</v>
<v>PreCmds, PostCmds = [{unicode:chardata(), unicode:chardata()}]</v>
- <v>Result = {ok, Engine::term()} | {error, Reason::term()}</v>
+ <v>Result = {ok, Engine::engine_ref()} | {error, Reason::term()}</v>
</type>
<desc>
<p>
Loads the OpenSSL engine given by <c>EngineId</c> if it is available and then returns ok and
- an engine handle. This function is the same as calling <c>engine_load/4</c> with
- <c>EngineMethods</c> set to a list of all the possible methods. An error tuple is
+ an engine handle. This function is the same as calling <c>engine_load/4</c> with
+ <c>EngineMethods</c> set to a list of all the possible methods. An error tuple is
returned if the engine can't be loaded.
</p>
<p>
The function throws a badarg if the parameters are in wrong format.
- It may also throw the exception notsup in case there is
+ It may also throw the exception notsup in case there is
no engine support in the underlying OpenSSL implementation.
</p>
<p>
@@ -1120,7 +1134,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<v>EngineId = unicode:chardata()</v>
<v>PreCmds, PostCmds = [{unicode:chardata(), unicode:chardata()}]</v>
<v>EngineMethods = [engine_method_type()]</v>
- <v>Result = {ok, Engine::term()} | {error, Reason::term()}</v>
+ <v>Result = {ok, Engine::engine_ref()} | {error, Reason::term()}</v>
</type>
<desc>
<p>
@@ -1129,7 +1143,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</p>
<p>
The function throws a badarg if the parameters are in wrong format.
- It may also throw the exception notsup in case there is
+ It may also throw the exception notsup in case there is
no engine support in the underlying OpenSSL implementation.
</p>
<p>
@@ -1143,17 +1157,17 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<name>engine_unload(Engine) -> Result</name>
<fsummary>Dynamical load an encryption engine</fsummary>
<type>
- <v>Engine = term()</v>
+ <v>Engine = engine_ref()</v>
<v>Result = ok | {error, Reason::term()}</v>
</type>
<desc>
<p>
- Unloads the OpenSSL engine given by <c>EngineId</c>.
+ Unloads the OpenSSL engine given by <c>Engine</c>.
An error tuple is returned if the engine can't be unloaded.
</p>
<p>
The function throws a badarg if the parameter is in wrong format.
- It may also throw the exception notsup in case there is
+ It may also throw the exception notsup in case there is
no engine support in the underlying OpenSSL implementation.
</p>
<p>
@@ -1164,19 +1178,24 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
</func>
<func>
- <name>engine_list() -> Result</name>
- <fsummary>List the known engine ids</fsummary>
+ <name>engine_by_id(EngineId) -> Result</name>
+ <fsummary>Get a reference to an already loaded engine</fsummary>
<type>
- <v>Result = [EngineId::unicode:chardata()]</v>
+ <v>EngineID = unicode:chardata()engine_ref()</v>
+ <v>Result = {ok, Engine::engine_ref()} | {error, Reason::term()}</v>
</type>
<desc>
- <p>List the id's of all engines in OpenSSL's internal list.</p>
<p>
- It may also throw the exception notsup in case there is
+ Get a reference to an already loaded engine with <c>EngineId</c>.
+ An error tuple is returned if the engine can't be unloaded.
+ </p>
+ <p>
+ The function throws a badarg if the parameter is in wrong format.
+ It may also throw the exception notsup in case there is
no engine support in the underlying OpenSSL implementation.
</p>
<p>
- See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
in the User's Guide.
</p>
</desc>
@@ -1186,7 +1205,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<name>engine_ctrl_cmd_string(Engine, CmdName, CmdArg) -> Result</name>
<fsummary>Sends ctrl commands to an OpenSSL engine</fsummary>
<type>
- <v>Engine = term()</v>
+ <v>Engine = engine_ref()</v>
<v>CmdName = unicode:chardata()</v>
<v>CmdArg = unicode:chardata()</v>
<v>Result = ok | {error, Reason::term()}</v>
@@ -1194,12 +1213,12 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<desc>
<p>
Sends ctrl commands to the OpenSSL engine given by <c>Engine</c>.
- This function is the same as calling <c>engine_ctrl_cmd_string/4</c> with
+ This function is the same as calling <c>engine_ctrl_cmd_string/4</c> with
<c>Optional</c> set to <c>false</c>.
</p>
<p>
The function throws a badarg if the parameters are in wrong format.
- It may also throw the exception notsup in case there is
+ It may also throw the exception notsup in case there is
no engine support in the underlying OpenSSL implementation.
</p>
</desc>
@@ -1209,7 +1228,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<name>engine_ctrl_cmd_string(Engine, CmdName, CmdArg, Optional) -> Result</name>
<fsummary>Sends ctrl commands to an OpenSSL engine</fsummary>
<type>
- <v>Engine = term()</v>
+ <v>Engine = engine_ref()</v>
<v>CmdName = unicode:chardata()</v>
<v>CmdArg = unicode:chardata()</v>
<v>Optional = boolean()</v>
@@ -1218,18 +1237,218 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre>
<desc>
<p>
Sends ctrl commands to the OpenSSL engine given by <c>Engine</c>.
- <c>Optional</c> is a boolean argument that can relax the semantics of the function.
- If set to <c>true</c> it will only return failure if the ENGINE supported the given
- command name but failed while executing it, if the ENGINE doesn't support the command
- name it will simply return success without doing anything. In this case we assume
+ <c>Optional</c> is a boolean argument that can relax the semantics of the function.
+ If set to <c>true</c> it will only return failure if the ENGINE supported the given
+ command name but failed while executing it, if the ENGINE doesn't support the command
+ name it will simply return success without doing anything. In this case we assume
the user is only supplying commands specific to the given ENGINE so we set this to
<c>false</c>.
</p>
<p>
The function throws a badarg if the parameters are in wrong format.
- It may also throw the exception notsup in case there is
+ It may also throw the exception notsup in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>engine_add(Engine) -> Result</name>
+ <fsummary>Add engine to OpenSSL internal list</fsummary>
+ <type>
+ <v>Engine = engine_ref()</v>
+ <v>Result = ok | {error, Reason::term()}</v>
+ </type>
+ <desc>
+ <p>Add the engine to OpenSSL's internal list.</p>
+ <p>
+ The function throws a badarg if the parameters are in wrong format.
+ It may also throw the exception notsup in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>engine_remove(Engine) -> Result</name>
+ <fsummary>Remove engine to OpenSSL internal list</fsummary>
+ <type>
+ <v>Engine = engine_ref()</v>
+ <v>Result = ok | {error, Reason::term()}</v>
+ </type>
+ <desc>
+ <p>Remove the engine from OpenSSL's internal list.</p>
+ <p>
+ The function throws a badarg if the parameters are in wrong format.
+ It may also throw the exception notsup in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>engine_get_id(Engine) -> EngineId</name>
+ <fsummary>Fetch engine ID</fsummary>
+ <type>
+ <v>Engine = engine_ref()</v>
+ <v>EngineId = unicode:chardata()</v>
+ </type>
+ <desc>
+ <p>Return the ID for the engine, or an empty binary if there is no id set.</p>
+ <p>
+ The function throws a badarg if the parameters are in wrong format.
+ It may also throw the exception notsup in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>engine_get_name(Engine) -> EngineName</name>
+ <fsummary>Fetch engine name</fsummary>
+ <type>
+ <v>Engine = engine_ref()</v>
+ <v>EngineName = unicode:chardata()</v>
+ </type>
+ <desc>
+ <p>Return the name (eg a description) for the engine, or an empty binary if there is no name set.</p>
+ <p>
+ The function throws a badarg if the parameters are in wrong format.
+ It may also throw the exception notsup in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>engine_list() -> Result</name>
+ <fsummary>List the known engine ids</fsummary>
+ <type>
+ <v>Result = [EngineId::unicode:chardata()]</v>
+ </type>
+ <desc>
+ <p>List the id's of all engines in OpenSSL's internal list.</p>
+ <p>
+ It may also throw the exception notsup in case there is
no engine support in the underlying OpenSSL implementation.
</p>
+ <p>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ in the User's Guide.
+ </p>
+ <p>
+ May throw exception notsup in case engine functionality is not supported by the underlying
+ OpenSSL implementation.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>ensure_engine_loaded(EngineId, LibPath) -> Result</name>
+ <fsummary>Ensure encryption engine just loaded once</fsummary>
+ <type>
+ <v>EngineId = unicode:chardata()</v>
+ <v>LibPath = unicode:chardata()</v>
+ <v>Result = {ok, Engine::engine_ref()} | {error, Reason::term()}</v>
+ </type>
+ <desc>
+ <p>
+ Loads the OpenSSL engine given by <c>EngineId</c> and the path to the dynamic library
+ implementing the engine. This function is the same as calling <c>ensure_engine_loaded/3</c> with
+ <c>EngineMethods</c> set to a list of all the possible methods. An error tuple is
+ returned if the engine can't be loaded.
+ </p>
+ <p>
+ The function throws a badarg if the parameters are in wrong format.
+ It may also throw the exception notsup in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ <p>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ in the User's Guide.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>ensure_engine_loaded(EngineId, LibPath, EngineMethods) -> Result</name>
+ <fsummary>Ensure encryption engine just loaded once</fsummary>
+ <type>
+ <v>EngineId = unicode:chardata()</v>
+ <v>LibPath = unicode:chardata()</v>
+ <v>EngineMethods = [engine_method_type()]</v>
+ <v>Result = {ok, Engine::engine_ref()} | {error, Reason::term()}</v>
+ </type>
+ <desc>
+ <p>
+ Loads the OpenSSL engine given by <c>EngineId</c> and the path to the dynamic library
+ implementing the engine. This function differs from the normal engine_load in that sense it
+ also add the engine id to the internal list in OpenSSL. Then in the following calls to the function
+ it just fetch the reference to the engine instead of loading it again.
+ An error tuple is returned if the engine can't be loaded.
+ </p>
+ <p>
+ The function throws a badarg if the parameters are in wrong format.
+ It may also throw the exception notsup in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ <p>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ in the User's Guide.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>ensure_engine_unloaded(Engine) -> Result</name>
+ <fsummary>Unload an engine loaded with the ensure function</fsummary>
+ <type>
+ <v>Engine = engine_ref()</v>
+ <v>Result = ok | {error, Reason::term()}</v>
+ </type>
+ <desc>
+ <p>
+ Unloads an engine loaded with the <c>ensure_engine_loaded</c> function.
+ It both removes the label from the OpenSSL internal engine list and unloads the engine.
+ This function is the same as calling <c>ensure_engine_unloaded/2</c> with
+ <c>EngineMethods</c> set to a list of all the possible methods. An error tuple is
+ returned if the engine can't be unloaded.
+ </p>
+ <p>
+ The function throws a badarg if the parameters are in wrong format.
+ It may also throw the exception notsup in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ <p>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ in the User's Guide.
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>ensure_engine_unloaded(Engine, EngineMethods) -> Result</name>
+ <fsummary>Unload an engine loaded with the ensure function</fsummary>
+ <type>
+ <v>Engine = engine_ref()</v>
+ <v>EngineMethods = [engine_method_type()]</v>
+ <v>Result = ok | {error, Reason::term()}</v>
+ </type>
+ <desc>
+ <p>
+ Unloads an engine loaded with the <c>ensure_engine_loaded</c> function.
+ It both removes the label from the OpenSSL internal engine list and unloads the engine.
+ An error tuple is returned if the engine can't be unloaded.
+ </p>
+ <p>
+ The function throws a badarg if the parameters are in wrong format.
+ It may also throw the exception notsup in case there is
+ no engine support in the underlying OpenSSL implementation.
+ </p>
+ <p>
+ See also the chapter <seealso marker="crypto:engine_load#engine_load">Engine Load</seealso>
+ in the User's Guide.
+ </p>
</desc>
</func>
diff --git a/lib/crypto/doc/src/engine_load.xml b/lib/crypto/doc/src/engine_load.xml
index e5c3f5d561..3d0aa0c32a 100644
--- a/lib/crypto/doc/src/engine_load.xml
+++ b/lib/crypto/doc/src/engine_load.xml
@@ -42,6 +42,9 @@
operations. The hardware implementation usually offers improved performance over its
software-based counterpart, which is known as cryptographic acceleration.
</p>
+ <note>
+ <p>The file name requirement on the engine dynamic library can differ between SSL versions.</p>
+ </note>
</section>
<section>
@@ -54,9 +57,6 @@
<code>
1> {ok, Engine} = crypto:engine_load(&lt;&lt;"otp_test_engine">>, [], []).
{ok, #Ref}</code>
- <note>
- <p>The file name requirement on the engine dynamic library can differ between SSL versions.</p>
- </note>
</section>
<section>
@@ -72,9 +72,6 @@
&lt;&lt;"LOAD">>],
[]).
{ok, #Ref}</code>
- <note>
- <p>The dynamic engine is not supported in LibreSSL from version 2.2.1</p>
- </note>
</section>
<section>
@@ -100,6 +97,28 @@ engine_method_pkey_meths, engine_method_pkey_asn1_meths].
</section>
<section>
+ <title>Load with the ensure loaded function</title>
+ <p>
+ This function makes sure the engine is loaded just once and the ID is added to the internal
+ engine list of OpenSSL. The following calls to the function will check if the ID is loaded
+ and then just get a new reference to the engine.
+ </p>
+ <code>
+ 5> {ok, Engine} = crypto:ensure_engine_loaded(&lt;&lt;"MD5">>,
+ &lt;&lt;"/some/path/otp_test_engine.so">>).
+ {ok, #Ref}</code>
+ <p>
+ To unload it use crypto:ensure_engine_unloaded/1 which removes the ID from the internal list
+ before unloading the engine.
+ </p>
+ <code>
+ 6> crypto:ensure_engine_unloaded(&lt;&lt;"MD5">>).
+ ok</code>
+ </section>
+
+
+
+ <section>
<title>List all engines currently loaded</title>
<code>
5> crypto:engine_list().
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 714cba58b9..f6a785303b 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -29,6 +29,7 @@
-export([generate_key/2, generate_key/3, compute_key/4]).
-export([hmac/3, hmac/4, hmac_init/2, hmac_update/2, hmac_final/1, hmac_final_n/2]).
-export([cmac/3, cmac/4]).
+-export([poly1305/2]).
-export([exor/2, strong_rand_bytes/1, mod_pow/3]).
-export([rand_seed/0, rand_seed_alg/1]).
-export([rand_seed_s/0, rand_seed_alg_s/1]).
@@ -51,9 +52,18 @@
engine_load/3,
engine_load/4,
engine_unload/1,
+ engine_by_id/1,
engine_list/0,
engine_ctrl_cmd_string/3,
- engine_ctrl_cmd_string/4
+ engine_ctrl_cmd_string/4,
+ engine_add/1,
+ engine_remove/1,
+ engine_get_id/1,
+ engine_get_name/1,
+ ensure_engine_loaded/2,
+ ensure_engine_loaded/3,
+ ensure_engine_unloaded/1,
+ ensure_engine_unloaded/2
]).
-export_type([engine_ref/0,
@@ -108,17 +118,11 @@ stop() ->
supports()->
{Hashs, PubKeys, Ciphers, Macs, Curves} = algorithms(),
-
[{hashs, Hashs},
{ciphers, Ciphers},
{public_keys, PubKeys},
- {macs, Macs}
- | case Curves of
- [] -> [];
- _ -> [{curves, Curves}] % Only show this experimental feature
- % if OpenSSL 1.1.1 beta4 or higher (where
- % eddsa and eddh is enabled)
- end
+ {macs, Macs},
+ {curves, Curves}
].
info_lib() -> ?nif_stub.
@@ -191,6 +195,11 @@ cmac(Type, Key, Data) ->
cmac(Type, Key, Data, MacSize) ->
erlang:binary_part(cmac(Type, Key, Data), 0, MacSize).
+-spec poly1305(iodata(), iodata()) -> binary().
+
+poly1305(Key, Data) ->
+ poly1305_nif(Key, Data).
+
%% Ecrypt/decrypt %%%
-spec block_encrypt(des_cbc | des_cfb |
@@ -306,7 +315,10 @@ next_iv(Type, Data, _Ivec) ->
next_iv(Type, Data).
stream_init(aes_ctr, Key, Ivec) ->
- {aes_ctr, aes_ctr_stream_init(Key, Ivec)}.
+ {aes_ctr, aes_ctr_stream_init(Key, Ivec)};
+stream_init(chacha20, Key, Ivec) ->
+ {chacha20, chacha20_stream_init(Key,Ivec)}.
+
stream_init(rc4, Key) ->
{rc4, notsup_to_error(rc4_set_key(Key))}.
@@ -488,7 +500,7 @@ sign(Algorithm, Type, Data, Key, Options) ->
-type engine_key_ref() :: #{engine := engine_ref(),
key_id := key_id(),
password => password(),
- term() => term()
+ term() => term()
}.
-type pk_algs() :: rsa | ecdsa | dss .
@@ -664,7 +676,7 @@ evp_compute_key_nif(_Curve, _OthersBin, _MyBin) -> ?nif_stub.
-type engine_method_type() :: engine_method_rsa | engine_method_dsa | engine_method_dh |
engine_method_rand | engine_method_ecdh | engine_method_ecdsa |
engine_method_ciphers | engine_method_digests | engine_method_store |
- engine_method_pkey_meths | engine_method_pkey_asn1_meths |
+ engine_method_pkey_meths | engine_method_pkey_asn1_meths |
engine_method_ec.
-type engine_ref() :: term().
@@ -681,7 +693,8 @@ engine_get_all_methods() ->
PreCmds::[{unicode:chardata(), unicode:chardata()}],
PostCmds::[{unicode:chardata(), unicode:chardata()}]) ->
{ok, Engine::engine_ref()} | {error, Reason::term()}.
-engine_load(EngineId, PreCmds, PostCmds) when is_list(PreCmds), is_list(PostCmds) ->
+engine_load(EngineId, PreCmds, PostCmds) when is_list(PreCmds),
+ is_list(PostCmds) ->
engine_load(EngineId, PreCmds, PostCmds, engine_get_all_methods()).
%%----------------------------------------------------------------------
@@ -698,28 +711,26 @@ engine_load(EngineId, PreCmds, PostCmds, EngineMethods) when is_list(PreCmds),
ok = notsup_to_error(engine_load_dynamic_nif()),
case notsup_to_error(engine_by_id_nif(ensure_bin_chardata(EngineId))) of
{ok, Engine} ->
- ok = engine_load_1(Engine, PreCmds, PostCmds, EngineMethods),
- {ok, Engine};
+ engine_load_1(Engine, PreCmds, PostCmds, EngineMethods);
{error, Error1} ->
{error, Error1}
end
catch
- throw:Error2 ->
- Error2
+ throw:Error2 ->
+ Error2
end.
engine_load_1(Engine, PreCmds, PostCmds, EngineMethods) ->
try
ok = engine_nif_wrapper(engine_ctrl_cmd_strings_nif(Engine, ensure_bin_cmds(PreCmds), 0)),
- ok = engine_nif_wrapper(engine_add_nif(Engine)),
ok = engine_nif_wrapper(engine_init_nif(Engine)),
engine_load_2(Engine, PostCmds, EngineMethods),
- ok
+ {ok, Engine}
catch
- throw:Error ->
- %% The engine couldn't initialise, release the structural reference
- ok = engine_free_nif(Engine),
- throw(Error)
+ throw:Error ->
+ %% The engine couldn't initialise, release the structural reference
+ ok = engine_free_nif(Engine),
+ throw(Error)
end.
engine_load_2(Engine, PostCmds, EngineMethods) ->
@@ -749,7 +760,6 @@ engine_unload(Engine, EngineMethods) ->
try
[ok = engine_nif_wrapper(engine_unregister_nif(Engine, engine_method_atom_to_int(Method))) ||
Method <- EngineMethods],
- ok = engine_nif_wrapper(engine_remove_nif(Engine)),
%% Release the functional reference from engine_init_nif
ok = engine_nif_wrapper(engine_finish_nif(Engine)),
%% Release the structural reference from engine_by_id_nif
@@ -760,6 +770,41 @@ engine_unload(Engine, EngineMethods) ->
end.
%%----------------------------------------------------------------------
+%% Function: engine_by_id/1
+%%----------------------------------------------------------------------
+engine_by_id(EngineId) ->
+ try
+ notsup_to_error(engine_by_id_nif(ensure_bin_chardata(EngineId)))
+ catch
+ throw:Error ->
+ Error
+ end.
+
+%%----------------------------------------------------------------------
+%% Function: engine_add/1
+%%----------------------------------------------------------------------
+engine_add(Engine) ->
+ notsup_to_error(engine_add_nif(Engine)).
+
+%%----------------------------------------------------------------------
+%% Function: engine_remove/1
+%%----------------------------------------------------------------------
+engine_remove(Engine) ->
+ notsup_to_error(engine_remove_nif(Engine)).
+
+%%----------------------------------------------------------------------
+%% Function: engine_get_id/1
+%%----------------------------------------------------------------------
+engine_get_id(Engine) ->
+ notsup_to_error(engine_get_id_nif(Engine)).
+
+%%----------------------------------------------------------------------
+%% Function: engine_get_name/1
+%%----------------------------------------------------------------------
+engine_get_name(Engine) ->
+ notsup_to_error(engine_get_name_nif(Engine)).
+
+%%----------------------------------------------------------------------
%% Function: engine_list/0
%%----------------------------------------------------------------------
-spec engine_list() ->
@@ -770,9 +815,9 @@ engine_list() ->
[];
{ok, Engine} ->
case notsup_to_error(engine_get_id_nif(Engine)) of
- {ok, <<>>} ->
+ <<>> ->
engine_list(Engine, []);
- {ok, EngineId} ->
+ EngineId ->
engine_list(Engine, [EngineId])
end
end.
@@ -783,9 +828,9 @@ engine_list(Engine0, IdList) ->
lists:reverse(IdList);
{ok, Engine1} ->
case notsup_to_error(engine_get_id_nif(Engine1)) of
- {ok, <<>>} ->
+ <<>> ->
engine_list(Engine1, IdList);
- {ok, EngineId} ->
+ EngineId ->
engine_list(Engine1, [EngineId |IdList])
end
end.
@@ -794,7 +839,7 @@ engine_list(Engine0, IdList) ->
%% Function: engine_ctrl_cmd_string/3
%%----------------------------------------------------------------------
-spec engine_ctrl_cmd_string(Engine::term(),
- CmdName::unicode:chardata(),
+ CmdName::unicode:chardata(),
CmdArg::unicode:chardata()) ->
ok | {error, Reason::term()}.
engine_ctrl_cmd_string(Engine, CmdName, CmdArg) ->
@@ -804,13 +849,13 @@ engine_ctrl_cmd_string(Engine, CmdName, CmdArg) ->
%% Function: engine_ctrl_cmd_string/4
%%----------------------------------------------------------------------
-spec engine_ctrl_cmd_string(Engine::term(),
- CmdName::unicode:chardata(),
+ CmdName::unicode:chardata(),
CmdArg::unicode:chardata(),
Optional::boolean()) ->
ok | {error, Reason::term()}.
engine_ctrl_cmd_string(Engine, CmdName, CmdArg, Optional) ->
- case engine_ctrl_cmd_strings_nif(Engine,
- ensure_bin_cmds([{CmdName, CmdArg}]),
+ case engine_ctrl_cmd_strings_nif(Engine,
+ ensure_bin_cmds([{CmdName, CmdArg}]),
bool_to_int(Optional)) of
ok ->
ok;
@@ -820,6 +865,82 @@ engine_ctrl_cmd_string(Engine, CmdName, CmdArg, Optional) ->
{error, Error}
end.
+%%----------------------------------------------------------------------
+%% Function: ensure_engine_loaded/2
+%% Special version of load that only uses dynamic engine to load
+%%----------------------------------------------------------------------
+ensure_engine_loaded(EngineId, LibPath) ->
+ ensure_engine_loaded(EngineId, LibPath, engine_get_all_methods()).
+
+%%----------------------------------------------------------------------
+%% Function: ensure_engine_loaded/3
+%% Special version of load that only uses dynamic engine to load
+%%----------------------------------------------------------------------
+ensure_engine_loaded(EngineId, LibPath, EngineMethods) ->
+ try
+ List = crypto:engine_list(),
+ case lists:member(EngineId, List) of
+ true ->
+ notsup_to_error(engine_by_id_nif(ensure_bin_chardata(EngineId)));
+ false ->
+ ok = notsup_to_error(engine_load_dynamic_nif()),
+ case notsup_to_error(engine_by_id_nif(ensure_bin_chardata(<<"dynamic">>))) of
+ {ok, Engine} ->
+ PreCommands = [{<<"SO_PATH">>, ensure_bin_chardata(LibPath)},
+ {<<"ID">>, ensure_bin_chardata(EngineId)},
+ <<"LOAD">>],
+ ensure_engine_loaded_1(Engine, PreCommands, EngineMethods);
+ {error, Error1} ->
+ {error, Error1}
+ end
+ end
+ catch
+ throw:Error2 ->
+ Error2
+ end.
+
+ensure_engine_loaded_1(Engine, PreCmds, Methods) ->
+ try
+ ok = engine_nif_wrapper(engine_ctrl_cmd_strings_nif(Engine, ensure_bin_cmds(PreCmds), 0)),
+ ok = engine_nif_wrapper(engine_add_nif(Engine)),
+ ok = engine_nif_wrapper(engine_init_nif(Engine)),
+ ensure_engine_loaded_2(Engine, Methods),
+ {ok, Engine}
+ catch
+ throw:Error ->
+ %% The engine couldn't initialise, release the structural reference
+ ok = engine_free_nif(Engine),
+ throw(Error)
+ end.
+
+ensure_engine_loaded_2(Engine, Methods) ->
+ try
+ [ok = engine_nif_wrapper(engine_register_nif(Engine, engine_method_atom_to_int(Method))) ||
+ Method <- Methods],
+ ok
+ catch
+ throw:Error ->
+ %% The engine registration failed, release the functional reference
+ ok = engine_finish_nif(Engine),
+ throw(Error)
+ end.
+%%----------------------------------------------------------------------
+%% Function: ensure_engine_unloaded/1
+%%----------------------------------------------------------------------
+ensure_engine_unloaded(Engine) ->
+ ensure_engine_unloaded(Engine, engine_get_all_methods()).
+
+%%----------------------------------------------------------------------
+%% Function: ensure_engine_unloaded/2
+%%----------------------------------------------------------------------
+ensure_engine_unloaded(Engine, EngineMethods) ->
+ case engine_remove(Engine) of
+ ok ->
+ engine_unload(Engine, EngineMethods);
+ {error, E} ->
+ {error, E}
+ end.
+
%%--------------------------------------------------------------------
%%% On load
%%--------------------------------------------------------------------
@@ -892,7 +1013,7 @@ path2bin(Path) when is_list(Path) ->
max_bytes() ->
?MAX_BYTES_TO_NIF.
-notsup_to_error(notsup) ->
+notsup_to_error(notsup) ->
erlang:error(notsup);
notsup_to_error(Other) ->
Other.
@@ -948,9 +1069,12 @@ hmac_final_nif(_Context) -> ?nif_stub.
hmac_final_nif(_Context, _MacSize) -> ?nif_stub.
%% CMAC
-
cmac_nif(_Type, _Key, _Data) -> ?nif_stub.
+%% POLY1305
+poly1305_nif(_Key, _Data) -> ?nif_stub.
+
+
%% CIPHERS --------------------------------------------------------------------
block_crypt_nif(_Type, _Key, _Ivec, _Text, _IsEncrypt) -> ?nif_stub.
@@ -1005,14 +1129,20 @@ do_stream_encrypt({aes_ctr, State0}, Data) ->
{{aes_ctr, State}, Cipher};
do_stream_encrypt({rc4, State0}, Data) ->
{State, Cipher} = rc4_encrypt_with_state(State0, Data),
- {{rc4, State}, Cipher}.
+ {{rc4, State}, Cipher};
+do_stream_encrypt({chacha20, State0}, Data) ->
+ {State, Cipher} = chacha20_stream_encrypt(State0, Data),
+ {{chacha20, State}, Cipher}.
do_stream_decrypt({aes_ctr, State0}, Data) ->
{State, Text} = aes_ctr_stream_decrypt(State0, Data),
{{aes_ctr, State}, Text};
do_stream_decrypt({rc4, State0}, Data) ->
{State, Text} = rc4_encrypt_with_state(State0, Data),
- {{rc4, State}, Text}.
+ {{rc4, State}, Text};
+do_stream_decrypt({chacha20, State0}, Data) ->
+ {State, Cipher} = chacha20_stream_decrypt(State0, Data),
+ {{chacha20, State}, Cipher}.
%%
@@ -1036,6 +1166,18 @@ aes_ctr_stream_decrypt(_State, _Cipher) -> ?nif_stub.
rc4_set_key(_Key) -> ?nif_stub.
rc4_encrypt_with_state(_State, _Data) -> ?nif_stub.
+%%
+%% CHACHA20 - stream cipher
+%%
+-type chacha20_state() :: term().
+-spec chacha20_stream_init(iodata(), binary()) -> chacha20_state().
+-spec chacha20_stream_encrypt(chacha20_state(), binary()) -> {chacha20_state(), binary()}.
+-spec chacha20_stream_decrypt(chacha20_state(), binary()) -> {chacha20_state(), binary()}.
+
+chacha20_stream_init(_Key, _IVec) -> ?nif_stub.
+chacha20_stream_encrypt(_State, _Data) -> ?nif_stub.
+chacha20_stream_decrypt(_State, _Data) -> ?nif_stub.
+
%% Secure remote password -------------------------------------------------------------------
user_srp_gen_key(Private, Generator, Prime) ->
@@ -1148,7 +1290,7 @@ privkey_to_pubkey(Alg, EngineMap) when Alg == rsa; Alg == dss; Alg == ecdsa ->
error:notsup ->
{error, notsup}
end.
-
+
privkey_to_pubkey_nif(_Alg, _EngineMap) -> ?nif_stub.
@@ -1314,6 +1456,7 @@ engine_unregister_nif(_Engine, _EngineMethod) -> ?nif_stub.
engine_get_first_nif() -> ?nif_stub.
engine_get_next_nif(_Engine) -> ?nif_stub.
engine_get_id_nif(_Engine) -> ?nif_stub.
+engine_get_name_nif(_Engine) -> ?nif_stub.
engine_get_all_methods_nif() -> ?nif_stub.
%%--------------------------------------------------------------------
@@ -1371,7 +1514,7 @@ get_test_engine() ->
Type = erlang:system_info(system_architecture),
LibDir = filename:join([code:priv_dir(crypto), "lib"]),
ArchDir = filename:join([LibDir, Type]),
- case filelib:is_dir(ArchDir) of
+ case filelib:is_dir(ArchDir) of
true -> check_otp_test_engine(ArchDir);
false -> check_otp_test_engine(LibDir)
end.
@@ -1389,4 +1532,3 @@ check_otp_test_engine(LibDir) ->
{error, notexist}
end
end.
-
diff --git a/lib/crypto/src/crypto_ec_curves.erl b/lib/crypto/src/crypto_ec_curves.erl
index 9602a7e24b..a0a2f99601 100644
--- a/lib/crypto/src/crypto_ec_curves.erl
+++ b/lib/crypto/src/crypto_ec_curves.erl
@@ -3,41 +3,7 @@
-export([curve/1, curves/0]).
curves() ->
- CryptoSupport = crypto:supports(),
- PubKeys = proplists:get_value(public_keys, CryptoSupport),
- HasEC = proplists:get_bool(ecdh, PubKeys),
- HasGF2m = proplists:get_bool(ec_gf2m, PubKeys),
- FIPSMode = crypto:info_fips() == enabled,
- prime_curves(HasEC, FIPSMode) ++ characteristic_two_curves(HasGF2m, FIPSMode).
-
-
-prime_curves(true, true) ->
- [secp160k1,secp160r1,secp160r2,
- secp192r1,secp192k1,secp224k1,secp224r1,secp256k1,secp256r1,secp384r1,
- secp521r1,prime192v1,prime192v2,prime192v3,prime239v1,prime239v2,prime239v3,
- prime256v1,wtls7,wtls9,wtls12,
- brainpoolP160r1,brainpoolP160t1,brainpoolP192r1,brainpoolP192t1,
- brainpoolP224r1,brainpoolP224t1,brainpoolP256r1,brainpoolP256t1,
- brainpoolP320r1,brainpoolP320t1,brainpoolP384r1,brainpoolP384t1,
- brainpoolP512r1,brainpoolP512t1];
-prime_curves(true, false) ->
- [secp112r1,secp112r2,secp128r1,secp128r2,wtls6,wtls8]
- ++ prime_curves(true, true);
-prime_curves(_, _) ->
- [].
-
-characteristic_two_curves(true, true) ->
- [sect163k1,sect163r1,
- sect163r2,sect193r1,sect193r2,sect233k1,sect233r1,sect239k1,sect283k1,
- sect283r1,sect409k1,sect409r1,sect571k1,sect571r1,c2pnb163v1,c2pnb163v2,
- c2pnb163v3,c2pnb176v1,c2tnb191v1,c2tnb191v2,c2tnb191v3,c2pnb208w1,c2tnb239v1,
- c2tnb239v2,c2tnb239v3,c2pnb272w1,c2pnb304w1,c2tnb359v1,c2pnb368w1,c2tnb431r1,
- wtls3,wtls5,wtls10,wtls11];
-characteristic_two_curves(true, _) ->
- [sect113r1,sect113r2,sect131r1,sect131r2,wtls1,wtls4,ipsec3,ipsec4]
- ++ characteristic_two_curves(true, true);
-characteristic_two_curves(_, _) ->
- [].
+ proplists:get_value(curves, crypto:supports()) -- [x25519,x448].
curve(secp112r1) ->
{
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index e5f86ea573..3257dfd373 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -77,6 +77,8 @@ groups() ->
{group, aes_ctr},
{group, aes_gcm},
{group, chacha20_poly1305},
+ {group, chacha20},
+ {group, poly1305},
{group, aes_cbc}]},
{fips, [], [{group, no_md4},
{group, no_md5},
@@ -112,6 +114,7 @@ groups() ->
{group, aes_ctr},
{group, aes_gcm},
{group, no_chacha20_poly1305},
+ {group, no_chacha20},
{group, aes_cbc}]},
{md4, [], [hash]},
{md5, [], [hash, hmac]},
@@ -134,7 +137,7 @@ groups() ->
]},
{dh, [], [generate_compute,
compute_bug]},
- {ecdh, [], [compute, generate]},
+ {ecdh, [], [generate_all_supported, compute, generate]},
{srp, [], [generate_compute]},
{des_cbc, [], [block]},
{des_cfb, [], [block]},
@@ -157,6 +160,8 @@ groups() ->
{aes_ctr, [], [stream]},
{aes_gcm, [], [aead]},
{chacha20_poly1305, [], [aead]},
+ {chacha20, [], [stream]},
+ {poly1305, [], [poly1305]},
{aes_cbc, [], [block]},
{no_md4, [], [no_support, no_hash]},
{no_md5, [], [no_support, no_hash, no_hmac]},
@@ -170,6 +175,7 @@ groups() ->
{no_blowfish_ofb64, [], [no_support, no_block]},
{no_aes_ige256, [], [no_support, no_block]},
{no_chacha20_poly1305, [], [no_support, no_aead]},
+ {no_chacha20, [], [no_support, no_stream_ivec]},
{no_rc2_cbc, [], [no_support, no_block]},
{no_rc4, [], [no_support, no_stream]},
{api_errors, [], [api_errors_ecdh]}
@@ -356,6 +362,20 @@ cmac(Config) when is_list(Config) ->
lists:foreach(fun cmac_check/1, Pairs),
lists:foreach(fun cmac_check/1, cmac_iolistify(Pairs)).
%%--------------------------------------------------------------------
+poly1305() ->
+ [{doc, "Test poly1305 function"}].
+poly1305(Config) ->
+ lists:foreach(
+ fun({Key, Txt, Expect}) ->
+ case crypto:poly1305(Key,Txt) of
+ Expect ->
+ ok;
+ Other ->
+ ct:fail({{crypto, poly1305, [Key, Txt]}, {expected, Expect}, {got, Other}})
+ end
+ end, proplists:get_value(poly1305, Config)).
+
+%%--------------------------------------------------------------------
block() ->
[{doc, "Test block ciphers"}].
block(Config) when is_list(Config) ->
@@ -420,6 +440,13 @@ no_stream(Config) when is_list(Config) ->
notsup(fun crypto:stream_init/2, [Type, <<"Key">>]).
%%--------------------------------------------------------------------
+no_stream_ivec() ->
+ [{doc, "Test disabled stream ciphers that uses ivec"}].
+no_stream_ivec(Config) when is_list(Config) ->
+ Type = ?config(type, Config),
+ notsup(fun crypto:stream_init/3, [Type, <<"Key">>, <<"Ivec">>]).
+
+%%--------------------------------------------------------------------
aead() ->
[{doc, "Test AEAD ciphers"}].
aead(Config) when is_list(Config) ->
@@ -510,6 +537,33 @@ compute(Config) when is_list(Config) ->
Gen = proplists:get_value(compute, Config),
lists:foreach(fun do_compute/1, Gen).
%%--------------------------------------------------------------------
+generate_all_supported() ->
+ [{doc, " Test that all curves from crypto:ec_curves/0 returns two binaries"}].
+generate_all_supported(_Config) ->
+ Results =
+ [try
+ crypto:generate_key(ecdh, C)
+ of
+ {B1,B2} when is_binary(B1) and is_binary(B2) ->
+ %% That is, seems like it works as expected.
+ {ok,C};
+ Err ->
+ ct:log("ERROR: Curve ~p generated ~p", [C,Err]),
+ {error,{C,Err}}
+ catch
+ Cls:Err:Stack ->
+ ct:log("ERROR: Curve ~p exception ~p:~p~n~p", [C,Cls,Err,Stack]),
+ {error,{C,{Cls,Err}}}
+ end
+ || C <- crypto:ec_curves()
+ ],
+ OK = [C || {ok,C} <- Results],
+ ct:log("Ok (len=~p): ~p", [length(OK), OK]),
+ false = lists:any(fun({error,_}) -> true;
+ (_) -> false
+ end, Results).
+
+%%--------------------------------------------------------------------
generate() ->
[{doc, " Test crypto:generate_key"}].
generate(Config) when is_list(Config) ->
@@ -730,16 +784,33 @@ stream_cipher({Type, Key, IV, PlainText}) ->
ok;
Other ->
ct:fail({{crypto, stream_decrypt, [State, CipherText]}, {expected, PlainText}, {got, Other}})
+ end;
+stream_cipher({Type, Key, IV, PlainText, CipherText}) ->
+ Plain = iolist_to_binary(PlainText),
+ State = crypto:stream_init(Type, Key, IV),
+ case crypto:stream_encrypt(State, PlainText) of
+ {_, CipherText} ->
+ ok;
+ {_, Other0} ->
+ ct:fail({{crypto, stream_encrypt, [State, Type, Key, IV, Plain]}, {expected, CipherText}, {got, Other0}})
+ end,
+ case crypto:stream_decrypt(State, CipherText) of
+ {_, Plain} ->
+ ok;
+ Other1 ->
+ ct:fail({{crypto, stream_decrypt, [State, CipherText]}, {expected, PlainText}, {got, Other1}})
end.
stream_cipher_incment({Type, Key, PlainTexts}) ->
State = crypto:stream_init(Type, Key),
- stream_cipher_incment(State, State, PlainTexts, [], iolist_to_binary(PlainTexts));
+ stream_cipher_incment_loop(State, State, PlainTexts, [], iolist_to_binary(PlainTexts));
stream_cipher_incment({Type, Key, IV, PlainTexts}) ->
State = crypto:stream_init(Type, Key, IV),
- stream_cipher_incment(State, State, PlainTexts, [], iolist_to_binary(PlainTexts)).
+ stream_cipher_incment_loop(State, State, PlainTexts, [], iolist_to_binary(PlainTexts));
+stream_cipher_incment({Type, Key, IV, PlainTexts, _CipherText}) ->
+ stream_cipher_incment({Type, Key, IV, PlainTexts}).
-stream_cipher_incment(_State, OrigState, [], Acc, Plain) ->
+stream_cipher_incment_loop(_State, OrigState, [], Acc, Plain) ->
CipherText = iolist_to_binary(lists:reverse(Acc)),
case crypto:stream_decrypt(OrigState, CipherText) of
{_, Plain} ->
@@ -747,9 +818,9 @@ stream_cipher_incment(_State, OrigState, [], Acc, Plain) ->
Other ->
ct:fail({{crypto, stream_decrypt, [OrigState, CipherText]}, {expected, Plain}, {got, Other}})
end;
-stream_cipher_incment(State0, OrigState, [PlainText | PlainTexts], Acc, Plain) ->
+stream_cipher_incment_loop(State0, OrigState, [PlainText | PlainTexts], Acc, Plain) ->
{State, CipherText} = crypto:stream_encrypt(State0, PlainText),
- stream_cipher_incment(State, OrigState, PlainTexts, [CipherText | Acc], Plain).
+ stream_cipher_incment_loop(State, OrigState, PlainTexts, [CipherText | Acc], Plain).
aead_cipher({Type, Key, PlainText, IV, AAD, CipherText, CipherTag}) ->
Plain = iolist_to_binary(PlainText),
@@ -1000,7 +1071,9 @@ do_cmac_iolistify({Type, Key, Text, Size, CMac}) ->
do_stream_iolistify({Type, Key, PlainText}) ->
{Type, iolistify(Key), iolistify(PlainText)};
do_stream_iolistify({Type, Key, IV, PlainText}) ->
- {Type, iolistify(Key), IV, iolistify(PlainText)}.
+ {Type, iolistify(Key), IV, iolistify(PlainText)};
+do_stream_iolistify({Type, Key, IV, PlainText, CipherText}) ->
+ {Type, iolistify(Key), IV, iolistify(PlainText), CipherText}.
do_block_iolistify({des_cbc = Type, Key, IV, PlainText}) ->
{Type, Key, IV, des_iolistify(PlainText)};
@@ -1405,6 +1478,18 @@ group_config(aes_gcm, Config) ->
group_config(chacha20_poly1305, Config) ->
AEAD = chacha20_poly1305(),
[{aead, AEAD} | Config];
+group_config(chacha20, Config) ->
+ Stream = chacha20(),
+ [{stream, Stream} | Config];
+group_config(poly1305, Config) ->
+ V = [%% {Key, Txt, Expect}
+ {%% RFC7539 2.5.2
+ crypto_SUITE:hexstr2bin("85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b"),
+ <<"Cryptographic Forum Research Group">>,
+ crypto_SUITE:hexstr2bin("a8061dc1305136c6c22b8baf0c0127a9")
+ }
+ ],
+ [{poly1305,V} | Config];
group_config(aes_cbc, Config) ->
Block = aes_cbc(Config),
[{block, Block} | Config];
@@ -2042,6 +2127,7 @@ aes_gcm(Config) ->
"gcmEncryptExtIV192.rsp",
"gcmEncryptExtIV256.rsp"]).
+
%% https://tools.ietf.org/html/rfc7539#appendix-A.5
chacha20_poly1305() ->
[
@@ -2087,6 +2173,103 @@ chacha20_poly1305() ->
hexstr2bin("eead9d67890cbb22392336fea1851f38")} %% CipherTag
].
+
+chacha20() ->
+%%% chacha20 (no mode) test vectors from RFC 7539 A.2
+ [
+ %% Test Vector #1:
+ {chacha20,
+ hexstr2bin("00000000000000000000000000000000"
+ "00000000000000000000000000000000"), %% Key
+ hexstr2bin("00000000" % Initial counter = 0, little-endian
+ "000000000000000000000000"), %% IV
+ hexstr2bin("00000000000000000000000000000000" %% PlainText
+ "00000000000000000000000000000000"
+ "00000000000000000000000000000000"
+ "00000000000000000000000000000000"),
+ hexstr2bin("76b8e0ada0f13d90405d6ae55386bd28" %% CipherText
+ "bdd219b8a08ded1aa836efcc8b770dc7"
+ "da41597c5157488d7724e03fb8d84a37"
+ "6a43b8f41518a11cc387b669b2ee6586")},
+ %% Test Vector #2:
+ {chacha20,
+ hexstr2bin("00000000000000000000000000000000"
+ "00000000000000000000000000000001"), %% Key
+ hexstr2bin("01000000" % Initial counter = 1, little-endian
+ "000000000000000000000002"), %% IV
+ hexstr2bin("416e79207375626d697373696f6e2074" %% PlainText
+ "6f20746865204945544620696e74656e"
+ "6465642062792074686520436f6e7472"
+ "696275746f7220666f72207075626c69"
+ "636174696f6e20617320616c6c206f72"
+ "2070617274206f6620616e2049455446"
+ "20496e7465726e65742d447261667420"
+ "6f722052464320616e6420616e792073"
+ "746174656d656e74206d616465207769"
+ "7468696e2074686520636f6e74657874"
+ "206f6620616e20494554462061637469"
+ "7669747920697320636f6e7369646572"
+ "656420616e20224945544620436f6e74"
+ "7269627574696f6e222e205375636820"
+ "73746174656d656e747320696e636c75"
+ "6465206f72616c2073746174656d656e"
+ "747320696e2049455446207365737369"
+ "6f6e732c2061732077656c6c20617320"
+ "7772697474656e20616e6420656c6563"
+ "74726f6e696320636f6d6d756e696361"
+ "74696f6e73206d61646520617420616e"
+ "792074696d65206f7220706c6163652c"
+ "20776869636820617265206164647265"
+ "7373656420746f"),
+ hexstr2bin("a3fbf07df3fa2fde4f376ca23e827370" %% CipherText
+ "41605d9f4f4f57bd8cff2c1d4b7955ec"
+ "2a97948bd3722915c8f3d337f7d37005"
+ "0e9e96d647b7c39f56e031ca5eb6250d"
+ "4042e02785ececfa4b4bb5e8ead0440e"
+ "20b6e8db09d881a7c6132f420e527950"
+ "42bdfa7773d8a9051447b3291ce1411c"
+ "680465552aa6c405b7764d5e87bea85a"
+ "d00f8449ed8f72d0d662ab052691ca66"
+ "424bc86d2df80ea41f43abf937d3259d"
+ "c4b2d0dfb48a6c9139ddd7f76966e928"
+ "e635553ba76c5c879d7b35d49eb2e62b"
+ "0871cdac638939e25e8a1e0ef9d5280f"
+ "a8ca328b351c3c765989cbcf3daa8b6c"
+ "cc3aaf9f3979c92b3720fc88dc95ed84"
+ "a1be059c6499b9fda236e7e818b04b0b"
+ "c39c1e876b193bfe5569753f88128cc0"
+ "8aaa9b63d1a16f80ef2554d7189c411f"
+ "5869ca52c5b83fa36ff216b9c1d30062"
+ "bebcfd2dc5bce0911934fda79a86f6e6"
+ "98ced759c3ff9b6477338f3da4f9cd85"
+ "14ea9982ccafb341b2384dd902f3d1ab"
+ "7ac61dd29c6f21ba5b862f3730e37cfd"
+ "c4fd806c22f221")},
+ %%Test Vector #3:
+ {chacha20,
+ hexstr2bin("1c9240a5eb55d38af333888604f6b5f0"
+ "473917c1402b80099dca5cbc207075c0"), %% Key
+ hexstr2bin("2a000000" % Initial counter = 42 (decimal), little-endian
+ "000000000000000000000002"), %% IV
+ hexstr2bin("2754776173206272696c6c69672c2061" %% PlainText
+ "6e642074686520736c6974687920746f"
+ "7665730a446964206779726520616e64"
+ "2067696d626c6520696e207468652077"
+ "6162653a0a416c6c206d696d73792077"
+ "6572652074686520626f726f676f7665"
+ "732c0a416e6420746865206d6f6d6520"
+ "7261746873206f757467726162652e"),
+ hexstr2bin("62e6347f95ed87a45ffae7426f27a1df" %% CipherText
+ "5fb69110044c0d73118effa95b01e5cf"
+ "166d3df2d721caf9b21e5fb14c616871"
+ "fd84c54f9d65b283196c7fe4f60553eb"
+ "f39c6402c42234e32a356b3e764312a6"
+ "1a5532055716ead6962568f87d3f3f77"
+ "04c6a8d1bcd1bf4d50d6154b6da731b1"
+ "87b58dfd728afa36757a797ac188d1")}
+ ].
+
+
rsa_plain() ->
<<"7896345786348756234 Hejsan Svejsan, erlang crypto debugger"
"09812312908312378623487263487623412039812 huagasd">>.
diff --git a/lib/crypto/test/engine_SUITE.erl b/lib/crypto/test/engine_SUITE.erl
index bb9aa49b50..4b3ea10315 100644
--- a/lib/crypto/test/engine_SUITE.erl
+++ b/lib/crypto/test/engine_SUITE.erl
@@ -39,6 +39,10 @@ all() ->
get_all_possible_methods,
engine_load_all_methods,
engine_load_some_methods,
+ multiple_engine_load,
+ engine_list,
+ get_id_and_name,
+ engine_by_id,
bad_arguments,
unknown_engine,
pre_command_fail_bad_value,
@@ -46,6 +50,7 @@ all() ->
failed_engine_init,
ctrl_cmd_string,
ctrl_cmd_string_optional,
+ ensure_load,
{group, engine_stored_key}
].
@@ -97,7 +102,7 @@ init_per_group(engine_stored_key, Config) ->
{error, notexist} ->
{skip, "OTP Test engine not found"};
{error, notsup} ->
- {skip, "Engine not supported on this OpenSSL version"};
+ {skip, "Engine not supported on this SSL version"};
{error, bad_engine_id} ->
{skip, "Dynamic Engine not supported"};
Other ->
@@ -132,11 +137,12 @@ get_all_possible_methods() ->
get_all_possible_methods(Config) when is_list(Config) ->
try
List = crypto:engine_get_all_methods(),
+ true = erlang:is_list(List),
ct:log("crypto:engine_get_all_methods() -> ~p\n", [List]),
ok
catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"}
end.
engine_load_all_methods()->
@@ -149,13 +155,12 @@ engine_load_all_methods(Config) when is_list(Config) ->
{error, notexist} ->
{skip, "OTP Test engine not found"};
{ok, Engine} ->
- try
+ try
Md5Hash1 = <<106,30,3,246,166,222,229,158,244,217,241,179,50,232,107,109>>,
Md5Hash1 = crypto:hash(md5, "Don't panic"),
Md5Hash2 = <<0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
case crypto:engine_load(<<"dynamic">>,
[{<<"SO_PATH">>, Engine},
- {<<"ID">>, <<"MD5">>},
<<"LOAD">>],
[]) of
{ok, E} ->
@@ -181,7 +186,7 @@ engine_load_all_methods(Config) when is_list(Config) ->
end
catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"}
end
end.
@@ -195,21 +200,20 @@ engine_load_some_methods(Config) when is_list(Config) ->
{error, notexist} ->
{skip, "OTP Test engine not found"};
{ok, Engine} ->
- try
+ try
Md5Hash1 = <<106,30,3,246,166,222,229,158,244,217,241,179,50,232,107,109>>,
Md5Hash1 = crypto:hash(md5, "Don't panic"),
Md5Hash2 = <<0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
EngineMethods = crypto:engine_get_all_methods() --
- [engine_method_dh,engine_method_rand,
+ [engine_method_dh, engine_method_rand,
engine_method_ciphers, engine_method_store,
engine_method_pkey_meths, engine_method_pkey_asn1_meths],
case crypto:engine_load(<<"dynamic">>,
[{<<"SO_PATH">>, Engine},
- {<<"ID">>, <<"MD5">>},
<<"LOAD">>],
[],
EngineMethods) of
- {ok, E} ->
+ {ok, E} ->
case crypto:hash(md5, "Don't panic") of
Md5Hash1 ->
ct:fail(fail_to_load_engine_still_original);
@@ -232,7 +236,168 @@ engine_load_some_methods(Config) when is_list(Config) ->
end
catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"}
+ end
+ end.
+
+multiple_engine_load()->
+ [{doc, "Use a dummy md5 engine that does not implement md5"
+ "but rather returns a static binary to test that crypto:engine_load "
+ "functions works when called multiple times."}].
+
+multiple_engine_load(Config) when is_list(Config) ->
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ try
+ Md5Hash1 = <<106,30,3,246,166,222,229,158,244,217,241,179,50,232,107,109>>,
+ Md5Hash1 = crypto:hash(md5, "Don't panic"),
+ Md5Hash2 = <<0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
+ case crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ []) of
+ {ok, E} ->
+ {ok, E1} = crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ []),
+ {ok, E2} = crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ []),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash1 ->
+ ct:fail(fail_to_load_still_original_engine);
+ Md5Hash2 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_load_engine)
+ end,
+ ok = crypto:engine_unload(E2),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash1 ->
+ ct:fail(fail_to_load_still_original_engine);
+ Md5Hash2 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_load_engine)
+ end,
+ ok = crypto:engine_unload(E),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash1 ->
+ ct:fail(fail_to_load_still_original_engine);
+ Md5Hash2 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_load_engine)
+ end,
+ ok = crypto:engine_unload(E1),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash2 ->
+ ct:fail(fail_to_unload_still_test_engine);
+ Md5Hash1 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_unload_engine)
+ end;
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end
+ end.
+
+engine_list()->
+ [{doc, "Test add and remove engine ID to the SSL internal engine list."}].
+
+engine_list(Config) when is_list(Config) ->
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ try
+ EngineList0 = crypto:engine_list(),
+ case crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ []) of
+ {ok, E} ->
+ EngineList0 = crypto:engine_list(),
+ ok = crypto:engine_add(E),
+ [<<"MD5">>] = lists:subtract(crypto:engine_list(), EngineList0),
+ ok = crypto:engine_remove(E),
+ EngineList0 = crypto:engine_list(),
+ ok = crypto:engine_unload(E);
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end
+ end.
+
+get_id_and_name()->
+ [{doc, "Test fetching id and name from an engine."}].
+
+get_id_and_name(Config) when is_list(Config) ->
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ try
+ case crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ []) of
+ {ok, E} ->
+ <<"MD5">> = crypto:engine_get_id(E),
+ <<"MD5 test engine">> = crypto:engine_get_name(E),
+ ok = crypto:engine_unload(E);
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end
+ end.
+
+engine_by_id()->
+ [{doc, "Test fetching a new reference the the engine when the"
+ "engine id is added to the SSL engine list."}].
+
+engine_by_id(Config) when is_list(Config) ->
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ try
+ case crypto:engine_load(<<"dynamic">>,
+ [{<<"SO_PATH">>, Engine},
+ <<"LOAD">>],
+ []) of
+ {ok, E} ->
+ case crypto:engine_by_id(<<"MD5">>) of
+ {error,bad_engine_id} ->
+ ok;
+ {ok, _} ->
+ ct:fail(fail_engine_found)
+ end,
+ ok = crypto:engine_add(E),
+ {ok, _E1} = crypto:engine_by_id(<<"MD5">>),
+ ok = crypto:engine_remove(E),
+ ok = crypto:engine_unload(E);
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
end
end.
@@ -246,7 +411,7 @@ bad_arguments(Config) when is_list(Config) ->
{error, notexist} ->
{skip, "OTP Test engine not found"};
{ok, Engine} ->
- try
+ try
try
crypto:engine_load(fail_engine, [], [])
catch
@@ -276,7 +441,7 @@ bad_arguments(Config) when is_list(Config) ->
end
catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"}
end
end.
@@ -289,7 +454,7 @@ unknown_engine(Config) when is_list(Config) ->
ok
catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"}
end.
pre_command_fail_bad_value() ->
@@ -311,7 +476,7 @@ pre_command_fail_bad_value(Config) when is_list(Config) ->
end
catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"}
end.
pre_command_fail_bad_key() ->
@@ -334,9 +499,9 @@ pre_command_fail_bad_key(Config) when is_list(Config) ->
{skip, "Dynamic Engine not supported"}
end
end
- catch
+ catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"}
end.
failed_engine_init()->
@@ -352,18 +517,20 @@ failed_engine_init(Config) when is_list(Config) ->
[{<<"SO_PATH">>, Engine},
{<<"ID">>, <<"MD5">>}],
[]) of
- {error, add_engine_failed} ->
+ {error, engine_init_failed} ->
ok;
{error, bad_engine_id} ->
{skip, "Dynamic Engine not supported"}
end
end
- catch
+ catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
+ {skip, "Engine not supported on this SSL version"}
end.
+%%-------------------------------------------------------------------------
+%% Test the optional flag in ctrl comands
ctrl_cmd_string()->
[{doc, "Test that a not known optional ctrl comand do not fail"}].
ctrl_cmd_string(Config) when is_list(Config) ->
@@ -377,22 +544,22 @@ ctrl_cmd_string(Config) when is_list(Config) ->
{<<"ID">>, <<"MD5">>},
<<"LOAD">>],
[]) of
- {ok, E} ->
+ {ok, E} ->
case crypto:engine_ctrl_cmd_string(E, <<"TEST">>, <<"17">>) of
ok ->
ct:fail(fail_ctrl_cmd_should_fail);
- {error,ctrl_cmd_failed} ->
+ {error,ctrl_cmd_failed} ->
ok
end,
- ok = crypto:engine_unload(E);
+ ok = crypto:engine_unload(E);
{error, bad_engine_id} ->
{skip, "Dynamic Engine not supported"}
end
end
- catch
+ catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
- end.
+ {skip, "Engine not supported on this SSL version"}
+ end.
ctrl_cmd_string_optional()->
[{doc, "Test that a not known optional ctrl comand do not fail"}].
@@ -407,22 +574,63 @@ ctrl_cmd_string_optional(Config) when is_list(Config) ->
{<<"ID">>, <<"MD5">>},
<<"LOAD">>],
[]) of
- {ok, E} ->
+ {ok, E} ->
case crypto:engine_ctrl_cmd_string(E, <<"TEST">>, <<"17">>, true) of
ok ->
ok;
- _ ->
+ _ ->
ct:fail(fail_ctrl_cmd_string)
end,
- ok = crypto:engine_unload(E);
+ ok = crypto:engine_unload(E);
{error, bad_engine_id} ->
{skip, "Dynamic Engine not supported"}
end
end
- catch
+ catch
error:notsup ->
- {skip, "Engine not supported on this OpenSSL version"}
- end.
+ {skip, "Engine not supported on this SSL version"}
+ end.
+
+ensure_load()->
+ [{doc, "Test the special ensure load function."}].
+
+ensure_load(Config) when is_list(Config) ->
+ case crypto:get_test_engine() of
+ {error, notexist} ->
+ {skip, "OTP Test engine not found"};
+ {ok, Engine} ->
+ try
+ Md5Hash1 = <<106,30,3,246,166,222,229,158,244,217,241,179,50,232,107,109>>,
+ Md5Hash1 = crypto:hash(md5, "Don't panic"),
+ Md5Hash2 = <<0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15>>,
+ case crypto:ensure_engine_loaded(<<"MD5">>, Engine) of
+ {ok, E} ->
+ {ok, _E1} = crypto:ensure_engine_loaded(<<"MD5">>, Engine),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash1 ->
+ ct:fail(fail_to_load_still_original_engine);
+ Md5Hash2 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_load_engine)
+ end,
+ ok = crypto:ensure_engine_unloaded(E),
+ case crypto:hash(md5, "Don't panic") of
+ Md5Hash2 ->
+ ct:fail(fail_to_unload_still_test_engine);
+ Md5Hash1 ->
+ ok;
+ _ ->
+ ct:fail(fail_to_unload_engine)
+ end;
+ {error, bad_engine_id} ->
+ {skip, "Dynamic Engine not supported"}
+ end
+ catch
+ error:notsup ->
+ {skip, "Engine not supported on this SSL version"}
+ end
+ end.
%%%----------------------------------------------------------------
%%% Pub/priv key storage tests. Those are for testing the crypto.erl
@@ -467,7 +675,7 @@ sign_verify_rsa_pwd_bad_pwd(Config) ->
_ -> {fail, "PWD prot pubkey sign succeded with no pwd!"}
catch
error:badarg -> ok
- end.
+ end.
priv_encrypt_pub_decrypt_rsa(Config) ->
Priv = #{engine => engine_ref(Config),
@@ -540,7 +748,7 @@ get_pub_from_priv_key_rsa_pwd_no_pwd(Config) ->
{skip, "RSA not supported"};
{error, Error} ->
{fail, {wrong_error,Error}};
- Pub ->
+ Pub ->
ct:log("rsa Pub = ~p",[Pub]),
{fail, "PWD prot pubkey fetch succeded although no pwd!"}
end.
@@ -556,7 +764,7 @@ get_pub_from_priv_key_rsa_pwd_bad_pwd(Config) ->
{skip, "RSA not supported"};
{error, Error} ->
{fail, {wrong_error,Error}};
- Pub ->
+ Pub ->
ct:log("rsa Pub = ~p",[Pub]),
{fail, "PWD prot pubkey fetch succeded with bad pwd!"}
end.
@@ -590,7 +798,7 @@ get_pub_from_priv_key_ecdsa(Config) ->
ct:log("ecdsa Pub = ~p",[Pub]),
sign_verify(ecdsa, sha, Priv, Pub)
end.
-
+
%%%================================================================
%%% Help for engine_stored_pub_priv_keys* test cases
%%%