aboutsummaryrefslogtreecommitdiff
path: root/lang
diff options
context:
space:
mode:
authorJean-Sébastien Pédron <dumbbell@FreeBSD.org>2018-11-06 14:12:22 +0000
committerJean-Sébastien Pédron <dumbbell@FreeBSD.org>2018-11-06 14:12:22 +0000
commit999d105526c0d73f3f885396b3e3b9cf51152a77 (patch)
tree29c92e2bb31560c40906c6b9506db9250e02ac02 /lang
parent70f2ae01896ce49c9ae64ef49f6d948d49e15276 (diff)
downloadports-999d105526c0d73f3f885396b3e3b9cf51152a77.tar.gz
ports-999d105526c0d73f3f885396b3e3b9cf51152a77.zip
Notes
Diffstat (limited to 'lang')
-rw-r--r--lang/erlang-runtime15/Makefile10
-rw-r--r--lang/erlang-runtime16/Makefile10
-rw-r--r--lang/erlang-runtime17/Makefile10
-rw-r--r--lang/erlang-runtime18/Makefile10
-rw-r--r--lang/erlang-runtime19/Makefile1
-rw-r--r--lang/erlang-runtime19/files/patch-OpenSSL-1.1-a1083
-rw-r--r--lang/erlang-runtime19/files/patch-OpenSSL-1.1-b293
-rw-r--r--lang/erlang/Makefile3
-rw-r--r--lang/erlang/files/patch-OpenSSL-1.1-a1083
-rw-r--r--lang/erlang/files/patch-OpenSSL-1.1-b293
10 files changed, 2792 insertions, 4 deletions
diff --git a/lang/erlang-runtime15/Makefile b/lang/erlang-runtime15/Makefile
index 75733b12d329..c157323d5d0f 100644
--- a/lang/erlang-runtime15/Makefile
+++ b/lang/erlang-runtime15/Makefile
@@ -46,6 +46,8 @@ OPTIONS_EXCLUDE+= DTRACE
OPTIONS_EXCLUDE_DragonFly= HIPE SCTP
OPTIONS_EXCLUDE_FreeBSD_10= DTRACE
+OPENSSL_VARS= BROKEN_SSL=openssl-devel openssl111
+
GNU_CONFIGURE= yes
LDFLAGS+= -L${LOCALBASE}/lib
USES= gmake ncurses perl5
@@ -76,6 +78,14 @@ WX_VARS= USE_WX=2.8+ WX_COMPS="wx contrib" USE_GL="gl glu"
.include <bsd.port.options.mk>
+.include <bsd.port.pre.mk>
+
+.if ${OPSYS} == FreeBSD
+. if ${OSVERSION} >= 1200085 && ${SSL_DEFAULT} == base
+BROKEN= Does not support OpenSSL 1.1, use Erlang 19+
+. endif
+.endif
+
.if ${OPSYS} == FreeBSD && ${OSVERSION} > 1100000
CFLAGS+= -DMAP_NORESERVE=0
.endif
diff --git a/lang/erlang-runtime16/Makefile b/lang/erlang-runtime16/Makefile
index 239d9a28d501..b84dcdfdf729 100644
--- a/lang/erlang-runtime16/Makefile
+++ b/lang/erlang-runtime16/Makefile
@@ -46,6 +46,8 @@ OPTIONS_EXCLUDE+= DTRACE
OPTIONS_EXCLUDE_DragonFly= HIPE SCTP
OPTIONS_EXCLUDE_FreeBSD_10= DTRACE
+OPENSSL_VARS= BROKEN_SSL=openssl-devel openssl111
+
GNU_CONFIGURE= yes
LDFLAGS+= -L${LOCALBASE}/lib
USES= gmake ncurses perl5
@@ -76,6 +78,14 @@ WX_VARS= USE_WX=2.8+ WX_COMPS="wx contrib" USE_GL="gl glu"
.include <bsd.port.options.mk>
+.include <bsd.port.pre.mk>
+
+.if ${OPSYS} == FreeBSD
+. if ${OSVERSION} >= 1200085 && ${SSL_DEFAULT} == base
+BROKEN= Does not support OpenSSL 1.1, use Erlang 19+
+. endif
+.endif
+
.if ${OPSYS} == FreeBSD && ${OSVERSION} > 1100000
CFLAGS+= -DMAP_NORESERVE=0
.endif
diff --git a/lang/erlang-runtime17/Makefile b/lang/erlang-runtime17/Makefile
index 5e5389051aeb..5928a522232d 100644
--- a/lang/erlang-runtime17/Makefile
+++ b/lang/erlang-runtime17/Makefile
@@ -65,7 +65,7 @@ OPTIONS_EXCLUDE_armv6= DTRACE
OPTIONS_EXCLUDE_armv7= DTRACE
OPTIONS_EXCLUDE_i386= DTRACE
-OPENSSL_VARS= BROKEN_SSL=openssl-devel
+OPENSSL_VARS= BROKEN_SSL=openssl-devel openssl111
GNU_CONFIGURE= yes
LDFLAGS+= -L${LOCALBASE}/lib
@@ -99,6 +99,14 @@ WX_VARS= USE_WX=2.8+ WX_COMPS="wx contrib" USE_GL="gl glu"
.include <bsd.port.options.mk>
+.include <bsd.port.pre.mk>
+
+.if ${OPSYS} == FreeBSD
+. if ${OSVERSION} >= 1200085 && ${SSL_DEFAULT} == base
+BROKEN= Does not support OpenSSL 1.1, use Erlang 19+
+. endif
+.endif
+
.if ${OPSYS} == FreeBSD && ${OSVERSION} > 1100000
CFLAGS+= -DMAP_NORESERVE=0
.endif
diff --git a/lang/erlang-runtime18/Makefile b/lang/erlang-runtime18/Makefile
index 2df82cd39474..d69d8807867c 100644
--- a/lang/erlang-runtime18/Makefile
+++ b/lang/erlang-runtime18/Makefile
@@ -66,7 +66,7 @@ OPTIONS_EXCLUDE_armv6= DTRACE
OPTIONS_EXCLUDE_armv7= DTRACE
OPTIONS_EXCLUDE_i386= DTRACE
-OPENSSL_VARS= BROKEN_SSL=openssl-devel
+OPENSSL_VARS= BROKEN_SSL=openssl-devel openssl111
GNU_CONFIGURE= yes
LDFLAGS+= -L${LOCALBASE}/lib
@@ -100,6 +100,14 @@ WX_VARS= USE_WX=2.8+ WX_COMPS="wx contrib" USE_GL="gl glu"
.include <bsd.port.options.mk>
+.include <bsd.port.pre.mk>
+
+.if ${OPSYS} == FreeBSD
+. if ${OSVERSION} >= 1200085 && ${SSL_DEFAULT} == base
+BROKEN= Does not support OpenSSL 1.1, use Erlang 19+
+. endif
+.endif
+
.if ${OPSYS} == FreeBSD && ${OSVERSION} > 1100000
CFLAGS+= -DMAP_NORESERVE=0
.endif
diff --git a/lang/erlang-runtime19/Makefile b/lang/erlang-runtime19/Makefile
index 1a5b64ff2874..89a53d983b70 100644
--- a/lang/erlang-runtime19/Makefile
+++ b/lang/erlang-runtime19/Makefile
@@ -3,6 +3,7 @@
PORTNAME= erlang
PORTVERSION= 19.3.6.11
+PORTREVISION= 1
CATEGORIES= lang parallel java
MASTER_SITES= http://www.erlang.org/download/:erlangorg \
http://erlang.stacken.kth.se/download/:erlangorg \
diff --git a/lang/erlang-runtime19/files/patch-OpenSSL-1.1-a b/lang/erlang-runtime19/files/patch-OpenSSL-1.1-a
new file mode 100644
index 000000000000..9a21938eaf42
--- /dev/null
+++ b/lang/erlang-runtime19/files/patch-OpenSSL-1.1-a
@@ -0,0 +1,1083 @@
+From 458c012e18eda87803ef356221d68955f4b8012d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
+Date: Thu, 24 Nov 2016 11:57:55 +0100
+Subject: [PATCH] Support OpenSSL 1.1.0
+
+---
+ lib/crypto/c_src/crypto.c | 486 +++++++++++++++++++++++++------------
+ lib/crypto/c_src/crypto_callback.c | 6 +-
+ lib/crypto/c_src/crypto_callback.h | 13 +-
+ 3 files changed, 345 insertions(+), 160 deletions(-)
+
+diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
+index 554aaf7587d..0031f9b9620 100644
+--- lib/crypto/c_src/crypto.c.orig 2018-02-14 17:16:13.270476000 +0100
++++ lib/crypto/c_src/crypto.c 2018-02-14 18:17:49.422680000 +0100
+@@ -64,56 +64,55 @@
+ /* Helper macro to construct a OPENSSL_VERSION_NUMBER.
+ * See openssl/opensslv.h
+ */
+-#define OpenSSL_version(MAJ, MIN, FIX, P) \
++#define PACKED_OPENSSL_VERSION(MAJ, MIN, FIX, P) \
+ ((((((((MAJ << 8) | MIN) << 8 ) | FIX) << 8) | (P-'a'+1)) << 4) | 0xf)
+
+-#define OpenSSL_version_plain(MAJ, MIN, FIX) \
+- OpenSSL_version(MAJ,MIN,FIX,('a'-1))
+-
++#define PACKED_OPENSSL_VERSION_PLAIN(MAJ, MIN, FIX) \
++ PACKED_OPENSSL_VERSION(MAJ,MIN,FIX,('a'-1))
+
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(1,0,0)
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
+ #include <openssl/modes.h>
+ #endif
+
+ #include "crypto_callback.h"
+
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(0,9,8) \
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(0,9,8) \
+ && !defined(OPENSSL_NO_SHA224) && defined(NID_sha224) \
+ && !defined(OPENSSL_NO_SHA256) /* disabled like this in my sha.h (?) */
+ # define HAVE_SHA224
+ #endif
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(0,9,8) \
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(0,9,8) \
+ && !defined(OPENSSL_NO_SHA256) && defined(NID_sha256)
+ # define HAVE_SHA256
+ #endif
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(0,9,8) \
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(0,9,8) \
+ && !defined(OPENSSL_NO_SHA384) && defined(NID_sha384)\
+ && !defined(OPENSSL_NO_SHA512) /* disabled like this in my sha.h (?) */
+ # define HAVE_SHA384
+ #endif
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(0,9,8) \
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(0,9,8) \
+ && !defined(OPENSSL_NO_SHA512) && defined(NID_sha512)
+ # define HAVE_SHA512
+ #endif
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version(0,9,7,'e')
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION(0,9,7,'e')
+ # define HAVE_DES_ede3_cfb_encrypt
+ #endif
+
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version(0,9,8,'o') \
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION(0,9,8,'o') \
+ && !defined(OPENSSL_NO_EC) \
+ && !defined(OPENSSL_NO_ECDH) \
+ && !defined(OPENSSL_NO_ECDSA)
+ # define HAVE_EC
+ #endif
+
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version(0,9,8,'c')
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION(0,9,8,'c')
+ # define HAVE_AES_IGE
+ #endif
+
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(1,0,1)
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,1)
+ # define HAVE_EVP_AES_CTR
+ # define HAVE_GCM
+-# if OPENSSL_VERSION_NUMBER < OpenSSL_version(1,0,1,'d')
++# if OPENSSL_VERSION_NUMBER < PACKED_OPENSSL_VERSION(1,0,1,'d')
+ # define HAVE_GCM_EVP_DECRYPT_BUG
+ # endif
+ #endif
+@@ -122,7 +121,7 @@
+ # define HAVE_CHACHA20_POLY1305
+ #endif
+
+-#if OPENSSL_VERSION_NUMBER <= OpenSSL_version(0,9,8,'l')
++#if OPENSSL_VERSION_NUMBER <= PACKED_OPENSSL_VERSION(0,9,8,'l')
+ # define HAVE_ECB_IVEC_BUG
+ #endif
+
+@@ -145,6 +144,7 @@
+
+ #endif
+
++
+ #ifdef VALGRIND
+ # include <valgrind/memcheck.h>
+
+@@ -213,6 +213,122 @@ do { \
+ } \
+ } while (0)
+
++#if OPENSSL_VERSION_NUMBER < PACKED_OPENSSL_VERSION_PLAIN(1,1,0)
++
++/*
++ * In OpenSSL 1.1.0, most structs are opaque. That means that
++ * the structs cannot be allocated as automatic variables on the
++ * C stack (because the size is unknown) and that it is necessary
++ * to use access functions.
++ *
++ * For backward compatibility to previous versions of OpenSSL, define
++ * on our versions of the new functions defined in 1.1.0 here, so that
++ * we don't have to sprinkle ifdefs throughout the code.
++ */
++
++static HMAC_CTX *HMAC_CTX_new(void);
++static void HMAC_CTX_free(HMAC_CTX *ctx);
++
++static HMAC_CTX *HMAC_CTX_new()
++{
++ HMAC_CTX *ctx = CRYPTO_malloc(sizeof(HMAC_CTX), __FILE__, __LINE__);
++ HMAC_CTX_init(ctx);
++ return ctx;
++}
++
++static void HMAC_CTX_free(HMAC_CTX *ctx)
++{
++ HMAC_CTX_cleanup(ctx);
++ return CRYPTO_free(ctx);
++}
++
++#define EVP_MD_CTX_new() EVP_MD_CTX_create()
++#define EVP_MD_CTX_free(ctx) EVP_MD_CTX_destroy(ctx)
++
++static INLINE int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d);
++static INLINE int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q);
++static INLINE int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp);
++
++static INLINE int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
++{
++ r->n = n;
++ r->e = e;
++ r->d = d;
++ return 1;
++}
++
++static INLINE int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q)
++{
++ r->p = p;
++ r->q = q;
++ return 1;
++}
++
++static INLINE int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp)
++{
++ r->dmp1 = dmp1;
++ r->dmq1 = dmq1;
++ r->iqmp = iqmp;
++ return 1;
++}
++
++static INLINE int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key);
++static INLINE int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g);
++
++static INLINE int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key)
++{
++ d->pub_key = pub_key;
++ d->priv_key = priv_key;
++ return 1;
++}
++
++static INLINE int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
++{
++ d->p = p;
++ d->q = q;
++ d->g = g;
++ return 1;
++}
++
++static INLINE int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key);
++static INLINE int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g);
++static INLINE void DH_get0_pqg(const DH *dh,
++ const BIGNUM **p, const BIGNUM **q, const BIGNUM **g);
++static INLINE void DH_get0_key(const DH *dh,
++ const BIGNUM **pub_key, const BIGNUM **priv_key);
++
++static INLINE int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key)
++{
++ dh->pub_key = pub_key;
++ dh->priv_key = priv_key;
++ return 1;
++}
++
++static INLINE int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
++{
++ dh->p = p;
++ dh->q = q;
++ dh->g = g;
++ return 1;
++}
++
++static INLINE void
++DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
++{
++ *p = dh->p;
++ *q = dh->q;
++ *g = dh->g;
++}
++
++static INLINE void
++DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key)
++{
++ *pub_key = dh->pub_key;
++ *priv_key = dh->priv_key;
++}
++
++#endif /* End of compatibility definitions. */
++
+ /* NIF interface declarations */
+ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info);
+ static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info);
+@@ -399,7 +515,7 @@ struct hmac_context
+ {
+ ErlNifMutex* mtx;
+ int alive;
+- HMAC_CTX ctx;
++ HMAC_CTX* ctx;
+ };
+ static void hmac_context_dtor(ErlNifEnv* env, struct hmac_context*);
+
+@@ -526,18 +642,24 @@ static struct cipher_type_t* get_cipher_
+ #define PRINTF_ERR1(FMT,A1)
+ #define PRINTF_ERR2(FMT,A1,A2)
+
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(1,0,0)
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
+ /* Define resource types for OpenSSL context structures. */
+ static ErlNifResourceType* evp_md_ctx_rtype;
+-static void evp_md_ctx_dtor(ErlNifEnv* env, EVP_MD_CTX* ctx) {
+- EVP_MD_CTX_cleanup(ctx);
++struct evp_md_ctx {
++ EVP_MD_CTX* ctx;
++};
++static void evp_md_ctx_dtor(ErlNifEnv* env, struct evp_md_ctx *ctx) {
++ EVP_MD_CTX_free(ctx->ctx);
+ }
+ #endif
+
+ #ifdef HAVE_EVP_AES_CTR
+ static ErlNifResourceType* evp_cipher_ctx_rtype;
+-static void evp_cipher_ctx_dtor(ErlNifEnv* env, EVP_CIPHER_CTX* ctx) {
+- EVP_CIPHER_CTX_cleanup(ctx);
++struct evp_cipher_ctx {
++ EVP_CIPHER_CTX* ctx;
++};
++static void evp_cipher_ctx_dtor(ErlNifEnv* env, struct evp_cipher_ctx* ctx) {
++ EVP_CIPHER_CTX_free(ctx->ctx);
+ }
+ #endif
+
+@@ -625,7 +747,7 @@ static int initialize(ErlNifEnv* env, ER
+ PRINTF_ERR0("CRYPTO: Could not open resource type 'hmac_context'");
+ return __LINE__;
+ }
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(1,0,0)
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
+ evp_md_ctx_rtype = enif_open_resource_type(env, NULL, "EVP_MD_CTX",
+ (ErlNifResourceDtor*) evp_md_ctx_dtor,
+ ERL_NIF_RT_CREATE|ERL_NIF_RT_TAKEOVER,
+@@ -937,12 +1059,12 @@ static ERL_NIF_TERM hash_nif(ErlNifEnv*
+ return ret;
+ }
+
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(1,0,0)
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
+
+ static ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+ {/* (Type) */
+ struct digest_type_t *digp = NULL;
+- EVP_MD_CTX *ctx;
++ struct evp_md_ctx *ctx;
+ ERL_NIF_TERM ret;
+
+ digp = get_digest_type(argv[0]);
+@@ -953,8 +1075,9 @@ static ERL_NIF_TERM hash_init_nif(ErlNif
+ return atom_notsup;
+ }
+
+- ctx = enif_alloc_resource(evp_md_ctx_rtype, sizeof(EVP_MD_CTX));
+- if (!EVP_DigestInit(ctx, digp->md.p)) {
++ ctx = enif_alloc_resource(evp_md_ctx_rtype, sizeof(struct evp_md_ctx));
++ ctx->ctx = EVP_MD_CTX_new();
++ if (!EVP_DigestInit(ctx->ctx, digp->md.p)) {
+ enif_release_resource(ctx);
+ return atom_notsup;
+ }
+@@ -964,7 +1087,7 @@ static ERL_NIF_TERM hash_init_nif(ErlNif
+ }
+ static ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+ {/* (Context, Data) */
+- EVP_MD_CTX *ctx, *new_ctx;
++ struct evp_md_ctx *ctx, *new_ctx;
+ ErlNifBinary data;
+ ERL_NIF_TERM ret;
+
+@@ -973,9 +1096,10 @@ static ERL_NIF_TERM hash_update_nif(ErlN
+ return enif_make_badarg(env);
+ }
+
+- new_ctx = enif_alloc_resource(evp_md_ctx_rtype, sizeof(EVP_MD_CTX));
+- if (!EVP_MD_CTX_copy(new_ctx, ctx) ||
+- !EVP_DigestUpdate(new_ctx, data.data, data.size)) {
++ new_ctx = enif_alloc_resource(evp_md_ctx_rtype, sizeof(struct evp_md_ctx));
++ new_ctx->ctx = EVP_MD_CTX_new();
++ if (!EVP_MD_CTX_copy(new_ctx->ctx, ctx->ctx) ||
++ !EVP_DigestUpdate(new_ctx->ctx, data.data, data.size)) {
+ enif_release_resource(new_ctx);
+ return atom_notsup;
+ }
+@@ -987,7 +1111,8 @@ static ERL_NIF_TERM hash_update_nif(ErlN
+ }
+ static ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+ {/* (Context) */
+- EVP_MD_CTX *ctx, new_ctx;
++ struct evp_md_ctx *ctx;
++ EVP_MD_CTX *new_ctx;
+ ERL_NIF_TERM ret;
+ unsigned ret_size;
+
+@@ -995,16 +1120,19 @@ static ERL_NIF_TERM hash_final_nif(ErlNi
+ return enif_make_badarg(env);
+ }
+
+- ret_size = (unsigned)EVP_MD_CTX_size(ctx);
++ ret_size = (unsigned)EVP_MD_CTX_size(ctx->ctx);
+ ASSERT(0 < ret_size && ret_size <= EVP_MAX_MD_SIZE);
+
+- if (!EVP_MD_CTX_copy(&new_ctx, ctx) ||
+- !EVP_DigestFinal(&new_ctx,
++ new_ctx = EVP_MD_CTX_new();
++ if (!EVP_MD_CTX_copy(new_ctx, ctx->ctx) ||
++ !EVP_DigestFinal(new_ctx,
+ enif_make_new_binary(env, ret_size, &ret),
+ &ret_size)) {
++ EVP_MD_CTX_free(new_ctx);
+ return atom_notsup;
+ }
+- ASSERT(ret_size == (unsigned)EVP_MD_CTX_size(ctx));
++ EVP_MD_CTX_free(new_ctx);
++ ASSERT(ret_size == (unsigned)EVP_MD_CTX_size(ctx->ctx));
+
+ return ret;
+ }
+@@ -1288,7 +1416,7 @@ static ERL_NIF_TERM hmac_nif(ErlNifEnv*
+ static void hmac_context_dtor(ErlNifEnv* env, struct hmac_context *obj)
+ {
+ if (obj->alive) {
+- HMAC_CTX_cleanup(&obj->ctx);
++ HMAC_CTX_free(obj->ctx);
+ obj->alive = 0;
+ }
+ enif_mutex_destroy(obj->mtx);
+@@ -1313,15 +1441,16 @@ static ERL_NIF_TERM hmac_init_nif(ErlNif
+ obj = enif_alloc_resource(hmac_context_rtype, sizeof(struct hmac_context));
+ obj->mtx = enif_mutex_create("crypto.hmac");
+ obj->alive = 1;
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(1,0,0)
++ obj->ctx = HMAC_CTX_new();
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
+ // Check the return value of HMAC_Init: it may fail in FIPS mode
+ // for disabled algorithms
+- if (!HMAC_Init(&obj->ctx, key.data, key.size, digp->md.p)) {
++ if (!HMAC_Init_ex(obj->ctx, key.data, key.size, digp->md.p, NULL)) {
+ enif_release_resource(obj);
+ return atom_notsup;
+ }
+ #else
+- HMAC_Init(&obj->ctx, key.data, key.size, digp->md.p);
++ HMAC_Init_ex(obj->ctx, key.data, key.size, digp->md.p, NULL);
+ #endif
+
+ ret = enif_make_resource(env, obj);
+@@ -1343,7 +1472,7 @@ static ERL_NIF_TERM hmac_update_nif(ErlN
+ enif_mutex_unlock(obj->mtx);
+ return enif_make_badarg(env);
+ }
+- HMAC_Update(&obj->ctx, data.data, data.size);
++ HMAC_Update(obj->ctx, data.data, data.size);
+ enif_mutex_unlock(obj->mtx);
+
+ CONSUME_REDS(env,data);
+@@ -1370,8 +1499,8 @@ static ERL_NIF_TERM hmac_final_nif(ErlNi
+ return enif_make_badarg(env);
+ }
+
+- HMAC_Final(&obj->ctx, mac_buf, &mac_len);
+- HMAC_CTX_cleanup(&obj->ctx);
++ HMAC_Final(obj->ctx, mac_buf, &mac_len);
++ HMAC_CTX_free(obj->ctx);
+ obj->alive = 0;
+ enif_mutex_unlock(obj->mtx);
+
+@@ -1390,7 +1519,7 @@ static ERL_NIF_TERM block_crypt_nif(ErlN
+ struct cipher_type_t *cipherp = NULL;
+ const EVP_CIPHER *cipher;
+ ErlNifBinary key, ivec, text;
+- EVP_CIPHER_CTX ctx;
++ EVP_CIPHER_CTX* ctx;
+ ERL_NIF_TERM ret;
+ unsigned char *out;
+ int ivec_size, out_size = 0;
+@@ -1438,30 +1567,30 @@ static ERL_NIF_TERM block_crypt_nif(ErlN
+
+ out = enif_make_new_binary(env, text.size, &ret);
+
+- EVP_CIPHER_CTX_init(&ctx);
+- if (!EVP_CipherInit_ex(&ctx, cipher, NULL, NULL, NULL,
++ ctx = EVP_CIPHER_CTX_new();
++ if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL,
+ (argv[argc - 1] == atom_true)) ||
+- !EVP_CIPHER_CTX_set_key_length(&ctx, key.size) ||
++ !EVP_CIPHER_CTX_set_key_length(ctx, key.size) ||
+ !(EVP_CIPHER_type(cipher) != NID_rc2_cbc ||
+- EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_SET_RC2_KEY_BITS, key.size * 8, NULL)) ||
+- !EVP_CipherInit_ex(&ctx, NULL, NULL,
++ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC2_KEY_BITS, key.size * 8, NULL)) ||
++ !EVP_CipherInit_ex(ctx, NULL, NULL,
+ key.data, ivec_size ? ivec.data : NULL, -1) ||
+- !EVP_CIPHER_CTX_set_padding(&ctx, 0)) {
++ !EVP_CIPHER_CTX_set_padding(ctx, 0)) {
+
+- EVP_CIPHER_CTX_cleanup(&ctx);
++ EVP_CIPHER_CTX_free(ctx);
+ return enif_raise_exception(env, atom_notsup);
+ }
+
+ if (text.size > 0 && /* OpenSSL 0.9.8h asserts text.size > 0 */
+- (!EVP_CipherUpdate(&ctx, out, &out_size, text.data, text.size)
++ (!EVP_CipherUpdate(ctx, out, &out_size, text.data, text.size)
+ || (ASSERT(out_size == text.size), 0)
+- || !EVP_CipherFinal_ex(&ctx, out + out_size, &out_size))) {
++ || !EVP_CipherFinal_ex(ctx, out + out_size, &out_size))) {
+
+- EVP_CIPHER_CTX_cleanup(&ctx);
++ EVP_CIPHER_CTX_free(ctx);
+ return enif_raise_exception(env, atom_notsup);
+ }
+ ASSERT(out_size == 0);
+- EVP_CIPHER_CTX_cleanup(&ctx);
++ EVP_CIPHER_CTX_free(ctx);
+ CONSUME_REDS(env, text);
+
+ return ret;
+@@ -1563,7 +1692,7 @@ static ERL_NIF_TERM aes_ctr_encrypt(ErlN
+ ErlNifBinary key, ivec, text;
+ #ifdef HAVE_EVP_AES_CTR
+ const EVP_CIPHER *cipher;
+- EVP_CIPHER_CTX ctx;
++ struct evp_cipher_ctx ctx;
+ unsigned char *out;
+ int outl = 0;
+ #else
+@@ -1621,7 +1750,7 @@ static ERL_NIF_TERM aes_ctr_encrypt(ErlN
+ static ERL_NIF_TERM aes_ctr_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+ {/* (Key, IVec) */
+ ErlNifBinary key_bin, ivec_bin;
+- EVP_CIPHER_CTX *ctx;
++ struct evp_cipher_ctx *ctx;
+ const EVP_CIPHER *cipher;
+ ERL_NIF_TERM ret;
+
+@@ -1639,18 +1768,18 @@ static ERL_NIF_TERM aes_ctr_stream_init(
+ default: return enif_make_badarg(env);
+ }
+
+- ctx = enif_alloc_resource(evp_cipher_ctx_rtype, sizeof(EVP_CIPHER_CTX));
+- EVP_CIPHER_CTX_init(ctx);
+- EVP_CipherInit_ex(ctx, cipher, NULL,
++ 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, 0);
++ EVP_CIPHER_CTX_set_padding(ctx->ctx, 0);
+ ret = enif_make_resource(env, ctx);
+ enif_release_resource(ctx);
+ return ret;
+ }
+ static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+ {/* (Context, Data) */
+- EVP_CIPHER_CTX *ctx, *new_ctx;
++ struct evp_cipher_ctx *ctx, *new_ctx;
+ ErlNifBinary data_bin;
+ ERL_NIF_TERM ret, cipher_term;
+ unsigned char *out;
+@@ -1660,11 +1789,11 @@ static ERL_NIF_TERM aes_ctr_stream_encry
+ || !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(EVP_CIPHER_CTX));
+- EVP_CIPHER_CTX_init(new_ctx);
+- EVP_CIPHER_CTX_copy(new_ctx, ctx);
++ 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, out, &outl, data_bin.data, data_bin.size);
++ 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);
+@@ -1735,7 +1864,7 @@ static ERL_NIF_TERM aes_ctr_stream_encry
+ static ERL_NIF_TERM aes_gcm_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+ {/* (Key,Iv,AAD,In) */
+ #if defined(HAVE_GCM)
+- EVP_CIPHER_CTX ctx;
++ EVP_CIPHER_CTX *ctx;
+ const EVP_CIPHER *cipher = NULL;
+ ErlNifBinary key, iv, aad, in;
+ unsigned int tag_len;
+@@ -1759,40 +1888,40 @@ static ERL_NIF_TERM aes_gcm_encrypt(ErlN
+ else if (key.size == 32)
+ cipher = EVP_aes_256_gcm();
+
+- EVP_CIPHER_CTX_init(&ctx);
++ ctx = EVP_CIPHER_CTX_new();
+
+- if (EVP_EncryptInit_ex(&ctx, cipher, NULL, NULL, NULL) != 1)
++ if (EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1)
+ goto out_err;
+
+- EVP_CIPHER_CTX_set_padding(&ctx, 0);
++ EVP_CIPHER_CTX_set_padding(ctx, 0);
+
+- if (EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, iv.size, NULL) != 1)
++ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv.size, NULL) != 1)
+ goto out_err;
+- if (EVP_EncryptInit_ex(&ctx, NULL, NULL, key.data, iv.data) != 1)
++ if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1)
+ goto out_err;
+- if (EVP_EncryptUpdate(&ctx, NULL, &len, aad.data, aad.size) != 1)
++ if (EVP_EncryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1)
+ goto out_err;
+
+ outp = enif_make_new_binary(env, in.size, &out);
+
+- if (EVP_EncryptUpdate(&ctx, outp, &len, in.data, in.size) != 1)
++ if (EVP_EncryptUpdate(ctx, outp, &len, in.data, in.size) != 1)
+ goto out_err;
+- if (EVP_EncryptFinal_ex(&ctx, outp+len, &len) != 1)
++ if (EVP_EncryptFinal_ex(ctx, outp+len, &len) != 1)
+ goto out_err;
+
+ tagp = enif_make_new_binary(env, tag_len, &out_tag);
+
+- if (EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_GET_TAG, tag_len, tagp) != 1)
++ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, tag_len, tagp) != 1)
+ goto out_err;
+
+- EVP_CIPHER_CTX_cleanup(&ctx);
++ EVP_CIPHER_CTX_free(ctx);
+
+ CONSUME_REDS(env, in);
+
+ return enif_make_tuple2(env, out, out_tag);
+
+ out_err:
+- EVP_CIPHER_CTX_cleanup(&ctx);
++ EVP_CIPHER_CTX_free(ctx);
+ return atom_error;
+
+ #else
+@@ -1805,7 +1934,7 @@ static ERL_NIF_TERM aes_gcm_decrypt(ErlN
+ #if defined(HAVE_GCM_EVP_DECRYPT_BUG)
+ return aes_gcm_decrypt_NO_EVP(env, argc, argv);
+ #elif defined(HAVE_GCM)
+- EVP_CIPHER_CTX ctx;
++ EVP_CIPHER_CTX *ctx;
+ const EVP_CIPHER *cipher = NULL;
+ ErlNifBinary key, iv, aad, in, tag;
+ unsigned char *outp;
+@@ -1828,34 +1957,34 @@ static ERL_NIF_TERM aes_gcm_decrypt(ErlN
+ else if (key.size == 32)
+ cipher = EVP_aes_256_gcm();
+
+- EVP_CIPHER_CTX_init(&ctx);
++ ctx = EVP_CIPHER_CTX_new();
+
+- if (EVP_DecryptInit_ex(&ctx, cipher, NULL, NULL, NULL) != 1)
++ if (EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1)
+ goto out_err;
+- if (EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, iv.size, NULL) != 1)
++ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv.size, NULL) != 1)
+ goto out_err;
+- if (EVP_DecryptInit_ex(&ctx, NULL, NULL, key.data, iv.data) != 1)
++ if (EVP_DecryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1)
+ goto out_err;
+- if (EVP_DecryptUpdate(&ctx, NULL, &len, aad.data, aad.size) != 1)
++ if (EVP_DecryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1)
+ goto out_err;
+
+ outp = enif_make_new_binary(env, in.size, &out);
+
+- if (EVP_DecryptUpdate(&ctx, outp, &len, in.data, in.size) != 1)
++ if (EVP_DecryptUpdate(ctx, outp, &len, in.data, in.size) != 1)
+ goto out_err;
+- if (EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_TAG, tag.size, tag.data) != 1)
++ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, tag.size, tag.data) != 1)
+ goto out_err;
+- if (EVP_DecryptFinal_ex(&ctx, outp+len, &len) != 1)
++ if (EVP_DecryptFinal_ex(ctx, outp+len, &len) != 1)
+ goto out_err;
+
+- EVP_CIPHER_CTX_cleanup(&ctx);
++ EVP_CIPHER_CTX_free(ctx);
+
+ CONSUME_REDS(env, in);
+
+ return out;
+
+ out_err:
+- EVP_CIPHER_CTX_cleanup(&ctx);
++ EVP_CIPHER_CTX_free(ctx);
+ return atom_error;
+ #else
+ return enif_raise_exception(env, atom_notsup);
+@@ -2234,13 +2363,10 @@ static ERL_NIF_TERM dss_verify_nif(ErlNi
+ }
+
+ dsa = DSA_new();
+- dsa->p = dsa_p;
+- dsa->q = dsa_q;
+- dsa->g = dsa_g;
+- dsa->priv_key = NULL;
+- dsa->pub_key = dsa_y;
+- i = DSA_verify(0, digest_bin.data, SHA_DIGEST_LENGTH,
+- sign_bin.data, sign_bin.size, dsa);
++ DSA_set0_pqg(dsa, dsa_p, dsa_q, dsa_g);
++ DSA_set0_key(dsa, dsa_y, NULL);
++ i = DSA_verify(0, digest_bin.data, SHA_DIGEST_LENGTH,
++ sign_bin.data, sign_bin.size, dsa);
+ DSA_free(dsa);
+ return(i > 0) ? atom_true : atom_false;
+ }
+@@ -2297,13 +2423,15 @@ static ERL_NIF_TERM rsa_verify_nif(ErlNi
+ ERL_NIF_TERM head, tail, ret;
+ int i;
+ RSA *rsa;
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(1,0,0)
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
+ EVP_PKEY *pkey;
+ EVP_PKEY_CTX *ctx;
+ #endif
+ const EVP_MD *md;
+ const ERL_NIF_TERM type = argv[0];
+ struct digest_type_t *digp = NULL;
++ BIGNUM *rsa_e;
++ BIGNUM *rsa_n;
+
+ digp = get_digest_type(type);
+ if (!digp) {
+@@ -2320,16 +2448,18 @@ static ERL_NIF_TERM rsa_verify_nif(ErlNi
+ || digest_bin.size != EVP_MD_size(md)
+ || !enif_inspect_binary(env, argv[2], &sign_bin)
+ || !enif_get_list_cell(env, argv[3], &head, &tail)
+- || !get_bn_from_bin(env, head, &rsa->e)
++ || !get_bn_from_bin(env, head, &rsa_e)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+- || !get_bn_from_bin(env, head, &rsa->n)
++ || !get_bn_from_bin(env, head, &rsa_n)
+ || !enif_is_empty_list(env, tail)) {
+
+ ret = enif_make_badarg(env);
+ goto done;
+ }
+
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(1,0,0)
++ (void) RSA_set0_key(rsa, rsa_n, rsa_e, NULL);
++
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
+ pkey = EVP_PKEY_new();
+ EVP_PKEY_set1_RSA(pkey, rsa);
+
+@@ -2440,34 +2570,44 @@ static int get_rsa_private_key(ErlNifEnv
+ {
+ /* key=[E,N,D]|[E,N,D,P1,P2,E1,E2,C] */
+ ERL_NIF_TERM head, tail;
++ BIGNUM *e, *n, *d;
++ BIGNUM *p, *q;
++ BIGNUM *dmp1, *dmq1, *iqmp;
+
+ if (!enif_get_list_cell(env, key, &head, &tail)
+- || !get_bn_from_bin(env, head, &rsa->e)
++ || !get_bn_from_bin(env, head, &e)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+- || !get_bn_from_bin(env, head, &rsa->n)
++ || !get_bn_from_bin(env, head, &n)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+- || !get_bn_from_bin(env, head, &rsa->d)
+- || (!enif_is_empty_list(env, tail) &&
+- (!enif_get_list_cell(env, tail, &head, &tail)
+- || !get_bn_from_bin(env, head, &rsa->p)
+- || !enif_get_list_cell(env, tail, &head, &tail)
+- || !get_bn_from_bin(env, head, &rsa->q)
+- || !enif_get_list_cell(env, tail, &head, &tail)
+- || !get_bn_from_bin(env, head, &rsa->dmp1)
+- || !enif_get_list_cell(env, tail, &head, &tail)
+- || !get_bn_from_bin(env, head, &rsa->dmq1)
+- || !enif_get_list_cell(env, tail, &head, &tail)
+- || !get_bn_from_bin(env, head, &rsa->iqmp)
+- || !enif_is_empty_list(env, tail)))) {
++ || !get_bn_from_bin(env, head, &d)) {
+ return 0;
+ }
++ (void) RSA_set0_key(rsa, n, e, d);
++ if (enif_is_empty_list(env, tail)) {
++ return 1;
++ }
++ if (!enif_get_list_cell(env, tail, &head, &tail)
++ || !get_bn_from_bin(env, head, &p)
++ || !enif_get_list_cell(env, tail, &head, &tail)
++ || !get_bn_from_bin(env, head, &q)
++ || !enif_get_list_cell(env, tail, &head, &tail)
++ || !get_bn_from_bin(env, head, &dmp1)
++ || !enif_get_list_cell(env, tail, &head, &tail)
++ || !get_bn_from_bin(env, head, &dmq1)
++ || !enif_get_list_cell(env, tail, &head, &tail)
++ || !get_bn_from_bin(env, head, &iqmp)
++ || !enif_is_empty_list(env, tail)) {
++ return 0;
++ }
++ (void) RSA_set0_factors(rsa, p, q);
++ (void) RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp);
+ return 1;
+ }
+
+ static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+ {/* (Type, Digest, Key=[E,N,D]|[E,N,D,P1,P2,E1,E2,C]) */
+ ErlNifBinary digest_bin, ret_bin;
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(1,0,0)
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
+ EVP_PKEY *pkey;
+ EVP_PKEY_CTX *ctx;
+ size_t rsa_s_len;
+@@ -2500,7 +2640,7 @@ static ERL_NIF_TERM rsa_sign_nif(ErlNifE
+ }
+
+
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(1,0,0)
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
+ pkey = EVP_PKEY_new();
+ EVP_PKEY_set1_RSA(pkey, rsa);
+ rsa_s_len=(size_t)EVP_PKEY_size(pkey);
+@@ -2547,6 +2687,8 @@ static ERL_NIF_TERM dss_sign_nif(ErlNifE
+ ERL_NIF_TERM head, tail;
+ unsigned int dsa_s_len;
+ DSA* dsa;
++ BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL;
++ BIGNUM *dummy_pub_key, *priv_key = NULL;
+ int i;
+
+ if (argv[0] != atom_sha
+@@ -2555,26 +2697,37 @@ static ERL_NIF_TERM dss_sign_nif(ErlNifE
+ return enif_make_badarg(env);
+ }
+
+- dsa = DSA_new();
+-
+- dsa->pub_key = NULL;
+ if (!enif_get_list_cell(env, argv[2], &head, &tail)
+- || !get_bn_from_bin(env, head, &dsa->p)
++ || !get_bn_from_bin(env, head, &dsa_p)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+- || !get_bn_from_bin(env, head, &dsa->q)
++ || !get_bn_from_bin(env, head, &dsa_q)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+- || !get_bn_from_bin(env, head, &dsa->g)
++ || !get_bn_from_bin(env, head, &dsa_g)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+- || !get_bn_from_bin(env, head, &dsa->priv_key)
++ || !get_bn_from_bin(env, head, &priv_key)
+ || !enif_is_empty_list(env,tail)) {
+- DSA_free(dsa);
++ if (dsa_p) BN_free(dsa_p);
++ if (dsa_q) BN_free(dsa_q);
++ if (dsa_g) BN_free(dsa_g);
++ if (priv_key) BN_free(priv_key);
+ return enif_make_badarg(env);
+ }
+
++ /* Note: DSA_set0_key() does not allow setting only the
++ * private key, although DSA_sign() does not use the
++ * public key. Work around this limitation by setting
++ * the public key to a copy of the private key.
++ */
++ dummy_pub_key = BN_dup(priv_key);
++
++ dsa = DSA_new();
++ DSA_set0_pqg(dsa, dsa_p, dsa_q, dsa_g);
++ DSA_set0_key(dsa, dummy_pub_key, priv_key);
+ enif_alloc_binary(DSA_size(dsa), &ret_bin);
+ i = DSA_sign(NID_sha1, digest_bin.data, SHA_DIGEST_LENGTH,
+ ret_bin.data, &dsa_s_len, dsa);
+ DSA_free(dsa);
++
+ if (i) {
+ if (dsa_s_len != ret_bin.size) {
+ enif_realloc_binary(&ret_bin, dsa_s_len);
+@@ -2611,20 +2764,22 @@ static ERL_NIF_TERM rsa_public_crypt(Erl
+ ERL_NIF_TERM head, tail;
+ int padding, i;
+ RSA* rsa;
++ BIGNUM *e, *n;
+
+ rsa = RSA_new();
+
+ if (!enif_inspect_binary(env, argv[0], &data_bin)
+ || !enif_get_list_cell(env, argv[1], &head, &tail)
+- || !get_bn_from_bin(env, head, &rsa->e)
++ || !get_bn_from_bin(env, head, &e)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+- || !get_bn_from_bin(env, head, &rsa->n)
++ || !get_bn_from_bin(env, head, &n)
+ || !enif_is_empty_list(env,tail)
+ || !rsa_pad(argv[2], &padding)) {
+
+ RSA_free(rsa);
+ return enif_make_badarg(env);
+ }
++ (void) RSA_set0_key(rsa, n, e, NULL);
+
+ enif_alloc_binary(RSA_size(rsa), &ret_bin);
+
+@@ -2705,6 +2860,7 @@ static ERL_NIF_TERM dh_generate_paramete
+ int p_len, g_len;
+ unsigned char *p_ptr, *g_ptr;
+ ERL_NIF_TERM ret_p, ret_g;
++ const BIGNUM *dh_p, *dh_q, *dh_g;
+
+ if (!enif_get_int(env, argv[0], &prime_len)
+ || !enif_get_int(env, argv[1], &generator)) {
+@@ -2715,15 +2871,16 @@ static ERL_NIF_TERM dh_generate_paramete
+ if (dh_params == NULL) {
+ return atom_error;
+ }
+- p_len = BN_num_bytes(dh_params->p);
+- g_len = BN_num_bytes(dh_params->g);
++ DH_get0_pqg(dh_params, &dh_p, &dh_q, &dh_g);
++ DH_free(dh_params);
++ p_len = BN_num_bytes(dh_p);
++ g_len = BN_num_bytes(dh_g);
+ p_ptr = enif_make_new_binary(env, p_len, &ret_p);
+ g_ptr = enif_make_new_binary(env, g_len, &ret_g);
+- BN_bn2bin(dh_params->p, p_ptr);
+- BN_bn2bin(dh_params->g, g_ptr);
++ BN_bn2bin(dh_p, p_ptr);
++ BN_bn2bin(dh_g, g_ptr);
+ ERL_VALGRIND_MAKE_MEM_DEFINED(p_ptr, p_len);
+ ERL_VALGRIND_MAKE_MEM_DEFINED(g_ptr, g_len);
+- DH_free(dh_params);
+ return enif_make_list2(env, ret_p, ret_g);
+ }
+
+@@ -2732,18 +2889,19 @@ static ERL_NIF_TERM dh_check(ErlNifEnv*
+ DH* dh_params;
+ int i;
+ ERL_NIF_TERM ret, head, tail;
+-
+- dh_params = DH_new();
++ BIGNUM *dh_p, *dh_g;
+
+ if (!enif_get_list_cell(env, argv[0], &head, &tail)
+- || !get_bn_from_bin(env, head, &dh_params->p)
++ || !get_bn_from_bin(env, head, &dh_p)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+- || !get_bn_from_bin(env, head, &dh_params->g)
++ || !get_bn_from_bin(env, head, &dh_g)
+ || !enif_is_empty_list(env,tail)) {
+
+- DH_free(dh_params);
+ return enif_make_badarg(env);
+ }
++
++ dh_params = DH_new();
++ DH_set0_pqg(dh_params, dh_p, NULL, dh_g);
+ if (DH_check(dh_params, &i)) {
+ if (i == 0) ret = atom_ok;
+ else if (i & DH_CHECK_P_NOT_PRIME) ret = atom_not_prime;
+@@ -2767,42 +2925,41 @@ static ERL_NIF_TERM dh_generate_key_nif(
+ ERL_NIF_TERM ret, ret_pub, ret_prv, head, tail;
+ int mpint; /* 0 or 4 */
+ unsigned long len = 0;
++ BIGNUM *priv_key = NULL;
++ BIGNUM *dh_p = NULL, *dh_g = NULL;
+
+- dh_params = DH_new();
+-
+- if (!(get_bn_from_bin(env, argv[0], &dh_params->priv_key)
++ if (!(get_bn_from_bin(env, argv[0], &priv_key)
+ || argv[0] == atom_undefined)
+ || !enif_get_list_cell(env, argv[1], &head, &tail)
+- || !get_bn_from_bin(env, head, &dh_params->p)
++ || !get_bn_from_bin(env, head, &dh_p)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+- || !get_bn_from_bin(env, head, &dh_params->g)
++ || !get_bn_from_bin(env, head, &dh_g)
+ || !enif_is_empty_list(env, tail)
+ || !enif_get_int(env, argv[2], &mpint) || (mpint & ~4)
+ || !enif_get_ulong(env, argv[3], &len) ) {
+- DH_free(dh_params);
++ if (priv_key) BN_free(priv_key);
++ if (dh_p) BN_free(dh_p);
++ if (dh_g) BN_free(dh_g);
+ return enif_make_badarg(env);
+ }
+
+- if (len) {
+- if (len < BN_num_bits(dh_params->p))
+- dh_params->length = len;
+- else {
+- DH_free(dh_params);
+- return enif_make_badarg(env);
+- }
+- }
++ dh_params = DH_new();
++ DH_set0_key(dh_params, NULL, priv_key);
++ DH_set0_pqg(dh_params, dh_p, NULL, dh_g);
+
+ if (DH_generate_key(dh_params)) {
+- pub_len = BN_num_bytes(dh_params->pub_key);
+- prv_len = BN_num_bytes(dh_params->priv_key);
++ const BIGNUM *pub_key, *priv_key;
++ DH_get0_key(dh_params, &pub_key, &priv_key);
++ pub_len = BN_num_bytes(pub_key);
++ prv_len = BN_num_bytes(priv_key);
+ pub_ptr = enif_make_new_binary(env, pub_len+mpint, &ret_pub);
+ prv_ptr = enif_make_new_binary(env, prv_len+mpint, &ret_prv);
+ if (mpint) {
+ put_int32(pub_ptr, pub_len); pub_ptr += 4;
+ put_int32(prv_ptr, prv_len); prv_ptr += 4;
+ }
+- BN_bn2bin(dh_params->pub_key, pub_ptr);
+- BN_bn2bin(dh_params->priv_key, prv_ptr);
++ BN_bn2bin(pub_key, pub_ptr);
++ BN_bn2bin(priv_key, prv_ptr);
+ ERL_VALGRIND_MAKE_MEM_DEFINED(pub_ptr, pub_len);
+ ERL_VALGRIND_MAKE_MEM_DEFINED(prv_ptr, prv_len);
+ ret = enif_make_tuple2(env, ret_pub, ret_prv);
+@@ -2817,26 +2974,37 @@ static ERL_NIF_TERM dh_generate_key_nif(
+ static ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+ {/* (OthersPublicKey, MyPrivateKey, DHParams=[P,G]) */
+ DH* dh_params;
+- BIGNUM* pubkey = NULL;
++ BIGNUM *dummy_pub_key = NULL, *priv_key = NULL;
++ BIGNUM *other_pub_key;
++ BIGNUM *dh_p = NULL, *dh_g = NULL;
+ int i;
+ ErlNifBinary ret_bin;
+ ERL_NIF_TERM ret, head, tail;
+
+ dh_params = DH_new();
+
+- if (!get_bn_from_bin(env, argv[0], &pubkey)
+- || !get_bn_from_bin(env, argv[1], &dh_params->priv_key)
++ if (!get_bn_from_bin(env, argv[0], &other_pub_key)
++ || !get_bn_from_bin(env, argv[1], &priv_key)
+ || !enif_get_list_cell(env, argv[2], &head, &tail)
+- || !get_bn_from_bin(env, head, &dh_params->p)
++ || !get_bn_from_bin(env, head, &dh_p)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+- || !get_bn_from_bin(env, head, &dh_params->g)
++ || !get_bn_from_bin(env, head, &dh_g)
+ || !enif_is_empty_list(env, tail)) {
+-
++ if (dh_p) BN_free(dh_p);
++ if (dh_g) BN_free(dh_g);
+ ret = enif_make_badarg(env);
+ }
+ else {
++ /* Note: DH_set0_key() does not allow setting only the
++ * private key, although DH_compute_key() does not use the
++ * public key. Work around this limitation by setting
++ * the public key to a copy of the private key.
++ */
++ dummy_pub_key = BN_dup(priv_key);
++ DH_set0_key(dh_params, dummy_pub_key, priv_key);
++ DH_set0_pqg(dh_params, dh_p, NULL, dh_g);
+ enif_alloc_binary(DH_size(dh_params), &ret_bin);
+- i = DH_compute_key(ret_bin.data, pubkey, dh_params);
++ i = DH_compute_key(ret_bin.data, other_pub_key, dh_params);
+ if (i > 0) {
+ if (i != ret_bin.size) {
+ enif_realloc_binary(&ret_bin, i);
+@@ -2848,7 +3016,7 @@ static ERL_NIF_TERM dh_compute_key_nif(E
+ ret = atom_error;
+ }
+ }
+- if (pubkey) BN_free(pubkey);
++ if (other_pub_key) BN_free(other_pub_key);
+ DH_free(dh_params);
+ return ret;
+ }
+@@ -3420,7 +3588,7 @@ static ERL_NIF_TERM ecdsa_sign_nif(ErlNi
+
+ enif_alloc_binary(ECDSA_size(key), &ret_bin);
+
+- i = ECDSA_sign(md->type, digest_bin.data, len,
++ i = ECDSA_sign(EVP_MD_type(md), digest_bin.data, len,
+ ret_bin.data, &dsa_s_len, key);
+
+ EC_KEY_free(key);
+@@ -3470,7 +3638,7 @@ static ERL_NIF_TERM ecdsa_verify_nif(Erl
+ || !get_ec_key(env, argv[3], atom_undefined, argv[4], &key))
+ goto badarg;
+
+- i = ECDSA_verify(md->type, digest_bin.data, len,
++ i = ECDSA_verify(EVP_MD_type(md), digest_bin.data, len,
+ sign_bin.data, sign_bin.size, key);
+
+ EC_KEY_free(key);
+diff --git a/lib/crypto/c_src/crypto_callback.c b/lib/crypto/c_src/crypto_callback.c
+index 4c23379f7f6..23d2bed0576 100644
+--- lib/crypto/c_src/crypto_callback.c.orig
++++ lib/crypto/c_src/crypto_callback.c
+@@ -62,7 +62,7 @@ static void nomem(size_t size, const char* op)
+ abort();
+ }
+
+-static void* crypto_alloc(size_t size)
++static void* crypto_alloc(size_t size CCB_FILE_LINE_ARGS)
+ {
+ void *ret = enif_alloc(size);
+
+@@ -70,7 +70,7 @@ static void* crypto_alloc(size_t size)
+ nomem(size, "allocate");
+ return ret;
+ }
+-static void* crypto_realloc(void* ptr, size_t size)
++static void* crypto_realloc(void* ptr, size_t size CCB_FILE_LINE_ARGS)
+ {
+ void* ret = enif_realloc(ptr, size);
+
+@@ -78,7 +78,7 @@ static void* crypto_realloc(void* ptr, size_t size)
+ nomem(size, "reallocate");
+ return ret;
+ }
+-static void crypto_free(void* ptr)
++static void crypto_free(void* ptr CCB_FILE_LINE_ARGS)
+ {
+ enif_free(ptr);
+ }
+diff --git a/lib/crypto/c_src/crypto_callback.h b/lib/crypto/c_src/crypto_callback.h
+index 894d86cfd95..2641cc0c8b9 100644
+--- lib/crypto/c_src/crypto_callback.h.orig
++++ lib/crypto/c_src/crypto_callback.h
+@@ -18,13 +18,20 @@
+ * %CopyrightEnd%
+ */
+
++#include <openssl/crypto.h>
++#if OPENSSL_VERSION_NUMBER < 0x10100000L
++# define CCB_FILE_LINE_ARGS
++#else
++# define CCB_FILE_LINE_ARGS , const char *file, int line
++#endif
++
+ struct crypto_callbacks
+ {
+ size_t sizeof_me;
+
+- void* (*crypto_alloc)(size_t size);
+- void* (*crypto_realloc)(void* ptr, size_t size);
+- void (*crypto_free)(void* ptr);
++ void* (*crypto_alloc)(size_t size CCB_FILE_LINE_ARGS);
++ void* (*crypto_realloc)(void* ptr, size_t size CCB_FILE_LINE_ARGS);
++ void (*crypto_free)(void* ptr CCB_FILE_LINE_ARGS);
+
+ /* openssl callbacks */
+ #ifdef OPENSSL_THREADS
diff --git a/lang/erlang-runtime19/files/patch-OpenSSL-1.1-b b/lang/erlang-runtime19/files/patch-OpenSSL-1.1-b
new file mode 100644
index 000000000000..781d5c687d9d
--- /dev/null
+++ b/lang/erlang-runtime19/files/patch-OpenSSL-1.1-b
@@ -0,0 +1,293 @@
+From 4dddb3c0b286e13f2cbccb0cdaa4bffcfee60033 Mon Sep 17 00:00:00 2001
+From: Yuki Ito <yuki@gnnk.net>
+Date: Tue, 20 Dec 2016 17:45:51 +0900
+Subject: [PATCH] crypto: Support chacha20_poly1305
+
+This commit reactivates chacha20_poly1305 and fixes the imprementation
+for the released OpenSSL 1.1.0 or later.
+---
+ lib/crypto/c_src/crypto.c | 152 ++++++++++++-------------------
+ lib/crypto/test/crypto_SUITE.erl | 49 ++++++++--
+ 2 files changed, 101 insertions(+), 100 deletions(-)
+
+diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
+index 0031f9b9620..68784cd24c9 100644
+--- lib/crypto/c_src/crypto.c
++++ lib/crypto/c_src/crypto.c
+@@ -117,7 +117,7 @@
+ # endif
+ #endif
+
+-#if defined(NID_chacha20) && !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,1,0)
+ # define HAVE_CHACHA20_POLY1305
+ #endif
+
+@@ -131,20 +131,6 @@
+ #include <openssl/ecdsa.h>
+ #endif
+
+-#if defined(HAVE_CHACHA20_POLY1305)
+-#include <openssl/chacha.h>
+-#include <openssl/poly1305.h>
+-
+-#if !defined(CHACHA20_NONCE_LEN)
+-# define CHACHA20_NONCE_LEN 8
+-#endif
+-#if !defined(POLY1305_TAG_LEN)
+-# define POLY1305_TAG_LEN 16
+-#endif
+-
+-#endif
+-
+-
+ #ifdef VALGRIND
+ # include <valgrind/memcheck.h>
+
+@@ -2038,71 +2024,61 @@
+ }
+ #endif /* HAVE_GCM_EVP_DECRYPT_BUG */
+
+-#if defined(HAVE_CHACHA20_POLY1305)
+-static void
+-poly1305_update_with_length(poly1305_state *poly1305,
+- const unsigned char *data, size_t data_len)
+-{
+- size_t j = data_len;
+- unsigned char length_bytes[8];
+- unsigned i;
+
+- for (i = 0; i < sizeof(length_bytes); i++) {
+- length_bytes[i] = j;
+- j >>= 8;
+- }
+-
+- CRYPTO_poly1305_update(poly1305, data, data_len);
+- CRYPTO_poly1305_update(poly1305, length_bytes, sizeof(length_bytes));
+-}
+-#endif
+-
+ static ERL_NIF_TERM chacha20_poly1305_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+ {/* (Key,Iv,AAD,In) */
+ #if defined(HAVE_CHACHA20_POLY1305)
++ EVP_CIPHER_CTX *ctx;
++ const EVP_CIPHER *cipher = NULL;
+ ErlNifBinary key, iv, aad, in;
+- unsigned char *outp;
++ unsigned char *outp, *tagp;
+ ERL_NIF_TERM out, out_tag;
+- ErlNifUInt64 in_len_64;
+- unsigned char poly1305_key[32];
+- poly1305_state poly1305;
++ int len;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 32
+- || !enif_inspect_binary(env, argv[1], &iv) || iv.size != CHACHA20_NONCE_LEN
++ || !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0 || iv.size > 16
+ || !enif_inspect_iolist_as_binary(env, argv[2], &aad)
+ || !enif_inspect_iolist_as_binary(env, argv[3], &in)) {
+ return enif_make_badarg(env);
+ }
+
+- /* Take from OpenSSL patch set/LibreSSL:
+- *
+- * The underlying ChaCha implementation may not overflow the block
+- * counter into the second counter word. Therefore we disallow
+- * individual operations that work on more than 2TB at a time.
+- * in_len_64 is needed because, on 32-bit platforms, size_t is only
+- * 32-bits and this produces a warning because it's always false.
+- * Casting to uint64_t inside the conditional is not sufficient to stop
+- * the warning. */
+- in_len_64 = in.size;
+- if (in_len_64 >= (1ULL << 32) * 64 - 64)
+- return enif_make_badarg(env);
++ cipher = EVP_chacha20_poly1305();
+
+- memset(poly1305_key, 0, sizeof(poly1305_key));
+- CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key), key.data, iv.data, 0);
++ ctx = EVP_CIPHER_CTX_new();
+
++ if (EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1)
++ goto out_err;
++
++ EVP_CIPHER_CTX_set_padding(ctx, 0);
++
++ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, iv.size, NULL) != 1)
++ goto out_err;
++ if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1)
++ goto out_err;
++ if (EVP_EncryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1)
++ goto out_err;
++
+ outp = enif_make_new_binary(env, in.size, &out);
+
+- CRYPTO_poly1305_init(&poly1305, poly1305_key);
+- poly1305_update_with_length(&poly1305, aad.data, aad.size);
+- CRYPTO_chacha_20(outp, in.data, in.size, key.data, iv.data, 1);
+- poly1305_update_with_length(&poly1305, outp, in.size);
++ if (EVP_EncryptUpdate(ctx, outp, &len, in.data, in.size) != 1)
++ goto out_err;
++ if (EVP_EncryptFinal_ex(ctx, outp+len, &len) != 1)
++ goto out_err;
+
+- CRYPTO_poly1305_finish(&poly1305, enif_make_new_binary(env, POLY1305_TAG_LEN, &out_tag));
++ tagp = enif_make_new_binary(env, 16, &out_tag);
+
++ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, tagp) != 1)
++ goto out_err;
++
++ EVP_CIPHER_CTX_free(ctx);
++
+ CONSUME_REDS(env, in);
+
+ return enif_make_tuple2(env, out, out_tag);
+
++out_err:
++ EVP_CIPHER_CTX_free(ctx);
++ return atom_error;
+ #else
+ return enif_raise_exception(env, atom_notsup);
+ #endif
+@@ -2111,53 +2087,52 @@
+ static ERL_NIF_TERM chacha20_poly1305_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+ {/* (Key,Iv,AAD,In,Tag) */
+ #if defined(HAVE_CHACHA20_POLY1305)
++ EVP_CIPHER_CTX *ctx;
++ const EVP_CIPHER *cipher = NULL;
+ ErlNifBinary key, iv, aad, in, tag;
+ unsigned char *outp;
+ ERL_NIF_TERM out;
+- ErlNifUInt64 in_len_64;
+- unsigned char poly1305_key[32];
+- unsigned char mac[POLY1305_TAG_LEN];
+- poly1305_state poly1305;
++ int len;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 32
+- || !enif_inspect_binary(env, argv[1], &iv) || iv.size != CHACHA20_NONCE_LEN
++ || !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0 || iv.size > 16
+ || !enif_inspect_iolist_as_binary(env, argv[2], &aad)
+ || !enif_inspect_iolist_as_binary(env, argv[3], &in)
+- || !enif_inspect_iolist_as_binary(env, argv[4], &tag) || tag.size != POLY1305_TAG_LEN) {
++ || !enif_inspect_iolist_as_binary(env, argv[4], &tag) || tag.size != 16) {
+ return enif_make_badarg(env);
+ }
+
+- /* Take from OpenSSL patch set/LibreSSL:
+- *
+- * The underlying ChaCha implementation may not overflow the block
+- * counter into the second counter word. Therefore we disallow
+- * individual operations that work on more than 2TB at a time.
+- * in_len_64 is needed because, on 32-bit platforms, size_t is only
+- * 32-bits and this produces a warning because it's always false.
+- * Casting to uint64_t inside the conditional is not sufficient to stop
+- * the warning. */
+- in_len_64 = in.size;
+- if (in_len_64 >= (1ULL << 32) * 64 - 64)
+- return enif_make_badarg(env);
++ cipher = EVP_chacha20_poly1305();
+
+- memset(poly1305_key, 0, sizeof(poly1305_key));
+- CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key), key.data, iv.data, 0);
++ ctx = EVP_CIPHER_CTX_new();
+
+- CRYPTO_poly1305_init(&poly1305, poly1305_key);
+- poly1305_update_with_length(&poly1305, aad.data, aad.size);
+- poly1305_update_with_length(&poly1305, in.data, in.size);
+- CRYPTO_poly1305_finish(&poly1305, mac);
++ if (EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1)
++ goto out_err;
++ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, iv.size, NULL) != 1)
++ goto out_err;
++ if (EVP_DecryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1)
++ goto out_err;
++ if (EVP_DecryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1)
++ goto out_err;
+
+- if (memcmp(mac, tag.data, POLY1305_TAG_LEN) != 0)
+- return atom_error;
+-
+ outp = enif_make_new_binary(env, in.size, &out);
+
+- CRYPTO_chacha_20(outp, in.data, in.size, key.data, iv.data, 1);
++ if (EVP_DecryptUpdate(ctx, outp, &len, in.data, in.size) != 1)
++ goto out_err;
++ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag.size, tag.data) != 1)
++ goto out_err;
++ if (EVP_DecryptFinal_ex(ctx, outp+len, &len) != 1)
++ goto out_err;
+
++ EVP_CIPHER_CTX_free(ctx);
++
+ CONSUME_REDS(env, in);
+
+ return out;
++
++out_err:
++ EVP_CIPHER_CTX_free(ctx);
++ return atom_error;
+ #else
+ return enif_raise_exception(env, atom_notsup);
+ #endif
+diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
+index 0c3b7a0445d..31f4e89ffe1 100644
+--- lib/crypto/test/crypto_SUITE.erl
++++ lib/crypto/test/crypto_SUITE.erl
+@@ -2249,16 +2249,49 @@ aes_gcm() ->
+ 1} %% TagLength
+ ].
+
+-%% http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
++%% https://tools.ietf.org/html/rfc7539#appendix-A.5
+ chacha20_poly1305() ->
+ [
+- {chacha20_poly1305, hexstr2bin("4290bcb154173531f314af57f3be3b500" %% Key
+- "6da371ece272afa1b5dbdd1100a1007"),
+- hexstr2bin("86d09974840bded2a5ca"), %% PlainText
+- hexstr2bin("cd7cf67be39c794a"), %% Nonce
+- hexstr2bin("87e229d4500845a079c0"), %% AAD
+- hexstr2bin("e3e446f7ede9a19b62a4"), %% CipherText
+- hexstr2bin("677dabf4e3d24b876bb284753896e1d6")} %% CipherTag
++ {chacha20_poly1305,
++ hexstr2bin("1c9240a5eb55d38af333888604f6b5f0" %% Key
++ "473917c1402b80099dca5cbc207075c0"),
++ hexstr2bin("496e7465726e65742d44726166747320" %% PlainText
++ "61726520647261667420646f63756d65"
++ "6e74732076616c696420666f72206120"
++ "6d6178696d756d206f6620736978206d"
++ "6f6e74687320616e64206d6179206265"
++ "20757064617465642c207265706c6163"
++ "65642c206f72206f62736f6c65746564"
++ "206279206f7468657220646f63756d65"
++ "6e747320617420616e792074696d652e"
++ "20497420697320696e617070726f7072"
++ "6961746520746f2075736520496e7465"
++ "726e65742d4472616674732061732072"
++ "65666572656e6365206d617465726961"
++ "6c206f7220746f206369746520746865"
++ "6d206f74686572207468616e20617320"
++ "2fe2809c776f726b20696e2070726f67"
++ "726573732e2fe2809d"),
++ hexstr2bin("000000000102030405060708"), %% Nonce
++ hexstr2bin("f33388860000000000004e91"), %% AAD
++ hexstr2bin("64a0861575861af460f062c79be643bd" %% CipherText
++ "5e805cfd345cf389f108670ac76c8cb2"
++ "4c6cfc18755d43eea09ee94e382d26b0"
++ "bdb7b73c321b0100d4f03b7f355894cf"
++ "332f830e710b97ce98c8a84abd0b9481"
++ "14ad176e008d33bd60f982b1ff37c855"
++ "9797a06ef4f0ef61c186324e2b350638"
++ "3606907b6a7c02b0f9f6157b53c867e4"
++ "b9166c767b804d46a59b5216cde7a4e9"
++ "9040c5a40433225ee282a1b0a06c523e"
++ "af4534d7f83fa1155b0047718cbc546a"
++ "0d072b04b3564eea1b422273f548271a"
++ "0bb2316053fa76991955ebd63159434e"
++ "cebb4e466dae5a1073a6727627097a10"
++ "49e617d91d361094fa68f0ff77987130"
++ "305beaba2eda04df997b714d6c6f2c29"
++ "a6ad5cb4022b02709b"),
++ hexstr2bin("eead9d67890cbb22392336fea1851f38")} %% CipherTag
+ ].
+
+ rsa_plain() ->
diff --git a/lang/erlang/Makefile b/lang/erlang/Makefile
index d4dd69cc0cea..0d926bf554e2 100644
--- a/lang/erlang/Makefile
+++ b/lang/erlang/Makefile
@@ -3,6 +3,7 @@
PORTNAME= erlang
PORTVERSION= 19.3.6.11
+PORTREVISION= 1
PORTEPOCH= 4
CATEGORIES= lang parallel java
MASTER_SITES= http://www.erlang.org/download/:erlangorg \
@@ -69,8 +70,6 @@ OPTIONS_EXCLUDE_armv6= DTRACE
OPTIONS_EXCLUDE_armv7= DTRACE
OPTIONS_EXCLUDE_i386= DTRACE
-OPENSSL_VARS= BROKEN_SSL=openssl-devel
-
GNU_CONFIGURE= yes
LDFLAGS+= -L${LOCALBASE}/lib
USES= gmake ncurses perl5
diff --git a/lang/erlang/files/patch-OpenSSL-1.1-a b/lang/erlang/files/patch-OpenSSL-1.1-a
new file mode 100644
index 000000000000..9a21938eaf42
--- /dev/null
+++ b/lang/erlang/files/patch-OpenSSL-1.1-a
@@ -0,0 +1,1083 @@
+From 458c012e18eda87803ef356221d68955f4b8012d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= <bjorn@erlang.org>
+Date: Thu, 24 Nov 2016 11:57:55 +0100
+Subject: [PATCH] Support OpenSSL 1.1.0
+
+---
+ lib/crypto/c_src/crypto.c | 486 +++++++++++++++++++++++++------------
+ lib/crypto/c_src/crypto_callback.c | 6 +-
+ lib/crypto/c_src/crypto_callback.h | 13 +-
+ 3 files changed, 345 insertions(+), 160 deletions(-)
+
+diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
+index 554aaf7587d..0031f9b9620 100644
+--- lib/crypto/c_src/crypto.c.orig 2018-02-14 17:16:13.270476000 +0100
++++ lib/crypto/c_src/crypto.c 2018-02-14 18:17:49.422680000 +0100
+@@ -64,56 +64,55 @@
+ /* Helper macro to construct a OPENSSL_VERSION_NUMBER.
+ * See openssl/opensslv.h
+ */
+-#define OpenSSL_version(MAJ, MIN, FIX, P) \
++#define PACKED_OPENSSL_VERSION(MAJ, MIN, FIX, P) \
+ ((((((((MAJ << 8) | MIN) << 8 ) | FIX) << 8) | (P-'a'+1)) << 4) | 0xf)
+
+-#define OpenSSL_version_plain(MAJ, MIN, FIX) \
+- OpenSSL_version(MAJ,MIN,FIX,('a'-1))
+-
++#define PACKED_OPENSSL_VERSION_PLAIN(MAJ, MIN, FIX) \
++ PACKED_OPENSSL_VERSION(MAJ,MIN,FIX,('a'-1))
+
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(1,0,0)
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
+ #include <openssl/modes.h>
+ #endif
+
+ #include "crypto_callback.h"
+
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(0,9,8) \
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(0,9,8) \
+ && !defined(OPENSSL_NO_SHA224) && defined(NID_sha224) \
+ && !defined(OPENSSL_NO_SHA256) /* disabled like this in my sha.h (?) */
+ # define HAVE_SHA224
+ #endif
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(0,9,8) \
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(0,9,8) \
+ && !defined(OPENSSL_NO_SHA256) && defined(NID_sha256)
+ # define HAVE_SHA256
+ #endif
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(0,9,8) \
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(0,9,8) \
+ && !defined(OPENSSL_NO_SHA384) && defined(NID_sha384)\
+ && !defined(OPENSSL_NO_SHA512) /* disabled like this in my sha.h (?) */
+ # define HAVE_SHA384
+ #endif
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(0,9,8) \
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(0,9,8) \
+ && !defined(OPENSSL_NO_SHA512) && defined(NID_sha512)
+ # define HAVE_SHA512
+ #endif
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version(0,9,7,'e')
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION(0,9,7,'e')
+ # define HAVE_DES_ede3_cfb_encrypt
+ #endif
+
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version(0,9,8,'o') \
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION(0,9,8,'o') \
+ && !defined(OPENSSL_NO_EC) \
+ && !defined(OPENSSL_NO_ECDH) \
+ && !defined(OPENSSL_NO_ECDSA)
+ # define HAVE_EC
+ #endif
+
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version(0,9,8,'c')
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION(0,9,8,'c')
+ # define HAVE_AES_IGE
+ #endif
+
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(1,0,1)
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,1)
+ # define HAVE_EVP_AES_CTR
+ # define HAVE_GCM
+-# if OPENSSL_VERSION_NUMBER < OpenSSL_version(1,0,1,'d')
++# if OPENSSL_VERSION_NUMBER < PACKED_OPENSSL_VERSION(1,0,1,'d')
+ # define HAVE_GCM_EVP_DECRYPT_BUG
+ # endif
+ #endif
+@@ -122,7 +121,7 @@
+ # define HAVE_CHACHA20_POLY1305
+ #endif
+
+-#if OPENSSL_VERSION_NUMBER <= OpenSSL_version(0,9,8,'l')
++#if OPENSSL_VERSION_NUMBER <= PACKED_OPENSSL_VERSION(0,9,8,'l')
+ # define HAVE_ECB_IVEC_BUG
+ #endif
+
+@@ -145,6 +144,7 @@
+
+ #endif
+
++
+ #ifdef VALGRIND
+ # include <valgrind/memcheck.h>
+
+@@ -213,6 +213,122 @@ do { \
+ } \
+ } while (0)
+
++#if OPENSSL_VERSION_NUMBER < PACKED_OPENSSL_VERSION_PLAIN(1,1,0)
++
++/*
++ * In OpenSSL 1.1.0, most structs are opaque. That means that
++ * the structs cannot be allocated as automatic variables on the
++ * C stack (because the size is unknown) and that it is necessary
++ * to use access functions.
++ *
++ * For backward compatibility to previous versions of OpenSSL, define
++ * on our versions of the new functions defined in 1.1.0 here, so that
++ * we don't have to sprinkle ifdefs throughout the code.
++ */
++
++static HMAC_CTX *HMAC_CTX_new(void);
++static void HMAC_CTX_free(HMAC_CTX *ctx);
++
++static HMAC_CTX *HMAC_CTX_new()
++{
++ HMAC_CTX *ctx = CRYPTO_malloc(sizeof(HMAC_CTX), __FILE__, __LINE__);
++ HMAC_CTX_init(ctx);
++ return ctx;
++}
++
++static void HMAC_CTX_free(HMAC_CTX *ctx)
++{
++ HMAC_CTX_cleanup(ctx);
++ return CRYPTO_free(ctx);
++}
++
++#define EVP_MD_CTX_new() EVP_MD_CTX_create()
++#define EVP_MD_CTX_free(ctx) EVP_MD_CTX_destroy(ctx)
++
++static INLINE int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d);
++static INLINE int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q);
++static INLINE int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp);
++
++static INLINE int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
++{
++ r->n = n;
++ r->e = e;
++ r->d = d;
++ return 1;
++}
++
++static INLINE int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q)
++{
++ r->p = p;
++ r->q = q;
++ return 1;
++}
++
++static INLINE int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp)
++{
++ r->dmp1 = dmp1;
++ r->dmq1 = dmq1;
++ r->iqmp = iqmp;
++ return 1;
++}
++
++static INLINE int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key);
++static INLINE int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g);
++
++static INLINE int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key)
++{
++ d->pub_key = pub_key;
++ d->priv_key = priv_key;
++ return 1;
++}
++
++static INLINE int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
++{
++ d->p = p;
++ d->q = q;
++ d->g = g;
++ return 1;
++}
++
++static INLINE int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key);
++static INLINE int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g);
++static INLINE void DH_get0_pqg(const DH *dh,
++ const BIGNUM **p, const BIGNUM **q, const BIGNUM **g);
++static INLINE void DH_get0_key(const DH *dh,
++ const BIGNUM **pub_key, const BIGNUM **priv_key);
++
++static INLINE int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key)
++{
++ dh->pub_key = pub_key;
++ dh->priv_key = priv_key;
++ return 1;
++}
++
++static INLINE int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
++{
++ dh->p = p;
++ dh->q = q;
++ dh->g = g;
++ return 1;
++}
++
++static INLINE void
++DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
++{
++ *p = dh->p;
++ *q = dh->q;
++ *g = dh->g;
++}
++
++static INLINE void
++DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key)
++{
++ *pub_key = dh->pub_key;
++ *priv_key = dh->priv_key;
++}
++
++#endif /* End of compatibility definitions. */
++
+ /* NIF interface declarations */
+ static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info);
+ static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info);
+@@ -399,7 +515,7 @@ struct hmac_context
+ {
+ ErlNifMutex* mtx;
+ int alive;
+- HMAC_CTX ctx;
++ HMAC_CTX* ctx;
+ };
+ static void hmac_context_dtor(ErlNifEnv* env, struct hmac_context*);
+
+@@ -526,18 +642,24 @@ static struct cipher_type_t* get_cipher_
+ #define PRINTF_ERR1(FMT,A1)
+ #define PRINTF_ERR2(FMT,A1,A2)
+
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(1,0,0)
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
+ /* Define resource types for OpenSSL context structures. */
+ static ErlNifResourceType* evp_md_ctx_rtype;
+-static void evp_md_ctx_dtor(ErlNifEnv* env, EVP_MD_CTX* ctx) {
+- EVP_MD_CTX_cleanup(ctx);
++struct evp_md_ctx {
++ EVP_MD_CTX* ctx;
++};
++static void evp_md_ctx_dtor(ErlNifEnv* env, struct evp_md_ctx *ctx) {
++ EVP_MD_CTX_free(ctx->ctx);
+ }
+ #endif
+
+ #ifdef HAVE_EVP_AES_CTR
+ static ErlNifResourceType* evp_cipher_ctx_rtype;
+-static void evp_cipher_ctx_dtor(ErlNifEnv* env, EVP_CIPHER_CTX* ctx) {
+- EVP_CIPHER_CTX_cleanup(ctx);
++struct evp_cipher_ctx {
++ EVP_CIPHER_CTX* ctx;
++};
++static void evp_cipher_ctx_dtor(ErlNifEnv* env, struct evp_cipher_ctx* ctx) {
++ EVP_CIPHER_CTX_free(ctx->ctx);
+ }
+ #endif
+
+@@ -625,7 +747,7 @@ static int initialize(ErlNifEnv* env, ER
+ PRINTF_ERR0("CRYPTO: Could not open resource type 'hmac_context'");
+ return __LINE__;
+ }
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(1,0,0)
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
+ evp_md_ctx_rtype = enif_open_resource_type(env, NULL, "EVP_MD_CTX",
+ (ErlNifResourceDtor*) evp_md_ctx_dtor,
+ ERL_NIF_RT_CREATE|ERL_NIF_RT_TAKEOVER,
+@@ -937,12 +1059,12 @@ static ERL_NIF_TERM hash_nif(ErlNifEnv*
+ return ret;
+ }
+
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(1,0,0)
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
+
+ static ERL_NIF_TERM hash_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+ {/* (Type) */
+ struct digest_type_t *digp = NULL;
+- EVP_MD_CTX *ctx;
++ struct evp_md_ctx *ctx;
+ ERL_NIF_TERM ret;
+
+ digp = get_digest_type(argv[0]);
+@@ -953,8 +1075,9 @@ static ERL_NIF_TERM hash_init_nif(ErlNif
+ return atom_notsup;
+ }
+
+- ctx = enif_alloc_resource(evp_md_ctx_rtype, sizeof(EVP_MD_CTX));
+- if (!EVP_DigestInit(ctx, digp->md.p)) {
++ ctx = enif_alloc_resource(evp_md_ctx_rtype, sizeof(struct evp_md_ctx));
++ ctx->ctx = EVP_MD_CTX_new();
++ if (!EVP_DigestInit(ctx->ctx, digp->md.p)) {
+ enif_release_resource(ctx);
+ return atom_notsup;
+ }
+@@ -964,7 +1087,7 @@ static ERL_NIF_TERM hash_init_nif(ErlNif
+ }
+ static ERL_NIF_TERM hash_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+ {/* (Context, Data) */
+- EVP_MD_CTX *ctx, *new_ctx;
++ struct evp_md_ctx *ctx, *new_ctx;
+ ErlNifBinary data;
+ ERL_NIF_TERM ret;
+
+@@ -973,9 +1096,10 @@ static ERL_NIF_TERM hash_update_nif(ErlN
+ return enif_make_badarg(env);
+ }
+
+- new_ctx = enif_alloc_resource(evp_md_ctx_rtype, sizeof(EVP_MD_CTX));
+- if (!EVP_MD_CTX_copy(new_ctx, ctx) ||
+- !EVP_DigestUpdate(new_ctx, data.data, data.size)) {
++ new_ctx = enif_alloc_resource(evp_md_ctx_rtype, sizeof(struct evp_md_ctx));
++ new_ctx->ctx = EVP_MD_CTX_new();
++ if (!EVP_MD_CTX_copy(new_ctx->ctx, ctx->ctx) ||
++ !EVP_DigestUpdate(new_ctx->ctx, data.data, data.size)) {
+ enif_release_resource(new_ctx);
+ return atom_notsup;
+ }
+@@ -987,7 +1111,8 @@ static ERL_NIF_TERM hash_update_nif(ErlN
+ }
+ static ERL_NIF_TERM hash_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+ {/* (Context) */
+- EVP_MD_CTX *ctx, new_ctx;
++ struct evp_md_ctx *ctx;
++ EVP_MD_CTX *new_ctx;
+ ERL_NIF_TERM ret;
+ unsigned ret_size;
+
+@@ -995,16 +1120,19 @@ static ERL_NIF_TERM hash_final_nif(ErlNi
+ return enif_make_badarg(env);
+ }
+
+- ret_size = (unsigned)EVP_MD_CTX_size(ctx);
++ ret_size = (unsigned)EVP_MD_CTX_size(ctx->ctx);
+ ASSERT(0 < ret_size && ret_size <= EVP_MAX_MD_SIZE);
+
+- if (!EVP_MD_CTX_copy(&new_ctx, ctx) ||
+- !EVP_DigestFinal(&new_ctx,
++ new_ctx = EVP_MD_CTX_new();
++ if (!EVP_MD_CTX_copy(new_ctx, ctx->ctx) ||
++ !EVP_DigestFinal(new_ctx,
+ enif_make_new_binary(env, ret_size, &ret),
+ &ret_size)) {
++ EVP_MD_CTX_free(new_ctx);
+ return atom_notsup;
+ }
+- ASSERT(ret_size == (unsigned)EVP_MD_CTX_size(ctx));
++ EVP_MD_CTX_free(new_ctx);
++ ASSERT(ret_size == (unsigned)EVP_MD_CTX_size(ctx->ctx));
+
+ return ret;
+ }
+@@ -1288,7 +1416,7 @@ static ERL_NIF_TERM hmac_nif(ErlNifEnv*
+ static void hmac_context_dtor(ErlNifEnv* env, struct hmac_context *obj)
+ {
+ if (obj->alive) {
+- HMAC_CTX_cleanup(&obj->ctx);
++ HMAC_CTX_free(obj->ctx);
+ obj->alive = 0;
+ }
+ enif_mutex_destroy(obj->mtx);
+@@ -1313,15 +1441,16 @@ static ERL_NIF_TERM hmac_init_nif(ErlNif
+ obj = enif_alloc_resource(hmac_context_rtype, sizeof(struct hmac_context));
+ obj->mtx = enif_mutex_create("crypto.hmac");
+ obj->alive = 1;
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(1,0,0)
++ obj->ctx = HMAC_CTX_new();
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
+ // Check the return value of HMAC_Init: it may fail in FIPS mode
+ // for disabled algorithms
+- if (!HMAC_Init(&obj->ctx, key.data, key.size, digp->md.p)) {
++ if (!HMAC_Init_ex(obj->ctx, key.data, key.size, digp->md.p, NULL)) {
+ enif_release_resource(obj);
+ return atom_notsup;
+ }
+ #else
+- HMAC_Init(&obj->ctx, key.data, key.size, digp->md.p);
++ HMAC_Init_ex(obj->ctx, key.data, key.size, digp->md.p, NULL);
+ #endif
+
+ ret = enif_make_resource(env, obj);
+@@ -1343,7 +1472,7 @@ static ERL_NIF_TERM hmac_update_nif(ErlN
+ enif_mutex_unlock(obj->mtx);
+ return enif_make_badarg(env);
+ }
+- HMAC_Update(&obj->ctx, data.data, data.size);
++ HMAC_Update(obj->ctx, data.data, data.size);
+ enif_mutex_unlock(obj->mtx);
+
+ CONSUME_REDS(env,data);
+@@ -1370,8 +1499,8 @@ static ERL_NIF_TERM hmac_final_nif(ErlNi
+ return enif_make_badarg(env);
+ }
+
+- HMAC_Final(&obj->ctx, mac_buf, &mac_len);
+- HMAC_CTX_cleanup(&obj->ctx);
++ HMAC_Final(obj->ctx, mac_buf, &mac_len);
++ HMAC_CTX_free(obj->ctx);
+ obj->alive = 0;
+ enif_mutex_unlock(obj->mtx);
+
+@@ -1390,7 +1519,7 @@ static ERL_NIF_TERM block_crypt_nif(ErlN
+ struct cipher_type_t *cipherp = NULL;
+ const EVP_CIPHER *cipher;
+ ErlNifBinary key, ivec, text;
+- EVP_CIPHER_CTX ctx;
++ EVP_CIPHER_CTX* ctx;
+ ERL_NIF_TERM ret;
+ unsigned char *out;
+ int ivec_size, out_size = 0;
+@@ -1438,30 +1567,30 @@ static ERL_NIF_TERM block_crypt_nif(ErlN
+
+ out = enif_make_new_binary(env, text.size, &ret);
+
+- EVP_CIPHER_CTX_init(&ctx);
+- if (!EVP_CipherInit_ex(&ctx, cipher, NULL, NULL, NULL,
++ ctx = EVP_CIPHER_CTX_new();
++ if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL,
+ (argv[argc - 1] == atom_true)) ||
+- !EVP_CIPHER_CTX_set_key_length(&ctx, key.size) ||
++ !EVP_CIPHER_CTX_set_key_length(ctx, key.size) ||
+ !(EVP_CIPHER_type(cipher) != NID_rc2_cbc ||
+- EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_SET_RC2_KEY_BITS, key.size * 8, NULL)) ||
+- !EVP_CipherInit_ex(&ctx, NULL, NULL,
++ EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC2_KEY_BITS, key.size * 8, NULL)) ||
++ !EVP_CipherInit_ex(ctx, NULL, NULL,
+ key.data, ivec_size ? ivec.data : NULL, -1) ||
+- !EVP_CIPHER_CTX_set_padding(&ctx, 0)) {
++ !EVP_CIPHER_CTX_set_padding(ctx, 0)) {
+
+- EVP_CIPHER_CTX_cleanup(&ctx);
++ EVP_CIPHER_CTX_free(ctx);
+ return enif_raise_exception(env, atom_notsup);
+ }
+
+ if (text.size > 0 && /* OpenSSL 0.9.8h asserts text.size > 0 */
+- (!EVP_CipherUpdate(&ctx, out, &out_size, text.data, text.size)
++ (!EVP_CipherUpdate(ctx, out, &out_size, text.data, text.size)
+ || (ASSERT(out_size == text.size), 0)
+- || !EVP_CipherFinal_ex(&ctx, out + out_size, &out_size))) {
++ || !EVP_CipherFinal_ex(ctx, out + out_size, &out_size))) {
+
+- EVP_CIPHER_CTX_cleanup(&ctx);
++ EVP_CIPHER_CTX_free(ctx);
+ return enif_raise_exception(env, atom_notsup);
+ }
+ ASSERT(out_size == 0);
+- EVP_CIPHER_CTX_cleanup(&ctx);
++ EVP_CIPHER_CTX_free(ctx);
+ CONSUME_REDS(env, text);
+
+ return ret;
+@@ -1563,7 +1692,7 @@ static ERL_NIF_TERM aes_ctr_encrypt(ErlN
+ ErlNifBinary key, ivec, text;
+ #ifdef HAVE_EVP_AES_CTR
+ const EVP_CIPHER *cipher;
+- EVP_CIPHER_CTX ctx;
++ struct evp_cipher_ctx ctx;
+ unsigned char *out;
+ int outl = 0;
+ #else
+@@ -1621,7 +1750,7 @@ static ERL_NIF_TERM aes_ctr_encrypt(ErlN
+ static ERL_NIF_TERM aes_ctr_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+ {/* (Key, IVec) */
+ ErlNifBinary key_bin, ivec_bin;
+- EVP_CIPHER_CTX *ctx;
++ struct evp_cipher_ctx *ctx;
+ const EVP_CIPHER *cipher;
+ ERL_NIF_TERM ret;
+
+@@ -1639,18 +1768,18 @@ static ERL_NIF_TERM aes_ctr_stream_init(
+ default: return enif_make_badarg(env);
+ }
+
+- ctx = enif_alloc_resource(evp_cipher_ctx_rtype, sizeof(EVP_CIPHER_CTX));
+- EVP_CIPHER_CTX_init(ctx);
+- EVP_CipherInit_ex(ctx, cipher, NULL,
++ 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, 0);
++ EVP_CIPHER_CTX_set_padding(ctx->ctx, 0);
+ ret = enif_make_resource(env, ctx);
+ enif_release_resource(ctx);
+ return ret;
+ }
+ static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+ {/* (Context, Data) */
+- EVP_CIPHER_CTX *ctx, *new_ctx;
++ struct evp_cipher_ctx *ctx, *new_ctx;
+ ErlNifBinary data_bin;
+ ERL_NIF_TERM ret, cipher_term;
+ unsigned char *out;
+@@ -1660,11 +1789,11 @@ static ERL_NIF_TERM aes_ctr_stream_encry
+ || !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(EVP_CIPHER_CTX));
+- EVP_CIPHER_CTX_init(new_ctx);
+- EVP_CIPHER_CTX_copy(new_ctx, ctx);
++ 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, out, &outl, data_bin.data, data_bin.size);
++ 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);
+@@ -1735,7 +1864,7 @@ static ERL_NIF_TERM aes_ctr_stream_encry
+ static ERL_NIF_TERM aes_gcm_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+ {/* (Key,Iv,AAD,In) */
+ #if defined(HAVE_GCM)
+- EVP_CIPHER_CTX ctx;
++ EVP_CIPHER_CTX *ctx;
+ const EVP_CIPHER *cipher = NULL;
+ ErlNifBinary key, iv, aad, in;
+ unsigned int tag_len;
+@@ -1759,40 +1888,40 @@ static ERL_NIF_TERM aes_gcm_encrypt(ErlN
+ else if (key.size == 32)
+ cipher = EVP_aes_256_gcm();
+
+- EVP_CIPHER_CTX_init(&ctx);
++ ctx = EVP_CIPHER_CTX_new();
+
+- if (EVP_EncryptInit_ex(&ctx, cipher, NULL, NULL, NULL) != 1)
++ if (EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1)
+ goto out_err;
+
+- EVP_CIPHER_CTX_set_padding(&ctx, 0);
++ EVP_CIPHER_CTX_set_padding(ctx, 0);
+
+- if (EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, iv.size, NULL) != 1)
++ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv.size, NULL) != 1)
+ goto out_err;
+- if (EVP_EncryptInit_ex(&ctx, NULL, NULL, key.data, iv.data) != 1)
++ if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1)
+ goto out_err;
+- if (EVP_EncryptUpdate(&ctx, NULL, &len, aad.data, aad.size) != 1)
++ if (EVP_EncryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1)
+ goto out_err;
+
+ outp = enif_make_new_binary(env, in.size, &out);
+
+- if (EVP_EncryptUpdate(&ctx, outp, &len, in.data, in.size) != 1)
++ if (EVP_EncryptUpdate(ctx, outp, &len, in.data, in.size) != 1)
+ goto out_err;
+- if (EVP_EncryptFinal_ex(&ctx, outp+len, &len) != 1)
++ if (EVP_EncryptFinal_ex(ctx, outp+len, &len) != 1)
+ goto out_err;
+
+ tagp = enif_make_new_binary(env, tag_len, &out_tag);
+
+- if (EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_GET_TAG, tag_len, tagp) != 1)
++ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, tag_len, tagp) != 1)
+ goto out_err;
+
+- EVP_CIPHER_CTX_cleanup(&ctx);
++ EVP_CIPHER_CTX_free(ctx);
+
+ CONSUME_REDS(env, in);
+
+ return enif_make_tuple2(env, out, out_tag);
+
+ out_err:
+- EVP_CIPHER_CTX_cleanup(&ctx);
++ EVP_CIPHER_CTX_free(ctx);
+ return atom_error;
+
+ #else
+@@ -1805,7 +1934,7 @@ static ERL_NIF_TERM aes_gcm_decrypt(ErlN
+ #if defined(HAVE_GCM_EVP_DECRYPT_BUG)
+ return aes_gcm_decrypt_NO_EVP(env, argc, argv);
+ #elif defined(HAVE_GCM)
+- EVP_CIPHER_CTX ctx;
++ EVP_CIPHER_CTX *ctx;
+ const EVP_CIPHER *cipher = NULL;
+ ErlNifBinary key, iv, aad, in, tag;
+ unsigned char *outp;
+@@ -1828,34 +1957,34 @@ static ERL_NIF_TERM aes_gcm_decrypt(ErlN
+ else if (key.size == 32)
+ cipher = EVP_aes_256_gcm();
+
+- EVP_CIPHER_CTX_init(&ctx);
++ ctx = EVP_CIPHER_CTX_new();
+
+- if (EVP_DecryptInit_ex(&ctx, cipher, NULL, NULL, NULL) != 1)
++ if (EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1)
+ goto out_err;
+- if (EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, iv.size, NULL) != 1)
++ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv.size, NULL) != 1)
+ goto out_err;
+- if (EVP_DecryptInit_ex(&ctx, NULL, NULL, key.data, iv.data) != 1)
++ if (EVP_DecryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1)
+ goto out_err;
+- if (EVP_DecryptUpdate(&ctx, NULL, &len, aad.data, aad.size) != 1)
++ if (EVP_DecryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1)
+ goto out_err;
+
+ outp = enif_make_new_binary(env, in.size, &out);
+
+- if (EVP_DecryptUpdate(&ctx, outp, &len, in.data, in.size) != 1)
++ if (EVP_DecryptUpdate(ctx, outp, &len, in.data, in.size) != 1)
+ goto out_err;
+- if (EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_TAG, tag.size, tag.data) != 1)
++ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, tag.size, tag.data) != 1)
+ goto out_err;
+- if (EVP_DecryptFinal_ex(&ctx, outp+len, &len) != 1)
++ if (EVP_DecryptFinal_ex(ctx, outp+len, &len) != 1)
+ goto out_err;
+
+- EVP_CIPHER_CTX_cleanup(&ctx);
++ EVP_CIPHER_CTX_free(ctx);
+
+ CONSUME_REDS(env, in);
+
+ return out;
+
+ out_err:
+- EVP_CIPHER_CTX_cleanup(&ctx);
++ EVP_CIPHER_CTX_free(ctx);
+ return atom_error;
+ #else
+ return enif_raise_exception(env, atom_notsup);
+@@ -2234,13 +2363,10 @@ static ERL_NIF_TERM dss_verify_nif(ErlNi
+ }
+
+ dsa = DSA_new();
+- dsa->p = dsa_p;
+- dsa->q = dsa_q;
+- dsa->g = dsa_g;
+- dsa->priv_key = NULL;
+- dsa->pub_key = dsa_y;
+- i = DSA_verify(0, digest_bin.data, SHA_DIGEST_LENGTH,
+- sign_bin.data, sign_bin.size, dsa);
++ DSA_set0_pqg(dsa, dsa_p, dsa_q, dsa_g);
++ DSA_set0_key(dsa, dsa_y, NULL);
++ i = DSA_verify(0, digest_bin.data, SHA_DIGEST_LENGTH,
++ sign_bin.data, sign_bin.size, dsa);
+ DSA_free(dsa);
+ return(i > 0) ? atom_true : atom_false;
+ }
+@@ -2297,13 +2423,15 @@ static ERL_NIF_TERM rsa_verify_nif(ErlNi
+ ERL_NIF_TERM head, tail, ret;
+ int i;
+ RSA *rsa;
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(1,0,0)
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
+ EVP_PKEY *pkey;
+ EVP_PKEY_CTX *ctx;
+ #endif
+ const EVP_MD *md;
+ const ERL_NIF_TERM type = argv[0];
+ struct digest_type_t *digp = NULL;
++ BIGNUM *rsa_e;
++ BIGNUM *rsa_n;
+
+ digp = get_digest_type(type);
+ if (!digp) {
+@@ -2320,16 +2448,18 @@ static ERL_NIF_TERM rsa_verify_nif(ErlNi
+ || digest_bin.size != EVP_MD_size(md)
+ || !enif_inspect_binary(env, argv[2], &sign_bin)
+ || !enif_get_list_cell(env, argv[3], &head, &tail)
+- || !get_bn_from_bin(env, head, &rsa->e)
++ || !get_bn_from_bin(env, head, &rsa_e)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+- || !get_bn_from_bin(env, head, &rsa->n)
++ || !get_bn_from_bin(env, head, &rsa_n)
+ || !enif_is_empty_list(env, tail)) {
+
+ ret = enif_make_badarg(env);
+ goto done;
+ }
+
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(1,0,0)
++ (void) RSA_set0_key(rsa, rsa_n, rsa_e, NULL);
++
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
+ pkey = EVP_PKEY_new();
+ EVP_PKEY_set1_RSA(pkey, rsa);
+
+@@ -2440,34 +2570,44 @@ static int get_rsa_private_key(ErlNifEnv
+ {
+ /* key=[E,N,D]|[E,N,D,P1,P2,E1,E2,C] */
+ ERL_NIF_TERM head, tail;
++ BIGNUM *e, *n, *d;
++ BIGNUM *p, *q;
++ BIGNUM *dmp1, *dmq1, *iqmp;
+
+ if (!enif_get_list_cell(env, key, &head, &tail)
+- || !get_bn_from_bin(env, head, &rsa->e)
++ || !get_bn_from_bin(env, head, &e)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+- || !get_bn_from_bin(env, head, &rsa->n)
++ || !get_bn_from_bin(env, head, &n)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+- || !get_bn_from_bin(env, head, &rsa->d)
+- || (!enif_is_empty_list(env, tail) &&
+- (!enif_get_list_cell(env, tail, &head, &tail)
+- || !get_bn_from_bin(env, head, &rsa->p)
+- || !enif_get_list_cell(env, tail, &head, &tail)
+- || !get_bn_from_bin(env, head, &rsa->q)
+- || !enif_get_list_cell(env, tail, &head, &tail)
+- || !get_bn_from_bin(env, head, &rsa->dmp1)
+- || !enif_get_list_cell(env, tail, &head, &tail)
+- || !get_bn_from_bin(env, head, &rsa->dmq1)
+- || !enif_get_list_cell(env, tail, &head, &tail)
+- || !get_bn_from_bin(env, head, &rsa->iqmp)
+- || !enif_is_empty_list(env, tail)))) {
++ || !get_bn_from_bin(env, head, &d)) {
+ return 0;
+ }
++ (void) RSA_set0_key(rsa, n, e, d);
++ if (enif_is_empty_list(env, tail)) {
++ return 1;
++ }
++ if (!enif_get_list_cell(env, tail, &head, &tail)
++ || !get_bn_from_bin(env, head, &p)
++ || !enif_get_list_cell(env, tail, &head, &tail)
++ || !get_bn_from_bin(env, head, &q)
++ || !enif_get_list_cell(env, tail, &head, &tail)
++ || !get_bn_from_bin(env, head, &dmp1)
++ || !enif_get_list_cell(env, tail, &head, &tail)
++ || !get_bn_from_bin(env, head, &dmq1)
++ || !enif_get_list_cell(env, tail, &head, &tail)
++ || !get_bn_from_bin(env, head, &iqmp)
++ || !enif_is_empty_list(env, tail)) {
++ return 0;
++ }
++ (void) RSA_set0_factors(rsa, p, q);
++ (void) RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp);
+ return 1;
+ }
+
+ static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+ {/* (Type, Digest, Key=[E,N,D]|[E,N,D,P1,P2,E1,E2,C]) */
+ ErlNifBinary digest_bin, ret_bin;
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(1,0,0)
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
+ EVP_PKEY *pkey;
+ EVP_PKEY_CTX *ctx;
+ size_t rsa_s_len;
+@@ -2500,7 +2640,7 @@ static ERL_NIF_TERM rsa_sign_nif(ErlNifE
+ }
+
+
+-#if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(1,0,0)
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
+ pkey = EVP_PKEY_new();
+ EVP_PKEY_set1_RSA(pkey, rsa);
+ rsa_s_len=(size_t)EVP_PKEY_size(pkey);
+@@ -2547,6 +2687,8 @@ static ERL_NIF_TERM dss_sign_nif(ErlNifE
+ ERL_NIF_TERM head, tail;
+ unsigned int dsa_s_len;
+ DSA* dsa;
++ BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL;
++ BIGNUM *dummy_pub_key, *priv_key = NULL;
+ int i;
+
+ if (argv[0] != atom_sha
+@@ -2555,26 +2697,37 @@ static ERL_NIF_TERM dss_sign_nif(ErlNifE
+ return enif_make_badarg(env);
+ }
+
+- dsa = DSA_new();
+-
+- dsa->pub_key = NULL;
+ if (!enif_get_list_cell(env, argv[2], &head, &tail)
+- || !get_bn_from_bin(env, head, &dsa->p)
++ || !get_bn_from_bin(env, head, &dsa_p)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+- || !get_bn_from_bin(env, head, &dsa->q)
++ || !get_bn_from_bin(env, head, &dsa_q)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+- || !get_bn_from_bin(env, head, &dsa->g)
++ || !get_bn_from_bin(env, head, &dsa_g)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+- || !get_bn_from_bin(env, head, &dsa->priv_key)
++ || !get_bn_from_bin(env, head, &priv_key)
+ || !enif_is_empty_list(env,tail)) {
+- DSA_free(dsa);
++ if (dsa_p) BN_free(dsa_p);
++ if (dsa_q) BN_free(dsa_q);
++ if (dsa_g) BN_free(dsa_g);
++ if (priv_key) BN_free(priv_key);
+ return enif_make_badarg(env);
+ }
+
++ /* Note: DSA_set0_key() does not allow setting only the
++ * private key, although DSA_sign() does not use the
++ * public key. Work around this limitation by setting
++ * the public key to a copy of the private key.
++ */
++ dummy_pub_key = BN_dup(priv_key);
++
++ dsa = DSA_new();
++ DSA_set0_pqg(dsa, dsa_p, dsa_q, dsa_g);
++ DSA_set0_key(dsa, dummy_pub_key, priv_key);
+ enif_alloc_binary(DSA_size(dsa), &ret_bin);
+ i = DSA_sign(NID_sha1, digest_bin.data, SHA_DIGEST_LENGTH,
+ ret_bin.data, &dsa_s_len, dsa);
+ DSA_free(dsa);
++
+ if (i) {
+ if (dsa_s_len != ret_bin.size) {
+ enif_realloc_binary(&ret_bin, dsa_s_len);
+@@ -2611,20 +2764,22 @@ static ERL_NIF_TERM rsa_public_crypt(Erl
+ ERL_NIF_TERM head, tail;
+ int padding, i;
+ RSA* rsa;
++ BIGNUM *e, *n;
+
+ rsa = RSA_new();
+
+ if (!enif_inspect_binary(env, argv[0], &data_bin)
+ || !enif_get_list_cell(env, argv[1], &head, &tail)
+- || !get_bn_from_bin(env, head, &rsa->e)
++ || !get_bn_from_bin(env, head, &e)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+- || !get_bn_from_bin(env, head, &rsa->n)
++ || !get_bn_from_bin(env, head, &n)
+ || !enif_is_empty_list(env,tail)
+ || !rsa_pad(argv[2], &padding)) {
+
+ RSA_free(rsa);
+ return enif_make_badarg(env);
+ }
++ (void) RSA_set0_key(rsa, n, e, NULL);
+
+ enif_alloc_binary(RSA_size(rsa), &ret_bin);
+
+@@ -2705,6 +2860,7 @@ static ERL_NIF_TERM dh_generate_paramete
+ int p_len, g_len;
+ unsigned char *p_ptr, *g_ptr;
+ ERL_NIF_TERM ret_p, ret_g;
++ const BIGNUM *dh_p, *dh_q, *dh_g;
+
+ if (!enif_get_int(env, argv[0], &prime_len)
+ || !enif_get_int(env, argv[1], &generator)) {
+@@ -2715,15 +2871,16 @@ static ERL_NIF_TERM dh_generate_paramete
+ if (dh_params == NULL) {
+ return atom_error;
+ }
+- p_len = BN_num_bytes(dh_params->p);
+- g_len = BN_num_bytes(dh_params->g);
++ DH_get0_pqg(dh_params, &dh_p, &dh_q, &dh_g);
++ DH_free(dh_params);
++ p_len = BN_num_bytes(dh_p);
++ g_len = BN_num_bytes(dh_g);
+ p_ptr = enif_make_new_binary(env, p_len, &ret_p);
+ g_ptr = enif_make_new_binary(env, g_len, &ret_g);
+- BN_bn2bin(dh_params->p, p_ptr);
+- BN_bn2bin(dh_params->g, g_ptr);
++ BN_bn2bin(dh_p, p_ptr);
++ BN_bn2bin(dh_g, g_ptr);
+ ERL_VALGRIND_MAKE_MEM_DEFINED(p_ptr, p_len);
+ ERL_VALGRIND_MAKE_MEM_DEFINED(g_ptr, g_len);
+- DH_free(dh_params);
+ return enif_make_list2(env, ret_p, ret_g);
+ }
+
+@@ -2732,18 +2889,19 @@ static ERL_NIF_TERM dh_check(ErlNifEnv*
+ DH* dh_params;
+ int i;
+ ERL_NIF_TERM ret, head, tail;
+-
+- dh_params = DH_new();
++ BIGNUM *dh_p, *dh_g;
+
+ if (!enif_get_list_cell(env, argv[0], &head, &tail)
+- || !get_bn_from_bin(env, head, &dh_params->p)
++ || !get_bn_from_bin(env, head, &dh_p)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+- || !get_bn_from_bin(env, head, &dh_params->g)
++ || !get_bn_from_bin(env, head, &dh_g)
+ || !enif_is_empty_list(env,tail)) {
+
+- DH_free(dh_params);
+ return enif_make_badarg(env);
+ }
++
++ dh_params = DH_new();
++ DH_set0_pqg(dh_params, dh_p, NULL, dh_g);
+ if (DH_check(dh_params, &i)) {
+ if (i == 0) ret = atom_ok;
+ else if (i & DH_CHECK_P_NOT_PRIME) ret = atom_not_prime;
+@@ -2767,42 +2925,41 @@ static ERL_NIF_TERM dh_generate_key_nif(
+ ERL_NIF_TERM ret, ret_pub, ret_prv, head, tail;
+ int mpint; /* 0 or 4 */
+ unsigned long len = 0;
++ BIGNUM *priv_key = NULL;
++ BIGNUM *dh_p = NULL, *dh_g = NULL;
+
+- dh_params = DH_new();
+-
+- if (!(get_bn_from_bin(env, argv[0], &dh_params->priv_key)
++ if (!(get_bn_from_bin(env, argv[0], &priv_key)
+ || argv[0] == atom_undefined)
+ || !enif_get_list_cell(env, argv[1], &head, &tail)
+- || !get_bn_from_bin(env, head, &dh_params->p)
++ || !get_bn_from_bin(env, head, &dh_p)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+- || !get_bn_from_bin(env, head, &dh_params->g)
++ || !get_bn_from_bin(env, head, &dh_g)
+ || !enif_is_empty_list(env, tail)
+ || !enif_get_int(env, argv[2], &mpint) || (mpint & ~4)
+ || !enif_get_ulong(env, argv[3], &len) ) {
+- DH_free(dh_params);
++ if (priv_key) BN_free(priv_key);
++ if (dh_p) BN_free(dh_p);
++ if (dh_g) BN_free(dh_g);
+ return enif_make_badarg(env);
+ }
+
+- if (len) {
+- if (len < BN_num_bits(dh_params->p))
+- dh_params->length = len;
+- else {
+- DH_free(dh_params);
+- return enif_make_badarg(env);
+- }
+- }
++ dh_params = DH_new();
++ DH_set0_key(dh_params, NULL, priv_key);
++ DH_set0_pqg(dh_params, dh_p, NULL, dh_g);
+
+ if (DH_generate_key(dh_params)) {
+- pub_len = BN_num_bytes(dh_params->pub_key);
+- prv_len = BN_num_bytes(dh_params->priv_key);
++ const BIGNUM *pub_key, *priv_key;
++ DH_get0_key(dh_params, &pub_key, &priv_key);
++ pub_len = BN_num_bytes(pub_key);
++ prv_len = BN_num_bytes(priv_key);
+ pub_ptr = enif_make_new_binary(env, pub_len+mpint, &ret_pub);
+ prv_ptr = enif_make_new_binary(env, prv_len+mpint, &ret_prv);
+ if (mpint) {
+ put_int32(pub_ptr, pub_len); pub_ptr += 4;
+ put_int32(prv_ptr, prv_len); prv_ptr += 4;
+ }
+- BN_bn2bin(dh_params->pub_key, pub_ptr);
+- BN_bn2bin(dh_params->priv_key, prv_ptr);
++ BN_bn2bin(pub_key, pub_ptr);
++ BN_bn2bin(priv_key, prv_ptr);
+ ERL_VALGRIND_MAKE_MEM_DEFINED(pub_ptr, pub_len);
+ ERL_VALGRIND_MAKE_MEM_DEFINED(prv_ptr, prv_len);
+ ret = enif_make_tuple2(env, ret_pub, ret_prv);
+@@ -2817,26 +2974,37 @@ static ERL_NIF_TERM dh_generate_key_nif(
+ static ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+ {/* (OthersPublicKey, MyPrivateKey, DHParams=[P,G]) */
+ DH* dh_params;
+- BIGNUM* pubkey = NULL;
++ BIGNUM *dummy_pub_key = NULL, *priv_key = NULL;
++ BIGNUM *other_pub_key;
++ BIGNUM *dh_p = NULL, *dh_g = NULL;
+ int i;
+ ErlNifBinary ret_bin;
+ ERL_NIF_TERM ret, head, tail;
+
+ dh_params = DH_new();
+
+- if (!get_bn_from_bin(env, argv[0], &pubkey)
+- || !get_bn_from_bin(env, argv[1], &dh_params->priv_key)
++ if (!get_bn_from_bin(env, argv[0], &other_pub_key)
++ || !get_bn_from_bin(env, argv[1], &priv_key)
+ || !enif_get_list_cell(env, argv[2], &head, &tail)
+- || !get_bn_from_bin(env, head, &dh_params->p)
++ || !get_bn_from_bin(env, head, &dh_p)
+ || !enif_get_list_cell(env, tail, &head, &tail)
+- || !get_bn_from_bin(env, head, &dh_params->g)
++ || !get_bn_from_bin(env, head, &dh_g)
+ || !enif_is_empty_list(env, tail)) {
+-
++ if (dh_p) BN_free(dh_p);
++ if (dh_g) BN_free(dh_g);
+ ret = enif_make_badarg(env);
+ }
+ else {
++ /* Note: DH_set0_key() does not allow setting only the
++ * private key, although DH_compute_key() does not use the
++ * public key. Work around this limitation by setting
++ * the public key to a copy of the private key.
++ */
++ dummy_pub_key = BN_dup(priv_key);
++ DH_set0_key(dh_params, dummy_pub_key, priv_key);
++ DH_set0_pqg(dh_params, dh_p, NULL, dh_g);
+ enif_alloc_binary(DH_size(dh_params), &ret_bin);
+- i = DH_compute_key(ret_bin.data, pubkey, dh_params);
++ i = DH_compute_key(ret_bin.data, other_pub_key, dh_params);
+ if (i > 0) {
+ if (i != ret_bin.size) {
+ enif_realloc_binary(&ret_bin, i);
+@@ -2848,7 +3016,7 @@ static ERL_NIF_TERM dh_compute_key_nif(E
+ ret = atom_error;
+ }
+ }
+- if (pubkey) BN_free(pubkey);
++ if (other_pub_key) BN_free(other_pub_key);
+ DH_free(dh_params);
+ return ret;
+ }
+@@ -3420,7 +3588,7 @@ static ERL_NIF_TERM ecdsa_sign_nif(ErlNi
+
+ enif_alloc_binary(ECDSA_size(key), &ret_bin);
+
+- i = ECDSA_sign(md->type, digest_bin.data, len,
++ i = ECDSA_sign(EVP_MD_type(md), digest_bin.data, len,
+ ret_bin.data, &dsa_s_len, key);
+
+ EC_KEY_free(key);
+@@ -3470,7 +3638,7 @@ static ERL_NIF_TERM ecdsa_verify_nif(Erl
+ || !get_ec_key(env, argv[3], atom_undefined, argv[4], &key))
+ goto badarg;
+
+- i = ECDSA_verify(md->type, digest_bin.data, len,
++ i = ECDSA_verify(EVP_MD_type(md), digest_bin.data, len,
+ sign_bin.data, sign_bin.size, key);
+
+ EC_KEY_free(key);
+diff --git a/lib/crypto/c_src/crypto_callback.c b/lib/crypto/c_src/crypto_callback.c
+index 4c23379f7f6..23d2bed0576 100644
+--- lib/crypto/c_src/crypto_callback.c.orig
++++ lib/crypto/c_src/crypto_callback.c
+@@ -62,7 +62,7 @@ static void nomem(size_t size, const char* op)
+ abort();
+ }
+
+-static void* crypto_alloc(size_t size)
++static void* crypto_alloc(size_t size CCB_FILE_LINE_ARGS)
+ {
+ void *ret = enif_alloc(size);
+
+@@ -70,7 +70,7 @@ static void* crypto_alloc(size_t size)
+ nomem(size, "allocate");
+ return ret;
+ }
+-static void* crypto_realloc(void* ptr, size_t size)
++static void* crypto_realloc(void* ptr, size_t size CCB_FILE_LINE_ARGS)
+ {
+ void* ret = enif_realloc(ptr, size);
+
+@@ -78,7 +78,7 @@ static void* crypto_realloc(void* ptr, size_t size)
+ nomem(size, "reallocate");
+ return ret;
+ }
+-static void crypto_free(void* ptr)
++static void crypto_free(void* ptr CCB_FILE_LINE_ARGS)
+ {
+ enif_free(ptr);
+ }
+diff --git a/lib/crypto/c_src/crypto_callback.h b/lib/crypto/c_src/crypto_callback.h
+index 894d86cfd95..2641cc0c8b9 100644
+--- lib/crypto/c_src/crypto_callback.h.orig
++++ lib/crypto/c_src/crypto_callback.h
+@@ -18,13 +18,20 @@
+ * %CopyrightEnd%
+ */
+
++#include <openssl/crypto.h>
++#if OPENSSL_VERSION_NUMBER < 0x10100000L
++# define CCB_FILE_LINE_ARGS
++#else
++# define CCB_FILE_LINE_ARGS , const char *file, int line
++#endif
++
+ struct crypto_callbacks
+ {
+ size_t sizeof_me;
+
+- void* (*crypto_alloc)(size_t size);
+- void* (*crypto_realloc)(void* ptr, size_t size);
+- void (*crypto_free)(void* ptr);
++ void* (*crypto_alloc)(size_t size CCB_FILE_LINE_ARGS);
++ void* (*crypto_realloc)(void* ptr, size_t size CCB_FILE_LINE_ARGS);
++ void (*crypto_free)(void* ptr CCB_FILE_LINE_ARGS);
+
+ /* openssl callbacks */
+ #ifdef OPENSSL_THREADS
diff --git a/lang/erlang/files/patch-OpenSSL-1.1-b b/lang/erlang/files/patch-OpenSSL-1.1-b
new file mode 100644
index 000000000000..781d5c687d9d
--- /dev/null
+++ b/lang/erlang/files/patch-OpenSSL-1.1-b
@@ -0,0 +1,293 @@
+From 4dddb3c0b286e13f2cbccb0cdaa4bffcfee60033 Mon Sep 17 00:00:00 2001
+From: Yuki Ito <yuki@gnnk.net>
+Date: Tue, 20 Dec 2016 17:45:51 +0900
+Subject: [PATCH] crypto: Support chacha20_poly1305
+
+This commit reactivates chacha20_poly1305 and fixes the imprementation
+for the released OpenSSL 1.1.0 or later.
+---
+ lib/crypto/c_src/crypto.c | 152 ++++++++++++-------------------
+ lib/crypto/test/crypto_SUITE.erl | 49 ++++++++--
+ 2 files changed, 101 insertions(+), 100 deletions(-)
+
+diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
+index 0031f9b9620..68784cd24c9 100644
+--- lib/crypto/c_src/crypto.c
++++ lib/crypto/c_src/crypto.c
+@@ -117,7 +117,7 @@
+ # endif
+ #endif
+
+-#if defined(NID_chacha20) && !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
++#if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,1,0)
+ # define HAVE_CHACHA20_POLY1305
+ #endif
+
+@@ -131,20 +131,6 @@
+ #include <openssl/ecdsa.h>
+ #endif
+
+-#if defined(HAVE_CHACHA20_POLY1305)
+-#include <openssl/chacha.h>
+-#include <openssl/poly1305.h>
+-
+-#if !defined(CHACHA20_NONCE_LEN)
+-# define CHACHA20_NONCE_LEN 8
+-#endif
+-#if !defined(POLY1305_TAG_LEN)
+-# define POLY1305_TAG_LEN 16
+-#endif
+-
+-#endif
+-
+-
+ #ifdef VALGRIND
+ # include <valgrind/memcheck.h>
+
+@@ -2038,71 +2024,61 @@
+ }
+ #endif /* HAVE_GCM_EVP_DECRYPT_BUG */
+
+-#if defined(HAVE_CHACHA20_POLY1305)
+-static void
+-poly1305_update_with_length(poly1305_state *poly1305,
+- const unsigned char *data, size_t data_len)
+-{
+- size_t j = data_len;
+- unsigned char length_bytes[8];
+- unsigned i;
+
+- for (i = 0; i < sizeof(length_bytes); i++) {
+- length_bytes[i] = j;
+- j >>= 8;
+- }
+-
+- CRYPTO_poly1305_update(poly1305, data, data_len);
+- CRYPTO_poly1305_update(poly1305, length_bytes, sizeof(length_bytes));
+-}
+-#endif
+-
+ static ERL_NIF_TERM chacha20_poly1305_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+ {/* (Key,Iv,AAD,In) */
+ #if defined(HAVE_CHACHA20_POLY1305)
++ EVP_CIPHER_CTX *ctx;
++ const EVP_CIPHER *cipher = NULL;
+ ErlNifBinary key, iv, aad, in;
+- unsigned char *outp;
++ unsigned char *outp, *tagp;
+ ERL_NIF_TERM out, out_tag;
+- ErlNifUInt64 in_len_64;
+- unsigned char poly1305_key[32];
+- poly1305_state poly1305;
++ int len;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 32
+- || !enif_inspect_binary(env, argv[1], &iv) || iv.size != CHACHA20_NONCE_LEN
++ || !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0 || iv.size > 16
+ || !enif_inspect_iolist_as_binary(env, argv[2], &aad)
+ || !enif_inspect_iolist_as_binary(env, argv[3], &in)) {
+ return enif_make_badarg(env);
+ }
+
+- /* Take from OpenSSL patch set/LibreSSL:
+- *
+- * The underlying ChaCha implementation may not overflow the block
+- * counter into the second counter word. Therefore we disallow
+- * individual operations that work on more than 2TB at a time.
+- * in_len_64 is needed because, on 32-bit platforms, size_t is only
+- * 32-bits and this produces a warning because it's always false.
+- * Casting to uint64_t inside the conditional is not sufficient to stop
+- * the warning. */
+- in_len_64 = in.size;
+- if (in_len_64 >= (1ULL << 32) * 64 - 64)
+- return enif_make_badarg(env);
++ cipher = EVP_chacha20_poly1305();
+
+- memset(poly1305_key, 0, sizeof(poly1305_key));
+- CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key), key.data, iv.data, 0);
++ ctx = EVP_CIPHER_CTX_new();
+
++ if (EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1)
++ goto out_err;
++
++ EVP_CIPHER_CTX_set_padding(ctx, 0);
++
++ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, iv.size, NULL) != 1)
++ goto out_err;
++ if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1)
++ goto out_err;
++ if (EVP_EncryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1)
++ goto out_err;
++
+ outp = enif_make_new_binary(env, in.size, &out);
+
+- CRYPTO_poly1305_init(&poly1305, poly1305_key);
+- poly1305_update_with_length(&poly1305, aad.data, aad.size);
+- CRYPTO_chacha_20(outp, in.data, in.size, key.data, iv.data, 1);
+- poly1305_update_with_length(&poly1305, outp, in.size);
++ if (EVP_EncryptUpdate(ctx, outp, &len, in.data, in.size) != 1)
++ goto out_err;
++ if (EVP_EncryptFinal_ex(ctx, outp+len, &len) != 1)
++ goto out_err;
+
+- CRYPTO_poly1305_finish(&poly1305, enif_make_new_binary(env, POLY1305_TAG_LEN, &out_tag));
++ tagp = enif_make_new_binary(env, 16, &out_tag);
+
++ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, tagp) != 1)
++ goto out_err;
++
++ EVP_CIPHER_CTX_free(ctx);
++
+ CONSUME_REDS(env, in);
+
+ return enif_make_tuple2(env, out, out_tag);
+
++out_err:
++ EVP_CIPHER_CTX_free(ctx);
++ return atom_error;
+ #else
+ return enif_raise_exception(env, atom_notsup);
+ #endif
+@@ -2111,53 +2087,52 @@
+ static ERL_NIF_TERM chacha20_poly1305_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+ {/* (Key,Iv,AAD,In,Tag) */
+ #if defined(HAVE_CHACHA20_POLY1305)
++ EVP_CIPHER_CTX *ctx;
++ const EVP_CIPHER *cipher = NULL;
+ ErlNifBinary key, iv, aad, in, tag;
+ unsigned char *outp;
+ ERL_NIF_TERM out;
+- ErlNifUInt64 in_len_64;
+- unsigned char poly1305_key[32];
+- unsigned char mac[POLY1305_TAG_LEN];
+- poly1305_state poly1305;
++ int len;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 32
+- || !enif_inspect_binary(env, argv[1], &iv) || iv.size != CHACHA20_NONCE_LEN
++ || !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0 || iv.size > 16
+ || !enif_inspect_iolist_as_binary(env, argv[2], &aad)
+ || !enif_inspect_iolist_as_binary(env, argv[3], &in)
+- || !enif_inspect_iolist_as_binary(env, argv[4], &tag) || tag.size != POLY1305_TAG_LEN) {
++ || !enif_inspect_iolist_as_binary(env, argv[4], &tag) || tag.size != 16) {
+ return enif_make_badarg(env);
+ }
+
+- /* Take from OpenSSL patch set/LibreSSL:
+- *
+- * The underlying ChaCha implementation may not overflow the block
+- * counter into the second counter word. Therefore we disallow
+- * individual operations that work on more than 2TB at a time.
+- * in_len_64 is needed because, on 32-bit platforms, size_t is only
+- * 32-bits and this produces a warning because it's always false.
+- * Casting to uint64_t inside the conditional is not sufficient to stop
+- * the warning. */
+- in_len_64 = in.size;
+- if (in_len_64 >= (1ULL << 32) * 64 - 64)
+- return enif_make_badarg(env);
++ cipher = EVP_chacha20_poly1305();
+
+- memset(poly1305_key, 0, sizeof(poly1305_key));
+- CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key), key.data, iv.data, 0);
++ ctx = EVP_CIPHER_CTX_new();
+
+- CRYPTO_poly1305_init(&poly1305, poly1305_key);
+- poly1305_update_with_length(&poly1305, aad.data, aad.size);
+- poly1305_update_with_length(&poly1305, in.data, in.size);
+- CRYPTO_poly1305_finish(&poly1305, mac);
++ if (EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1)
++ goto out_err;
++ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, iv.size, NULL) != 1)
++ goto out_err;
++ if (EVP_DecryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1)
++ goto out_err;
++ if (EVP_DecryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1)
++ goto out_err;
+
+- if (memcmp(mac, tag.data, POLY1305_TAG_LEN) != 0)
+- return atom_error;
+-
+ outp = enif_make_new_binary(env, in.size, &out);
+
+- CRYPTO_chacha_20(outp, in.data, in.size, key.data, iv.data, 1);
++ if (EVP_DecryptUpdate(ctx, outp, &len, in.data, in.size) != 1)
++ goto out_err;
++ if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag.size, tag.data) != 1)
++ goto out_err;
++ if (EVP_DecryptFinal_ex(ctx, outp+len, &len) != 1)
++ goto out_err;
+
++ EVP_CIPHER_CTX_free(ctx);
++
+ CONSUME_REDS(env, in);
+
+ return out;
++
++out_err:
++ EVP_CIPHER_CTX_free(ctx);
++ return atom_error;
+ #else
+ return enif_raise_exception(env, atom_notsup);
+ #endif
+diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
+index 0c3b7a0445d..31f4e89ffe1 100644
+--- lib/crypto/test/crypto_SUITE.erl
++++ lib/crypto/test/crypto_SUITE.erl
+@@ -2249,16 +2249,49 @@ aes_gcm() ->
+ 1} %% TagLength
+ ].
+
+-%% http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
++%% https://tools.ietf.org/html/rfc7539#appendix-A.5
+ chacha20_poly1305() ->
+ [
+- {chacha20_poly1305, hexstr2bin("4290bcb154173531f314af57f3be3b500" %% Key
+- "6da371ece272afa1b5dbdd1100a1007"),
+- hexstr2bin("86d09974840bded2a5ca"), %% PlainText
+- hexstr2bin("cd7cf67be39c794a"), %% Nonce
+- hexstr2bin("87e229d4500845a079c0"), %% AAD
+- hexstr2bin("e3e446f7ede9a19b62a4"), %% CipherText
+- hexstr2bin("677dabf4e3d24b876bb284753896e1d6")} %% CipherTag
++ {chacha20_poly1305,
++ hexstr2bin("1c9240a5eb55d38af333888604f6b5f0" %% Key
++ "473917c1402b80099dca5cbc207075c0"),
++ hexstr2bin("496e7465726e65742d44726166747320" %% PlainText
++ "61726520647261667420646f63756d65"
++ "6e74732076616c696420666f72206120"
++ "6d6178696d756d206f6620736978206d"
++ "6f6e74687320616e64206d6179206265"
++ "20757064617465642c207265706c6163"
++ "65642c206f72206f62736f6c65746564"
++ "206279206f7468657220646f63756d65"
++ "6e747320617420616e792074696d652e"
++ "20497420697320696e617070726f7072"
++ "6961746520746f2075736520496e7465"
++ "726e65742d4472616674732061732072"
++ "65666572656e6365206d617465726961"
++ "6c206f7220746f206369746520746865"
++ "6d206f74686572207468616e20617320"
++ "2fe2809c776f726b20696e2070726f67"
++ "726573732e2fe2809d"),
++ hexstr2bin("000000000102030405060708"), %% Nonce
++ hexstr2bin("f33388860000000000004e91"), %% AAD
++ hexstr2bin("64a0861575861af460f062c79be643bd" %% CipherText
++ "5e805cfd345cf389f108670ac76c8cb2"
++ "4c6cfc18755d43eea09ee94e382d26b0"
++ "bdb7b73c321b0100d4f03b7f355894cf"
++ "332f830e710b97ce98c8a84abd0b9481"
++ "14ad176e008d33bd60f982b1ff37c855"
++ "9797a06ef4f0ef61c186324e2b350638"
++ "3606907b6a7c02b0f9f6157b53c867e4"
++ "b9166c767b804d46a59b5216cde7a4e9"
++ "9040c5a40433225ee282a1b0a06c523e"
++ "af4534d7f83fa1155b0047718cbc546a"
++ "0d072b04b3564eea1b422273f548271a"
++ "0bb2316053fa76991955ebd63159434e"
++ "cebb4e466dae5a1073a6727627097a10"
++ "49e617d91d361094fa68f0ff77987130"
++ "305beaba2eda04df997b714d6c6f2c29"
++ "a6ad5cb4022b02709b"),
++ hexstr2bin("eead9d67890cbb22392336fea1851f38")} %% CipherTag
+ ].
+
+ rsa_plain() ->