[packages/erlang/ERLANG_19] - up to 19.3; partial fix for openssl build

arekm arekm at pld-linux.org
Wed Jul 3 10:07:14 CEST 2019


commit f76ab4f99deb6e0bc945ce9d765710a3979019a9
Author: Arkadiusz Miśkiewicz <arekm at maven.pl>
Date:   Wed Jul 3 10:06:48 2019 +0200

    - up to 19.3; partial fix for openssl build

 erlang.spec   |   14 +-
 git.patch     |  448 ++++++++++++++++++++++++
 openssl.patch | 1062 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1520 insertions(+), 4 deletions(-)
---
diff --git a/erlang.spec b/erlang.spec
index ad64eb7..f24d175 100644
--- a/erlang.spec
+++ b/erlang.spec
@@ -14,21 +14,23 @@
 Summary:	OpenSource Erlang/OTP
 Summary(pl.UTF-8):	Erlang/OTP z otwartymi źródłami
 Name:		erlang
-Version:	19.2
+Version:	19.3
 Release:	1
 Epoch:		2
 %define		_version	%(echo %{version} | tr _ -)
 License:	APLv2
 Group:		Development/Languages
 Source0:	http://www.erlang.org/download/otp_src_%{_version}.tar.gz
-# Source0-md5:	7cdd18a826dd7bda0ca46d1c3b2efca6
+# Source0-md5:	a8c259ec47bf84e77510673e1b76b6db
 Source1:	http://www.erlang.org/download/otp_doc_man_%{_version}.tar.gz
-# Source1-md5:	4464aa2a63196880883de9636e177cff
+# Source1-md5:	63f115d98934f4483a0341c567193747
 Source2:	epmd.service
 Source3:	epmd.socket
 Source4:	epmd at .service
 Source5:	epmd at .socket
 Patch0:		%{name}-fPIC.patch
+Patch1:		git.patch
+Patch2:		openssl.patch
 URL:		http://www.erlang.org/
 %{?with_java:BuildRequires:	/usr/bin/jar}
 BuildRequires:	autoconf
@@ -66,6 +68,9 @@ rozpowszechnianiu Erlanga poza Ericssonem.
 %{__tar} xzf %{SOURCE1} man/ COPYRIGHT
 #%patch0 -p1
 
+%patch1 -p1
+%patch2 -p1
+
 %build
 find . -name config.sub | xargs -n 1 cp -f /usr/share/automake/config.sub
 curd=$(pwd)
@@ -80,7 +85,8 @@ done
 %endif
 	--disable-silent-rules \
 	--enable-smp-support \
-	--with-javac%{!?with_java:=no}
+	--with-javac%{!?with_java:=no} \
+	--with-ssl
 rm -f lib/ssl/SKIP
 ERL_TOP=`pwd`; export ERL_TOP
  %{__make} -j1 \
diff --git a/git.patch b/git.patch
new file mode 100644
index 0000000..ba571dc
--- /dev/null
+++ b/git.patch
@@ -0,0 +1,448 @@
+commit 25aa0128340d819e85e641f0ef8b9e0fd5fdda0b
+Author: Björn Gustavsson <bjorn at erlang.org>
+Date:   Tue Nov 29 07:45:15 2016 +0100
+
+    configure.in: Fix test for SSL with Kerberos
+    
+    OpenSSL 1.1.0 and higher does not support Kerberos and no longer
+    defines OPENSSL_NO_KRB5 to indicate that. Test the version number
+    as well as OPENSSL_NO_KRB5.
+
+diff --git a/erts/configure.in b/erts/configure.in
+index 98f3e6bcc5..fd7dc783f3 100644
+--- a/erts/configure.in
++++ b/erts/configure.in
+@@ -4447,12 +4447,14 @@ esac
+ 
+ if test "x$SSL_APP" != "x" ; then
+     dnl We found openssl, now check if we use kerberos 5 support
++    dnl FIXME: Do we still support platforms that have Kerberos?
+     AC_MSG_CHECKING(for OpenSSL kerberos 5 support)
+     old_CPPFLAGS=$CPPFLAGS
+     CPPFLAGS=$SSL_INCLUDE
+     AC_EGREP_CPP(^yes$,[
++#include <openssl/opensslv.h>
+ #include <openssl/opensslconf.h>
+-#ifndef OPENSSL_NO_KRB5
++#if OPENSSL_VERSION_NUMBER < 0x1010000fL && !defined(OPENSSL_NO_KRB5)
+ yes
+ #endif
+       ],[
+commit e30294f44d02200c20a80f1a3a2bb075afc3747d
+Author: Björn Gustavsson <bjorn at erlang.org>
+Date:   Thu Nov 24 10:11:13 2016 +0100
+
+    configure.in: Fix configure test for usable OpenSSL
+    
+    In OpenSSL 1.1.0, HMAC_CTX no longer has a complete definition,
+    and can no longer be allocated as a stack variable. Therefore,
+    the code in the configure test for usable OpenSSL library will
+    not compile.
+    
+    Call the HMAC() function instead since it exists in all versions of
+    of OpenSSL that we support. Note that the code will only be compiled
+    and linked, not run, so the argument values don't matter as long as
+    they have the correct type.
+
+diff --git a/erts/configure.in b/erts/configure.in
+index fd7dc783f3..2018e19b76 100644
+--- a/erts/configure.in
++++ b/erts/configure.in
+@@ -4285,8 +4285,7 @@ yes
+ 					#include <stdio.h>
+  					#include <openssl/hmac.h>],
+  					[ 
+- 					HMAC_CTX hc;
+- 					HMAC_CTX_init(&hc);		
++					HMAC(0, 0, 0, 0, 0, 0, 0);
+  					],
+  					[ssl_linkable=yes],
+  					[ssl_linkable=no])
+@@ -4341,8 +4340,7 @@ dnl		so it is - be adoptable
+ 			#include <stdio.h>
+  			#include <openssl/hmac.h>],
+  			[ 
+- 			HMAC_CTX hc;
+- 			HMAC_CTX_init(&hc);		
++			HMAC(0, 0, 0, 0, 0, 0, 0);
+  			],
+  			[ssl_dyn_linkable=yes],
+  			[ssl_dyn_linkable=no])
+@@ -4605,8 +4603,7 @@ yes)   # Use standard lib locations for ssl runtime library path
+                          #include <openssl/hmac.h>
+                     ],
+                     [ 
+-                         HMAC_CTX hc;
+-                         HMAC_CTX_init(&hc);		
++			 HMAC(0, 0, 0, 0, 0, 0, 0);
+                     ],
+                     [rpath_success=yes],
+                     [rpath_success=no])
+commit 78a5de9611c25a4e7b5248aa9828f949f3a5c131
+Author: Björn Gustavsson <bjorn at erlang.org>
+Date:   Thu Nov 24 10:55:10 2016 +0100
+
+    crypto.c: Disable broken code for ChaCha and Poly1305
+    
+    In June 2014, fb9d36c2c7c1 added support for the AES GCM ciphers
+    (ChaCha/Poly1305) based on a development version of OpenSSL 1.1.0.
+    The code is seriously broken when used with the released OpenSSL 1.1.0.
+
+diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
+index 86b839eddb..554aaf7587 100644
+--- a/lib/crypto/c_src/crypto.c
++++ b/lib/crypto/c_src/crypto.c
+@@ -138,6 +138,13 @@
+ #include <openssl/ecdsa.h>
+ #endif
+ 
++/*
++ * FIXME: The support for ChaCha and Poly1305 is based on pre-releases
++ * of OpenSSL 1.1.0. It is seriously broken when used with the released
++ * OpenSSL 1.1.0 or later.
++ */
++#undef HAVE_CHACHA20_POLY1305
++
+ #if defined(HAVE_CHACHA20_POLY1305)
+ #include <openssl/chacha.h>
+ #include <openssl/poly1305.h>
+commit 1cdaf0a6fd8dbbf08fe88dd148424df4da683f48
+Author: Petr Gotthard <petr.gotthard at centrum.cz>
+Date:   Sat Jul 30 10:51:47 2016 -0700
+
+    crypto:cmac calculating the Cipher-based Message Authentication Code
+    
+    The ERL-82 issue requests a way to calculate a CMAC in Erlang. The
+    AES128 CMAC is standartized in RFC 4493 and used e.g. for message
+    authentication in the LoRaWAN networks.
+    
+    The CMAC is implemented by OpenSSL since v1.0.1, but as @IngelaAndin
+    stated in response to the ERL-82, the current crypto implementation
+    does not include functions that call those OpenSSL cryptolib functions.
+    
+    This commit introduces a new function `crypto:cmac` that calls
+    the corresponding OpenSSL functions and calculates the CMAC.
+    
+    Only the cmac_nif is implemented. The incremental functions (init,
+    update, final) are not provided because the current OpenSSL does
+    not allow custom memory allocators like `enif_alloc_resource`.
+    
+    The Erlang user guide states that at least OpenSSL 0.9.8 is required,
+    so I added few #ifdefs so the code is compatible with all versions.
+    However, the OpenSSL pages say that the pre-1.0.1 versions (0.9.8 and
+    1.0.0) are no longer maintained. Even the 1.0.1 will be retired by
+    Dec 2016. Hence I believe that adding a 1.0.1-only function like CMAC
+    should be OK.
+
+diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
+index 7183c395ae..240bfc8341 100644
+--- a/lib/crypto/c_src/crypto.c
++++ b/lib/crypto/c_src/crypto.c
+@@ -108,6 +108,7 @@
+ #if OPENSSL_VERSION_NUMBER >= OpenSSL_version_plain(1,0,1)
+ # define HAVE_EVP_AES_CTR
+ # define HAVE_GCM
++# define HAVE_CMAC
+ # if OPENSSL_VERSION_NUMBER < OpenSSL_version(1,0,1,'d')
+ #  define HAVE_GCM_EVP_DECRYPT_BUG
+ # endif
+@@ -121,6 +122,10 @@
+ # define HAVE_ECB_IVEC_BUG
+ #endif
+ 
++#if defined(HAVE_CMAC)
++#include <openssl/cmac.h>
++#endif
++
+ #if defined(HAVE_EC)
+ #include <openssl/ec.h>
+ #include <openssl/ecdh.h>
+@@ -224,6 +229,7 @@ static ERL_NIF_TERM hmac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]
+ static ERL_NIF_TERM hmac_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+ static ERL_NIF_TERM hmac_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+ static ERL_NIF_TERM hmac_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
++static ERL_NIF_TERM cmac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+ static ERL_NIF_TERM block_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+ static ERL_NIF_TERM aes_cfb_8_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+ static ERL_NIF_TERM aes_ige_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+@@ -294,6 +300,7 @@ static ErlNifFunc nif_funcs[] = {
+     {"hmac_update_nif", 2, hmac_update_nif},
+     {"hmac_final_nif", 1, hmac_final_nif},
+     {"hmac_final_nif", 2, hmac_final_nif},
++    {"cmac_nif", 3, cmac_nif},
+     {"block_crypt_nif", 5, block_crypt_nif},
+     {"block_crypt_nif", 4, block_crypt_nif},
+     {"aes_ige_crypt_nif", 4, aes_ige_crypt_nif},
+@@ -1346,6 +1353,53 @@ static ERL_NIF_TERM hmac_final_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
+     return ret;
+ }
+ 
++static ERL_NIF_TERM cmac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
++{/* (Type, Key, Data) */
++#if defined(HAVE_CMAC)
++    struct cipher_type_t *cipherp = NULL;
++    const EVP_CIPHER     *cipher;
++    CMAC_CTX             *ctx;
++    ErlNifBinary         key;
++    ErlNifBinary         data;
++    ERL_NIF_TERM         ret;
++    unsigned             ret_size;
++
++    if (!enif_inspect_iolist_as_binary(env, argv[1], &key)
++        || !(cipherp = get_cipher_type(argv[0], key.size))
++        || !enif_inspect_iolist_as_binary(env, argv[2], &data)) {
++        return enif_make_badarg(env);
++    }
++    cipher = cipherp->cipher.p;
++    if (!cipher) {
++        return enif_raise_exception(env, atom_notsup);
++    }
++
++    ctx = CMAC_CTX_new();
++    if (!CMAC_Init(ctx, key.data, key.size, cipher, NULL)) {
++        CMAC_CTX_free(ctx);
++        return atom_notsup;
++    }
++
++    if (!CMAC_Update(ctx, data.data, data.size) ||
++        !CMAC_Final(ctx,
++                    enif_make_new_binary(env, EVP_CIPHER_block_size(cipher), &ret),
++                    &ret_size)) {
++        CMAC_CTX_free(ctx);
++        return atom_notsup;
++    }
++    ASSERT(ret_size == (unsigned)EVP_CIPHER_block_size(cipher));
++
++    CMAC_CTX_free(ctx);
++    CONSUME_REDS(env, data);
++    return ret;
++#else
++    /* The CMAC functionality was introduced in OpenSSL 1.0.1
++     * Although OTP requires at least version 0.9.8, the versions 0.9.8 and 1.0.0 are
++     * no longer maintained. */
++    return atom_notsup;
++#endif
++}
++
+ static ERL_NIF_TERM block_crypt_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+ {/* (Type, Key, Ivec, Text, IsEncrypt) or (Type, Key, Text, IsEncrypt) */
+     struct cipher_type_t *cipherp = NULL;
+diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
+index 5a5627747c..728233d226 100644
+--- a/lib/crypto/doc/src/crypto.xml
++++ b/lib/crypto/doc/src/crypto.xml
+@@ -453,6 +453,24 @@
+       </desc>
+     </func>
+ 
++    <func>
++      <name>cmac(Type, Key, Data) -> Mac</name>
++      <name>cmac(Type, Key, Data, MacLength) -> Mac</name>
++      <fsummary>Calculates the Cipher-based Message Authentication Code.</fsummary>
++      <type>
++        <v>Type = block_cipher()</v>
++        <v>Key = iodata()</v>
++        <v>Data = iodata()</v>
++        <v>MacLength = integer()</v>
++        <v>Mac = binary()</v>
++      </type>
++      <desc>
++        <p>Computes a CMAC of type <c>Type</c> from <c>Data</c> using
++        <c>Key</c> as the authentication key.</p> <p><c>MacLength</c>
++        will limit the size of the resultant <c>Mac</c>.</p>
++      </desc>
++    </func>
++
+     <func>
+       <name>info_lib() -> [{Name,VerNum,VerStr}]</name>
+       <fsummary>Provides information about the libraries used by crypto.</fsummary>
+diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
+index 025d57e9c5..ba824eb9cd 100644
+--- a/lib/crypto/src/crypto.erl
++++ b/lib/crypto/src/crypto.erl
+@@ -27,6 +27,7 @@
+ -export([sign/4, verify/5]).
+ -export([generate_key/2, generate_key/3, compute_key/4]).
+ -export([hmac/3, hmac/4, hmac_init/2, hmac_update/2, hmac_final/1, hmac_final_n/2]).
++-export([cmac/3, cmac/4]).
+ -export([exor/2, strong_rand_bytes/1, mod_pow/3]).
+ -export([rand_uniform/2]).
+ -export([block_encrypt/3, block_decrypt/3, block_encrypt/4, block_decrypt/4]).
+@@ -271,6 +272,14 @@ hmac_final(Context) ->
+ hmac_final_n(Context, HashLen) ->
+     notsup_to_error(hmac_final_nif(Context, HashLen)).
+ 
++-spec cmac(_, iodata(), iodata()) -> binary().
++-spec cmac(_, iodata(), iodata(), integer()) -> binary().
++
++cmac(Type, Key, Data) ->
++    notsup_to_error(cmac_nif(Type, Key, Data)).
++cmac(Type, Key, Data, MacSize) ->
++    erlang:binary_part(cmac(Type, Key, Data), 0, MacSize).
++
+ %% Ecrypt/decrypt %%%
+ 
+ -spec block_encrypt(des_cbc | des_cfb |
+@@ -782,6 +791,10 @@ hmac_update_nif(_Context, _Data) -> ?nif_stub.
+ hmac_final_nif(_Context) -> ?nif_stub.
+ hmac_final_nif(_Context, _MacSize) -> ?nif_stub.
+ 
++%% CMAC
++
++cmac_nif(_Type, _Key, _Data) -> ?nif_stub.
++
+ %%
+ %%  MD5_MAC
+ %%
+@@ -1460,6 +1473,7 @@ mod_exp_nif(_Base,_Exp,_Mod,_bin_hdr) -> ?nif_stub.
+ 
+ -define(FUNC_LIST, [hash, hash_init, hash_update, hash_final,
+ 		    hmac, hmac_init, hmac_update, hmac_final, hmac_final_n,
++		    cmac,
+ 		    %% deprecated
+ 		    md4, md4_init, md4_update, md4_final,
+ 		    md5, md5_init, md5_update, md5_final,
+diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
+index 6732f27824..90514821a8 100644
+--- a/lib/crypto/test/crypto_SUITE.erl
++++ b/lib/crypto/test/crypto_SUITE.erl
+@@ -95,10 +95,10 @@ groups() ->
+      {des_ede3,[], [block]},
+      {des3_cbf,[], [block]},
+      {rc2_cbc,[], [block]},
+-     {aes_cbc128,[], [block]},
++     {aes_cbc128,[], [block, cmac]},
+      {aes_cfb8,[], [block]},
+      {aes_cfb128,[], [block]},
+-     {aes_cbc256,[], [block]},
++     {aes_cbc256,[], [block, cmac]},
+      {aes_ecb,[], [block]},
+      {aes_ige256,[], [block]},
+      {blowfish_cbc, [], [block]},
+@@ -194,6 +194,13 @@ hmac(Config) when is_list(Config) ->
+     hmac(Type, lists:map(fun iolistify/1, Keys), lists:map(fun iolistify/1, Data), Expected),
+     hmac_increment(Type).
+ %%--------------------------------------------------------------------
++cmac() ->
++     [{doc, "Test all different cmac functions"}].
++cmac(Config) when is_list(Config) ->
++    Pairs = proplists:get_value(cmac, Config),
++    lists:foreach(fun cmac_check/1, Pairs),
++    lists:foreach(fun cmac_check/1, cmac_iolistify(Pairs)).
++%%--------------------------------------------------------------------
+ block() ->
+      [{doc, "Test block ciphers"}].
+ block(Config) when is_list(Config) ->
+@@ -346,6 +353,23 @@ hmac_increment(State0, [Increment | Rest]) ->
+     State = crypto:hmac_update(State0, Increment),
+     hmac_increment(State, Rest).
+ 
++cmac_check({Type, Key, Text, CMac}) ->
++    ExpCMac = iolist_to_binary(CMac),
++    case crypto:cmac(Type, Key, Text) of
++        ExpCMac ->
++            ok;
++        Other ->
++            ct:fail({{crypto, cmac, [Type, Key, Text]}, {expected, ExpCMac}, {got, Other}})
++    end;
++cmac_check({Type, Key, Text, Size, CMac}) ->
++    ExpCMac = iolist_to_binary(CMac),
++    case crypto:cmac(Type, Key, Text, Size) of
++        ExpCMac ->
++            ok;
++        Other ->
++            ct:fail({{crypto, cmac, [Type, Key, Text, Size]}, {expected, ExpCMac}, {got, Other}})
++    end.
++
+ block_cipher({Type, Key,  PlainText}) ->
+     Plain = iolist_to_binary(PlainText),
+     CipherText = crypto:block_encrypt(Type, Key, PlainText),
+@@ -566,11 +590,18 @@ mkint(C) when $a =< C, C =< $f ->
+ is_supported(Group) ->
+     lists:member(Group, lists:append([Algo ||  {_, Algo}  <- crypto:supports()])). 
+ 
++cmac_iolistify(Blocks) ->
++    lists:map(fun do_cmac_iolistify/1, Blocks).
+ block_iolistify(Blocks) ->
+     lists:map(fun do_block_iolistify/1, Blocks).
+ stream_iolistify(Streams) ->
+     lists:map(fun do_stream_iolistify/1, Streams).
+ 
++do_cmac_iolistify({Type, Key, Text, CMac}) ->
++    {Type, iolistify(Key), iolistify(Text), CMac};
++do_cmac_iolistify({Type, Key, Text, Size, CMac}) ->
++    {Type, iolistify(Key), iolistify(Text), Size, CMac}.
++
+ do_stream_iolistify({Type, Key, PlainText}) ->
+     {Type, iolistify(Key), iolistify(PlainText)};
+ do_stream_iolistify({Type, Key, IV, PlainText}) ->
+@@ -798,12 +829,14 @@ group_config(des_ede3, Config) ->
+ group_config(rc2_cbc, Config) ->
+     Block = rc2_cbc(),
+     [{block, Block} | Config];
+-group_config(aes_cbc128, Config) ->
++group_config(aes_cbc128 = Type, Config) ->
+     Block = aes_cbc128(),
+-    [{block, Block} | Config];
+-group_config(aes_cbc256, Config) ->
++    Pairs = cmac_nist(Type),
++    [{block, Block}, {cmac, Pairs} | Config];
++group_config(aes_cbc256 = Type, Config) ->
+     Block = aes_cbc256(),
+-    [{block, Block} | Config];
++    Pairs = cmac_nist(Type),
++    [{block, Block}, {cmac, Pairs} | Config];
+ group_config(aes_ecb, Config) ->
+     Block = aes_ecb(),
+     [{block, Block} | Config];    
+@@ -2324,6 +2357,50 @@ ecc() ->
+                  end,
+                  TestCases).
+ 
++%% Test data from Appendix D of NIST Special Publication 800-38B
++%% http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf
++%% The same AES128 test data are also in the RFC 4493
++%% https://tools.ietf.org/html/rfc4493
++cmac_nist(aes_cbc128 = Type) ->
++    Key = hexstr2bin("2b7e151628aed2a6abf7158809cf4f3c"),
++    [{Type, Key, <<"">>,
++                 hexstr2bin("bb1d6929e95937287fa37d129b756746")},
++    {Type, Key, hexstr2bin("6bc1bee22e409f96e93d7e117393172a"),
++                hexstr2bin("070a16b46b4d4144f79bdd9dd04a287c")},
++    {Type, Key, hexstr2bin("6bc1bee22e409f96e93d7e117393172a"
++                           "ae2d8a571e03ac9c9eb76fac45af8e51"
++                           "30c81c46a35ce411"),
++                hexstr2bin("dfa66747de9ae63030ca32611497c827")},
++    {Type, Key, hexstr2bin("6bc1bee22e409f96e93d7e117393172a"
++                           "ae2d8a571e03ac9c9eb76fac45af8e51"
++                           "30c81c46a35ce411e5fbc1191a0a52ef"
++                           "f69f2445df4f9b17ad2b417be66c3710"),
++                hexstr2bin("51f0bebf7e3b9d92fc49741779363cfe")},
++    % truncation
++    {Type, Key, <<"">>, 4,
++                 hexstr2bin("bb1d6929")}];
++
++cmac_nist(aes_cbc256 = Type) ->
++    Key = hexstr2bin("603deb1015ca71be2b73aef0857d7781"
++                     "1f352c073b6108d72d9810a30914dff4"),
++    [{Type, Key, <<"">>,
++                 hexstr2bin("028962f61b7bf89efc6b551f4667d983")},
++    {Type, Key, hexstr2bin("6bc1bee22e409f96e93d7e117393172a"),
++                hexstr2bin("28a7023f452e8f82bd4bf28d8c37c35c")},
++    {Type, Key, hexstr2bin("6bc1bee22e409f96e93d7e117393172a"
++                           "ae2d8a571e03ac9c9eb76fac45af8e51"
++                           "30c81c46a35ce411"),
++                hexstr2bin("aaf3d8f1de5640c232f5b169b9c911e6")},
++    {Type, Key, hexstr2bin("6bc1bee22e409f96e93d7e117393172a"
++                           "ae2d8a571e03ac9c9eb76fac45af8e51"
++                           "30c81c46a35ce411e5fbc1191a0a52ef"
++                           "f69f2445df4f9b17ad2b417be66c3710"),
++                hexstr2bin("e1992190549f6ed5696a2c056c315410")},
++    % truncation
++    {Type, Key, <<"">>, 4,
++                 hexstr2bin("028962f6")}].
++
++
+ no_padding() ->
+     Public = [_, Mod] = rsa_public(),
+     Private = rsa_private(),
diff --git a/openssl.patch b/openssl.patch
new file mode 100644
index 0000000..9c3ac0f
--- /dev/null
+++ b/openssl.patch
@@ -0,0 +1,1062 @@
+--- a/lib/crypto/c_src/crypto_callback.c
++++ b/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);
+ }
+--- a/lib/crypto/c_src/crypto_callback.h
++++ b/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
+--- a/lib/crypto/c_src/crypto.c
++++ b/lib/crypto/c_src/crypto.c
+@@ -64,57 +64,57 @@
+ /* 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
+ # define HAVE_CMAC
+-# 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
+@@ -123,7 +123,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
+ 
+@@ -157,6 +157,7 @@
+ 
+ #endif
+ 
++
+ #ifdef VALGRIND
+     #  include <valgrind/memcheck.h>
+ 
+@@ -225,6 +226,122 @@
+     }                                                   \
+  } 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 +516,7 @@
+ {
+     ErlNifMutex* mtx;
+     int alive;
+-    HMAC_CTX ctx;
++    HMAC_CTX* ctx;
+ };
+ static void hmac_context_dtor(ErlNifEnv* env, struct hmac_context*);
+ 
+@@ -526,18 +643,24 @@
+ #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 +748,7 @@
+ 	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 +1060,12 @@
+     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 +1076,9 @@
+ 	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 +1088,7 @@
+ }
+ 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 +1097,10 @@
+         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 +1112,8 @@
+ }
+ 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 +1121,19 @@
+         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 +1417,7 @@
+ 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 +1442,16 @@
+     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 +1473,7 @@
+ 	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 +1500,8 @@
+ 	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);
+ 
+@@ -1437,7 +1567,7 @@
+     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;
+@@ -1478,30 +1608,30 @@
+ 
+     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;
+@@ -1578,7 +1708,7 @@
+ 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;
+ 
+@@ -1596,18 +1726,18 @@
+     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;
+@@ -1617,11 +1747,11 @@
+         || !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);
+@@ -1692,7 +1822,7 @@
+ 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;
+@@ -1716,40 +1846,40 @@
+     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
+@@ -1762,7 +1892,7 @@
+ #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;
+@@ -1785,34 +1915,34 @@
+     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);
+@@ -2134,13 +2264,10 @@
+     }
+ 
+     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;
+ }
+@@ -2197,13 +2324,15 @@
+     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) {
+@@ -2220,16 +2349,18 @@
+         || 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);
+ 
+@@ -2319,34 +2450,44 @@
+ {
+     /* 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;
+@@ -2379,7 +2520,7 @@
+     }
+ 
+ 
+-#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);
+@@ -2426,6 +2567,8 @@
+     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
+@@ -2434,26 +2577,37 @@
+ 	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);
+@@ -2490,20 +2644,22 @@
+     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); 
+ 
+@@ -2584,6 +2740,7 @@
+     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)) {
+@@ -2594,15 +2751,16 @@
+     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);    
+ }
+ 
+@@ -2611,18 +2769,19 @@
+     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;
+@@ -2645,26 +2804,32 @@
+     unsigned char *pub_ptr, *prv_ptr;
+     ERL_NIF_TERM ret, ret_pub, ret_prv, head, tail;
+     int mpint; /* 0 or 4 */
++    BIGNUM *priv_key = NULL;
++    BIGNUM *dh_p = NULL, *dh_g = NULL;
+     unsigned long len = 0;
+ 
+-    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);
+     }
+ 
++    dh_params = DH_new();
++    DH_set0_key(dh_params, NULL, priv_key);
++    DH_set0_pqg(dh_params, dh_p, NULL, dh_g);
++
+     if (len) {
+-        if (len < BN_num_bits(dh_params->p))
+-            dh_params->length = len;
++        if (len < BN_num_bits(dh_p))
++            DH_set_length(dh_params, len);
+         else {
+             DH_free(dh_params);
+             return enif_make_badarg(env);
+@@ -2672,16 +2837,18 @@
+     }
+ 
+     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);
+@@ -2696,26 +2863,37 @@
+ 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); 
+@@ -2727,7 +2905,7 @@
+ 	    ret = atom_error;
+ 	}
+     }
+-    if (pubkey) BN_free(pubkey);
++    if (other_pub_key) BN_free(other_pub_key);
+     DH_free(dh_params);
+     return ret;
+ }
+@@ -3299,7 +3477,7 @@
+ 
+     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);
+@@ -3349,7 +3527,7 @@
+ 	|| !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);
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/erlang.git/commitdiff/f76ab4f99deb6e0bc945ce9d765710a3979019a9



More information about the pld-cvs-commit mailing list