diff options
author | Hans Nilsson <[email protected]> | 2018-09-18 10:23:38 +0200 |
---|---|---|
committer | Hans Nilsson <[email protected]> | 2018-09-18 10:23:38 +0200 |
commit | 9638dad5c6b873d612c5529f1b918f2e3add79e7 (patch) | |
tree | d703dc1c972f13f7c2b9f764fb137fbe463d596e | |
parent | a578ee7615e72a8eb0ad0e35ae94437b41db96ee (diff) | |
parent | e737809f0338179bdafa9c9210d5c04c99e5559f (diff) | |
download | otp-9638dad5c6b873d612c5529f1b918f2e3add79e7.tar.gz otp-9638dad5c6b873d612c5529f1b918f2e3add79e7.tar.bz2 otp-9638dad5c6b873d612c5529f1b918f2e3add79e7.zip |
Merge branch 'hans/crypto/chacha_poly_into_aead_fns/OTP-15300' into maint
* hans/crypto/chacha_poly_into_aead_fns/OTP-15300:
crypto: Fix bad return/exception for unsupported cipher
crypto: Use aead functions for CHACHA20_POLY1305
-rw-r--r-- | lib/crypto/c_src/crypto.c | 246 | ||||
-rw-r--r-- | lib/crypto/src/crypto.erl | 19 |
2 files changed, 82 insertions, 183 deletions
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index 3172059414..d40d285f86 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -553,9 +553,6 @@ static ERL_NIF_TERM aead_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar static ERL_NIF_TERM aes_gcm_decrypt_NO_EVP(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); #endif -static ERL_NIF_TERM chacha20_poly1305_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM chacha20_poly1305_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); - static ERL_NIF_TERM chacha20_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM chacha20_stream_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); @@ -648,9 +645,6 @@ static ErlNifFunc nif_funcs[] = { {"aead_encrypt", 6, aead_encrypt}, {"aead_decrypt", 6, aead_decrypt}, - {"chacha20_poly1305_encrypt", 4, chacha20_poly1305_encrypt}, - {"chacha20_poly1305_decrypt", 5, chacha20_poly1305_decrypt}, - {"chacha20_stream_init", 2, chacha20_stream_init}, {"chacha20_stream_encrypt", 2, chacha20_stream_crypt}, {"chacha20_stream_decrypt", 2, chacha20_stream_crypt}, @@ -726,6 +720,9 @@ static ERL_NIF_TERM atom_aes_gcm; #ifdef HAVE_CCM static ERL_NIF_TERM atom_aes_ccm; #endif +#ifdef HAVE_CHACHA20_POLY1305 +static ERL_NIF_TERM atom_chacha20_poly1305; +#endif #ifdef HAVE_ECB_IVEC_BUG static ERL_NIF_TERM atom_aes_ecb; static ERL_NIF_TERM atom_des_ecb; @@ -1172,6 +1169,9 @@ static int initialize(ErlNifEnv* env, ERL_NIF_TERM load_info) #ifdef HAVE_CCM atom_aes_ccm = enif_make_atom(env, "aes_ccm"); #endif +#ifdef HAVE_CHACHA20_POLY1305 + atom_chacha20_poly1305 = enif_make_atom(env,"chacha20_poly1305"); +#endif #ifdef HAVE_ECB_IVEC_BUG atom_aes_ecb = enif_make_atom(env, "aes_ecb"); atom_des_ecb = enif_make_atom(env, "des_ecb"); @@ -2592,46 +2592,53 @@ static ERL_NIF_TERM aead_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar /* Use cipher_type some day. Must check block_encrypt|decrypt first */ #if defined(HAVE_GCM) - if ((type == atom_aes_gcm) - && (iv.size > 0) - && (1 <= tag_len && tag_len <= 16)) { - ctx_ctrl_set_ivlen = EVP_CTRL_GCM_SET_IVLEN; - ctx_ctrl_get_tag = EVP_CTRL_GCM_GET_TAG; - if (key.size == 16) cipher = EVP_aes_128_gcm(); - else if (key.size == 24) cipher = EVP_aes_192_gcm(); - else if (key.size == 32) cipher = EVP_aes_256_gcm(); - else + if (type == atom_aes_gcm) { + if ((iv.size > 0) + && (1 <= tag_len && tag_len <= 16)) { + ctx_ctrl_set_ivlen = EVP_CTRL_GCM_SET_IVLEN; + ctx_ctrl_get_tag = EVP_CTRL_GCM_GET_TAG; + if (key.size == 16) cipher = EVP_aes_128_gcm(); + else if (key.size == 24) cipher = EVP_aes_192_gcm(); + else if (key.size == 32) cipher = EVP_aes_256_gcm(); + else enif_make_badarg(env); + } else enif_make_badarg(env); - } else #endif #if defined(HAVE_CCM) - if ((type == atom_aes_ccm) - && (7 <= iv.size && iv.size <= 13) - && (4 <= tag_len && tag_len <= 16) - && ((tag_len & 1) == 0) - ) { - ctx_ctrl_set_ivlen = EVP_CTRL_CCM_SET_IVLEN; - ctx_ctrl_get_tag = EVP_CTRL_CCM_GET_TAG; - if (key.size == 16) cipher = EVP_aes_128_ccm(); - else if (key.size == 24) cipher = EVP_aes_192_ccm(); - else if (key.size == 32) cipher = EVP_aes_256_ccm(); - else + if (type == atom_aes_ccm) { + if ((7 <= iv.size && iv.size <= 13) + && (4 <= tag_len && tag_len <= 16) + && ((tag_len & 1) == 0) + ) { + ctx_ctrl_set_ivlen = EVP_CTRL_CCM_SET_IVLEN; + ctx_ctrl_get_tag = EVP_CTRL_CCM_GET_TAG; + if (key.size == 16) cipher = EVP_aes_128_ccm(); + else if (key.size == 24) cipher = EVP_aes_192_ccm(); + else if (key.size == 32) cipher = EVP_aes_256_ccm(); + else enif_make_badarg(env); + } else enif_make_badarg(env); - } else #endif - enif_make_badarg(env); +#if defined(HAVE_CHACHA20_POLY1305) + if (type == atom_chacha20_poly1305) { + if ((key.size == 32) + && (1 <= iv.size && iv.size <= 16) + && (tag_len == 16) + ) { + ctx_ctrl_set_ivlen = EVP_CTRL_AEAD_SET_IVLEN; + ctx_ctrl_get_tag = EVP_CTRL_AEAD_GET_TAG, + cipher = EVP_chacha20_poly1305(); + } else enif_make_badarg(env); + } else +#endif + return enif_raise_exception(env, atom_notsup); ctx = EVP_CIPHER_CTX_new(); if (EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1) goto out_err; if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_set_ivlen, iv.size, NULL) != 1) goto out_err; -#if defined(HAVE_GCM) - if (type == atom_aes_gcm) { - if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) goto out_err; - } else -#endif #if defined(HAVE_CCM) if (type == atom_aes_ccm) { if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, tag_len, NULL) != 1) goto out_err; @@ -2639,14 +2646,14 @@ static ERL_NIF_TERM aead_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar if (EVP_EncryptUpdate(ctx, NULL, &len, NULL, in.size) != 1) goto out_err; } else #endif - goto out_err; + if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) goto out_err; if (EVP_EncryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1) goto out_err; outp = enif_make_new_binary(env, in.size, &out); if (EVP_EncryptUpdate(ctx, outp, &len, in.data, in.size) != 1) goto out_err; - if (EVP_EncryptFinal_ex(ctx, outp, &len) != 1) goto out_err; + if (EVP_EncryptFinal_ex(ctx, outp/*+len*/, &len) != 1) goto out_err; tagp = enif_make_new_binary(env, tag_len, &out_tag); @@ -2673,7 +2680,7 @@ static ERL_NIF_TERM aead_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar ErlNifBinary key, iv, aad, in, tag; unsigned char *outp; ERL_NIF_TERM type, out; - int len, ctx_ctrl_set_ivlen; + int len, ctx_ctrl_set_ivlen, ctx_ctrl_set_tag; type = argv[0]; #if defined(HAVE_GCM_EVP_DECRYPT_BUG) @@ -2692,30 +2699,43 @@ static ERL_NIF_TERM aead_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar /* Use cipher_type some day. Must check block_encrypt|decrypt first */ #if defined(HAVE_GCM) - if ((type == atom_aes_gcm) - && (iv.size > 0)) { - ctx_ctrl_set_ivlen = EVP_CTRL_GCM_SET_IVLEN; - if (key.size == 16) cipher = EVP_aes_128_gcm(); - else if (key.size == 24) cipher = EVP_aes_192_gcm(); - else if (key.size == 32) cipher = EVP_aes_256_gcm(); - else + if (type == atom_aes_gcm) { + if (iv.size > 0) { + ctx_ctrl_set_ivlen = EVP_CTRL_GCM_SET_IVLEN; + ctx_ctrl_set_tag = EVP_CTRL_GCM_SET_TAG; + if (key.size == 16) cipher = EVP_aes_128_gcm(); + else if (key.size == 24) cipher = EVP_aes_192_gcm(); + else if (key.size == 32) cipher = EVP_aes_256_gcm(); + else enif_make_badarg(env); + } else enif_make_badarg(env); - } else #endif #if defined(HAVE_CCM) - if ((type == atom_aes_ccm) - && (iv.size > 0)) { - ctx_ctrl_set_ivlen = EVP_CTRL_CCM_SET_IVLEN; - if (key.size == 16) cipher = EVP_aes_128_ccm(); - else if (key.size == 24) cipher = EVP_aes_192_ccm(); - else if (key.size == 32) cipher = EVP_aes_256_ccm(); - else + if (type == atom_aes_ccm) { + if (iv.size > 0) { + ctx_ctrl_set_ivlen = EVP_CTRL_CCM_SET_IVLEN; + if (key.size == 16) cipher = EVP_aes_128_ccm(); + else if (key.size == 24) cipher = EVP_aes_192_ccm(); + else if (key.size == 32) cipher = EVP_aes_256_ccm(); + else enif_make_badarg(env); + } else enif_make_badarg(env); - } else #endif - enif_make_badarg(env); +#if defined(HAVE_CHACHA20_POLY1305) + if (type == atom_chacha20_poly1305) { + if ((key.size == 32) + && (1 <= iv.size && iv.size <= 16) + && tag.size == 16 + ) { + ctx_ctrl_set_ivlen = EVP_CTRL_AEAD_SET_IVLEN; + ctx_ctrl_set_tag = EVP_CTRL_AEAD_SET_TAG; + cipher = EVP_chacha20_poly1305(); + } else enif_make_badarg(env); + } else +#endif + return enif_raise_exception(env, atom_notsup); outp = enif_make_new_binary(env, in.size, &out); @@ -2740,9 +2760,9 @@ static ERL_NIF_TERM aead_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar if (EVP_DecryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1) goto out_err; if (EVP_DecryptUpdate(ctx, outp, &len, in.data, in.size) != 1) goto out_err; -#if defined(HAVE_GCM) +#if defined(HAVE_GCM) || defined(HAVE_CHACHA20_POLY1305) if (type == atom_aes_gcm) { - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, tag.size, tag.data) != 1) goto out_err; + if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_set_tag, tag.size, tag.data) != 1) goto out_err; if (EVP_DecryptFinal_ex(ctx, outp+len, &len) != 1) goto out_err; } #endif @@ -2807,120 +2827,6 @@ out_err: #endif /* HAVE_GCM_EVP_DECRYPT_BUG */ -static ERL_NIF_TERM chacha20_poly1305_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Key,Iv,AAD,In) */ -#if defined(HAVE_CHACHA20_POLY1305) - EVP_CIPHER_CTX *ctx; - const EVP_CIPHER *cipher = NULL; - ErlNifBinary key, iv, aad, in; - unsigned char *outp, *tagp; - ERL_NIF_TERM out, out_tag; - int len; - - if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 32 - || !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0 || iv.size > 16 - || !enif_inspect_iolist_as_binary(env, argv[2], &aad) - || !enif_inspect_iolist_as_binary(env, argv[3], &in)) { - return enif_make_badarg(env); - } - - cipher = EVP_chacha20_poly1305(); - - ctx = EVP_CIPHER_CTX_new(); - - if (EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1) - goto out_err; - - EVP_CIPHER_CTX_set_padding(ctx, 0); - - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, iv.size, NULL) != 1) - goto out_err; - if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) - goto out_err; - if (EVP_EncryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1) - goto out_err; - - outp = enif_make_new_binary(env, in.size, &out); - - if (EVP_EncryptUpdate(ctx, outp, &len, in.data, in.size) != 1) - goto out_err; - if (EVP_EncryptFinal_ex(ctx, outp+len, &len) != 1) - goto out_err; - - tagp = enif_make_new_binary(env, 16, &out_tag); - - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, tagp) != 1) - goto out_err; - - EVP_CIPHER_CTX_free(ctx); - - CONSUME_REDS(env, in); - - return enif_make_tuple2(env, out, out_tag); - -out_err: - EVP_CIPHER_CTX_free(ctx); - return atom_error; -#else - return enif_raise_exception(env, atom_notsup); -#endif -} - -static ERL_NIF_TERM chacha20_poly1305_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Key,Iv,AAD,In,Tag) */ -#if defined(HAVE_CHACHA20_POLY1305) - EVP_CIPHER_CTX *ctx; - const EVP_CIPHER *cipher = NULL; - ErlNifBinary key, iv, aad, in, tag; - unsigned char *outp; - ERL_NIF_TERM out; - int len; - - if (!enif_inspect_iolist_as_binary(env, argv[0], &key) || key.size != 32 - || !enif_inspect_binary(env, argv[1], &iv) || iv.size == 0 || iv.size > 16 - || !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 != 16) { - return enif_make_badarg(env); - } - - cipher = EVP_chacha20_poly1305(); - - ctx = EVP_CIPHER_CTX_new(); - - if (EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1) - goto out_err; - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, iv.size, NULL) != 1) - goto out_err; - if (EVP_DecryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) - goto out_err; - if (EVP_DecryptUpdate(ctx, NULL, &len, aad.data, aad.size) != 1) - goto out_err; - - outp = enif_make_new_binary(env, in.size, &out); - - if (EVP_DecryptUpdate(ctx, outp, &len, in.data, in.size) != 1) - goto out_err; - if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag.size, tag.data) != 1) - goto out_err; - if (EVP_DecryptFinal_ex(ctx, outp+len, &len) != 1) - goto out_err; - - EVP_CIPHER_CTX_free(ctx); - - CONSUME_REDS(env, in); - - return out; - -out_err: - EVP_CIPHER_CTX_free(ctx); - return atom_error; -#else - return enif_raise_exception(env, atom_notsup); -#endif -} - - static ERL_NIF_TERM chacha20_stream_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Key, IV) */ #if defined(HAVE_CHACHA20) diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 960fe46c09..2db73c4af0 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -526,8 +526,9 @@ block_encrypt(Type, Key, Ivec, {AAD, PlainText}) when Type =:= aes_gcm; block_encrypt(Type, Key, Ivec, {AAD, PlainText, TagLength}) when Type =:= aes_gcm; Type =:= aes_ccm -> aead_encrypt(Type, Key, Ivec, AAD, PlainText, TagLength); -block_encrypt(chacha20_poly1305, Key, Ivec, {AAD, PlainText}) -> - chacha20_poly1305_encrypt(Key, Ivec, AAD, PlainText). +block_encrypt(chacha20_poly1305=Type, Key, Ivec, {AAD, PlainText}) -> + aead_encrypt(Type, Key, Ivec, AAD, PlainText, 16). + -spec block_decrypt(Type::block_cipher_with_iv(), Key::key()|des3_key(), Ivec::binary(), Data::iodata()) -> binary(); (Type::aead_cipher(), Key::iodata(), Ivec::binary(), @@ -557,11 +558,9 @@ block_decrypt(des3_cfb, Key0, Ivec, Data) -> block_decrypt(aes_ige256, Key, Ivec, Data) -> notsup_to_error(aes_ige_crypt_nif(Key, Ivec, Data, false)); block_decrypt(Type, Key, Ivec, {AAD, Data, Tag}) when Type =:= aes_gcm; - Type =:= aes_ccm -> - aead_decrypt(Type, Key, Ivec, AAD, Data, Tag); -block_decrypt(chacha20_poly1305, Key, Ivec, {AAD, Data, Tag}) -> - chacha20_poly1305_decrypt(Key, Ivec, AAD, Data, Tag). - + Type =:= aes_ccm; + Type =:= chacha20_poly1305 -> + aead_decrypt(Type, Key, Ivec, AAD, Data, Tag). -spec block_encrypt(Type::block_cipher_without_iv(), Key::key(), PlainText::iodata()) -> binary(). @@ -1617,12 +1616,6 @@ aead_encrypt(_Type, _Key, _Ivec, _AAD, _In, _TagLength) -> ?nif_stub. aead_decrypt(_Type, _Key, _Ivec, _AAD, _In, _Tag) -> ?nif_stub. %% -%% Chacha20/Ppoly1305 -%% -chacha20_poly1305_encrypt(_Key, _Ivec, _AAD, _In) -> ?nif_stub. -chacha20_poly1305_decrypt(_Key, _Ivec, _AAD, _In, _Tag) -> ?nif_stub. - -%% %% AES - with 256 bit key in infinite garble extension mode (IGE) %% |