aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/crypto/c_src/aead.c248
-rw-r--r--lib/crypto/c_src/aead.h3
-rw-r--r--lib/crypto/c_src/api_ng.c26
-rw-r--r--lib/crypto/c_src/api_ng.h2
-rw-r--r--lib/crypto/c_src/cipher.c40
-rw-r--r--lib/crypto/c_src/cipher.h2
-rw-r--r--lib/crypto/c_src/common.h5
-rw-r--r--lib/crypto/c_src/crypto.c5
-rw-r--r--lib/crypto/src/crypto.erl313
-rw-r--r--lib/crypto/test/crypto_SUITE.erl693
-rw-r--r--lib/ssh/src/ssh_transport.erl16
11 files changed, 812 insertions, 541 deletions
diff --git a/lib/crypto/c_src/aead.c b/lib/crypto/c_src/aead.c
index 4ed16615a5..ab0e609130 100644
--- a/lib/crypto/c_src/aead.c
+++ b/lib/crypto/c_src/aead.c
@@ -22,36 +22,65 @@
#include "aes.h"
#include "cipher.h"
-ERL_NIF_TERM aead_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Type,Key,Iv,AAD,In) */
+
+
+ERL_NIF_TERM aead_cipher(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/*
+ (Type,Key,Iv,AAD,In,TagLen,true)
+ (Type,Key,Iv,AAD,In,Tag,false)
+ */
#if defined(HAVE_AEAD)
const struct cipher_type_t *cipherp;
EVP_CIPHER_CTX *ctx = NULL;
const EVP_CIPHER *cipher = NULL;
- ErlNifBinary key, iv, aad, in;
+ ErlNifBinary key, iv, aad, in, tag;
unsigned int tag_len;
- unsigned char *outp, *tagp;
- ERL_NIF_TERM type, out, out_tag, ret;
- int len, ctx_ctrl_set_ivlen, ctx_ctrl_get_tag, ctx_ctrl_set_tag;
+ unsigned char *outp, *tagp, *tag_data;
+ ERL_NIF_TERM type, out, out_tag, ret, encflg_arg;
+ int len, encflg;
+
+ encflg_arg = argv[6];
+
+ /* Fetch the flag telling if we are going to encrypt (=true) or decrypt (=false) */
+ if (encflg_arg == atom_true)
+ encflg = 1;
+ else if (encflg_arg == atom_false)
+ encflg = 0;
+ else if (encflg_arg == atom_undefined)
+ /* For compat funcs in crypto.erl */
+ encflg = -1;
+ else
+ {
+ ret = EXCP_BADARG(env, "Bad enc flag");
+ goto done;
+ }
type = argv[0];
- ASSERT(argc == 6);
-
if (!enif_is_atom(env, type))
{ret = EXCP_BADARG(env, "non-atom cipher type"); goto done;}
if (!enif_inspect_iolist_as_binary(env, argv[1], &key))
{ret = EXCP_BADARG(env, "non-binary key"); goto done;}
- if (!enif_inspect_binary(env, argv[2], &iv))
+ if (!enif_inspect_iolist_as_binary(env, argv[2], &iv))
{ret = EXCP_BADARG(env, "non-binary iv"); goto done;}
- if (!enif_inspect_iolist_as_binary(env, argv[3], &aad))
- {ret = EXCP_BADARG(env, "non-binary AAD"); goto done;}
- if (!enif_inspect_iolist_as_binary(env, argv[4], &in))
+ if (!enif_inspect_iolist_as_binary(env, argv[3], &in))
{ret = EXCP_BADARG(env, "non-binary text"); goto done;}
- if (!enif_get_uint(env, argv[5], &tag_len))
- {ret = EXCP_BADARG(env, ""); goto done;}
+ if (!enif_inspect_iolist_as_binary(env, argv[4], &aad))
+ {ret = EXCP_BADARG(env, "non-binary AAD"); goto done;}
+
+ if (encflg) {
+ if (!enif_get_uint(env, argv[5], &tag_len))
+ {ret = EXCP_BADARG(env, "Bad Tag length"); goto done;}
+ tag_data = NULL;
+ } else {
+ if (!enif_inspect_iolist_as_binary(env, argv[5], &tag))
+ {ret = EXCP_BADARG(env, "non-binary Tag"); goto done;}
+ tag_len = tag.size;
+ tag_data = tag.data;
+ }
if (tag_len > INT_MAX
+ || key.size > INT_MAX
|| iv.size > INT_MAX
|| in.size > INT_MAX
|| aad.size > INT_MAX)
@@ -66,167 +95,88 @@ ERL_NIF_TERM aead_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
if ((cipher = cipherp->cipher.p) == NULL)
{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 defined(HAVE_GCM_EVP_DECRYPT_BUG)
+ if ( !encflg && (cipherp->flags & GCM_MODE))
+ return aes_gcm_decrypt_NO_EVP(env, argc, argv);
+#endif
+
if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
- {ret = EXCP_ERROR(env, ""); goto done;}
+ {ret = EXCP_ERROR(env, "Can't allocate ctx"); goto done;}
- if (EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1)
- {ret = EXCP_ERROR(env, ""); goto done;}
- if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_set_ivlen, (int)iv.size, NULL) != 1)
- {ret = EXCP_ERROR(env, ""); goto done;}
+ if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, encflg) != 1)
+ {ret = EXCP_ERROR(env, "CipherInit failed"); goto done;}
+ if (EVP_CIPHER_CTX_ctrl(ctx, cipherp->extra.aead.ctx_ctrl_set_ivlen, (int)iv.size, NULL) != 1)
+ {ret = EXCP_BADARG(env, "Bad IV length"); 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)
- {ret = EXCP_ERROR(env, ""); goto done;}
- if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1)
- {ret = EXCP_ERROR(env, ""); goto done;}
- if (EVP_EncryptUpdate(ctx, NULL, &len, NULL, (int)in.size) != 1)
- {ret = EXCP_ERROR(env, ""); goto done;}
+ if (cipherp->flags & CCM_MODE) {
+ if (EVP_CIPHER_CTX_ctrl(ctx, cipherp->extra.aead.ctx_ctrl_set_tag, (int)tag_len, tag_data) != 1)
+ {ret = EXCP_BADARG(env, "Can't set tag"); goto done;}
+ if (EVP_CipherInit_ex(ctx, NULL, NULL, key.data, iv.data, -1) != 1)
+ {ret = EXCP_BADARG(env, "Can't set key or iv"); goto done;}
+ if (EVP_CipherUpdate(ctx, NULL, &len, NULL, (int)in.size) != 1)
+ {ret = EXCP_BADARG(env, "Can't set text size"); goto done;}
} else
#endif
{
- if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1)
- {ret = EXCP_ERROR(env, ""); goto done;}
+ if (EVP_CipherInit_ex(ctx, NULL, NULL, key.data, iv.data, -1) != 1)
+ {ret = EXCP_BADARG(env, "Can't set key or iv"); goto done;}
}
- if (EVP_EncryptUpdate(ctx, NULL, &len, aad.data, (int)aad.size) != 1)
- {ret = EXCP_ERROR(env, ""); goto done;}
+ if (EVP_CipherUpdate(ctx, NULL, &len, aad.data, (int)aad.size) != 1)
+ {ret = EXCP_BADARG(env, "Can't set AAD"); goto done;}
if ((outp = enif_make_new_binary(env, in.size, &out)) == NULL)
- {ret = EXCP_ERROR(env, ""); goto done;}
-
- if (EVP_EncryptUpdate(ctx, outp, &len, in.data, (int)in.size) != 1)
- {ret = EXCP_ERROR(env, ""); goto done;}
- if (EVP_EncryptFinal_ex(ctx, outp/*+len*/, &len) != 1)
- {ret = EXCP_ERROR(env, ""); goto done;}
-
- if ((tagp = enif_make_new_binary(env, tag_len, &out_tag)) == NULL)
- {ret = EXCP_ERROR(env, ""); goto done;}
+ {ret = EXCP_ERROR(env, "Can't make 'Out' binary"); goto done;}
- if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_get_tag, (int)tag_len, tagp) != 1)
- {ret = EXCP_ERROR(env, ""); goto done;}
-
- CONSUME_REDS(env, in);
- ret = enif_make_tuple2(env, out, out_tag);
-
- done:
- if (ctx)
- EVP_CIPHER_CTX_free(ctx);
- return ret;
-
-#else
- return EXCP_NOTSUP(env, "");
-#endif
-}
-
-ERL_NIF_TERM aead_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
-{/* (Type,Key,Iv,AAD,In,Tag) */
-#if defined(HAVE_AEAD)
- const struct cipher_type_t *cipherp;
- EVP_CIPHER_CTX *ctx = NULL;
- const EVP_CIPHER *cipher = NULL;
- ErlNifBinary key, iv, aad, in, tag;
- unsigned char *outp;
- ERL_NIF_TERM type, out, ret;
- int len, ctx_ctrl_set_ivlen, ctx_ctrl_set_tag;
-
- ASSERT(argc == 6);
-
- type = argv[0];
-#if defined(HAVE_GCM_EVP_DECRYPT_BUG)
- if (type == atom_aes_gcm)
- return aes_gcm_decrypt_NO_EVP(env, argc, argv);
-#endif
-
- if (!enif_is_atom(env, type))
- {ret = EXCP_BADARG(env, "non-atom cipher type"); goto done;}
- if (!enif_inspect_iolist_as_binary(env, argv[1], &key))
- {ret = EXCP_BADARG(env, "non-binary key"); goto done;}
- if (!enif_inspect_binary(env, argv[2], &iv))
- {ret = EXCP_BADARG(env, "non-binary iv"); goto done;}
- if (!enif_inspect_iolist_as_binary(env, argv[3], &aad))
- {ret = EXCP_BADARG(env, "non-binary AAD"); goto done;}
- if (!enif_inspect_iolist_as_binary(env, argv[4], &in))
- {ret = EXCP_BADARG(env, ""); goto done;}
- if (!enif_inspect_iolist_as_binary(env, argv[5], &tag))
- {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)
- {ret = EXCP_BADARG(env, "binary too long"); goto done;}
-
- if ((cipherp = get_cipher_type(type, key.size)) == NULL)
- {ret = EXCP_BADARG(env, "Unknown cipher"); goto done;}
- if (cipherp->flags & NON_EVP_CIPHER)
- {ret = EXCP_BADARG(env, "Bad cipher"); goto done;}
- if ( !(cipherp->flags & AEAD_CIPHER) )
- {ret = EXCP_BADARG(env, "Not aead cipher"); goto done;}
- if ((cipher = cipherp->cipher.p) == NULL)
- {ret = EXCP_NOTSUP(env, "Cipher not supported in this libcrypto version"); goto done;}
+ if (EVP_CipherUpdate(ctx, outp, &len, in.data, (int)in.size) != 1)
+ {
+ if (encflg)
+ ret = EXCP_BADARG(env, "Can't set in-text");
+ else
+ /* Decrypt error */
+ ret = atom_error;
+ 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 (encflg)
+ {
+ if (EVP_CipherFinal_ex(ctx, outp/*+len*/, &len) != 1)
+ {ret = EXCP_ERROR(env, "Encrypt error"); goto done;}
- if ((outp = enif_make_new_binary(env, in.size, &out)) == NULL)
- {ret = EXCP_ERROR(env, ""); goto done;}
+ if ((tagp = enif_make_new_binary(env, tag_len, &out_tag)) == NULL)
+ {ret = EXCP_ERROR(env, "Can't make 'Out' binary"); goto done;}
- if ((ctx = EVP_CIPHER_CTX_new()) == NULL)
- {ret = EXCP_ERROR(env, ""); goto done;}
- if (EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1)
- {ret = EXCP_ERROR(env, ""); goto done;}
- if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_set_ivlen, (int)iv.size, NULL) != 1)
- {ret = EXCP_ERROR(env, ""); goto done;}
+ if (EVP_CIPHER_CTX_ctrl(ctx, cipherp->extra.aead.ctx_ctrl_get_tag, (int)tag_len, tagp) != 1)
+ {ret = EXCP_ERROR(env, "Can't get Tag"); 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)
- {ret = EXCP_ERROR(env, ""); goto done;}
- if (EVP_DecryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1)
- {ret = EXCP_ERROR(env, ""); goto done;}
- if (EVP_DecryptUpdate(ctx, NULL, &len, NULL, (int)in.size) != 1)
- {ret = EXCP_ERROR(env, ""); goto done;}
- }
+ ret = enif_make_tuple2(env, out, out_tag);
+ }
else
-#endif
{
- if (EVP_DecryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1)
- {ret = EXCP_ERROR(env, ""); goto done;}
- }
-
- if (EVP_DecryptUpdate(ctx, NULL, &len, aad.data, (int)aad.size) != 1)
- {ret = EXCP_ERROR(env, ""); goto done;}
- if (EVP_DecryptUpdate(ctx, outp, &len, in.data, (int)in.size) != 1)
- {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;
- if (EVP_DecryptFinal_ex(ctx, outp+len, &len) != 1)
- goto err;
- }
+ if (cipherp->flags & GCM_MODE) {
+ if (EVP_CIPHER_CTX_ctrl(ctx, cipherp->extra.aead.ctx_ctrl_set_tag, (int)tag_len, tag.data) != 1)
+ /* Decrypt error */
+ {ret = atom_error; goto done;}
+ if (EVP_DecryptFinal_ex(ctx, outp+len, &len) != 1)
+ /* Decrypt error */
+ {ret = atom_error; goto done;}
+ }
#endif
- CONSUME_REDS(env, in);
- ret = out;
- goto done;
+ ret = out;
+ }
- err:
- /* Decrypt failed, that is, wrong tag */
- ret = atom_error;
+ CONSUME_REDS(env, in);
- done:
+done:
if (ctx)
EVP_CIPHER_CTX_free(ctx);
return ret;
#else
- return EXCP_NOTSUP(env, "");
+ return EXCP_NOTSUP(env, "Unsupported Cipher");
#endif
}
+
+
diff --git a/lib/crypto/c_src/aead.h b/lib/crypto/c_src/aead.h
index 54c0711535..2ec7a8a930 100644
--- a/lib/crypto/c_src/aead.h
+++ b/lib/crypto/c_src/aead.h
@@ -23,7 +23,6 @@
#include "common.h"
-ERL_NIF_TERM aead_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-ERL_NIF_TERM aead_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+ERL_NIF_TERM aead_cipher(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
#endif /* E_AEAD_H__ */
diff --git a/lib/crypto/c_src/api_ng.c b/lib/crypto/c_src/api_ng.c
index 5d063c3ae4..107723d2cb 100644
--- a/lib/crypto/c_src/api_ng.c
+++ b/lib/crypto/c_src/api_ng.c
@@ -27,7 +27,7 @@
*
*/
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[]);
+ERL_NIF_TERM ng_crypto_one_time(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
#ifdef HAVE_ECB_IVEC_BUG
/* <= 0.9.8l returns faulty ivec length */
@@ -93,6 +93,13 @@ static int get_init_args(ErlNifEnv* env,
goto err;
}
+ if ((*cipherp)->flags & AEAD_CIPHER)
+ {
+ *return_term = EXCP_BADARG(env, "Missing arguments for this cipher");
+ goto err;
+ }
+
+
if (FORBIDDEN_IN_FIPS(*cipherp))
{
*return_term = EXCP_NOTSUP(env, "Forbidden in FIPS");
@@ -413,13 +420,15 @@ int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in)
ERL_NIF_TERM ng_crypto_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Context, Data [, IV]) */
struct evp_cipher_ctx *ctx_res;
+ struct evp_cipher_ctx ctx_res_copy;
ERL_NIF_TERM ret;
+ ctx_res_copy.ctx = NULL;
+
if (!enif_get_resource(env, argv[0], (ErlNifResourceType*)evp_cipher_ctx_rtype, (void**)&ctx_res))
return EXCP_BADARG(env, "Bad 1:st arg");
if (argc == 3) {
- struct evp_cipher_ctx ctx_res_copy;
ErlNifBinary ivec_bin;
memcpy(&ctx_res_copy, ctx_res, sizeof ctx_res_copy);
@@ -474,6 +483,9 @@ ERL_NIF_TERM ng_crypto_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
get_update_args(env, ctx_res, argv[1], &ret);
err:
+ if (ctx_res_copy.ctx)
+ EVP_CIPHER_CTX_free(ctx_res_copy.ctx);
+
return ret; /* Both success and error */
}
@@ -504,7 +516,7 @@ ERL_NIF_TERM ng_crypto_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
/* One shot */
/*************************************************************************/
-ERL_NIF_TERM ng_crypto_one_shot(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+ERL_NIF_TERM ng_crypto_one_time(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Cipher, Key, IVec, Data, Encrypt) */
struct evp_cipher_ctx ctx_res;
const struct cipher_type_t *cipherp;
@@ -521,7 +533,7 @@ ERL_NIF_TERM ng_crypto_one_shot(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
return ret;
}
-ERL_NIF_TERM ng_crypto_one_shot_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+ERL_NIF_TERM ng_crypto_one_time_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Cipher, Key, IVec, Data, Encrypt) % if no IV for the Cipher, set IVec = <<>>
*/
ErlNifBinary data_bin;
@@ -536,10 +548,10 @@ ERL_NIF_TERM ng_crypto_one_shot_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
/* Run long jobs on a dirty scheduler to not block the current emulator thread */
if (data_bin.size > MAX_BYTES_TO_NIF) {
- return enif_schedule_nif(env, "ng_crypto_one_shot",
+ return enif_schedule_nif(env, "ng_crypto_one_time",
ERL_NIF_DIRTY_JOB_CPU_BOUND,
- ng_crypto_one_shot, argc, argv);
+ ng_crypto_one_time, argc, argv);
}
- return ng_crypto_one_shot(env, argc, argv);
+ return ng_crypto_one_time(env, argc, argv);
}
diff --git a/lib/crypto/c_src/api_ng.h b/lib/crypto/c_src/api_ng.h
index 5c7d9af3c5..aaf67524ae 100644
--- a/lib/crypto/c_src/api_ng.h
+++ b/lib/crypto/c_src/api_ng.h
@@ -25,6 +25,6 @@
ERL_NIF_TERM ng_crypto_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
ERL_NIF_TERM ng_crypto_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-ERL_NIF_TERM ng_crypto_one_shot_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+ERL_NIF_TERM ng_crypto_one_time_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
#endif /* E_AES_H__ */
diff --git a/lib/crypto/c_src/cipher.c b/lib/crypto/c_src/cipher.c
index 2652e1db4e..13de3562e8 100644
--- a/lib/crypto/c_src/cipher.c
+++ b/lib/crypto/c_src/cipher.c
@@ -117,31 +117,31 @@ static struct cipher_type_t cipher_types[] =
#endif
#if defined(HAVE_GCM)
- {{"aes_gcm"}, {&EVP_aes_128_gcm}, 16, AEAD_CIPHER, {{EVP_CTRL_GCM_SET_IVLEN,EVP_CTRL_GCM_GET_TAG,EVP_CTRL_GCM_SET_TAG}}},
- {{"aes_gcm"}, {&EVP_aes_192_gcm}, 24, AEAD_CIPHER, {{EVP_CTRL_GCM_SET_IVLEN,EVP_CTRL_GCM_GET_TAG,EVP_CTRL_GCM_SET_TAG}}},
- {{"aes_gcm"}, {&EVP_aes_256_gcm}, 32, AEAD_CIPHER, {{EVP_CTRL_GCM_SET_IVLEN,EVP_CTRL_GCM_GET_TAG,EVP_CTRL_GCM_SET_TAG}}},
- {{"aes_128_gcm"}, {&EVP_aes_128_gcm}, 16, AEAD_CIPHER, {{EVP_CTRL_GCM_SET_IVLEN,EVP_CTRL_GCM_GET_TAG,EVP_CTRL_GCM_SET_TAG}}},
- {{"aes_192_gcm"}, {&EVP_aes_192_gcm}, 24, AEAD_CIPHER, {{EVP_CTRL_GCM_SET_IVLEN,EVP_CTRL_GCM_GET_TAG,EVP_CTRL_GCM_SET_TAG}}},
- {{"aes_256_gcm"}, {&EVP_aes_256_gcm}, 32, AEAD_CIPHER, {{EVP_CTRL_GCM_SET_IVLEN,EVP_CTRL_GCM_GET_TAG,EVP_CTRL_GCM_SET_TAG}}},
+ {{"aes_gcm"}, {&EVP_aes_128_gcm}, 16, AEAD_CIPHER|GCM_MODE, {{EVP_CTRL_GCM_SET_IVLEN,EVP_CTRL_GCM_GET_TAG,EVP_CTRL_GCM_SET_TAG}}},
+ {{"aes_gcm"}, {&EVP_aes_192_gcm}, 24, AEAD_CIPHER|GCM_MODE, {{EVP_CTRL_GCM_SET_IVLEN,EVP_CTRL_GCM_GET_TAG,EVP_CTRL_GCM_SET_TAG}}},
+ {{"aes_gcm"}, {&EVP_aes_256_gcm}, 32, AEAD_CIPHER|GCM_MODE, {{EVP_CTRL_GCM_SET_IVLEN,EVP_CTRL_GCM_GET_TAG,EVP_CTRL_GCM_SET_TAG}}},
+ {{"aes_128_gcm"}, {&EVP_aes_128_gcm}, 16, AEAD_CIPHER|GCM_MODE, {{EVP_CTRL_GCM_SET_IVLEN,EVP_CTRL_GCM_GET_TAG,EVP_CTRL_GCM_SET_TAG}}},
+ {{"aes_192_gcm"}, {&EVP_aes_192_gcm}, 24, AEAD_CIPHER|GCM_MODE, {{EVP_CTRL_GCM_SET_IVLEN,EVP_CTRL_GCM_GET_TAG,EVP_CTRL_GCM_SET_TAG}}},
+ {{"aes_256_gcm"}, {&EVP_aes_256_gcm}, 32, AEAD_CIPHER|GCM_MODE, {{EVP_CTRL_GCM_SET_IVLEN,EVP_CTRL_GCM_GET_TAG,EVP_CTRL_GCM_SET_TAG}}},
#else
- {{"aes_gcm"}, {NULL}, 0, AEAD_CIPHER, {{0,0,0}}},
- {{"aes_128_gcm"}, {NULL}, 16, AEAD_CIPHER, {{0,0,0}}},
- {{"aes_192_gcm"}, {NULL}, 24, AEAD_CIPHER, {{0,0,0}}},
- {{"aes_256_gcm"}, {NULL}, 32, AEAD_CIPHER, {{0,0,0}}},
+ {{"aes_gcm"}, {NULL}, 0, AEAD_CIPHER|GCM_MODE, {{0,0,0}}},
+ {{"aes_128_gcm"}, {NULL}, 16, AEAD_CIPHER|GCM_MODE, {{0,0,0}}},
+ {{"aes_192_gcm"}, {NULL}, 24, AEAD_CIPHER|GCM_MODE, {{0,0,0}}},
+ {{"aes_256_gcm"}, {NULL}, 32, AEAD_CIPHER|GCM_MODE, {{0,0,0}}},
#endif
#if defined(HAVE_CCM)
- {{"aes_ccm"}, {&EVP_aes_128_ccm}, 16, AEAD_CIPHER, {{EVP_CTRL_CCM_SET_IVLEN,EVP_CTRL_CCM_GET_TAG,EVP_CTRL_CCM_SET_TAG}}},
- {{"aes_ccm"}, {&EVP_aes_192_ccm}, 24, AEAD_CIPHER, {{EVP_CTRL_CCM_SET_IVLEN,EVP_CTRL_CCM_GET_TAG,EVP_CTRL_CCM_SET_TAG}}},
- {{"aes_ccm"}, {&EVP_aes_256_ccm}, 32, AEAD_CIPHER, {{EVP_CTRL_CCM_SET_IVLEN,EVP_CTRL_CCM_GET_TAG,EVP_CTRL_CCM_SET_TAG}}},
- {{"aes_128_ccm"}, {&EVP_aes_128_ccm}, 16, AEAD_CIPHER, {{EVP_CTRL_CCM_SET_IVLEN,EVP_CTRL_CCM_GET_TAG,EVP_CTRL_CCM_SET_TAG}}},
- {{"aes_192_ccm"}, {&EVP_aes_192_ccm}, 24, AEAD_CIPHER, {{EVP_CTRL_CCM_SET_IVLEN,EVP_CTRL_CCM_GET_TAG,EVP_CTRL_CCM_SET_TAG}}},
- {{"aes_256_ccm"}, {&EVP_aes_256_ccm}, 32, AEAD_CIPHER, {{EVP_CTRL_CCM_SET_IVLEN,EVP_CTRL_CCM_GET_TAG,EVP_CTRL_CCM_SET_TAG}}},
+ {{"aes_ccm"}, {&EVP_aes_128_ccm}, 16, AEAD_CIPHER|CCM_MODE, {{EVP_CTRL_CCM_SET_IVLEN,EVP_CTRL_CCM_GET_TAG,EVP_CTRL_CCM_SET_TAG}}},
+ {{"aes_ccm"}, {&EVP_aes_192_ccm}, 24, AEAD_CIPHER|CCM_MODE, {{EVP_CTRL_CCM_SET_IVLEN,EVP_CTRL_CCM_GET_TAG,EVP_CTRL_CCM_SET_TAG}}},
+ {{"aes_ccm"}, {&EVP_aes_256_ccm}, 32, AEAD_CIPHER|CCM_MODE, {{EVP_CTRL_CCM_SET_IVLEN,EVP_CTRL_CCM_GET_TAG,EVP_CTRL_CCM_SET_TAG}}},
+ {{"aes_128_ccm"}, {&EVP_aes_128_ccm}, 16, AEAD_CIPHER|CCM_MODE, {{EVP_CTRL_CCM_SET_IVLEN,EVP_CTRL_CCM_GET_TAG,EVP_CTRL_CCM_SET_TAG}}},
+ {{"aes_192_ccm"}, {&EVP_aes_192_ccm}, 24, AEAD_CIPHER|CCM_MODE, {{EVP_CTRL_CCM_SET_IVLEN,EVP_CTRL_CCM_GET_TAG,EVP_CTRL_CCM_SET_TAG}}},
+ {{"aes_256_ccm"}, {&EVP_aes_256_ccm}, 32, AEAD_CIPHER|CCM_MODE, {{EVP_CTRL_CCM_SET_IVLEN,EVP_CTRL_CCM_GET_TAG,EVP_CTRL_CCM_SET_TAG}}},
#else
- {{"aes_ccm"}, {NULL}, 0, AEAD_CIPHER, {{0,0,0}}},
- {{"aes_128_ccm"}, {NULL}, 16, AEAD_CIPHER, {{0,0,0}}},
- {{"aes_192_ccm"}, {NULL}, 24, AEAD_CIPHER, {{0,0,0}}},
- {{"aes_256_ccm"}, {NULL}, 32, AEAD_CIPHER, {{0,0,0}}},
+ {{"aes_ccm"}, {NULL}, 0, AEAD_CIPHER|CCM_MODE, {{0,0,0}}},
+ {{"aes_128_ccm"}, {NULL}, 16, AEAD_CIPHER|CCM_MODE, {{0,0,0}}},
+ {{"aes_192_ccm"}, {NULL}, 24, AEAD_CIPHER|CCM_MODE, {{0,0,0}}},
+ {{"aes_256_ccm"}, {NULL}, 32, AEAD_CIPHER|CCM_MODE, {{0,0,0}}},
#endif
/*==== Specialy handled ciphers, only for inclusion in algorithm's list ====*/
diff --git a/lib/crypto/c_src/cipher.h b/lib/crypto/c_src/cipher.h
index b94873940f..0e51c410eb 100644
--- a/lib/crypto/c_src/cipher.h
+++ b/lib/crypto/c_src/cipher.h
@@ -46,6 +46,8 @@ struct cipher_type_t {
#define AEAD_CIPHER 8
#define NON_EVP_CIPHER 16
#define AES_CTR_COMPAT 32
+#define CCM_MODE 64
+#define GCM_MODE 128
#ifdef FIPS_SUPPORT
diff --git a/lib/crypto/c_src/common.h b/lib/crypto/c_src/common.h
index 0bf7f09f4f..a7e59d5d01 100644
--- a/lib/crypto/c_src/common.h
+++ b/lib/crypto/c_src/common.h
@@ -38,8 +38,11 @@
/* All nif functions return a valid value or throws an exception */
#define EXCP(Env, Id, Str) enif_raise_exception((Env), \
- enif_make_tuple2((Env), \
+ enif_make_tuple3((Env), \
(Id), \
+ enif_make_tuple2((Env), \
+ enif_make_string((Env),__FILE__,(ERL_NIF_LATIN1)), \
+ enif_make_int((Env), __LINE__)), \
enif_make_string((Env),(Str),(ERL_NIF_LATIN1)) ))
#define EXCP_NOTSUP(Env, Str) EXCP((Env), atom_notsup, (Str))
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index 4aed06a489..a8014745c8 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -81,7 +81,7 @@ static ErlNifFunc nif_funcs[] = {
{"ng_crypto_init_nif", 4, ng_crypto_init_nif, 0},
{"ng_crypto_update_nif", 2, ng_crypto_update_nif, 0},
{"ng_crypto_update_nif", 3, ng_crypto_update_nif, 0},
- {"ng_crypto_one_shot_nif", 5, ng_crypto_one_shot_nif, 0},
+ {"ng_crypto_one_time_nif", 5, ng_crypto_one_time_nif, 0},
{"strong_rand_bytes_nif", 1, strong_rand_bytes_nif, 0},
{"strong_rand_range_nif", 1, strong_rand_range_nif, 0},
{"rand_uniform_nif", 2, rand_uniform_nif, 0},
@@ -105,8 +105,7 @@ static ErlNifFunc nif_funcs[] = {
{"rand_seed_nif", 1, rand_seed_nif, 0},
- {"aead_encrypt", 6, aead_encrypt, 0},
- {"aead_decrypt", 6, aead_decrypt, 0},
+ {"aead_cipher", 7, aead_cipher, 0},
{"poly1305_nif", 2, poly1305_nif, 0},
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index fd13481951..04b2f62266 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -58,7 +58,8 @@
%% New interface
-export([crypto_init/4, crypto_init/3,
crypto_update/2,
- crypto_one_shot/5,
+ crypto_one_time/4, crypto_one_time/5,
+ crypto_aead/6, crypto_aead/7,
crypto_init_dyn_iv/3,
crypto_update_dyn_iv/3
]).
@@ -276,48 +277,153 @@
-type edwards_curve_ed() :: ed25519 | ed448 .
-%%%
--type cipher() :: block_cipher()
- | stream_cipher()
- | aead_cipher() .
+%%%----------------------------------------------------------------
+%%% New cipher schema
+%%%
+-type cipher() :: cipher_no_iv()
+ | cipher_iv()
+ | cipher_aead() .
--type block_cipher() :: block_cipher_iv() | block_cipher_no_iv() .
+-type cipher_no_iv() :: aes_128_ecb
+ | aes_192_ecb
+ | aes_256_ecb
--type block_cipher_iv() :: cbc_cipher()
- | cfb_cipher()
- | aes_ige256
- | blowfish_ofb64
- | rc2_cbc .
+ | blowfish_ecb
+ | des_ecb
+ | rc4 .
--type cbc_cipher() :: des_cbc | des_ede3_cbc
- | blowfish_cbc
- | aes_cbc | aes_128_cbc | aes_192_cbc | aes_256_cbc
- | alias_cbc() .
--type alias_cbc() :: des3_cbc | des_ede3
- | aes_cbc128 | aes_cbc256 .
+-type cipher_iv() :: aes_128_cbc
+ | aes_192_cbc
+ | aes_256_cbc
+
+ | aes_128_cfb128
+ | aes_192_cfb128
+ | aes_256_cfb128
+
+ | aes_128_cfb8
+ | aes_192_cfb8
+ | aes_256_cfb8
--type aead_cipher() :: aes_gcm
+ | aes_128_ctr
+ | aes_192_ctr
+ | aes_256_ctr
+
+ | aes_ige256
+
+ | blowfish_cbc
+ | blowfish_cfb64
+ | blowfish_ofb64
+ | chacha20
+ | des_ede3_cbc
+ | des_ede3_cfb
+
+ | des_cbc
+ | des_cfb
+ | rc2_cbc .
+
+
+-type cipher_aead() :: aes_128_ccm
+ | aes_192_ccm
+ | aes_256_ccm
+
| aes_128_gcm
| aes_192_gcm
| aes_256_gcm
- | aes_ccm
- | aes_128_ccm
- | aes_192_ccm
- | aes_256_ccm
+
| chacha20_poly1305 .
--type cfb_cipher() :: aes_cfb8
- | aes_cfb128
- | blowfish_cfb64
- | des_cfb
- | des_ede3_cfb
- | alias_cfb() .
--type alias_cfb() :: des_ede3_cbf | des3_cbf
- | des3_cfb .
+%% -type retired_cipher_no_iv_aliases() :: aes_ecb .
+
+%% -type retired_cipher_iv_aliases() :: aes_cbc
+%% | aes_cbc128 % aes_128_cbc
+%% | aes_cbc256 % aes_256_cbc
+%% | aes_cfb128
+%% | aes_cfb8
+%% | aes_ctr
+%% | des3_cbc % des_ede3_cbc
+%% | des_ede3 % des_ede3_cbc
+%% | des_ede3_cbf % des_ede3_cfb
+%% | des3_cbf % des_ede3_cfb
+%% | des3_cfb . % des_ede3_cfb
+
+%% -type retired_cipher_aead_aliases() :: aes_ccm
+%% | aes_gcm .
--type block_cipher_no_iv() :: ecb_cipher() .
--type ecb_cipher() :: des_ecb | blowfish_ecb | aes_ecb .
+%%%----------------------------------------------------------------
+%%% Old cipher scheme
+%%%
+%%%
+-type block_cipher_without_iv() :: ecb_cipher() .
+
+-type block_cipher_with_iv() :: cbc_cipher()
+ | cfb_cipher()
+ | blowfish_ofb64
+ | aes_ige256 .
+
+-type stream_cipher() :: ctr_cipher()
+ | chacha20
+ | rc4 .
+
+
+%%%----
+-type cbc_cipher() :: aes_128_cbc
+ | aes_192_cbc
+ | aes_256_cbc
+ | blowfish_cbc
+ | des_cbc
+ | des_ede3_cbc
+ | rc2_cbc
+ | retired_cbc_cipher_aliases() .
+
+-type retired_cbc_cipher_aliases() :: aes_cbc % aes_*_cbc
+ | aes_cbc128 % aes_128_cbc
+ | aes_cbc256 % aes_256_cbc
+ | des3_cbc % des_ede3_cbc
+ | des_ede3 . % des_ede3_cbc
+
+%%%----
+-type cfb_cipher() :: aes_128_cfb128
+ | aes_192_cfb128
+ | aes_256_cfb128
+ | aes_128_cfb8
+ | aes_192_cfb8
+ | aes_256_cfb8
+ | blowfish_cfb64
+ | des_cfb
+ | des_ede3_cfb
+ | retired_cfb_cipher_aliases() .
+
+-type retired_cfb_cipher_aliases() :: aes_cfb8 % aes_*_cfb8
+ | aes_cfb128 % aes_*_cfb128
+ | des3_cbf % des_ede3_cfb, cfb misspelled
+ | des3_cfb % des_ede3_cfb
+ | des_ede3_cbf .% cfb misspelled
+
+
+%%%----
+-type ctr_cipher() :: aes_128_ctr
+ | aes_192_ctr
+ | aes_256_ctr
+ | retired_ctr_cipher_aliases() .
+
+-type retired_ctr_cipher_aliases() :: aes_ctr . % aes_*_ctr
+
+%%%----
+-type ecb_cipher() :: aes_128_ecb
+ | aes_192_ecb
+ | aes_256_ecb
+ | blowfish_ecb
+ | retired_ecb_cipher_aliases() .
+
+-type retired_ecb_cipher_aliases() :: aes_ecb .
+
+%%%----
+-type aead_cipher() :: aes_gcm | aes_ccm | chacha20_poly1305 .
+
+
+%%%----- end old cipher schema ------------------------------------
+%%%----------------------------------------------------------------
-type key() :: iodata().
-type des3_key() :: [key()].
@@ -564,9 +670,9 @@ poly1305(Key, Data) ->
-define(COMPAT(CALL),
try begin CALL end
catch
- error:{error,_} ->
+ error:{error, {_File,_Line}, _Reason} ->
error(badarg);
- error:{E,_Reason} when E==notsup ; E==badarg ->
+ error:{E, {_File,_Line}, _Reason} when E==notsup ; E==badarg ->
error(E)
end).
@@ -611,7 +717,7 @@ cipher_info(Type) ->
%%%---- Block ciphers
%%%----------------------------------------------------------------
--spec block_encrypt(Type::block_cipher_iv(), Key::key()|des3_key(), Ivec::binary(), PlainText::iodata()) ->
+-spec block_encrypt(Type::block_cipher_with_iv(), Key::key()|des3_key(), Ivec::binary(), PlainText::iodata()) ->
binary() | run_time_error();
(Type::aead_cipher(), Key::iodata(), Ivec::binary(), {AAD::binary(), PlainText::iodata()}) ->
{binary(), binary()} | run_time_error();
@@ -627,34 +733,24 @@ block_encrypt(Type, Key0, Ivec, Data) ->
?COMPAT(
case Data of
{AAD, PlainText} ->
- aead_encrypt(alias(Type,Key), Key, Ivec, AAD, PlainText, aead_tag_len(Type));
+ crypto_aead(alias(Type,Key), Key, Ivec, PlainText, AAD, true);
{AAD, PlainText, TagLength} ->
- aead_encrypt(alias(Type,Key), Key, Ivec, AAD, PlainText, TagLength);
+ crypto_aead(alias(Type,Key), Key, Ivec, PlainText, AAD, TagLength, true);
PlainText ->
- crypto_one_shot(alias(Type,Key), Key, Ivec, PlainText, true)
+ crypto_one_time(alias(Type,Key), Key, Ivec, PlainText, true)
end).
--spec block_encrypt(Type::block_cipher_no_iv(), Key::key(), PlainText::iodata()) ->
+-spec block_encrypt(Type::block_cipher_without_iv(), Key::key(), PlainText::iodata()) ->
binary() | run_time_error().
block_encrypt(Type, Key0, PlainText) ->
Key = iolist_to_binary(Key0),
- ?COMPAT(crypto_one_shot(alias(Type,Key), Key, <<>>, PlainText, true)).
+ ?COMPAT(crypto_one_time(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.
-
%%%----------------------------------------------------------------
%%%----------------------------------------------------------------
--spec block_decrypt(Type::block_cipher_iv(), Key::key()|des3_key(), Ivec::binary(), Data::iodata()) ->
+-spec block_decrypt(Type::block_cipher_with_iv(), Key::key()|des3_key(), Ivec::binary(), Data::iodata()) ->
binary() | run_time_error();
(Type::aead_cipher(), Key::iodata(), Ivec::binary(),
{AAD::binary(), Data::iodata(), Tag::binary()}) ->
@@ -668,18 +764,18 @@ block_decrypt(Type, Key0, Ivec, Data) ->
?COMPAT(
case Data of
{AAD, CryptoText, Tag} ->
- aead_decrypt(alias(Type,Key), Key, Ivec, AAD, CryptoText, Tag);
+ crypto_aead(alias(Type,Key), Key, Ivec, CryptoText, AAD, Tag, false);
CryptoText ->
- crypto_one_shot(alias(Type,Key), Key, Ivec, CryptoText, false)
+ crypto_one_time(alias(Type,Key), Key, Ivec, CryptoText, false)
end).
--spec block_decrypt(Type::block_cipher_no_iv(), Key::key(), Data::iodata()) ->
+-spec block_decrypt(Type::block_cipher_without_iv(), Key::key(), Data::iodata()) ->
binary() | run_time_error().
block_decrypt(Type, Key0, CryptoText) ->
Key = iolist_to_binary(Key0),
- ?COMPAT(crypto_one_shot(alias(Type,Key), Key, <<>>, CryptoText, false)).
+ ?COMPAT(crypto_one_time(alias(Type,Key), Key, CryptoText, false)).
%%%-------- Stream ciphers API
@@ -687,17 +783,9 @@ block_decrypt(Type, Key0, CryptoText) ->
crypto_state() | {crypto_state(),flg_undefined}
}.
--type stream_cipher() :: stream_cipher_iv() | stream_cipher_no_iv() .
--type stream_cipher_no_iv() :: rc4 .
--type stream_cipher_iv() :: aes_ctr
- | aes_128_ctr
- | aes_192_ctr
- | aes_256_ctr
- | chacha20 .
-
%%%---- stream_init
-spec stream_init(Type, Key, IVec) -> State | run_time_error()
- when Type :: stream_cipher_iv(),
+ when Type :: stream_cipher(),
Key :: iodata(),
IVec ::binary(),
State :: stream_state() .
@@ -711,7 +799,7 @@ stream_init(Type, Key0, IVec) when is_binary(IVec) ->
-spec stream_init(Type, Key) -> State | run_time_error()
- when Type :: stream_cipher_no_iv(),
+ when Type :: rc4,
Key :: iodata(),
State :: stream_state() .
stream_init(rc4 = Type, Key0) ->
@@ -792,38 +880,35 @@ next_iv(Type, Data, _Ivec) ->
%%%
-spec crypto_init(Cipher, Key, EncryptFlag) -> State | descriptive_error()
- when Cipher :: block_cipher_no_iv()
- | stream_cipher_no_iv(),
+ when Cipher :: cipher_no_iv(),
Key :: iodata(),
EncryptFlag :: boolean(),
State :: crypto_state() .
crypto_init(Cipher, Key, EncryptFlag) ->
%% The IV is supposed to be supplied by calling crypto_update/3
- ng_crypto_init_nif(alias(Cipher), iolist_to_binary(Key), <<>>, EncryptFlag).
+ ng_crypto_init_nif(Cipher, iolist_to_binary(Key), <<>>, EncryptFlag).
-spec crypto_init(Cipher, Key, IV, EncryptFlag) -> State | descriptive_error()
- when Cipher :: stream_cipher_iv()
- | block_cipher_iv(),
+ when Cipher :: cipher_iv(),
Key :: iodata(),
IV :: iodata(),
EncryptFlag :: boolean(),
State :: crypto_state() .
crypto_init(Cipher, Key, IV, EncryptFlag) ->
- ng_crypto_init_nif(alias(Cipher), iolist_to_binary(Key), iolist_to_binary(IV), EncryptFlag).
+ ng_crypto_init_nif(Cipher, iolist_to_binary(Key), iolist_to_binary(IV), EncryptFlag).
%%%----------------------------------------------------------------
-spec crypto_init_dyn_iv(Cipher, Key, EncryptFlag) -> State | descriptive_error()
- when Cipher :: stream_cipher_iv()
- | block_cipher_iv(),
+ when Cipher :: cipher_iv(),
Key :: iodata(),
EncryptFlag :: boolean(),
State :: crypto_state() .
crypto_init_dyn_iv(Cipher, Key, EncryptFlag) ->
%% The IV is supposed to be supplied by calling crypto_update/3
- ng_crypto_init_nif(alias(Cipher), iolist_to_binary(Key), undefined, EncryptFlag).
+ ng_crypto_init_nif(Cipher, iolist_to_binary(Key), undefined, EncryptFlag).
%%%----------------------------------------------------------------
%%%
@@ -866,29 +951,86 @@ crypto_update_dyn_iv(State, Data0, IV) ->
%%% The size must be an integer multiple of the crypto's blocksize.
%%%
--spec crypto_one_shot(Cipher, Key, IV, Data, EncryptFlag) ->
+-spec crypto_one_time(Cipher, Key, Data, EncryptFlag) ->
Result | descriptive_error()
- when Cipher :: stream_cipher()
- | block_cipher(),
+ when Cipher :: cipher_no_iv(),
Key :: iodata(),
- IV :: iodata() | undefined,
Data :: iodata(),
EncryptFlag :: boolean(),
Result :: binary() .
-crypto_one_shot(Cipher, Key, undefined, Data, EncryptFlag) ->
- crypto_one_shot(Cipher, Key, <<>>, Data, EncryptFlag);
+crypto_one_time(Cipher, Key, Data, EncryptFlag) ->
+ crypto_one_time(Cipher, Key, <<>>, Data, EncryptFlag).
-crypto_one_shot(Cipher, Key, IV, Data0, EncryptFlag) ->
+-spec crypto_one_time(Cipher, Key, IV, Data, EncryptFlag) ->
+ Result | descriptive_error()
+ when Cipher :: cipher_iv(),
+ Key :: iodata(),
+ IV :: iodata(),
+ Data :: iodata(),
+ EncryptFlag :: boolean(),
+ Result :: binary() .
+
+crypto_one_time(Cipher, Key, IV, Data0, EncryptFlag) ->
case iolist_to_binary(Data0) of
<<>> ->
<<>>; % Known to fail on OpenSSL 0.9.8h
Data ->
- ng_crypto_one_shot_nif(alias(Cipher),
+ ng_crypto_one_time_nif(Cipher,
iolist_to_binary(Key), iolist_to_binary(IV), Data,
EncryptFlag)
end.
+
+-spec crypto_aead(Cipher, Key, IV, InText, AAD, EncFlag::true) ->
+ Result | descriptive_error()
+ when Cipher :: cipher_aead(),
+ Key :: iodata(),
+ IV :: iodata(),
+ InText :: iodata(),
+ AAD :: iodata(),
+ Result :: EncryptResult,
+ EncryptResult :: {OutCryptoText, OutTag},
+ OutCryptoText :: binary(),
+ OutTag :: binary().
+
+crypto_aead(Cipher, Key, IV, PlainText, AAD, true) ->
+ crypto_aead(Cipher, Key, IV, PlainText, AAD, aead_tag_len(Cipher), true).
+
+
+-spec crypto_aead(Cipher, Key, IV, InText, AAD, TagOrTagLength, EncFlag) ->
+ Result | descriptive_error()
+ when Cipher :: cipher_aead(),
+ Key :: iodata(),
+ IV :: iodata(),
+ InText :: iodata(),
+ AAD :: iodata(),
+ TagOrTagLength :: EncryptTagLength | DecryptTag,
+ EncryptTagLength :: non_neg_integer(), % or pos_integer() 1..
+ DecryptTag :: iodata(),
+ EncFlag :: boolean(),
+ Result :: EncryptResult | DecryptResult,
+ EncryptResult :: {OutCryptoText, OutTag},
+ DecryptResult :: OutPlainText | error,
+ OutCryptoText :: binary(),
+ OutTag :: binary(),
+ OutPlainText :: binary().
+
+crypto_aead(Cipher, Key, IV, TextIn, AAD, TagOrTagLength, EncFlg) ->
+ aead_cipher(Cipher, Key, IV, TextIn, AAD, TagOrTagLength, EncFlg).
+
+
+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;
+aead_tag_len(_) -> error({badarg, "Not an AEAD cipher"}).
+
%%%----------------------------------------------------------------
%%% NIFs
@@ -909,9 +1051,9 @@ ng_crypto_update_nif(_State, _Data) -> ?nif_stub.
ng_crypto_update_nif(_State, _Data, _IV) -> ?nif_stub.
--spec ng_crypto_one_shot_nif(atom(), binary(), binary(), binary(), boolean() ) ->
+-spec ng_crypto_one_time_nif(atom(), binary(), binary(), binary(), boolean() ) ->
binary() | descriptive_error().
-ng_crypto_one_shot_nif(_Cipher, _Key, _IVec, _Data, _EncryptFlg) -> ?nif_stub.
+ng_crypto_one_time_nif(_Cipher, _Key, _IVec, _Data, _EncryptFlg) -> ?nif_stub.
%%%----------------------------------------------------------------
%%% Cipher aliases
@@ -2060,8 +2202,7 @@ 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, _Key, _Ivec, _AAD, _In, _TagLength) -> ?nif_stub.
-aead_decrypt(_Type, _Key, _Ivec, _AAD, _In, _Tag) -> ?nif_stub.
+aead_cipher(_Type, _Key, _Ivec, _AAD, _In, _TagOrTagLength, _EncFlg) -> ?nif_stub.
%%
%% AES - with 256 bit key in infinite garble extension mode (IGE)
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index ce5097de47..6a2727a622 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -45,6 +45,42 @@ all() ->
hash_info
].
+-define(NEW_CIPHER_TYPE_SCHEMA,
+ {group, des_ede3_cbc},
+ {group, des_ede3_cfb},
+ {group, aes_128_cbc},
+ {group, aes_192_cbc},
+ {group, aes_256_cbc},
+ {group, aes_128_ctr},
+ {group, aes_192_ctr},
+ {group, aes_256_ctr},
+ {group, aes_128_ccm},
+ {group, aes_192_ccm},
+ {group, aes_256_ccm},
+ {group, aes_128_ecb},
+ {group, aes_192_ecb},
+ {group, aes_256_ecb},
+ {group, aes_128_gcm},
+ {group, aes_192_gcm},
+ {group, aes_256_gcm},
+ {group, des_ede3_cbc},
+ {group, des_ede3_cfb}
+ ).
+
+-define(RETIRED_TYPE_ALIASES,
+ {group, aes_cbc},
+ {group, aes_cbc128},
+ {group, aes_cbc256},
+ {group, aes_ccm},
+ {group, aes_ctr},
+ {group, aes_gcm},
+ {group, aes_ecb},
+ {group, des3_cfb},
+ {group, des3_cbc},
+ {group, des3_cbf},
+ {group, des_ede3}
+ ).
+
groups() ->
[{non_fips, [], [
{group, blake2b},
@@ -67,35 +103,29 @@ groups() ->
{group, sha3_512},
{group, sha512},
{group, sha},
+ {group, poly1305},
{group, dh},
{group, ecdh},
{group, srp},
- {group, aes_cbc},
- {group, aes_ccm},
- {group, aes_gcm},
{group, chacha20_poly1305},
{group, chacha20},
- {group, des3_cfb},
- {group, aes_cbc128},
- {group, aes_cbc256},
- {group, aes_cfb128},
- {group, aes_cfb8},
- {group, aes_ctr},
- {group, aes_ige256},
{group, blowfish_cbc},
{group, blowfish_cfb64},
{group, blowfish_ecb},
{group, blowfish_ofb64},
- {group, des3_cbc},
- {group, des3_cbf},
+
+ {group, aes_cfb128},
+ {group, aes_cfb8},
+ {group, aes_ige256},
{group, des_cbc},
{group, des_cfb},
- {group, des_ede3},
- {group, poly1305},
{group, rc2_cbc},
- {group, rc4}
+ {group, rc4},
+
+ ?NEW_CIPHER_TYPE_SCHEMA,
+ ?RETIRED_TYPE_ALIASES
]},
{fips, [], [
{group, no_blake2b},
@@ -114,123 +144,142 @@ groups() ->
{group, sha256},
{group, sha384},
{group, sha512},
+ {group, no_poly1305},
{group, dh},
{group, ecdh},
{group, no_srp},
- {group, aes_cbc},
- {group, aes_ccm},
- {group, aes_gcm},
{group, no_chacha20_poly1305},
{group, no_chacha20},
- {group, des3_cfb},
- {group, aes_cbc128},
- {group, aes_cbc256},
- {group, no_aes_cfb128},
- {group, no_aes_cfb8},
- {group, aes_ctr},
- {group, no_aes_ige256},
{group, no_blowfish_cbc},
{group, no_blowfish_cfb64},
{group, no_blowfish_ecb},
{group, no_blowfish_ofb64},
- {group, des3_cbc},
- {group, des3_cbf},
+
+ {group, no_aes_cfb128},
+ {group, no_aes_cfb8},
+ {group, no_aes_ige256},
{group, no_des_cbc},
{group, no_des_cfb},
- {group, des_ede3},
- {group, no_poly1305},
{group, no_rc2_cbc},
- {group, no_rc4}
+ {group, no_rc4},
+
+ ?NEW_CIPHER_TYPE_SCHEMA,
+ ?RETIRED_TYPE_ALIASES
]},
- {md4, [], [hash]},
- {md5, [], [hash, hmac]},
- {ripemd160, [], [hash]},
- {sha, [], [hash, hmac]},
- {sha224, [], [hash, hmac]},
- {sha256, [], [hash, hmac]},
- {sha384, [], [hash, hmac]},
- {sha512, [], [hash, hmac]},
- {sha3_224, [], [hash, hmac]},
- {sha3_256, [], [hash, hmac]},
- {sha3_384, [], [hash, hmac]},
- {sha3_512, [], [hash, hmac]},
- {blake2b, [], [hash, hmac]},
- {blake2s, [], [hash, hmac]},
- {no_blake2b, [], [no_hash, no_hmac]},
- {no_blake2s, [], [no_hash, no_hmac]},
- {rsa, [], [sign_verify,
- public_encrypt,
- private_encrypt,
- generate
- ]},
- {dss, [], [sign_verify
- %% Does not work yet: ,public_encrypt, private_encrypt
- ]},
- {ecdsa, [], [sign_verify
- %% Does not work yet: ,public_encrypt, private_encrypt
- ]},
- {ed25519, [], [sign_verify
- %% Does not work yet: ,public_encrypt, private_encrypt
- ]},
- {ed448, [], [sign_verify
- %% Does not work yet: ,public_encrypt, private_encrypt
- ]},
- {dh, [], [generate_compute,
- compute_bug]},
- {ecdh, [], [use_all_elliptic_curves, compute, generate]},
- {srp, [], [generate_compute]},
- {des_cbc, [], [block, api_ng, api_ng_one_shot, api_ng_tls]},
- {des_cfb, [], [block, api_ng, api_ng_one_shot, api_ng_tls]},
- {des3_cbc,[], [block, api_ng, api_ng_one_shot, api_ng_tls]},
- {des_ede3,[], [block, api_ng, api_ng_one_shot, api_ng_tls]},
- {des3_cbf,[], [block, api_ng, api_ng_one_shot, api_ng_tls]},
- {des3_cfb,[], [block, api_ng, api_ng_one_shot, api_ng_tls]},
- {rc2_cbc,[], [block, api_ng, api_ng_one_shot, api_ng_tls]},
- {aes_cbc128,[], [block, api_ng, api_ng_one_shot, api_ng_tls, cmac]},
- {aes_cfb8,[], [block, api_ng, api_ng_one_shot, api_ng_tls]},
- {aes_cfb128,[], [block, api_ng, api_ng_one_shot, api_ng_tls]},
- {aes_cbc256,[], [block, api_ng, api_ng_one_shot, api_ng_tls, cmac]},
- {aes_ecb,[], [block, api_ng, api_ng_one_shot, api_ng_tls]},
- {aes_ige256,[], [block]},
- {blowfish_cbc, [], [block, api_ng, api_ng_one_shot, api_ng_tls]},
- {blowfish_ecb, [], [block, api_ng, api_ng_one_shot, api_ng_tls]},
- {blowfish_cfb64, [], [block, api_ng, api_ng_one_shot, api_ng_tls]},
- {blowfish_ofb64,[], [block, api_ng, api_ng_one_shot, api_ng_tls]},
- {rc4, [], [stream, api_ng, api_ng_one_shot, api_ng_tls]},
- {aes_ctr, [], [stream, api_ng, api_ng_one_shot, api_ng_tls]},
- {aes_ccm, [], [aead]},
- {aes_gcm, [], [aead]},
- {chacha20_poly1305, [], [aead]},
- {chacha20, [], [stream, api_ng, api_ng_one_shot, api_ng_tls]},
- {poly1305, [], [poly1305]},
- {no_poly1305, [], [no_poly1305]},
- {aes_cbc, [], [block, api_ng, api_ng_one_shot, api_ng_tls]},
- {no_aes_cfb8,[], [no_support, no_block]},
- {no_aes_cfb128,[], [no_support, no_block]},
- {no_md4, [], [no_support, no_hash]},
- {no_md5, [], [no_support, no_hash, no_hmac]},
- {no_ed25519, [], [no_support, no_sign_verify
- %% Does not work yet: ,public_encrypt, private_encrypt
- ]},
- {no_ed448, [], [no_support, no_sign_verify
- %% Does not work yet: ,public_encrypt, private_encrypt
- ]},
- {no_ripemd160, [], [no_support, no_hash]},
- {no_srp, [], [no_support, no_generate_compute]},
- {no_des_cbc, [], [no_support, no_block]},
- {no_des_cfb, [], [no_support, no_block]},
- {no_blowfish_cbc, [], [no_support, no_block]},
- {no_blowfish_ecb, [], [no_support, no_block]},
- {no_blowfish_cfb64, [], [no_support, no_block]},
- {no_blowfish_ofb64, [], [no_support, no_block]},
- {no_aes_ige256, [], [no_support, no_block]},
+
+ {md4, [], [hash]},
+ {md5, [], [hash, hmac]},
+ {ripemd160, [], [hash]},
+ {sha, [], [hash, hmac]},
+ {sha224, [], [hash, hmac]},
+ {sha256, [], [hash, hmac]},
+ {sha384, [], [hash, hmac]},
+ {sha512, [], [hash, hmac]},
+ {sha3_224, [], [hash, hmac]},
+ {sha3_256, [], [hash, hmac]},
+ {sha3_384, [], [hash, hmac]},
+ {sha3_512, [], [hash, hmac]},
+ {blake2b, [], [hash, hmac]},
+ {blake2s, [], [hash, hmac]},
+ {no_blake2b, [], [no_hash, no_hmac]},
+ {no_blake2s, [], [no_hash, no_hmac]},
+ {rsa, [], [sign_verify,
+ public_encrypt,
+ private_encrypt,
+ generate
+ ]},
+ {dss, [], [sign_verify
+ %% Does not work yet: ,public_encrypt, private_encrypt
+ ]},
+ {ecdsa, [], [sign_verify
+ %% Does not work yet: ,public_encrypt, private_encrypt
+ ]},
+ {ed25519, [], [sign_verify
+ %% Does not work yet: ,public_encrypt, private_encrypt
+ ]},
+ {ed448, [], [sign_verify
+ %% Does not work yet: ,public_encrypt, private_encrypt
+ ]},
+ {dh, [], [generate_compute, compute_bug]},
+ {ecdh, [], [use_all_elliptic_curves, compute, generate]},
+ {srp, [], [generate_compute]},
+ {des_cbc, [], [block, api_ng, api_ng_one_shot, api_ng_tls]},
+ {des_cfb, [], [block, api_ng, api_ng_one_shot, api_ng_tls]},
+ {des_ede3_cbc, [], [block, api_ng, api_ng_one_shot, api_ng_tls]},
+ {des_ede3_cfb, [], [block, api_ng, api_ng_one_shot, api_ng_tls]},
+ {rc2_cbc, [], [block, api_ng, api_ng_one_shot, api_ng_tls]},
+ {aes_cfb8, [], [block, api_ng, api_ng_one_shot, api_ng_tls]},
+ {no_aes_cfb8, [], [no_support, no_block]},
+ {aes_cfb128, [], [block, api_ng, api_ng_one_shot, api_ng_tls]},
+ {no_aes_cfb128, [], [no_support, no_block]},
+ {aes_ige256, [], [block]},
+ {no_aes_ige256, [], [no_support, no_block]},
+ {blowfish_cbc, [], [block, api_ng, api_ng_one_shot, api_ng_tls]},
+ {blowfish_ecb, [], [block, api_ng, api_ng_one_shot]},
+ {blowfish_cfb64, [], [block, api_ng, api_ng_one_shot, api_ng_tls]},
+ {blowfish_ofb64, [], [block, api_ng, api_ng_one_shot, api_ng_tls]},
+ {rc4, [], [stream, api_ng, api_ng_one_shot, api_ng_tls]},
+ {aes_ctr, [], [stream]},
+ {chacha20_poly1305, [], [aead]},
+ {chacha20, [], [stream, api_ng, api_ng_one_shot, api_ng_tls]},
+ {poly1305, [], [poly1305]},
+ {no_poly1305, [], [no_poly1305]},
+ {no_aes_cfb128, [], [no_support, no_block]},
+ {no_md4, [], [no_support, no_hash]},
+ {no_md5, [], [no_support, no_hash, no_hmac]},
+ {no_ed25519, [], [no_support, no_sign_verify
+ %% Does not work yet: ,public_encrypt, private_encrypt
+ ]},
+ {no_ed448, [], [no_support, no_sign_verify
+ %% Does not work yet: ,public_encrypt, private_encrypt
+ ]},
+ {no_ripemd160, [], [no_support, no_hash]},
+ {no_srp, [], [no_support, no_generate_compute]},
+ {no_des_cbc, [], [no_support, no_block]},
+ {no_des_cfb, [], [no_support, no_block]},
+ {no_blowfish_cbc, [], [no_support, no_block]},
+ {no_blowfish_ecb, [], [no_support, no_block]},
+ {no_blowfish_cfb64, [], [no_support, no_block]},
+ {no_blowfish_ofb64, [], [no_support, no_block]},
+ {no_aes_ige256, [], [no_support, no_block]},
{no_chacha20_poly1305, [], [no_support, no_aead]},
- {no_chacha20, [], [no_support, no_stream_ivec]},
- {no_rc2_cbc, [], [no_support, no_block]},
- {no_rc4, [], [no_support, no_stream]},
- {api_errors, [], [api_errors_ecdh]}
+ {no_chacha20, [], [no_support, no_stream_ivec]},
+ {no_rc2_cbc, [], [no_support, no_block]},
+ {no_rc4, [], [no_support, no_stream]},
+ {api_errors, [], [api_errors_ecdh]},
+
+ %% New cipher nameing schema
+ {des_ede3_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls]},
+ {des_ede3_cfb, [], [api_ng, api_ng_one_shot, api_ng_tls]},
+ {aes_128_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls]},
+ {aes_192_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls]},
+ {aes_256_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls]},
+ {aes_128_ctr, [], [api_ng, api_ng_one_shot, api_ng_tls]},
+ {aes_192_ctr, [], [api_ng, api_ng_one_shot, api_ng_tls]},
+ {aes_256_ctr, [], [api_ng, api_ng_one_shot, api_ng_tls]},
+ {aes_128_ccm, [], [aead]},
+ {aes_192_ccm, [], [aead]},
+ {aes_256_ccm, [], [aead]},
+ {aes_128_ecb, [], [api_ng, api_ng_one_shot]},
+ {aes_192_ecb, [], [api_ng, api_ng_one_shot]},
+ {aes_256_ecb, [], [api_ng, api_ng_one_shot]},
+ {aes_128_gcm, [], [aead]},
+ {aes_192_gcm, [], [aead]},
+ {aes_256_gcm, [], [aead]},
+
+ %% Retired aliases
+ {aes_cbc, [], [block]},
+ {aes_cbc128, [], [block]},
+ {aes_cbc256, [], [block]},
+ {aes_ccm, [], [aead]},
+ {aes_ecb, [], [block]},
+ {aes_gcm, [], [aead]},
+ {des3_cbc, [], [block]},
+ {des_ede3, [], [block]},
+ {des3_cbf, [], [block]},
+ {des3_cfb, [], [block]}
].
%%-------------------------------------------------------------------
@@ -430,7 +479,6 @@ poly1305(Config) ->
no_poly1305() ->
[{doc, "Test disabled poly1305 function"}].
no_poly1305(Config) ->
- Type = ?config(type, Config),
Key = <<133,214,190,120,87,85,109,51,127,68,82,254,66,213,6,168,1,
3,128,138,251,13,178,253,74,191,246,175,65,73,245,27>>,
Txt = <<"Cryptographic Forum Research Group">>,
@@ -440,7 +488,7 @@ no_poly1305(Config) ->
block() ->
[{doc, "Test block ciphers"}].
block(Config) when is_list(Config) ->
- Blocks = lazy_eval(proplists:get_value(block, Config)),
+ [_|_] = Blocks = lazy_eval(proplists:get_value(cipher, Config)),
lists:foreach(fun block_cipher/1, Blocks),
lists:foreach(fun block_cipher/1, block_iolistify(Blocks)),
lists:foreach(fun block_cipher_increment/1, block_iolistify(Blocks)).
@@ -449,7 +497,7 @@ block(Config) when is_list(Config) ->
no_block() ->
[{doc, "Test disabled block ciphers"}].
no_block(Config) when is_list(Config) ->
- Blocks = lazy_eval(proplists:get_value(block, Config)),
+ [_|_] = Blocks = lazy_eval(proplists:get_value(cipher, Config)),
Args = case Blocks of
[{_Type, _Key, _PlainText} = A | _] ->
tuple_to_list(A);
@@ -466,10 +514,8 @@ api_ng() ->
[{doc, "Test new api"}].
api_ng(Config) when is_list(Config) ->
- Blocks = lazy_eval(proplists:get_value(block, Config, [])),
- Streams = lazy_eval(proplists:get_value(stream, Config, [])),
- lists:foreach(fun api_ng_cipher_increment/1, Blocks++Streams).
-
+ [_|_] = Ciphers = lazy_eval(proplists:get_value(cipher, Config, [])),
+ lists:foreach(fun api_ng_cipher_increment/1, Ciphers).
api_ng_cipher_increment({Type, Key, PlainTexts}=_X) ->
ct:log("~p",[_X]),
@@ -523,9 +569,8 @@ api_ng_one_shot() ->
[{doc, "Test new api"}].
api_ng_one_shot(Config) when is_list(Config) ->
- Blocks = lazy_eval(proplists:get_value(block, Config, [])),
- Streams = lazy_eval(proplists:get_value(stream, Config, [])),
- lists:foreach(fun do_api_ng_one_shot/1, Blocks++Streams).
+ [_|_] = Ciphers = lazy_eval(proplists:get_value(cipher, Config, [])),
+ lists:foreach(fun do_api_ng_one_shot/1, Ciphers).
do_api_ng_one_shot({Type, Key, PlainTexts}=_X) ->
ct:log("~p",[_X]),
@@ -537,8 +582,8 @@ do_api_ng_one_shot({Type, Key, IV, PlainTexts}=_X) ->
do_api_ng_one_shot({Type, Key, IV, PlainText0, ExpectedEncText}=_X) ->
ct:log("~p",[_X]),
- PlainText = iolist_to_binary(PlainText0),
- EncTxt = crypto:crypto_one_shot(Type, Key, IV, PlainText, true),
+ PlainText = iolist_to_binary(lazy_eval(PlainText0)),
+ EncTxt = crypto:crypto_one_time(Type, Key, IV, PlainText, true),
case ExpectedEncText of
undefined ->
ok;
@@ -546,14 +591,14 @@ do_api_ng_one_shot({Type, Key, IV, PlainText0, ExpectedEncText}=_X) ->
ok;
_ ->
ct:log("encode~nIn: ~p~nExpected: ~p~nEnc: ~p~n", [{Type,Key,IV,PlainText}, ExpectedEncText, EncTxt]),
- ct:fail("api_ng_one_shot (encode)",[])
+ ct:fail("api_ng_one_time (encode)",[])
end,
- case crypto:crypto_one_shot(Type, Key, IV, EncTxt, false) of
+ case crypto:crypto_one_time(Type, Key, IV, EncTxt, false) of
PlainText ->
ok;
OtherPT ->
ct:log("decode~nIn: ~p~nExpected: ~p~nDec: ~p~n", [{Type,Key,IV,EncTxt}, PlainText, OtherPT]),
- ct:fail("api_ng_one_shot (decode)",[])
+ ct:fail("api_ng_one_time (decode)",[])
end.
%%--------------------------------------------------------------------
@@ -561,9 +606,8 @@ api_ng_tls() ->
[{doc, "Test special tls api"}].
api_ng_tls(Config) when is_list(Config) ->
- Blocks = lazy_eval(proplists:get_value(block, Config, [])),
- Streams = lazy_eval(proplists:get_value(stream, Config, [])),
- lists:foreach(fun do_api_ng_tls/1, Blocks++Streams).
+ [_|_] = Ciphers = lazy_eval(proplists:get_value(cipher, Config, [])),
+ lists:foreach(fun do_api_ng_tls/1, Ciphers).
do_api_ng_tls({Type, Key, PlainTexts}=_X) ->
@@ -576,7 +620,7 @@ do_api_ng_tls({Type, Key, IV, PlainTexts}=_X) ->
do_api_ng_tls({Type, Key, IV, PlainText0, ExpectedEncText}=_X) ->
ct:log("~p",[_X]),
- PlainText = iolist_to_binary(PlainText0),
+ PlainText = iolist_to_binary(lazy_eval(PlainText0)),
Renc = crypto:crypto_init_dyn_iv(Type, Key, true),
Rdec = crypto:crypto_init_dyn_iv(Type, Key, false),
EncTxt = crypto:crypto_update_dyn_iv(Renc, PlainText, IV),
@@ -616,7 +660,7 @@ no_aead() ->
[{doc, "Test disabled aead ciphers"}].
no_aead(Config) when is_list(Config) ->
EncArg4 =
- case lazy_eval(proplists:get_value(aead, Config)) of
+ case lazy_eval(proplists:get_value(cipher, Config)) of
[{Type, Key, PlainText, Nonce, AAD, CipherText, CipherTag, TagLen, _Info} | _] ->
{AAD, PlainText, TagLen};
[{Type, Key, PlainText, Nonce, AAD, CipherText, CipherTag, _Info} | _] ->
@@ -631,7 +675,7 @@ no_aead(Config) when is_list(Config) ->
stream() ->
[{doc, "Test stream ciphers"}].
stream(Config) when is_list(Config) ->
- Streams = lazy_eval(proplists:get_value(stream, Config)),
+ [_|_] = Streams = lazy_eval(proplists:get_value(cipher, Config)),
lists:foreach(fun stream_cipher/1, Streams),
lists:foreach(fun stream_cipher/1, stream_iolistify(Streams)),
@@ -654,8 +698,7 @@ no_stream_ivec(Config) when is_list(Config) ->
aead() ->
[{doc, "Test AEAD ciphers"}].
aead(Config) when is_list(Config) ->
- AEADs = lazy_eval(proplists:get_value(aead, Config)),
-
+ [_|_] = AEADs = lazy_eval(proplists:get_value(cipher, Config)),
FilteredAEADs =
case proplists:get_bool(fips, Config) of
false ->
@@ -668,7 +711,6 @@ aead(Config) when is_list(Config) ->
IVLen >= 12
end, AEADs)
end,
-
lists:foreach(fun aead_cipher/1, FilteredAEADs).
%%--------------------------------------------------------------------
@@ -985,13 +1027,27 @@ block_cipher({Type, Key, IV, PlainText, CipherText}) ->
ct:fail({{crypto, block_decrypt, [Type, Key, IV, CipherText]}, {expected, Plain}, {got, Other1}})
end.
-block_cipher_increment({Type, Key, IV, PlainTexts})
- when Type == des_cbc; Type == aes_cbc; Type == des3_cbc ->
+block_cipher_increment({Type, Key, IV, PlainTexts}) when Type == des_cbc ;
+ Type == des3_cbc ;
+ Type == aes_128_cbc ;
+ Type == aes_192_cbc ;
+ Type == aes_256_cbc
+ ->
block_cipher_increment(Type, Key, IV, IV, PlainTexts, iolist_to_binary(PlainTexts), []);
-block_cipher_increment({Type, Key, IV, PlainTexts, CipherText})
- when Type == des_cbc; Type == des3_cbc ->
+block_cipher_increment({Type, Key, IV, PlainTexts, CipherText}) when Type == des_cbc;
+ Type == des_ede3_cbc ;
+ Type == des3_cbc ;
+ Type == des_ede3 ;
+ Type == des_ede3_cfb ;
+ Type == des_ede3_cbf ;
+ Type == des3_cbf ;
+ Type == des3_cfb
+ ->
block_cipher_increment(Type, Key, IV, IV, PlainTexts, iolist_to_binary(PlainTexts), CipherText, []);
-block_cipher_increment({Type, Key, IV, PlainTexts, _CipherText}) when Type == aes_cbc ->
+block_cipher_increment({Type, Key, IV, PlainTexts, _CipherText}) when Type == aes_128_cbc ;
+ Type == aes_192_cbc ;
+ Type == aes_256_cbc
+ ->
Plain = iolist_to_binary(PlainTexts),
Blocks = [iolistify(Block) || << Block:128/bitstring >> <= Plain],
block_cipher_increment(Type, Key, IV, IV, Blocks, Plain, []);
@@ -1025,8 +1081,9 @@ block_cipher_increment(Type, Key, IV0, IV, [PlainText | PlainTexts], Plain, Ciph
NextIV = crypto:next_iv(Type, CT),
block_cipher_increment(Type, Key, IV0, NextIV, PlainTexts, Plain, CipherText, [CT | Acc]).
-stream_cipher({Type, Key, PlainText}) ->
- Plain = iolist_to_binary(PlainText),
+stream_cipher({Type, Key, PlainText0}) ->
+ PlainText = lazy_eval(PlainText0),
+ Plain = iolist_to_binary(lazy_eval(PlainText)),
StateE = crypto:stream_init(Type, Key),
StateD = crypto:stream_init(Type, Key),
{_, CipherText} = crypto:stream_encrypt(StateE, PlainText),
@@ -1036,7 +1093,8 @@ stream_cipher({Type, Key, PlainText}) ->
Other ->
ct:fail({{crypto, stream_decrypt, [StateD, CipherText]}, {expected, PlainText}, {got, Other}})
end;
-stream_cipher({Type, Key, IV, PlainText}) ->
+stream_cipher({Type, Key, IV, PlainText0}) ->
+ PlainText = lazy_eval(PlainText0),
Plain = iolist_to_binary(PlainText),
StateE = crypto:stream_init(Type, Key, IV),
StateD = crypto:stream_init(Type, Key, IV),
@@ -1047,7 +1105,8 @@ stream_cipher({Type, Key, IV, PlainText}) ->
Other ->
ct:fail({{crypto, stream_decrypt, [StateD, CipherText]}, {expected, PlainText}, {got, Other}})
end;
-stream_cipher({Type, Key, IV, PlainText, CipherText}) ->
+stream_cipher({Type, Key, IV, PlainText0, CipherText}) ->
+ PlainText = lazy_eval(PlainText0),
Plain = iolist_to_binary(PlainText),
StateE = crypto:stream_init(Type, Key, IV),
StateD = crypto:stream_init(Type, Key, IV),
@@ -1112,7 +1171,7 @@ aead_cipher({Type, Key, PlainText, IV, AAD, CipherText, CipherTag, Info}) ->
aead_cipher({Type, Key, PlainText, IV, AAD, CipherText, CipherTag, TagLen, Info}) ->
<<TruncatedCipherTag:TagLen/binary, _/binary>> = CipherTag,
Plain = iolist_to_binary(PlainText),
- case crypto:block_encrypt(Type, Key, IV, {AAD, Plain, TagLen}) of
+ try crypto:block_encrypt(Type, Key, IV, {AAD, Plain, TagLen}) of
{CipherText, TruncatedCipherTag} ->
ok;
Other0 ->
@@ -1121,6 +1180,18 @@ aead_cipher({Type, Key, PlainText, IV, AAD, CipherText, CipherTag, TagLen, Info}
[{info,Info}, {key,Key}, {pt,PlainText}, {iv,IV}, {aad,AAD}, {ct,CipherText}, {tag,CipherTag}, {taglen,TagLen}]},
{expected, {CipherText, TruncatedCipherTag}},
{got, Other0}})
+ catch
+ error:E ->
+ ct:log("~p",[{Type, Key, PlainText, IV, AAD, CipherText, CipherTag, TagLen, Info}]),
+ try crypto:crypto_aead(Type, Key, IV, PlainText, AAD, TagLen, true)
+ of
+ RR ->
+ ct:log("Works: ~p",[RR])
+ catch
+ CC:EE ->
+ ct:log("~p:~p", [CC,EE])
+ end,
+ ct:fail("~p",[E])
end,
case crypto:block_decrypt(Type, Key, IV, {AAD, CipherText, TruncatedCipherTag}) of
Plain ->
@@ -1369,16 +1440,15 @@ do_stream_iolistify({Type, Key, IV, PlainText}) ->
{Type, iolistify(Key), IV, iolistify(PlainText)};
do_stream_iolistify({Type, Key, IV, PlainText, CipherText}) ->
{Type, iolistify(Key), IV, iolistify(PlainText), CipherText}.
-
-do_block_iolistify({des_cbc = Type, Key, IV, PlainText}) ->
- {Type, Key, IV, des_iolistify(PlainText)};
-do_block_iolistify({des3_cbc = Type, Key, IV, PlainText}) ->
- {Type, Key, IV, des_iolistify(PlainText)};
-do_block_iolistify({des3_cbf = Type, Key, IV, PlainText}) ->
- {Type, Key, IV, des_iolistify(PlainText)};
-do_block_iolistify({des3_cfb = Type, Key, IV, PlainText}) ->
- {Type, Key, IV, des_iolistify(PlainText)};
-do_block_iolistify({des_ede3 = Type, Key, IV, PlainText}) ->
+do_block_iolistify({Type, Key, IV, PlainText}) when Type == des_cbc ;
+ Type == des_ede3_cbc ;
+ Type == des3_cbc ;
+ Type == des_ede3 ;
+ Type == des_ede3_cfb ;
+ Type == des_ede3_cbf ;
+ Type == des3_cbf ;
+ Type == des3_cfb
+ ->
{Type, Key, IV, des_iolistify(PlainText)};
do_block_iolistify({Type, Key, PlainText}) ->
{Type, iolistify(Key), iolistify(PlainText)};
@@ -1387,10 +1457,13 @@ do_block_iolistify({Type, Key, IV, PlainText}) ->
do_block_iolistify({Type, Key, IV, PlainText, CipherText}) ->
{Type, iolistify(Key), IV, iolistify(PlainText), CipherText}.
-iolistify(<<"Test With Truncation">>)->
+iolistify(X) ->
+ iolistify1(lazy_eval(X)).
+
+iolistify1(<<"Test With Truncation">>)->
%% Do not iolistify as it spoils this special case
<<"Test With Truncation">>;
-iolistify(Msg) when is_binary(Msg) ->
+iolistify1(Msg) when is_binary(Msg) ->
Length = erlang:byte_size(Msg),
Split = Length div 2,
List0 = binary_to_list(Msg),
@@ -1400,8 +1473,8 @@ iolistify(Msg) when is_binary(Msg) ->
{List1, List2}->
[List1, List2]
end;
-iolistify(Msg) ->
- iolistify(list_to_binary(Msg)).
+iolistify1(Msg) when is_list(Msg) ->
+ iolistify1(list_to_binary(Msg)).
des_iolistify(Msg) ->
des_iolist(erlang:byte_size(Msg) div 8, Msg, []).
@@ -1710,7 +1783,6 @@ group_config(dss = Type, Config) ->
MsgPubEnc = <<"7896345786348 Asldi">>,
PubPrivEnc = [{dss, Public, Private, MsgPubEnc, []}],
[{sign_verify, SignVerify}, {pub_priv_encrypt, PubPrivEnc} | Config];
-
group_config(ecdsa = Type, Config) ->
{Private, Public} = ec_key_named(),
Msg = ec_msg(),
@@ -1722,15 +1794,13 @@ group_config(ecdsa = Type, Config) ->
MsgPubEnc = <<"7896345786348 Asldi">>,
PubPrivEnc = [{ecdsa, Public, Private, MsgPubEnc, []}],
[{sign_verify, SignVerify}, {pub_priv_encrypt, PubPrivEnc} | Config];
-
group_config(Type, Config) when Type == ed25519 ; Type == ed448 ->
TestVectors = eddsa(Type),
[{sign_verify,TestVectors} | Config];
-
-
group_config(srp, Config) ->
GenerateCompute = [srp3(), srp6(), srp6a(), srp6a_smaller_prime()],
[{generate_compute, GenerateCompute} | Config];
+
group_config(ecdh, Config) ->
Compute = ecdh(),
Generate = ecc(),
@@ -1738,77 +1808,19 @@ group_config(ecdh, Config) ->
group_config(dh, Config) ->
GenerateCompute = [dh()],
[{generate_compute, GenerateCompute} | Config];
-group_config(des_cbc, Config) ->
- Block = des_cbc(),
- [{block, Block} | Config];
-group_config(des_cfb, Config) ->
- Block = des_cfb(),
- [{block, Block} | Config];
-group_config(des3_cbc, Config) ->
- Block = des3_cbc(),
- [{block, Block} | Config];
-group_config(des3_cbf, Config) ->
- Block = des3_cbf(),
- [{block, Block} | Config];
-group_config(des3_cfb, Config) ->
- Block = des3_cfb(),
- [{block, Block} | Config];
-group_config(des_ede3, Config) ->
- Block = des_ede3(),
- [{block, Block} | Config];
-group_config(rc2_cbc, Config) ->
- Block = rc2_cbc(),
- [{block, Block} | Config];
+
group_config(aes_cbc128 = Type, Config) ->
Block = fun() -> aes_cbc128(Config) end,
Pairs = fun() -> cmac_nist(Config, Type) end,
- [{block, Block}, {cmac, Pairs} | Config];
+ [{cipher, Block}, {cmac, Pairs} | Config];
group_config(aes_cbc256 = Type, Config) ->
Block = fun() -> aes_cbc256(Config) end,
Pairs = fun() -> cmac_nist(Config, Type) end,
- [{block, Block}, {cmac, Pairs} | Config];
-group_config(aes_ecb, Config) ->
- Block = fun() -> aes_ecb(Config) end,
- [{block, Block} | Config];
-group_config(aes_ige256, Config) ->
- Block = aes_ige256(),
- [{block, Block} | Config];
-group_config(aes_cfb8, Config) ->
- Block = fun() -> aes_cfb8(Config) end,
- [{block, Block} | Config];
-group_config(aes_cfb128, Config) ->
- Block = fun() -> aes_cfb128(Config) end,
- [{block, Block} | Config];
-group_config(blowfish_cbc, Config) ->
- Block = blowfish_cbc(),
- [{block, Block} | Config];
-group_config(blowfish_ecb, Config) ->
- Block = blowfish_ecb(),
- [{block, Block} | Config];
-group_config(blowfish_cfb64, Config) ->
- Block = blowfish_cfb64(),
- [{block, Block} | Config];
-group_config(blowfish_ofb64, Config) ->
- Block = blowfish_ofb64(),
- [{block, Block} | Config];
-group_config(rc4, Config) ->
- Stream = rc4(),
- [{stream, Stream} | Config];
-group_config(aes_ctr, Config) ->
- Stream = aes_ctr(),
- [{stream, Stream} | Config];
-group_config(aes_ccm, Config) ->
- AEAD = fun() -> aes_ccm(Config) end,
- [{aead, AEAD} | Config];
-group_config(aes_gcm, Config) ->
- AEAD = fun() -> aes_gcm(Config) end,
- [{aead, AEAD} | Config];
+ [{cipher, Block}, {cmac, Pairs} | Config];
group_config(chacha20_poly1305, Config) ->
- AEAD = chacha20_poly1305(),
- [{aead, AEAD} | Config];
-group_config(chacha20, Config) ->
- Stream = chacha20(),
- [{stream, Stream} | Config];
+ AEAD = chacha20_poly1305(Config),
+ [{cipher, AEAD} | Config];
+
group_config(poly1305, Config) ->
V = [%% {Key, Txt, Expect}
{%% RFC7539 2.5.2
@@ -1818,11 +1830,12 @@ group_config(poly1305, Config) ->
}
],
[{poly1305,V} | Config];
-group_config(aes_cbc, Config) ->
- Block = aes_cbc(Config),
- [{block, Block} | Config];
-group_config(_, Config) ->
- Config.
+
+group_config(F, Config) ->
+ TestVectors = fun() -> ?MODULE:F(Config) end,
+ [{cipher, TestVectors} | Config].
+
+
rsa_sign_verify_tests(Config, Msg, Public, Private, PublicS, PrivateS, OptsToTry) ->
case ?config(fips, Config) of
@@ -2413,19 +2426,19 @@ rfc4231_hmac_sha512() ->
"debd71f8867289865df5a32d20cdc944"
"b6022cac3c4982b10d5eeb55c3e4de15"
"134676fb6de0446065c97440fa8c6a58")].
-des_cbc() ->
+des_cbc(_) ->
[{des_cbc,
hexstr2bin("0123456789abcdef"),
hexstr2bin("1234567890abcdef"),
<<"Now is the time for all ">> }].
-des_cfb() ->
+des_cfb(_) ->
[{des_cfb,
hexstr2bin("0123456789abcdef"),
hexstr2bin("1234567890abcdef"),
<<"Now is the">>}].
-des3_cbc() ->
+des3_cbc(_) ->
[{des3_cbc,
[hexstr2bin("0123456789abcdef"),
hexstr2bin("fedcba9876543210"),
@@ -2434,7 +2447,7 @@ des3_cbc() ->
<<"Now is the time for all ">>
}].
-des_ede3() ->
+des_ede3(_) ->
[{des_ede3,
[hexstr2bin("8000000000000000"),
hexstr2bin("4000000000000000"),
@@ -2443,7 +2456,23 @@ des_ede3() ->
hexstr2bin("0000000000000000")
}].
-des3_cbf() ->
+des_ede3_cbc(_) ->
+ [{des_ede3_cbc,
+ [hexstr2bin("0123456789abcdef"),
+ hexstr2bin("fedcba9876543210"),
+ hexstr2bin("0f2d4b6987a5c3e1")],
+ hexstr2bin("1234567890abcdef"),
+ <<"Now is the time for all ">>
+ },
+ {des_ede3_cbc,
+ [hexstr2bin("8000000000000000"),
+ hexstr2bin("4000000000000000"),
+ hexstr2bin("2000000000000000")],
+ hexstr2bin("7AD16FFB79C45926"),
+ hexstr2bin("0000000000000000")
+ }].
+
+des3_cbf(_) ->
[{des3_cbf,
[hexstr2bin("0123456789abcdef"),
hexstr2bin("fedcba9876543210"),
@@ -2452,7 +2481,7 @@ des3_cbf() ->
<<"Now is the time for all ">>
}].
-des3_cfb() ->
+des3_cfb(_) ->
[{des3_cfb,
[hexstr2bin("0123456789abcdef"),
hexstr2bin("fedcba9876543210"),
@@ -2461,7 +2490,16 @@ des3_cfb() ->
<<"Now is the time for all ">>
}].
-rc2_cbc() ->
+des_ede3_cfb(_) ->
+ [{des_ede3_cfb,
+ [hexstr2bin("0123456789abcdef"),
+ hexstr2bin("fedcba9876543210"),
+ hexstr2bin("0f2d4b6987a5c3e1")],
+ hexstr2bin("1234567890abcdef"),
+ <<"Now is the time for all ">>
+ }].
+
+rc2_cbc(_) ->
[{rc2_cbc,
<<146,210,160,124,215,227,153,239,227,17,222,140,3,93,27,191>>,
<<72,91,135,182,25,42,35,210>>,
@@ -2470,7 +2508,8 @@ rc2_cbc() ->
%% AES CBC test vectors from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
aes_cbc(Config) ->
- read_rsp(Config, aes_cbc,
+ %% RETIRED aes_*_cbc
+ read_rsp(Config, aes_cbc,
["CBCVarTxt128.rsp", "CBCVarKey128.rsp", "CBCGFSbox128.rsp", "CBCKeySbox128.rsp",
"CBCVarTxt192.rsp", "CBCVarKey192.rsp", "CBCGFSbox192.rsp", "CBCKeySbox192.rsp",
"CBCVarTxt256.rsp", "CBCVarKey256.rsp", "CBCGFSbox256.rsp", "CBCKeySbox256.rsp",
@@ -2478,15 +2517,32 @@ aes_cbc(Config) ->
]).
aes_cbc128(Config) ->
+ %% RETIRED aes_128_cbc
read_rsp(Config, aes_cbc128,
["CBCVarTxt128.rsp", "CBCVarKey128.rsp", "CBCGFSbox128.rsp", "CBCKeySbox128.rsp",
"CBCMMT128.rsp"]).
aes_cbc256(Config) ->
+ %% RETIRED aes_256_cbc
read_rsp(Config, aes_cbc256,
["CBCVarTxt256.rsp", "CBCVarKey256.rsp", "CBCGFSbox256.rsp", "CBCKeySbox256.rsp",
"CBCMMT256.rsp"]).
+aes_128_cbc(Config) ->
+ read_rsp(Config, aes_128_cbc,
+ ["CBCVarTxt128.rsp", "CBCVarKey128.rsp", "CBCGFSbox128.rsp", "CBCKeySbox128.rsp",
+ "CBCMMT128.rsp"]).
+
+aes_192_cbc(Config) ->
+ read_rsp(Config, aes_192_cbc,
+ ["CBCVarTxt192.rsp", "CBCVarKey192.rsp", "CBCGFSbox192.rsp", "CBCKeySbox192.rsp",
+ "CBCMMT192.rsp"]).
+
+aes_256_cbc(Config) ->
+ read_rsp(Config, aes_256_cbc,
+ ["CBCVarTxt256.rsp", "CBCVarKey256.rsp", "CBCGFSbox256.rsp", "CBCKeySbox256.rsp",
+ "CBCMMT256.rsp"]).
+
aes_ecb(Config) ->
read_rsp(Config, aes_ecb,
["ECBVarTxt128.rsp", "ECBVarKey128.rsp", "ECBGFSbox128.rsp", "ECBKeySbox128.rsp",
@@ -2494,7 +2550,22 @@ aes_ecb(Config) ->
"ECBVarTxt256.rsp", "ECBVarKey256.rsp", "ECBGFSbox256.rsp", "ECBKeySbox256.rsp",
"ECBMMT128.rsp", "ECBMMT192.rsp", "ECBMMT256.rsp"]).
-aes_ige256() ->
+aes_128_ecb(Config) ->
+ read_rsp(Config, aes_128_ecb,
+ ["ECBVarTxt128.rsp", "ECBVarKey128.rsp", "ECBGFSbox128.rsp", "ECBKeySbox128.rsp",
+ "ECBMMT128.rsp"]).
+
+aes_192_ecb(Config) ->
+ read_rsp(Config, aes_192_ecb,
+ ["ECBVarTxt192.rsp", "ECBVarKey192.rsp", "ECBGFSbox192.rsp", "ECBKeySbox192.rsp",
+ "ECBMMT192.rsp"]).
+
+aes_256_ecb(Config) ->
+ read_rsp(Config, aes_256_ecb,
+ ["ECBVarTxt256.rsp", "ECBVarKey256.rsp", "ECBGFSbox256.rsp", "ECBKeySbox256.rsp",
+ "ECBMMT256.rsp"]).
+
+aes_ige256(_) ->
[{aes_ige256,
hexstr2bin("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"),
hexstr2bin("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"),
@@ -2527,14 +2598,14 @@ aes_cfb128(Config) ->
"CFB128VarTxt256.rsp", "CFB128VarKey256.rsp", "CFB128GFSbox256.rsp", "CFB128KeySbox256.rsp",
"CFB128MMT128.rsp", "CFB128MMT192.rsp", "CFB128MMT256.rsp"]).
-blowfish_cbc() ->
+blowfish_cbc(_) ->
[{blowfish_cbc,
hexstr2bin("0123456789ABCDEFF0E1D2C3B4A59687"),
hexstr2bin("FEDCBA9876543210"),
hexstr2bin("37363534333231204E6F77206973207468652074696D6520666F722000000000")
}].
-blowfish_ecb() ->
+blowfish_ecb(_) ->
[
{blowfish_ecb,
hexstr2bin("0000000000000000"),
@@ -2631,26 +2702,26 @@ blowfish_ecb() ->
hexstr2bin("FFFFFFFFFFFFFFFF")}
].
-blowfish_cfb64() ->
+blowfish_cfb64(_) ->
[{blowfish_cfb64,
hexstr2bin("0123456789ABCDEFF0E1D2C3B4A59687"),
hexstr2bin("FEDCBA9876543210"),
hexstr2bin("37363534333231204E6F77206973207468652074696D6520666F722000")
}].
-blowfish_ofb64() ->
+blowfish_ofb64(_) ->
[{blowfish_ofb64,
hexstr2bin("0123456789ABCDEFF0E1D2C3B4A59687"),
hexstr2bin("FEDCBA9876543210"),
hexstr2bin("37363534333231204E6F77206973207468652074696D6520666F722000")
}].
-rc4() ->
+rc4(_) ->
[{rc4, <<"apaapa">>, <<"Yo baby yo">>},
{rc4, <<"apaapa">>, list_to_binary(lists:seq(0, 255))},
{rc4, <<"apaapa">>, long_msg()}
].
-aes_ctr() ->
+aes_ctr(_) ->
[ %% F.5.3 CTR-AES192.Encrypt
{aes_ctr, hexstr2bin("2b7e151628aed2a6abf7158809cf4f3c"),
hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"),
@@ -2699,24 +2770,109 @@ aes_ctr() ->
].
+aes_128_ctr(_) ->
+ [ %% F.5.3 CTR-AES192.Encrypt
+ {aes_128_ctr, hexstr2bin("2b7e151628aed2a6abf7158809cf4f3c"),
+ hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"),
+ hexstr2bin("6bc1bee22e409f96e93d7e117393172a")},
+ {aes_128_ctr, hexstr2bin("2b7e151628aed2a6abf7158809cf4f3c"),
+ hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdff00"),
+ hexstr2bin("ae2d8a571e03ac9c9eb76fac45af8e51")},
+ {aes_128_ctr, hexstr2bin("2b7e151628aed2a6abf7158809cf4f3c"),
+ hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdff01"),
+ hexstr2bin("30c81c46a35ce411e5fbc1191a0a52ef") },
+ {aes_128_ctr, hexstr2bin("2b7e151628aed2a6abf7158809cf4f3c"),
+ hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdff02"),
+ hexstr2bin("f69f2445df4f9b17ad2b417be66c3710")}
+ ].
+
+aes_192_ctr(_) ->
+ [ %% F.5.3 CTR-AES192.Encrypt
+ {aes_192_ctr, hexstr2bin("8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"),
+ hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"),
+ hexstr2bin("6bc1bee22e409f96e93d7e117393172a")},
+ {aes_192_ctr, hexstr2bin("8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"),
+ hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdff00"),
+ hexstr2bin("ae2d8a571e03ac9c9eb76fac45af8e51")},
+ {aes_192_ctr, hexstr2bin("8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"),
+ hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdff01"),
+ hexstr2bin("30c81c46a35ce411e5fbc1191a0a52ef")},
+ {aes_192_ctr, hexstr2bin("8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"),
+ hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdff02"),
+ hexstr2bin("f69f2445df4f9b17ad2b417be66c3710")}
+ ].
+
+aes_256_ctr(_) ->
+ [ %% F.5.5 CTR-AES256.Encrypt
+ {aes_256_ctr, hexstr2bin("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"),
+ hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"),
+ hexstr2bin("6bc1bee22e409f96e93d7e117393172a")},
+ {aes_256_ctr, hexstr2bin("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"),
+ hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdff00"),
+ hexstr2bin("ae2d8a571e03ac9c9eb76fac45af8e51")},
+ {aes_256_ctr, hexstr2bin("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"),
+ hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdff01"),
+ hexstr2bin("30c81c46a35ce411e5fbc1191a0a52ef")},
+ {aes_256_ctr, hexstr2bin("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"),
+ hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdff02"),
+ hexstr2bin("f69f2445df4f9b17ad2b417be66c3710")},
+
+ {aes_256_ctr, hexstr2bin("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"),
+ hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"),
+ long_msg()}
+ ].
+
+
aes_gcm(Config) ->
- read_rsp(Config, aes_gcm,
+ %% RETIRED aes_*_gcm
+ read_rsp(Config, aes_gcm,
+ ["gcmDecrypt128.rsp",
+ "gcmDecrypt192.rsp",
+ "gcmDecrypt256.rsp",
+ "gcmEncryptExtIV128.rsp",
+ "gcmEncryptExtIV192.rsp",
+ "gcmEncryptExtIV256.rsp"]).
+
+aes_128_gcm(Config) ->
+ read_rsp(Config, aes_128_gcm,
["gcmDecrypt128.rsp",
- "gcmDecrypt192.rsp",
- "gcmDecrypt256.rsp",
- "gcmEncryptExtIV128.rsp",
- "gcmEncryptExtIV192.rsp",
+ "gcmEncryptExtIV128.rsp"]).
+
+aes_192_gcm(Config) ->
+ read_rsp(Config, aes_192_gcm,
+ ["gcmDecrypt192.rsp",
+ "gcmEncryptExtIV192.rsp"]).
+
+aes_256_gcm(Config) ->
+ read_rsp(Config, aes_256_gcm,
+ ["gcmDecrypt256.rsp",
"gcmEncryptExtIV256.rsp"]).
+
aes_ccm(Config) ->
- read_rsp(Config, aes_ccm,
- ["VADT128.rsp", "VADT192.rsp", "VADT256.rsp",
- "VNT128.rsp", "VNT192.rsp", "VNT256.rsp",
- "VPT128.rsp", "VPT192.rsp", "VPT256.rsp"
- ]).
+ %% RETIRED aes_*_ccm
+ read_rsp(Config, aes_ccm,
+ ["VADT128.rsp", "VADT192.rsp", "VADT256.rsp",
+ "VNT128.rsp", "VNT192.rsp", "VNT256.rsp",
+ "VPT128.rsp", "VPT192.rsp", "VPT256.rsp"
+ ]).
+
+aes_128_ccm(Config) ->
+ read_rsp(Config, aes_128_ccm,
+ ["VADT128.rsp", "VNT128.rsp", "VPT128.rsp"]).
+
+aes_192_ccm(Config) ->
+ read_rsp(Config, aes_192_ccm,
+ ["VADT192.rsp", "VNT192.rsp", "VPT192.rsp"]).
+
+aes_256_ccm(Config) ->
+ read_rsp(Config, aes_256_ccm,
+ ["VADT256.rsp", "VNT256.rsp", "VPT256.rsp"]).
+
+
%% https://tools.ietf.org/html/rfc7539#appendix-A.5
-chacha20_poly1305() ->
+chacha20_poly1305(_) ->
[
{chacha20_poly1305,
hexstr2bin("1c9240a5eb55d38af333888604f6b5f0" %% Key
@@ -2763,7 +2919,7 @@ chacha20_poly1305() ->
].
-chacha20() ->
+chacha20(_) ->
%%% chacha20 (no mode) test vectors from RFC 7539 A.2
[
%% Test Vector #1:
@@ -3697,9 +3853,18 @@ parse_rsp(_Type, [], _State, Acc) ->
Acc;
parse_rsp(_Type, [<<"DECRYPT">>|_], _State, Acc) ->
Acc;
+parse_rsp(_Type, [<<"ENCRYPT">>|_], _State, Acc) ->
+ Acc;
%% AES format
parse_rsp(Type, [<<"COUNT = ", _/binary>>,
<<"KEY = ", Key/binary>>,
+ <<"PLAINTEXT = ", PlainText/binary>>,
+ <<"CIPHERTEXT = ", CipherText/binary>>|Next], State, Acc) ->
+ parse_rsp(Type, Next, State,
+ [{Type, hexstr2bin(Key),
+ hexstr2bin(PlainText), hexstr2bin(CipherText)}|Acc]);
+parse_rsp(Type, [<<"COUNT = ", _/binary>>,
+ <<"KEY = ", Key/binary>>,
<<"IV = ", IV/binary>>,
<<"PLAINTEXT = ", PlainText/binary>>,
<<"CIPHERTEXT = ", CipherText/binary>>|Next], State, Acc) ->
diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl
index 1f4e281a30..2299346a30 100644
--- a/lib/ssh/src/ssh_transport.erl
+++ b/lib/ssh/src/ssh_transport.erl
@@ -170,7 +170,7 @@ supported_algorithms(cipher) ->
{'AEAD_AES_256_GCM', [{ciphers,aes_256_gcm}]},
{'AEAD_AES_128_GCM', [{ciphers,aes_128_gcm}]},
{'aes128-cbc', [{ciphers,aes_128_cbc}]},
- {'3des-cbc', [{ciphers,des3_cbc}]}
+ {'3des-cbc', [{ciphers,des_ede3_cbc}]}
]
));
supported_algorithms(mac) ->
@@ -1340,7 +1340,7 @@ cipher('AEAD_AES_256_GCM') ->
pkt_type = aead};
cipher('3des-cbc') ->
- #cipher{impl = des3_cbc,
+ #cipher{impl = des_ede3_cbc,
key_bytes = 24,
iv_bytes = 8,
block_bytes = 8};
@@ -1445,12 +1445,12 @@ encrypt(#ssh{encrypt = '[email protected]',
<<LenData:4/binary, PayloadData/binary>>) ->
%% Encrypt length
IV1 = <<0:8/unit:8, Seq:8/unit:8>>,
- EncLen = crypto:crypto_one_shot(chacha20, K1, IV1, LenData, true),
+ EncLen = crypto:crypto_one_time(chacha20, K1, IV1, LenData, true),
%% Encrypt payload
IV2 = <<1:8/little-unit:8, Seq:8/unit:8>>,
- EncPayloadData = crypto:crypto_one_shot(chacha20, K2, IV2, PayloadData, true),
+ EncPayloadData = crypto:crypto_one_time(chacha20, K2, IV2, PayloadData, true),
%% MAC tag
- PolyKey = crypto:crypto_one_shot(chacha20, K2, <<0:8/unit:8,Seq:8/unit:8>>, <<0:32/unit:8>>, true),
+ PolyKey = crypto:crypto_one_time(chacha20, K2, <<0:8/unit:8,Seq:8/unit:8>>, <<0:32/unit:8>>, true),
EncBytes = <<EncLen/binary,EncPayloadData/binary>>,
Ctag = crypto:poly1305(PolyKey, EncBytes),
%% Result
@@ -1519,7 +1519,7 @@ decrypt(Ssh, <<>>) ->
decrypt(#ssh{decrypt = '[email protected]',
decrypt_keys = {K1,_K2},
recv_sequence = Seq} = Ssh, {length,EncryptedLen}) ->
- PacketLenBin = crypto:crypto_one_shot(chacha20, K1, <<0:8/unit:8, Seq:8/unit:8>>, EncryptedLen, false),
+ PacketLenBin = crypto:crypto_one_time(chacha20, K1, <<0:8/unit:8, Seq:8/unit:8>>, EncryptedLen, false),
{Ssh, PacketLenBin};
decrypt(#ssh{decrypt = '[email protected]',
@@ -1527,12 +1527,12 @@ decrypt(#ssh{decrypt = '[email protected]',
recv_sequence = Seq} = Ssh, {AAD,Ctext,Ctag}) ->
%% The length is already decoded and used to divide the input
%% Check the mac (important that it is timing-safe):
- PolyKey = crypto:crypto_one_shot(chacha20, K2, <<0:8/unit:8,Seq:8/unit:8>>, <<0:32/unit:8>>, false),
+ PolyKey = crypto:crypto_one_time(chacha20, K2, <<0:8/unit:8,Seq:8/unit:8>>, <<0:32/unit:8>>, false),
case equal_const_time(Ctag, crypto:poly1305(PolyKey, <<AAD/binary,Ctext/binary>>)) of
true ->
%% MAC is ok, decode
IV2 = <<1:8/little-unit:8, Seq:8/unit:8>>,
- PlainText = crypto:crypto_one_shot(chacha20, K2, IV2, Ctext, false),
+ PlainText = crypto:crypto_one_time(chacha20, K2, IV2, Ctext, false),
{Ssh, PlainText};
false ->
{Ssh,error}