mirror of
https://git.freebsd.org/ports.git
synced 2025-06-09 23:00:30 -04:00
With some patching [1], Erlang 19.x supports OpenSSL 1.1.x (lang/erlang, lang/erlang-runtime19). However, previous versions are now marked as broken with OpenSSL 1.1.x. PR: 225898 Submitted by: brnrd [1] Obtained from: Upstream
1083 lines
37 KiB
Text
1083 lines
37 KiB
Text
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
|