diff --git a/lib/crypto/c_src/aead.c b/lib/crypto/c_src/aead.c index 67e149354229..f4ac6aa07092 100644 --- a/lib/crypto/c_src/aead.c +++ b/lib/crypto/c_src/aead.c @@ -78,6 +78,7 @@ ERL_NIF_TERM aead_cipher_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a if ((ctx_res = enif_alloc_resource(aead_cipher_ctx_rtype, sizeof(struct aead_cipher_ctx))) == NULL) return EXCP_ERROR(env, "Can't allocate resource"); + ctx_res->ctx = NULL; ctx_res->env = enif_alloc_env(); encflg_arg = argv[3]; @@ -133,6 +134,9 @@ ERL_NIF_TERM aead_cipher_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a {ret = EXCP_ERROR(env, "Can't allocate ctx"); goto done;} if (EVP_CipherInit_ex(ctx_res->ctx, ctx_res->cipherp->cipher.p, NULL, NULL, NULL, ctx_res->encflg) != 1) {ret = EXCP_ERROR(env, "CipherInit failed"); goto done;} + if (!EVP_CIPHER_CTX_set_key_length(ctx_res->ctx, (int)key.size)) + {ret = EXCP_BADARG_N(env, 1, "Bad Key length"); goto done;} + ret = enif_make_resource(env, ctx_res); @@ -232,6 +236,8 @@ ERL_NIF_TERM aead_cipher_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] {ret = EXCP_ERROR(env, "Can't allocate ctx"); 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_set_key_length(ctx, (int)key.size)) + {ret = EXCP_BADARG_N(env, 1, "Bad Key length"); goto done;} } else { /* argc = 4 {state, IV, InData, AAD } */ diff --git a/lib/crypto/c_src/cipher.c b/lib/crypto/c_src/cipher.c index b57563b3a712..053c25142bd1 100644 --- a/lib/crypto/c_src/cipher.c +++ b/lib/crypto/c_src/cipher.c @@ -127,7 +127,7 @@ static struct cipher_type_t cipher_types[] = /*==== AEAD ciphers ====*/ #if defined(HAVE_CHACHA20_POLY1305) - {{"chacha20_poly1305"}, "chacha20-poly1305", {&EVP_chacha20_poly1305}, 0, NO_FIPS_CIPHER | AEAD_CIPHER, AEAD_CTRL}, + {{"chacha20_poly1305"}, "chacha20-poly1305", {&EVP_chacha20_poly1305}, 32, NO_FIPS_CIPHER | AEAD_CIPHER, AEAD_CTRL}, #else {{"chacha20_poly1305"}, "chacha20-poly1305", {NULL}, 0, NO_FIPS_CIPHER | AEAD_CIPHER, {{0,0,0}}}, #endif diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl index e1f6de608bc8..b2bb53a75992 100644 --- a/lib/crypto/test/crypto_SUITE.erl +++ b/lib/crypto/test/crypto_SUITE.erl @@ -37,8 +37,9 @@ end_per_testcase/2, %% Test cases: - aead_bad_tag/1, aead_ng/1, + aead_bad_tag/1, + aead_bad_key_length/1, all_ciphers/1, api_errors_ecdh/1, api_ng/0, @@ -462,9 +463,9 @@ groups() -> {sm4_ofb, [], [api_ng, api_ng_one_shot]}, {sm4_cfb, [], [api_ng, api_ng_one_shot]}, {sm4_ctr, [], [api_ng, api_ng_one_shot]}, - {sm4_gcm, [], [aead_ng, aead_bad_tag]}, - {sm4_ccm, [], [aead_ng, aead_bad_tag]}, - {chacha20_poly1305, [], [aead_ng, aead_bad_tag]}, + {sm4_gcm, [], [aead_ng, aead_bad_tag, aead_bad_key_length]}, + {sm4_ccm, [], [aead_ng, aead_bad_tag, aead_bad_key_length]}, + {chacha20_poly1305, [], [aead_ng, aead_bad_tag, aead_bad_key_length]}, {chacha20, [], [api_ng, api_ng_one_shot]}, {poly1305, [], [poly1305]}, {no_poly1305, [], [no_poly1305]}, @@ -510,15 +511,15 @@ groups() -> {aes_128_ctr, [], [api_ng, api_ng_one_shot]}, {aes_192_ctr, [], [api_ng, api_ng_one_shot]}, {aes_256_ctr, [], [api_ng, api_ng_one_shot]}, - {aes_128_ccm, [], [aead_ng, aead_bad_tag]}, - {aes_192_ccm, [], [aead_ng, aead_bad_tag]}, - {aes_256_ccm, [], [aead_ng, aead_bad_tag]}, + {aes_128_ccm, [], [aead_ng, aead_bad_tag, aead_bad_key_length]}, + {aes_192_ccm, [], [aead_ng, aead_bad_tag, aead_bad_key_length]}, + {aes_256_ccm, [], [aead_ng, aead_bad_tag, aead_bad_key_length]}, {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_ng, aead_bad_tag]}, - {aes_192_gcm, [], [aead_ng, aead_bad_tag]}, - {aes_256_gcm, [], [aead_ng, aead_bad_tag]}, + {aes_128_gcm, [], [aead_ng, aead_bad_tag, aead_bad_key_length]}, + {aes_192_gcm, [], [aead_ng, aead_bad_tag, aead_bad_key_length]}, + {aes_256_gcm, [], [aead_ng, aead_bad_tag, aead_bad_key_length]}, {aes_128_ofb, [], [api_ng, api_ng_one_shot]}, {aes_192_ofb, [], [api_ng, api_ng_one_shot]}, {aes_256_ofb, [], [api_ng, api_ng_one_shot]} @@ -1136,6 +1137,23 @@ aead_bad_tag(Config) -> end, do_cipher_tests(fun aead_cipher_bad_tag/1, FilteredAEADs). +%%-------------------------------------------------------------------- +aead_bad_key_length(Config) -> + [_|_] = AEADs = lazy_eval(proplists:get_value(cipher, Config)), + FilteredAEADs = + case proplists:get_bool(fips, Config) of + false -> + AEADs; + true -> + %% In FIPS mode, the IV length must be at least 12 bytes. + lists:filter( + fun(Tuple) -> + IVLen = byte_size(element(4, Tuple)), + IVLen >= 12 + end, AEADs) + end, + do_cipher_tests(fun aead_cipher_bad_key_length/1, FilteredAEADs). + %%-------------------------------------------------------------------- sign_verify() -> [{doc, "Sign/verify digital signatures"}]. @@ -1811,6 +1829,35 @@ aead_cipher_bad_tag({Type, Key, _PlainText, IV, AAD, CipherText, CipherTag, TagL fun() -> crypto:crypto_one_time_aead(Type, Key, IV, CipherText, AAD, BadTruncatedTag, false) end, error). +aead_cipher_bad_key_length({Type, Key, PlainText, IV, AAD, _CipherText, _CipherTag, _Info}=T) -> + F = fun(K) -> + try crypto:crypto_one_time_aead(Type, K, IV, PlainText, AAD, true) of + Res -> ct:fail("Call should fail, but succeeded with return: ~p~n", [Res]) + catch error : {badarg, _, _} -> ok + end + end, + KeyExtended = <>/binary>>, + F(KeyExtended), + KeyTruncatedSize = byte_size(Key) - 1, + <> = Key, + F(KeyTruncated); +aead_cipher_bad_key_length({Type, Key, PlainText, IV, AAD, _CipherText, _CipherTag, TagLen, _Info}=T) -> + F = fun(K) -> + try crypto:crypto_one_time_aead(Type, K, IV, PlainText, AAD, TagLen, true) of + Res1 -> ct:fail("Call should fail, but succeeded with return: ~p~n", [Res1]) + catch error : {badarg, _, _} -> ok + end, + try crypto:crypto_one_time_aead_init(Type, K, TagLen, true) of + Res2 -> ct:fail("Call should fail, but succeeded with return: ~p~n", [Res2]) + catch error : {badarg, _, _} -> ok + end + end, + KeyExtended = <>/binary>>, + F(KeyExtended), + KeyTruncatedSize = byte_size(Key) - 1, + <> = Key, + F(KeyTruncated). + cipher_test(T, Fe, Ee, Fd, Ed) -> %% Test encrypt