aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Nilsson <[email protected]>2019-03-22 10:31:29 +0100
committerHans Nilsson <[email protected]>2019-03-22 10:31:29 +0100
commitefe5385cd8b5c5477a840557b90da6f44256f83e (patch)
treeb1e113dc27755d64e38f3f40c32bf66a2770b98d
parent7ddbc128e6eabe662a15e37f85045284ad9f27c8 (diff)
parentea884fc1297a675ccbb08420bf1eae9f1faa94a2 (diff)
downloadotp-efe5385cd8b5c5477a840557b90da6f44256f83e.tar.gz
otp-efe5385cd8b5c5477a840557b90da6f44256f83e.tar.bz2
otp-efe5385cd8b5c5477a840557b90da6f44256f83e.zip
Merge branch 'hans/crypto/aead_error_handling'
* hans/crypto/aead_error_handling: crypto: New error schema in aead.c crypto: Move new error macros to common.h crypto: Use key length in alias/2
-rw-r--r--lib/crypto/c_src/aead.c109
-rw-r--r--lib/crypto/c_src/api_ng.c12
-rw-r--r--lib/crypto/c_src/common.h11
-rw-r--r--lib/crypto/src/crypto.erl132
4 files changed, 148 insertions, 116 deletions
diff --git a/lib/crypto/c_src/aead.c b/lib/crypto/c_src/aead.c
index 3ee04f1be9..4ed16615a5 100644
--- a/lib/crypto/c_src/aead.c
+++ b/lib/crypto/c_src/aead.c
@@ -39,87 +39,79 @@ ERL_NIF_TERM aead_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
ASSERT(argc == 6);
if (!enif_is_atom(env, type))
- goto bad_arg;
+ {ret = EXCP_BADARG(env, "non-atom cipher type"); goto done;}
if (!enif_inspect_iolist_as_binary(env, argv[1], &key))
- goto bad_arg;
+ {ret = EXCP_BADARG(env, "non-binary key"); goto done;}
if (!enif_inspect_binary(env, argv[2], &iv))
- goto bad_arg;
+ {ret = EXCP_BADARG(env, "non-binary iv"); goto done;}
if (!enif_inspect_iolist_as_binary(env, argv[3], &aad))
- goto bad_arg;
+ {ret = EXCP_BADARG(env, "non-binary AAD"); goto done;}
if (!enif_inspect_iolist_as_binary(env, argv[4], &in))
- goto bad_arg;
+ {ret = EXCP_BADARG(env, "non-binary text"); goto done;}
if (!enif_get_uint(env, argv[5], &tag_len))
- goto bad_arg;
+ {ret = EXCP_BADARG(env, ""); goto done;}
if (tag_len > INT_MAX
|| iv.size > INT_MAX
|| in.size > INT_MAX
|| aad.size > INT_MAX)
- goto bad_arg;
+ {ret = EXCP_BADARG(env, "binary too long"); goto done;}
if ((cipherp = get_cipher_type(type, key.size)) == NULL)
- goto bad_arg;
+ {ret = EXCP_BADARG(env, "Unknown cipher"); goto done;}
if (cipherp->flags & NON_EVP_CIPHER)
- goto bad_arg;
+ {ret = EXCP_BADARG(env, "Bad cipher"); goto done;}
if (! (cipherp->flags & AEAD_CIPHER) )
- goto bad_arg;
+ {ret = EXCP_BADARG(env, "Not aead cipher"); goto done;}
if ((cipher = cipherp->cipher.p) == NULL)
- return enif_raise_exception(env, atom_notsup);
+ {ret = EXCP_NOTSUP(env, "Cipher not supported in this libcrypto version"); goto done;}
ctx_ctrl_set_ivlen = cipherp->extra.aead.ctx_ctrl_set_ivlen;
ctx_ctrl_get_tag = cipherp->extra.aead.ctx_ctrl_get_tag;
ctx_ctrl_set_tag = cipherp->extra.aead.ctx_ctrl_set_tag;
if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
- goto err;
+ {ret = EXCP_ERROR(env, ""); goto done;}
if (EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1)
- goto err;
+ {ret = EXCP_ERROR(env, ""); goto done;}
if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_set_ivlen, (int)iv.size, NULL) != 1)
- goto err;
+ {ret = EXCP_ERROR(env, ""); goto done;}
#if defined(HAVE_CCM)
if (type == atom_aes_ccm) {
if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_set_tag, (int)tag_len, NULL) != 1)
- goto err;
+ {ret = EXCP_ERROR(env, ""); goto done;}
if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1)
- goto err;
+ {ret = EXCP_ERROR(env, ""); goto done;}
if (EVP_EncryptUpdate(ctx, NULL, &len, NULL, (int)in.size) != 1)
- goto err;
+ {ret = EXCP_ERROR(env, ""); goto done;}
} else
#endif
{
if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1)
- goto err;
+ {ret = EXCP_ERROR(env, ""); goto done;}
}
if (EVP_EncryptUpdate(ctx, NULL, &len, aad.data, (int)aad.size) != 1)
- goto err;
+ {ret = EXCP_ERROR(env, ""); goto done;}
if ((outp = enif_make_new_binary(env, in.size, &out)) == NULL)
- goto err;
+ {ret = EXCP_ERROR(env, ""); goto done;}
if (EVP_EncryptUpdate(ctx, outp, &len, in.data, (int)in.size) != 1)
- goto err;
+ {ret = EXCP_ERROR(env, ""); goto done;}
if (EVP_EncryptFinal_ex(ctx, outp/*+len*/, &len) != 1)
- goto err;
+ {ret = EXCP_ERROR(env, ""); goto done;}
if ((tagp = enif_make_new_binary(env, tag_len, &out_tag)) == NULL)
- goto err;
+ {ret = EXCP_ERROR(env, ""); goto done;}
if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_get_tag, (int)tag_len, tagp) != 1)
- goto err;
+ {ret = EXCP_ERROR(env, ""); goto done;}
CONSUME_REDS(env, in);
ret = enif_make_tuple2(env, out, out_tag);
- goto done;
-
- bad_arg:
- ret = enif_make_badarg(env);
- goto done;
-
- err:
- ret = atom_error;
done:
if (ctx)
@@ -127,7 +119,7 @@ ERL_NIF_TERM aead_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
return ret;
#else
- return enif_raise_exception(env, atom_notsup);
+ return EXCP_NOTSUP(env, "");
#endif
}
@@ -151,72 +143,72 @@ ERL_NIF_TERM aead_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
#endif
if (!enif_is_atom(env, type))
- goto bad_arg;
+ {ret = EXCP_BADARG(env, "non-atom cipher type"); goto done;}
if (!enif_inspect_iolist_as_binary(env, argv[1], &key))
- goto bad_arg;
+ {ret = EXCP_BADARG(env, "non-binary key"); goto done;}
if (!enif_inspect_binary(env, argv[2], &iv))
- goto bad_arg;
+ {ret = EXCP_BADARG(env, "non-binary iv"); goto done;}
if (!enif_inspect_iolist_as_binary(env, argv[3], &aad))
- goto bad_arg;
+ {ret = EXCP_BADARG(env, "non-binary AAD"); goto done;}
if (!enif_inspect_iolist_as_binary(env, argv[4], &in))
- goto bad_arg;
+ {ret = EXCP_BADARG(env, ""); goto done;}
if (!enif_inspect_iolist_as_binary(env, argv[5], &tag))
- goto bad_arg;
+ {ret = EXCP_BADARG(env, "non-binary text"); goto done;}
if (tag.size > INT_MAX
|| key.size > INT_MAX
|| iv.size > INT_MAX
|| in.size > INT_MAX
|| aad.size > INT_MAX)
- goto bad_arg;
+ {ret = EXCP_BADARG(env, "binary too long"); goto done;}
if ((cipherp = get_cipher_type(type, key.size)) == NULL)
- goto bad_arg;
+ {ret = EXCP_BADARG(env, "Unknown cipher"); goto done;}
if (cipherp->flags & NON_EVP_CIPHER)
- goto bad_arg;
+ {ret = EXCP_BADARG(env, "Bad cipher"); goto done;}
if ( !(cipherp->flags & AEAD_CIPHER) )
- goto bad_arg;
+ {ret = EXCP_BADARG(env, "Not aead cipher"); goto done;}
if ((cipher = cipherp->cipher.p) == NULL)
- return enif_raise_exception(env, atom_notsup);
+ {ret = EXCP_NOTSUP(env, "Cipher not supported in this libcrypto version"); goto done;}
ctx_ctrl_set_ivlen = cipherp->extra.aead.ctx_ctrl_set_ivlen;
ctx_ctrl_set_tag = cipherp->extra.aead.ctx_ctrl_set_tag;
if ((outp = enif_make_new_binary(env, in.size, &out)) == NULL)
- goto err;
+ {ret = EXCP_ERROR(env, ""); goto done;}
if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
- goto err;
+ {ret = EXCP_ERROR(env, ""); goto done;}
if (EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1)
- goto err;
+ {ret = EXCP_ERROR(env, ""); goto done;}
if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_set_ivlen, (int)iv.size, NULL) != 1)
- goto err;
+ {ret = EXCP_ERROR(env, ""); goto done;}
#if defined(HAVE_CCM)
if (type == atom_aes_ccm) {
if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_set_tag, (int)tag.size, tag.data) != 1)
- goto err;
+ {ret = EXCP_ERROR(env, ""); goto done;}
if (EVP_DecryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1)
- goto err;
+ {ret = EXCP_ERROR(env, ""); goto done;}
if (EVP_DecryptUpdate(ctx, NULL, &len, NULL, (int)in.size) != 1)
- goto err;
+ {ret = EXCP_ERROR(env, ""); goto done;}
}
else
#endif
{
if (EVP_DecryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1)
- goto err;
+ {ret = EXCP_ERROR(env, ""); goto done;}
}
if (EVP_DecryptUpdate(ctx, NULL, &len, aad.data, (int)aad.size) != 1)
- goto err;
+ {ret = EXCP_ERROR(env, ""); goto done;}
if (EVP_DecryptUpdate(ctx, outp, &len, in.data, (int)in.size) != 1)
- goto err;
+ {ret = EXCP_ERROR(env, ""); goto done;}
#if defined(HAVE_GCM)
if (type == atom_aes_gcm) {
if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_set_tag, (int)tag.size, tag.data) != 1)
- goto err;
+ goto err;
if (EVP_DecryptFinal_ex(ctx, outp+len, &len) != 1)
goto err;
}
@@ -225,11 +217,8 @@ ERL_NIF_TERM aead_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
ret = out;
goto done;
- bad_arg:
- ret = enif_make_badarg(env);
- goto done;
-
err:
+ /* Decrypt failed, that is, wrong tag */
ret = atom_error;
done:
@@ -238,6 +227,6 @@ ERL_NIF_TERM aead_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
return ret;
#else
- return enif_raise_exception(env, atom_notsup);
+ return EXCP_NOTSUP(env, "");
#endif
}
diff --git a/lib/crypto/c_src/api_ng.c b/lib/crypto/c_src/api_ng.c
index f4312114ed..5d063c3ae4 100644
--- a/lib/crypto/c_src/api_ng.c
+++ b/lib/crypto/c_src/api_ng.c
@@ -29,18 +29,6 @@
ERL_NIF_TERM ng_crypto_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
ERL_NIF_TERM ng_crypto_one_shot(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-
-
-/* All nif functions return a valid value or throws an exception */
-#define EXCP(Env, Class, Str) enif_raise_exception((Env), \
- enif_make_tuple2((Env), (Class), \
- enif_make_string((Env),(Str),(ERL_NIF_LATIN1)) ))
-
-#define EXCP_NOTSUP(Env, Str) EXCP((Env), atom_notsup, (Str))
-#define EXCP_BADARG(Env, Str) EXCP((Env), atom_badarg, (Str))
-#define EXCP_ERROR(Env, Str) EXCP((Env), atom_error, (Str))
-
-
#ifdef HAVE_ECB_IVEC_BUG
/* <= 0.9.8l returns faulty ivec length */
# define GET_IV_LEN(Ciph) ((Ciph)->flags & ECB_BUG_0_9_8L) ? 0 : EVP_CIPHER_iv_length((Ciph)->cipher.p)
diff --git a/lib/crypto/c_src/common.h b/lib/crypto/c_src/common.h
index 2bc8bdd73c..0bf7f09f4f 100644
--- a/lib/crypto/c_src/common.h
+++ b/lib/crypto/c_src/common.h
@@ -35,4 +35,15 @@
#include "openssl_config.h"
#include "atoms.h"
+
+/* All nif functions return a valid value or throws an exception */
+#define EXCP(Env, Id, Str) enif_raise_exception((Env), \
+ enif_make_tuple2((Env), \
+ (Id), \
+ enif_make_string((Env),(Str),(ERL_NIF_LATIN1)) ))
+
+#define EXCP_NOTSUP(Env, Str) EXCP((Env), atom_notsup, (Str))
+#define EXCP_BADARG(Env, Str) EXCP((Env), atom_badarg, (Str))
+#define EXCP_ERROR(Env, Str) EXCP((Env), atom_error, (Str))
+
#endif /* E_COMMON_H__ */
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index a5e60fbe75..fd13481951 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -562,8 +562,10 @@ poly1305(Key, Data) ->
%%%================================================================
-define(COMPAT(CALL),
- try CALL
+ try begin CALL end
catch
+ error:{error,_} ->
+ error(badarg);
error:{E,_Reason} when E==notsup ; E==badarg ->
error(E)
end).
@@ -617,33 +619,38 @@ cipher_info(Type) ->
{binary(), binary()} | run_time_error().
-block_encrypt(Type, Key, Ivec, Data) ->
- do_block_encrypt(alias(Type), Key, Ivec, Data).
-
-do_block_encrypt(Type, Key, Ivec, PlainText) when Type =:= aes_ige256 ->
+block_encrypt(aes_ige256, Key, Ivec, PlainText) ->
notsup_to_error(aes_ige_crypt_nif(Key, Ivec, PlainText, true));
-do_block_encrypt(Type, Key, Ivec, {AAD, PlainText}) when Type =:= chacha20_poly1305 ->
- aead_encrypt(Type, Key, Ivec, AAD, PlainText, 16);
-
-do_block_encrypt(Type, Key, Ivec, Data) when Type =:= aes_gcm;
- Type =:= aes_ccm ->
- case Data of
- {AAD, PlainText} ->
- aead_encrypt(Type, Key, Ivec, AAD, PlainText);
- {AAD, PlainText, TagLength} ->
- aead_encrypt(Type, Key, Ivec, AAD, PlainText, TagLength)
- end;
-
-do_block_encrypt(Type, Key, Ivec, PlainText) ->
- ?COMPAT(crypto_one_shot(Type, Key, Ivec, PlainText, true)).
-
+block_encrypt(Type, Key0, Ivec, Data) ->
+ Key = iolist_to_binary(Key0),
+ ?COMPAT(
+ case Data of
+ {AAD, PlainText} ->
+ aead_encrypt(alias(Type,Key), Key, Ivec, AAD, PlainText, aead_tag_len(Type));
+ {AAD, PlainText, TagLength} ->
+ aead_encrypt(alias(Type,Key), Key, Ivec, AAD, PlainText, TagLength);
+ PlainText ->
+ crypto_one_shot(alias(Type,Key), Key, Ivec, PlainText, true)
+ end).
-spec block_encrypt(Type::block_cipher_no_iv(), Key::key(), PlainText::iodata()) ->
binary() | run_time_error().
-block_encrypt(Type, Key, PlainText) ->
- ?COMPAT(crypto_one_shot(Type, Key, <<>>, PlainText, true)).
+block_encrypt(Type, Key0, PlainText) ->
+ Key = iolist_to_binary(Key0),
+ ?COMPAT(crypto_one_shot(alias(Type,Key), Key, <<>>, PlainText, true)).
+
+
+aead_tag_len(chacha20_poly1305) -> 16;
+aead_tag_len(aes_ccm) -> 12;
+aead_tag_len(aes_128_ccm) -> 12;
+aead_tag_len(aes_192_ccm) -> 12;
+aead_tag_len(aes_256_ccm) -> 12;
+aead_tag_len(aes_gcm) -> 16;
+aead_tag_len(aes_128_gcm) -> 16;
+aead_tag_len(aes_192_gcm) -> 16;
+aead_tag_len(aes_256_gcm) -> 16.
%%%----------------------------------------------------------------
%%%----------------------------------------------------------------
@@ -653,26 +660,26 @@ block_encrypt(Type, Key, PlainText) ->
{AAD::binary(), Data::iodata(), Tag::binary()}) ->
binary() | error | run_time_error() .
-block_decrypt(Type, Key, Ivec, Data) ->
- do_block_decrypt(alias(Type), Key, Ivec, Data).
-
-do_block_decrypt(aes_ige256, Key, Ivec, Data) ->
+block_decrypt(aes_ige256, Key, Ivec, Data) ->
notsup_to_error(aes_ige_crypt_nif(Key, Ivec, Data, false));
-do_block_decrypt(Type, Key, Ivec, {AAD, Data, Tag}) when Type =:= aes_gcm;
- Type =:= aes_ccm;
- Type =:= chacha20_poly1305 ->
- aead_decrypt(Type, Key, Ivec, AAD, Data, Tag);
-
-do_block_decrypt(Type, Key, Ivec, Data) ->
- ?COMPAT(crypto_one_shot(Type, Key, Ivec, Data, false)).
+block_decrypt(Type, Key0, Ivec, Data) ->
+ Key = iolist_to_binary(Key0),
+ ?COMPAT(
+ case Data of
+ {AAD, CryptoText, Tag} ->
+ aead_decrypt(alias(Type,Key), Key, Ivec, AAD, CryptoText, Tag);
+ CryptoText ->
+ crypto_one_shot(alias(Type,Key), Key, Ivec, CryptoText, false)
+ end).
-spec block_decrypt(Type::block_cipher_no_iv(), Key::key(), Data::iodata()) ->
binary() | run_time_error().
-block_decrypt(Type, Key, Data) ->
- ?COMPAT(crypto_one_shot(Type, Key, <<>>, Data, false)).
+block_decrypt(Type, Key0, CryptoText) ->
+ Key = iolist_to_binary(Key0),
+ ?COMPAT(crypto_one_shot(alias(Type,Key), Key, <<>>, CryptoText, false)).
%%%-------- Stream ciphers API
@@ -694,9 +701,10 @@ block_decrypt(Type, Key, Data) ->
Key :: iodata(),
IVec ::binary(),
State :: stream_state() .
-stream_init(Type, Key, IVec) when is_binary(IVec) ->
- Ref = ?COMPAT(ng_crypto_init_nif(alias(Type),
- iolist_to_binary(Key), iolist_to_binary(IVec),
+stream_init(Type, Key0, IVec) when is_binary(IVec) ->
+ Key = iolist_to_binary(Key0),
+ Ref = ?COMPAT(ng_crypto_init_nif(alias(Type,Key),
+ Key, iolist_to_binary(IVec),
undefined)
),
{Type, {Ref,flg_undefined}}.
@@ -706,9 +714,10 @@ stream_init(Type, Key, IVec) when is_binary(IVec) ->
when Type :: stream_cipher_no_iv(),
Key :: iodata(),
State :: stream_state() .
-stream_init(rc4 = Type, Key) ->
- Ref = ?COMPAT(ng_crypto_init_nif(alias(Type),
- iolist_to_binary(Key), <<>>,
+stream_init(rc4 = Type, Key0) ->
+ Key = iolist_to_binary(Key0),
+ Ref = ?COMPAT(ng_crypto_init_nif(alias(Type,Key),
+ Key, <<>>,
undefined)
),
{Type, {Ref,flg_undefined}}.
@@ -923,6 +932,44 @@ alias(aes_cbc256) -> aes_256_cbc;
alias(Alg) -> Alg.
+
+%%%---- des_ede3_cbc
+alias(des3_cbc, _) -> des_ede3_cbc;
+alias(des_ede3, _) -> des_ede3_cbc;
+%%%---- des_ede3_cfb
+alias(des_ede3_cbf,_ ) -> des_ede3_cfb;
+alias(des3_cbf, _) -> des_ede3_cfb;
+alias(des3_cfb, _) -> des_ede3_cfb;
+%%%---- aes_*_cbc
+alias(aes_cbc128, _) -> aes_128_cbc;
+alias(aes_cbc256, _) -> aes_256_cbc;
+
+alias(aes_cbc, Key) when size(Key)==128 -> aes_128_cbc;
+alias(aes_cbc, Key) when size(Key)==192 -> aes_192_cbc;
+alias(aes_cbc, Key) when size(Key)==256 -> aes_256_cbc;
+
+alias(aes_cfb8, Key) when size(Key)==128 -> aes_128_cfb8;
+alias(aes_cfb8, Key) when size(Key)==192 -> aes_192_cfb8;
+alias(aes_cfb8, Key) when size(Key)==256 -> aes_256_cfb8;
+
+alias(aes_cfb128, Key) when size(Key)==128 -> aes_128_cfb128;
+alias(aes_cfb128, Key) when size(Key)==192 -> aes_192_cfb128;
+alias(aes_cfb128, Key) when size(Key)==256 -> aes_256_cfb128;
+
+alias(aes_ctr, Key) when size(Key)==128 -> aes_128_ctr;
+alias(aes_ctr, Key) when size(Key)==192 -> aes_192_ctr;
+alias(aes_ctr, Key) when size(Key)==256 -> aes_256_ctr;
+
+alias(aes_gcm, Key) when size(Key)==128 -> aes_128_gcm;
+alias(aes_gcm, Key) when size(Key)==192 -> aes_192_gcm;
+alias(aes_gcm, Key) when size(Key)==256 -> aes_256_gcm;
+
+alias(aes_ccm, Key) when size(Key)==128 -> aes_128_ccm;
+alias(aes_ccm, Key) when size(Key)==192 -> aes_192_ccm;
+alias(aes_ccm, Key) when size(Key)==256 -> aes_256_ccm;
+
+alias(Alg, _) -> Alg.
+
%%%================================================================
%%%
%%% RAND - pseudo random numbers using RN_ and BN_ functions in crypto lib
@@ -2013,9 +2060,6 @@ cipher_info_nif(_Type) -> ?nif_stub.
%% AES - in Galois/Counter Mode (GCM)
%%
%% The default tag length is EVP_GCM_TLS_TAG_LEN(16),
-aead_encrypt(Type=aes_ccm, Key, Ivec, AAD, In) -> aead_encrypt(Type, Key, Ivec, AAD, In, 12);
-aead_encrypt(Type=aes_gcm, Key, Ivec, AAD, In) -> aead_encrypt(Type, Key, Ivec, AAD, In, 16).
-
aead_encrypt(_Type, _Key, _Ivec, _AAD, _In, _TagLength) -> ?nif_stub.
aead_decrypt(_Type, _Key, _Ivec, _AAD, _In, _Tag) -> ?nif_stub.