aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2016-02-26 18:07:12 +0100
committerErlang/OTP <[email protected]>2016-02-26 18:07:12 +0100
commit8678df7411bd7633d1e71b523c96d8cfbb4d930e (patch)
treebc4203193aa14bb5c1e84d74636bf29e0dc4696c
parent0f6b72141b7e04699aae3394b2b29191c8acdec5 (diff)
parent8055ad8a5b6ce0c1e9c1c9c7eafccef179415bb3 (diff)
downloadotp-8678df7411bd7633d1e71b523c96d8cfbb4d930e.tar.gz
otp-8678df7411bd7633d1e71b523c96d8cfbb4d930e.tar.bz2
otp-8678df7411bd7633d1e71b523c96d8cfbb4d930e.zip
Merge branch 'sverk/r16/crypto-EVP-aes_cbc/OTP-13384' into maint-r16
* sverk/r16/crypto-EVP-aes_cbc/OTP-13384: crypto: Fix undefined symbol EVP_CIPHER_CTX_new crypto: use EVP for AES-CBC
-rw-r--r--lib/crypto/c_src/crypto.c54
1 files changed, 39 insertions, 15 deletions
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index 42fb172953..f9ded34670 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -2058,11 +2058,12 @@ done:
static ERL_NIF_TERM aes_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Key, IVec, Data, IsEncrypt) */
ErlNifBinary key_bin, ivec_bin, data_bin;
- AES_KEY aes_key;
unsigned char ivec[16];
- int i;
+ int enc, i = 0, outlen = 0;
+ EVP_CIPHER_CTX ctx;
+ const EVP_CIPHER *cipher = NULL;
unsigned char* ret_ptr;
- ERL_NIF_TERM ret;
+ ERL_NIF_TERM ret;
if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
|| (key_bin.size != 16 && key_bin.size != 32)
@@ -2074,20 +2075,43 @@ static ERL_NIF_TERM aes_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
return enif_make_badarg(env);
}
- if (argv[3] == atom_true) {
- i = AES_ENCRYPT;
- AES_set_encrypt_key(key_bin.data, key_bin.size*8, &aes_key);
- }
- else {
- i = AES_DECRYPT;
- AES_set_decrypt_key(key_bin.data, key_bin.size*8, &aes_key);
- }
+ if (argv[3] == atom_true)
+ enc = 1;
+ else
+ enc = 0;
+
+ EVP_CIPHER_CTX_init(&ctx);
+
+ if (key_bin.size == 16)
+ cipher = EVP_aes_128_cbc();
+ else if (key_bin.size == 32)
+ cipher = EVP_aes_256_cbc();
+
+ memcpy(ivec, ivec_bin.data, 16); /* writeable copy */
+
+ /* openssl docs say we need to leave at least 3 blocks available
+ at the end of the buffer for EVP calls. let's be safe */
+ ret_ptr = enif_make_new_binary(env, data_bin.size + 16*3, &ret);
+
+ if (EVP_CipherInit_ex(&ctx, cipher, NULL, key_bin.data, ivec, enc) != 1)
+ return enif_make_badarg(env);
+
+ /* disable padding, we only handle whole blocks */
+ EVP_CIPHER_CTX_set_padding(&ctx, 0);
+
+ if (EVP_CipherUpdate(&ctx, ret_ptr, &i, data_bin.data, data_bin.size) != 1)
+ return enif_make_badarg(env);
+ outlen += i;
+ if (EVP_CipherFinal_ex(&ctx, ret_ptr + outlen, &i) != 1)
+ return enif_make_badarg(env);
+ outlen += i;
+
+ EVP_CIPHER_CTX_cleanup(&ctx);
- ret_ptr = enif_make_new_binary(env, data_bin.size, &ret);
- memcpy(ivec, ivec_bin.data, 16); /* writable copy */
- AES_cbc_encrypt(data_bin.data, ret_ptr, data_bin.size, &aes_key, ivec, i);
CONSUME_REDS(env,data_bin);
- return ret;
+
+ /* the garbage collector is going to love this */
+ return enif_make_sub_binary(env, ret, 0, outlen);
}
static ERL_NIF_TERM do_exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])