diff options
-rw-r--r-- | lang/erlang-runtime15/Makefile | 13 | ||||
-rw-r--r-- | lang/erlang-runtime16/Makefile | 13 | ||||
-rw-r--r-- | lang/erlang-runtime17/Makefile | 13 | ||||
-rw-r--r-- | lang/erlang-runtime18/Makefile | 10 | ||||
-rw-r--r-- | lang/erlang-runtime19/Makefile | 1 | ||||
-rw-r--r-- | lang/erlang-runtime19/files/patch-OpenSSL-1.1-a | 1083 | ||||
-rw-r--r-- | lang/erlang-runtime19/files/patch-OpenSSL-1.1-b | 293 | ||||
-rw-r--r-- | lang/erlang/Makefile | 3 | ||||
-rw-r--r-- | lang/erlang/files/patch-OpenSSL-1.1-a | 1083 | ||||
-rw-r--r-- | lang/erlang/files/patch-OpenSSL-1.1-b | 293 |
10 files changed, 2801 insertions, 4 deletions
diff --git a/lang/erlang-runtime15/Makefile b/lang/erlang-runtime15/Makefile index 0ded1face669..64e8d27060ff 100644 --- a/lang/erlang-runtime15/Makefile +++ b/lang/erlang-runtime15/Makefile @@ -19,6 +19,9 @@ EXTRACT_ONLY= ${DISTNAME}${EXTRACT_SUFX} MAINTAINER= erlang@FreeBSD.org COMMENT= Functional programming language from Ericsson +BROKEN_SSL= openssl111 +BROKEN_SSL_REASON_openssl111= Does not support OpenSSL 1.1, use Erlang 19+ + WRKSRC= ${WRKDIR}/otp_src_R15B03 ERLANG_LIB= ${PORTNAME}${PORTVERSION:C/\..*//} @@ -45,6 +48,8 @@ OPTIONS_EXCLUDE+= DTRACE OPTIONS_EXCLUDE_DragonFly= HIPE SCTP +OPENSSL_VARS= BROKEN_SSL=openssl-devel openssl111 + GNU_CONFIGURE= yes LDFLAGS+= -L${LOCALBASE}/lib USES= gmake ncurses perl5 @@ -75,6 +80,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 CFLAGS+= -DMAP_NORESERVE=0 .endif diff --git a/lang/erlang-runtime16/Makefile b/lang/erlang-runtime16/Makefile index 07bb416b2c0c..0585c9fd1078 100644 --- a/lang/erlang-runtime16/Makefile +++ b/lang/erlang-runtime16/Makefile @@ -19,6 +19,9 @@ EXTRACT_ONLY= ${DISTNAME}${EXTRACT_SUFX} MAINTAINER= erlang@FreeBSD.org COMMENT= Functional programming language from Ericsson +BROKEN_SSL= openssl111 +BROKEN_SSL_REASON_openssl111= Does not support OpenSSL 1.1, use Erlang 19+ + WRKSRC= ${WRKDIR}/otp_src_${ERLANG_REL} ERLANG_LIB= ${PORTNAME}${PORTVERSION:C/\..*//} @@ -45,6 +48,8 @@ OPTIONS_EXCLUDE+= DTRACE OPTIONS_EXCLUDE_DragonFly= HIPE SCTP +OPENSSL_VARS= BROKEN_SSL=openssl-devel openssl111 + GNU_CONFIGURE= yes LDFLAGS+= -L${LOCALBASE}/lib USES= gmake ncurses perl5 @@ -75,6 +80,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 CFLAGS+= -DMAP_NORESERVE=0 .endif diff --git a/lang/erlang-runtime17/Makefile b/lang/erlang-runtime17/Makefile index 4aefa6eb9dd7..5f05e2a5f341 100644 --- a/lang/erlang-runtime17/Makefile +++ b/lang/erlang-runtime17/Makefile @@ -28,6 +28,9 @@ PATCHFILES= patch-otp-17.5.1 patch-otp-17.5.2 patch-otp-17.5.3 \ MAINTAINER= erlang@FreeBSD.org COMMENT= Functional programming language from Ericsson +BROKEN_SSL= openssl111 +BROKEN_SSL_REASON_openssl111= Does not support OpenSSL 1.1, use Erlang 19+ + WRKSRC= ${WRKDIR}/otp_src_${ERLANG_REL} ERLANG_LIB= ${PORTNAME}${PORTVERSION:C/\..*//} @@ -64,7 +67,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 @@ -98,6 +101,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 CFLAGS+= -DMAP_NORESERVE=0 .endif diff --git a/lang/erlang-runtime18/Makefile b/lang/erlang-runtime18/Makefile index f3bf66073c36..548b9896bf34 100644 --- a/lang/erlang-runtime18/Makefile +++ b/lang/erlang-runtime18/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 CFLAGS+= -DMAP_NORESERVE=0 .endif diff --git a/lang/erlang-runtime19/Makefile b/lang/erlang-runtime19/Makefile index fd0f0498f4d5..97195c06af99 100644 --- a/lang/erlang-runtime19/Makefile +++ b/lang/erlang-runtime19/Makefile @@ -3,6 +3,7 @@ PORTNAME= erlang PORTVERSION= 19.3.6.12 +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 4a727d44ec97..0effe2865061 100644 --- a/lang/erlang/Makefile +++ b/lang/erlang/Makefile @@ -3,6 +3,7 @@ PORTNAME= erlang PORTVERSION= 19.3.6.12 +PORTREVISION= 1 PORTEPOCH= 4 CATEGORIES= lang parallel java MASTER_SITES= http://www.erlang.org/download/:erlangorg \ @@ -68,8 +69,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() -> |