aboutsummaryrefslogtreecommitdiffstats
path: root/lib/crypto
diff options
context:
space:
mode:
authorSverker Eriksson <[email protected]>2016-04-18 15:16:04 +0200
committerSverker Eriksson <[email protected]>2016-04-18 15:16:04 +0200
commit77c3110b00d7f5e80ca1da77df79650e2fa66efe (patch)
tree3d2adb583f71535749b7aadfe9f62074ab3c4a34 /lib/crypto
parent6aa696eb58127f3da12ad1640347fd5c285954a6 (diff)
parentb3d2334d78fe23502b81ae095617fb585d0ba3c3 (diff)
downloadotp-77c3110b00d7f5e80ca1da77df79650e2fa66efe.tar.gz
otp-77c3110b00d7f5e80ca1da77df79650e2fa66efe.tar.bz2
otp-77c3110b00d7f5e80ca1da77df79650e2fa66efe.zip
Merge branch 'mururu/crypto/aes-gcm-tag-len.PR-998.OTP-13483'
Diffstat (limited to 'lib/crypto')
-rw-r--r--lib/crypto/c_src/crypto.c14
-rw-r--r--lib/crypto/doc/src/crypto.xml2
-rw-r--r--lib/crypto/src/crypto.erl7
-rw-r--r--lib/crypto/test/crypto_SUITE.erl46
4 files changed, 61 insertions, 8 deletions
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index 768922d57a..1be22a0b8a 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},
@@ -1648,6 +1648,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;
@@ -1656,7 +1657,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);
}
@@ -1688,9 +1690,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);
@@ -1723,7 +1725,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);
}
@@ -1749,7 +1751,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 60fdc627fd..e0b989436f 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -203,6 +203,7 @@
<func>
<name>block_encrypt(Type, Key, Ivec, PlainText) -> CipherText</name>
<name>block_encrypt(AeadType, Key, Ivec, {AAD, PlainText}) -> {CipherText, CipherTag}</name>
+ <name>block_encrypt(aes_gcm, Key, Ivec, {AAD, PlainText, TagLength}) -> {CipherText, CipherTag}</name>
<fsummary>Encrypt <c>PlainText</c> according to <c>Type</c> block cipher</fsummary>
<type>
<v>Type = block_cipher() </v>
@@ -210,6 +211,7 @@
<v>Key = block_key() </v>
<v>PlainText = iodata() </v>
<v>AAD = IVec = CipherText = CipherTag = binary()</v>
+ <v>TagLength = 1..16</v>
</type>
<desc>
<p>Encrypt <c>PlainText</c> according to <c>Type</c> block cipher.
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index fb252118a3..a154476560 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.
%%
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index fc85019705..0d18cd8017 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -462,6 +462,21 @@ aead_cipher({Type, Key, PlainText, IV, AAD, CipherText, CipherTag}) ->
ok;
Other1 ->
ct:fail({{crypto, block_decrypt, [CipherText]}, {expected, Plain}, {got, Other1}})
+ end;
+aead_cipher({Type, Key, PlainText, IV, AAD, CipherText, CipherTag, TagLen}) ->
+ <<TruncatedCipherTag:TagLen/binary, _/binary>> = CipherTag,
+ Plain = iolist_to_binary(PlainText),
+ case crypto:block_encrypt(Type, Key, IV, {AAD, Plain, TagLen}) of
+ {CipherText, TruncatedCipherTag} ->
+ ok;
+ Other0 ->
+ ct:fail({{crypto, block_encrypt, [Plain, PlainText]}, {expected, {CipherText, TruncatedCipherTag}}, {got, Other0}})
+ end,
+ case crypto:block_decrypt(Type, Key, IV, {AAD, CipherText, TruncatedCipherTag}) of
+ Plain ->
+ ok;
+ Other1 ->
+ ct:fail({{crypto, block_decrypt, [CipherText]}, {expected, Plain}, {got, Other1}})
end.
do_sign_verify({Type, Hash, Public, Private, Msg}) ->
@@ -1938,7 +1953,36 @@ aes_gcm() ->
"eeb2b22aafde6419a058ab4f6f746bf4"
"0fc0c3b780f244452da3ebf1c5d82cde"
"a2418997200ef82e44ae7e3f"),
- hexstr2bin("a44a8266ee1c8eb0c8b5d4cf5ae9f19a")} %% CipherTag
+ hexstr2bin("a44a8266ee1c8eb0c8b5d4cf5ae9f19a")}, %% CipherTag
+
+ %% Test Case 0 for TagLength = 1
+ {aes_gcm, hexstr2bin("00000000000000000000000000000000"), %% Key
+ hexstr2bin(""), %% PlainText
+ hexstr2bin("000000000000000000000000"), %% IV
+ hexstr2bin(""), %% AAD
+ hexstr2bin(""), %% CipherText
+ hexstr2bin("58"), %% CipherTag
+ 1}, %% TagLength
+
+ %% Test Case 18 for TagLength = 1
+ {aes_gcm, hexstr2bin("feffe9928665731c6d6a8f9467308308" %% Key
+ "feffe9928665731c6d6a8f9467308308"),
+ hexstr2bin("d9313225f88406e5a55909c5aff5269a" %% PlainText
+ "86a7a9531534f7da2e4c303d8a318a72"
+ "1c3c0c95956809532fcf0e2449a6b525"
+ "b16aedf5aa0de657ba637b39"),
+ hexstr2bin("9313225df88406e555909c5aff5269aa" %% IV
+ "6a7a9538534f7da1e4c303d2a318a728"
+ "c3c0c95156809539fcf0e2429a6b5254"
+ "16aedbf5a0de6a57a637b39b"),
+ hexstr2bin("feedfacedeadbeeffeedfacedeadbeef" %% AAD
+ "abaddad2"),
+ hexstr2bin("5a8def2f0c9e53f1f75d7853659e2a20" %% CipherText
+ "eeb2b22aafde6419a058ab4f6f746bf4"
+ "0fc0c3b780f244452da3ebf1c5d82cde"
+ "a2418997200ef82e44ae7e3f"),
+ hexstr2bin("a4"), %% CipherTag
+ 1} %% TagLength
].
%% http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04