aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYura Beznos <[email protected]>2013-08-13 19:00:00 +0400
committerHenrik Nord <[email protected]>2013-09-30 15:36:16 +0200
commit9f2cdf704fa0732817b4c49067cd561dd13ff730 (patch)
treec276add5ec76f39e222adb9f55ed5d1e439bf7cb
parentb44a8d0e488be8ecbb018fbdb3926e129caf0ed0 (diff)
downloadotp-9f2cdf704fa0732817b4c49067cd561dd13ff730.tar.gz
otp-9f2cdf704fa0732817b4c49067cd561dd13ff730.tar.bz2
otp-9f2cdf704fa0732817b4c49067cd561dd13ff730.zip
crypto: Add IGE mode for AES
-rw-r--r--lib/crypto/c_src/crypto.c37
-rw-r--r--lib/crypto/doc/src/crypto.xml4
-rw-r--r--lib/crypto/src/crypto.erl44
-rw-r--r--lib/crypto/test/crypto_SUITE.erl24
4 files changed, 103 insertions, 6 deletions
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index c28ff8136c..5caa47bcf4 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -221,6 +221,7 @@ static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
static ERL_NIF_TERM dss_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM aes_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM aes_ige_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM do_exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_set_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -349,6 +350,7 @@ static ErlNifFunc nif_funcs[] = {
{"dss_verify_nif", 4, dss_verify_nif},
{"rsa_verify_nif", 4, rsa_verify_nif},
{"aes_cbc_crypt", 4, aes_cbc_crypt},
+ {"aes_ige_crypt", 4, aes_ige_crypt},
{"do_exor", 2, do_exor},
{"rc4_encrypt", 2, rc4_encrypt},
{"rc4_set_key", 1, rc4_set_key},
@@ -2090,6 +2092,41 @@ static ERL_NIF_TERM aes_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
return ret;
}
+static ERL_NIF_TERM aes_ige_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Key, IVec, Data, IsEncrypt) */
+ ErlNifBinary key_bin, ivec_bin, data_bin;
+ AES_KEY aes_key;
+ unsigned char ivec[32];
+ int i;
+ unsigned char* ret_ptr;
+ ERL_NIF_TERM ret;
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &key_bin)
+ || (key_bin.size != 16 && key_bin.size != 32)
+ || !enif_inspect_binary(env, argv[1], &ivec_bin)
+ || ivec_bin.size != 32
+ || !enif_inspect_iolist_as_binary(env, argv[2], &data_bin)
+ || data_bin.size % 16 != 0) {
+
+ return enif_make_badarg(env);
+ }
+
+ if (argv[3] == atom_true) {
+ i = AES_ENCRYPT;
+ AES_set_encrypt_key(key_bin.data, key_bin.size*8, &aes_key);
+ }
+ else {
+ i = AES_DECRYPT;
+ AES_set_decrypt_key(key_bin.data, key_bin.size*8, &aes_key);
+ }
+
+ ret_ptr = enif_make_new_binary(env, data_bin.size, &ret);
+ memcpy(ivec, ivec_bin.data, 32); /* writable copy */
+ AES_ige_encrypt(data_bin.data, ret_ptr, data_bin.size, &aes_key, ivec, i);
+ CONSUME_REDS(env,data_bin);
+ return ret;
+}
+
static ERL_NIF_TERM do_exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Data1, Data2) */
ErlNifBinary d1, d2;
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index 5bb2365109..49c020dbe5 100644
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -118,7 +118,7 @@
<p><code>stream_cipher() = rc4 | aes_ctr </code></p>
- <p><code>block_cipher() = aes_cbc128 | aes_cfb128 | blowfish_cbc |
+ <p><code>block_cipher() = aes_cbc128 | aes_cfb128 | aes_ige256 | blowfish_cbc |
blowfish_cfb64 | des_cbc | des_cfb | des3_cbc | des3_cbf
| des_ede3 | rc2_cbc </code></p>
@@ -142,7 +142,7 @@
Note that both md4 and md5 are recommended only for compatibility with existing applications.
</p>
<p><code> cipher_algorithms() = des_cbc | des_cfb | des3_cbc | des3_cbf | des_ede3 |
- blowfish_cbc | blowfish_cfb64 | aes_cbc128 | aes_cfb128| aes_cbc256 | rc2_cbc | aes_ctr| rc4 </code> </p>
+ blowfish_cbc | blowfish_cfb64 | aes_cbc128 | aes_cfb128| aes_cbc256 | aes_ige256 | rc2_cbc | aes_ctr| rc4 </code> </p>
<p><code> public_key_algorithms() = rsa |dss | ecdsa | dh | ecdh </code> </p>
</section>
diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl
index 8e8370f3b0..0e8b80c1f9 100644
--- a/lib/crypto/src/crypto.erl
+++ b/lib/crypto/src/crypto.erl
@@ -215,7 +215,7 @@ supports()->
[{hashs, Algs -- [ec]},
{ciphers, [des_cbc, des_cfb, des3_cbc, des3_cbf, des_ede3, blowfish_cbc,
blowfish_cfb64, blowfish_ofb64, blowfish_ecb, aes_cbc128, aes_cfb128,
- aes_cbc256, rc2_cbc, aes_ctr, rc4
+ aes_cbc256, aes_ige256, rc2_cbc, aes_ctr, rc4
]},
PubKeyAlgs
].
@@ -309,13 +309,16 @@ block_encrypt(aes_cbc128, Key, Ivec, Data) ->
aes_cbc_128_encrypt(Key, Ivec, Data);
block_encrypt(aes_cbc256, Key, Ivec, Data) ->
aes_cbc_256_encrypt(Key, Ivec, Data);
+block_encrypt(aes_ige256, Key, Ivec, Data) ->
+ aes_ige_256_encrypt(Key, Ivec, Data);
block_encrypt(aes_cfb128, Key, Ivec, Data) ->
aes_cfb_128_encrypt(Key, Ivec, Data);
block_encrypt(rc2_cbc, Key, Ivec, Data) ->
rc2_cbc_encrypt(Key, Ivec, Data).
-spec block_decrypt(des_cbc | des_cfb | des3_cbc | des3_cbf | des_ede3 | blowfish_cbc |
- blowfish_cfb64 | blowfish_ofb64 | aes_cbc128 | aes_cbc256 | aes_cfb128 | rc2_cbc,
+ blowfish_cfb64 | blowfish_ofb64 | aes_cbc128 | aes_cbc256 | aes_ige256 |
+ aes_cfb128 | rc2_cbc,
Key::iodata(), Ivec::binary(), Data::iodata()) -> binary().
block_decrypt(des_cbc, Key, Ivec, Data) ->
@@ -338,6 +341,8 @@ block_decrypt(aes_cbc128, Key, Ivec, Data) ->
aes_cbc_128_decrypt(Key, Ivec, Data);
block_decrypt(aes_cbc256, Key, Ivec, Data) ->
aes_cbc_256_decrypt(Key, Ivec, Data);
+block_decrypt(aes_ige256, Key, Ivec, Data) ->
+ aes_ige_256_decrypt(Key, Ivec, Data);
block_decrypt(aes_cfb128, Key, Ivec, Data) ->
aes_cfb_128_decrypt(Key, Ivec, Data);
block_decrypt(rc2_cbc, Key, Ivec, Data) ->
@@ -357,14 +362,16 @@ block_decrypt(des_ecb, Key, Data) ->
block_decrypt(blowfish_ecb, Key, Data) ->
blowfish_ecb_decrypt(Key, Data).
--spec next_iv(des_cbc | des3_cbc | aes_cbc, Data::iodata()) -> binary().
+-spec next_iv(des_cbc | des3_cbc | aes_cbc | aes_ige, Data::iodata()) -> binary().
next_iv(des_cbc, Data) ->
des_cbc_ivec(Data);
next_iv(des3_cbc, Data) ->
des_cbc_ivec(Data);
next_iv(aes_cbc, Data) ->
- aes_cbc_ivec(Data).
+ aes_cbc_ivec(Data);
+next_iv(aes_ige, Data) ->
+ aes_ige_ivec(Data).
-spec next_iv(des_cfb, Data::iodata(), Ivec::binary()) -> binary().
@@ -1255,6 +1262,35 @@ aes_cbc_ivec(Data) when is_list(Data) ->
aes_cbc_ivec(list_to_binary(Data)).
+%%
+%% AES - with 256 bit key in infinite garble extension mode (IGE)
+%%
+
+-spec aes_ige_256_decrypt(iodata(), binary(), iodata()) ->
+ binary().
+
+aes_ige_256_encrypt(Key, IVec, Data) ->
+ aes_ige_crypt(Key, IVec, Data, true).
+
+aes_ige_256_decrypt(Key, IVec, Data) ->
+ aes_ige_crypt(Key, IVec, Data, false).
+
+aes_ige_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub.
+
+%%
+%% aes_ige_ivec(Data) -> binary()
+%%
+%% Returns the IVec to be used in the next iteration of
+%% aes_ige_*_[encrypt|decrypt].
+%% IVec size: 32 bytes
+%%
+aes_ige_ivec(Data) when is_binary(Data) ->
+ {_, IVec} = split_binary(Data, size(Data) - 32),
+ IVec;
+aes_ige_ivec(Data) when is_list(Data) ->
+ aes_ige_ivec(list_to_binary(Data)).
+
+
%% Stream ciphers --------------------------------------------------------------------
stream_crypt(Fun, State, Data, Size, MaxByts, []) when Size =< MaxByts ->
diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl
index 58aaa78d28..7074f00696 100644
--- a/lib/crypto/test/crypto_SUITE.erl
+++ b/lib/crypto/test/crypto_SUITE.erl
@@ -56,6 +56,7 @@ all() ->
{group, aes_cbc128},
{group, aes_cfb128},
{group, aes_cbc256},
+ {group, aes_ige256},
{group, rc2_cbc},
{group, rc4},
{group, aes_ctr},
@@ -90,6 +91,7 @@ groups() ->
{aes_cbc128,[], [block]},
{aes_cfb128,[], [block]},
{aes_cbc256,[], [block]},
+ {aes_ige256,[], [block]},
{blowfish_cbc, [], [block]},
{blowfish_ecb, [], [block]},
{blowfish_cfb64, [], [block]},
@@ -692,6 +694,9 @@ group_config(aes_cbc128, Config) ->
group_config(aes_cbc256, Config) ->
Block = aes_cbc256(),
[{block, Block} | Config];
+group_config(aes_ige256, Config) ->
+ Block = aes_ige256(),
+ [{block, Block} | Config];
group_config(aes_cfb128, Config) ->
Block = aes_cfb128(),
[{block, Block} | Config];
@@ -1106,6 +1111,25 @@ aes_cbc256() ->
hexstr2bin("f69f2445df4f9b17ad2b417be66c3710")}
].
+aes_ige256() ->
+ [{aes_ige256,
+ hexstr2bin("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"),
+ hexstr2bin("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"),
+ hexstr2bin("6bc1bee22e409f96e93d7e117393172a")},
+ {aes_ige256,
+ hexstr2bin("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"),
+ hexstr2bin("4D0F9E735749215C05CB20DA00F7814B77D33F8A668BEBBAC1739AB20302D4FE"),
+ hexstr2bin("ae2d8a571e03ac9c9eb76fac45af8e51")},
+ {aes_ige256,
+ hexstr2bin("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"),
+ hexstr2bin("2A5569424DAE1ACEABDEEA108DB4606AE21A9227CAB5F55BF52535CFA2B34717"),
+ hexstr2bin("30c81c46a35ce411e5fbc1191a0a52ef")},
+ {aes_ige256,
+ hexstr2bin("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"),
+ hexstr2bin("15D5A583D2D668E518E683D9BDF1B6D0E0C3B1E5D5C1D51E964822E1ADE88DFA"),
+ hexstr2bin("f69f2445df4f9b17ad2b417be66c3710")}
+ ].
+
aes_cfb128() ->
[{aes_cfb128,
hexstr2bin("2b7e151628aed2a6abf7158809cf4f3c"),