From f4f588683dce36c4470171cb6af74763778498ff Mon Sep 17 00:00:00 2001 From: Yuki Ito Date: Fri, 25 Mar 2016 17:55:17 +0900 Subject: crypto: Enable AES-GCM tag length to change This commit enables AES-GCM encryption/decryption to change its tag length between 1 to 16 bytes. --- lib/crypto/c_src/crypto.c | 14 ++++++++------ lib/crypto/doc/src/crypto.xml | 2 ++ lib/crypto/src/crypto.erl | 7 ++++++- 3 files changed, 16 insertions(+), 7 deletions(-) (limited to 'lib/crypto') diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index d1f620d892..e77bbe184b 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -314,7 +314,7 @@ static ErlNifFunc nif_funcs[] = { {"rand_seed_nif", 1, rand_seed_nif}, - {"aes_gcm_encrypt", 4, aes_gcm_encrypt}, + {"aes_gcm_encrypt", 5, aes_gcm_encrypt}, {"aes_gcm_decrypt", 5, aes_gcm_decrypt}, {"chacha20_poly1305_encrypt", 4, chacha20_poly1305_encrypt}, @@ -1629,6 +1629,7 @@ static ERL_NIF_TERM aes_gcm_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM EVP_CIPHER_CTX ctx; const EVP_CIPHER *cipher = NULL; ErlNifBinary key, iv, aad, in; + unsigned int tag_len; unsigned char *outp, *tagp; ERL_NIF_TERM out, out_tag; int len; @@ -1637,7 +1638,8 @@ static ERL_NIF_TERM aes_gcm_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM || (key.size != 16 && key.size != 24 && key.size != 32) || !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0 || !enif_inspect_iolist_as_binary(env, argv[2], &aad) - || !enif_inspect_iolist_as_binary(env, argv[3], &in)) { + || !enif_inspect_iolist_as_binary(env, argv[3], &in) + || !enif_get_uint(env, argv[4], &tag_len) || tag_len < 1 || tag_len > 16) { return enif_make_badarg(env); } @@ -1669,9 +1671,9 @@ static ERL_NIF_TERM aes_gcm_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM if (EVP_EncryptFinal_ex(&ctx, outp+len, &len) != 1) goto out_err; - tagp = enif_make_new_binary(env, EVP_GCM_TLS_TAG_LEN, &out_tag); + tagp = enif_make_new_binary(env, tag_len, &out_tag); - if (EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_GET_TAG, EVP_GCM_TLS_TAG_LEN, tagp) != 1) + if (EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_GET_TAG, tag_len, tagp) != 1) goto out_err; EVP_CIPHER_CTX_cleanup(&ctx); @@ -1704,7 +1706,7 @@ static ERL_NIF_TERM aes_gcm_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM || !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0 || !enif_inspect_iolist_as_binary(env, argv[2], &aad) || !enif_inspect_iolist_as_binary(env, argv[3], &in) - || !enif_inspect_iolist_as_binary(env, argv[4], &tag) || tag.size != EVP_GCM_TLS_TAG_LEN) { + || !enif_inspect_iolist_as_binary(env, argv[4], &tag)) { return enif_make_badarg(env); } @@ -1730,7 +1732,7 @@ static ERL_NIF_TERM aes_gcm_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM if (EVP_DecryptUpdate(&ctx, outp, &len, in.data, in.size) != 1) goto out_err; - if (EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_TAG, EVP_GCM_TLS_TAG_LEN, tag.data) != 1) + if (EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_TAG, tag.size, tag.data) != 1) goto out_err; if (EVP_DecryptFinal_ex(&ctx, outp+len, &len) != 1) goto out_err; diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml index d3e827b3e6..9cb9587964 100644 --- a/lib/crypto/doc/src/crypto.xml +++ b/lib/crypto/doc/src/crypto.xml @@ -203,6 +203,7 @@ block_encrypt(Type, Key, Ivec, PlainText) -> CipherText block_encrypt(AeadType, Key, Ivec, {AAD, PlainText}) -> {CipherText, CipherTag} + block_encrypt(aes_gcm, Key, Ivec, {AAD, PlainText, TagLength}) -> {CipherText, CipherTag} Encrypt PlainText according to Type block cipher Type = block_cipher() @@ -210,6 +211,7 @@ Key = block_key() PlainText = iodata() AAD = IVec = CipherText = CipherTag = binary() + TagLength = 1..16

Encrypt PlainText according to Type block cipher. diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 3e24ff2b0a..a9dbca3caf 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -302,6 +302,8 @@ block_encrypt(aes_ige256, Key, Ivec, Data) -> aes_ige_crypt_nif(Key, Ivec, Data, true); block_encrypt(aes_gcm, Key, Ivec, {AAD, Data}) -> aes_gcm_encrypt(Key, Ivec, AAD, Data); +block_encrypt(aes_gcm, Key, Ivec, {AAD, Data, TagLength}) -> + aes_gcm_encrypt(Key, Ivec, AAD, Data, TagLength); block_encrypt(chacha20_poly1305, Key, Ivec, {AAD, Data}) -> chacha20_poly1305_encrypt(Key, Ivec, AAD, Data). @@ -917,7 +919,10 @@ aes_cfb_128_decrypt(Key, IVec, Data) -> %% %% AES - in Galois/Counter Mode (GCM) %% -aes_gcm_encrypt(_Key, _Ivec, _AAD, _In) -> ?nif_stub. +%% The default tag length is EVP_GCM_TLS_TAG_LEN(16), +aes_gcm_encrypt(Key, Ivec, AAD, In) -> + aes_gcm_encrypt(Key, Ivec, AAD, In, 16). +aes_gcm_encrypt(_Key, _Ivec, _AAD, _In, _TagLength) -> ?nif_stub. aes_gcm_decrypt(_Key, _Ivec, _AAD, _In, _Tag) -> ?nif_stub. %% -- cgit v1.2.3