aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorHans Nilsson <[email protected]>2019-03-15 11:55:29 +0100
committerHans Nilsson <[email protected]>2019-03-19 12:45:56 +0100
commit4cf7703e671a522cafd86b6efc81b8b6775e0077 (patch)
tree170814b58d984e4bc4d0b0c7f044e31333cd7187 /lib
parent86cd8b95b704ac236d02f31a92545ca996816c2c (diff)
downloadotp-4cf7703e671a522cafd86b6efc81b8b6775e0077.tar.gz
otp-4cf7703e671a522cafd86b6efc81b8b6775e0077.tar.bz2
otp-4cf7703e671a522cafd86b6efc81b8b6775e0077.zip
crypto: Handle EVP_CIPHER_CTX copying correctly
Diffstat (limited to 'lib')
-rw-r--r--lib/crypto/c_src/api_ng.c65
-rw-r--r--lib/crypto/c_src/openssl_config.h1
2 files changed, 59 insertions, 7 deletions
diff --git a/lib/crypto/c_src/api_ng.c b/lib/crypto/c_src/api_ng.c
index f727b5e90f..6315a03ade 100644
--- a/lib/crypto/c_src/api_ng.c
+++ b/lib/crypto/c_src/api_ng.c
@@ -218,7 +218,7 @@ static int get_init_args(ErlNifEnv* env,
goto err;
}
}
- // enif_fprintf(stderr, "%s:%u %T %T %u\r\n", __FILE__, __LINE__, cipher_arg, ivec_arg, ivec_len);
+
if (ivec_arg == atom_undefined || ivec_len == 0)
{
if (!EVP_CipherInit_ex(ctx_res->ctx, NULL, NULL, key_bin.data, NULL, -1)) {
@@ -233,8 +233,6 @@ static int get_init_args(ErlNifEnv* env,
goto err;
}
- // enif_fprintf(stderr, "%s:%u\r\n", __FILE__, __LINE__);
-
EVP_CIPHER_CTX_set_padding(ctx_res->ctx, 0);
*return_term = atom_ok;
@@ -270,7 +268,6 @@ static int get_update_args(ErlNifEnv* env,
ASSERT(in_data_bin.size <= INT_MAX);
#if !defined(HAVE_EVP_AES_CTR)
- // enif_fprintf(stdout, "%s:%u state = %T\r\n", __FILE__, __LINE__, ctx_res->state);
if (ctx_res->state != atom_undefined) {
ERL_NIF_TERM state0, newstate_and_outdata;
const ERL_NIF_TERM *tuple_argv;
@@ -381,6 +378,48 @@ ERL_NIF_TERM ng_crypto_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
/* Encrypt/decrypt */
/*************************************************************************/
+#if !defined(HAVE_EVP_CIPHER_CTX_COPY)
+/*
+ The EVP_CIPHER_CTX_copy is not available in older cryptolibs although
+ the function is needed.
+ Instead of implement it in-place, we have a copy here as a compatibility
+ function
+*/
+
+int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in);
+
+int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in)
+{
+ if ((in == NULL) || (in->cipher == NULL))
+ {
+ return 0;
+ }
+#ifndef OPENSSL_NO_ENGINE
+ /* Make sure it's safe to copy a cipher context using an ENGINE */
+ if (in->engine && !ENGINE_init(in->engine))
+ return 0;
+#endif
+
+ EVP_CIPHER_CTX_cleanup(out);
+ memcpy(out,in,sizeof *out);
+
+ if (in->cipher_data && in->cipher->ctx_size)
+ {
+ out->cipher_data=OPENSSL_malloc(in->cipher->ctx_size);
+ if (!out->cipher_data)
+ return 0;
+ memcpy(out->cipher_data,in->cipher_data,in->cipher->ctx_size);
+ }
+
+#if defined(EVP_CIPH_CUSTOM_COPY) && defined(EVP_CTRL_COPY)
+ if (in->cipher->flags & EVP_CIPH_CUSTOM_COPY)
+ return in->cipher->ctrl((EVP_CIPHER_CTX *)in, EVP_CTRL_COPY, 0, out);
+#endif
+ return 1;
+}
+/****** End of compatibility function ******/
+#endif
+
ERL_NIF_TERM ng_crypto_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Context, Data [, IV]) */
@@ -393,7 +432,21 @@ ERL_NIF_TERM ng_crypto_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
if (argc == 3) {
struct evp_cipher_ctx ctx_res_copy;
ErlNifBinary ivec_bin;
- memcpy(&ctx_res_copy, ctx_res, sizeof(ctx_res_copy));
+
+ memcpy(&ctx_res_copy, ctx_res, sizeof ctx_res_copy);
+#if !defined(HAVE_EVP_AES_CTR)
+ if (ctx_res_copy.state == atom_undefined)
+ /* Not going to use aes_ctr compat functions */
+#endif
+ {
+ ctx_res_copy.ctx = EVP_CIPHER_CTX_new();
+
+ if (!EVP_CIPHER_CTX_copy(ctx_res_copy.ctx, ctx_res->ctx)) {
+ ret = EXCP_ERROR(env, "Can't copy ctx_res");
+ goto err;
+ }
+ }
+
ctx_res = &ctx_res_copy;
if (!enif_inspect_iolist_as_binary(env, argv[2], &ivec_bin))
@@ -405,12 +458,10 @@ ERL_NIF_TERM ng_crypto_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
if (ctx_res_copy.iv_len != ivec_bin.size)
{
ret = EXCP_BADARG(env, "Bad iv size");
- printf("Expect %d\r\n", ctx_res_copy.iv_len);
goto err;
}
#if !defined(HAVE_EVP_AES_CTR)
- // enif_fprintf(stdout, "%s:%u state = %T\r\n", __FILE__, __LINE__, ctx_res->state);
if ((ctx_res_copy.state != atom_undefined) ) {
/* replace the iv in state with argv[2] */
ERL_NIF_TERM state0;
diff --git a/lib/crypto/c_src/openssl_config.h b/lib/crypto/c_src/openssl_config.h
index 1c138e3bd1..46868cb987 100644
--- a/lib/crypto/c_src/openssl_config.h
+++ b/lib/crypto/c_src/openssl_config.h
@@ -109,6 +109,7 @@
#ifndef HAS_LIBRESSL
# if OPENSSL_VERSION_NUMBER >= PACKED_OPENSSL_VERSION_PLAIN(1,0,0)
# define HAS_EVP_PKEY_CTX
+# define HAVE_EVP_CIPHER_CTX_COPY
# endif
#endif