diff options
Diffstat (limited to 'lib/crypto')
27 files changed, 1857 insertions, 828 deletions
diff --git a/lib/crypto/c_src/aead.c b/lib/crypto/c_src/aead.c index 4ed16615a5..ab0e609130 100644 --- a/lib/crypto/c_src/aead.c +++ b/lib/crypto/c_src/aead.c @@ -22,36 +22,65 @@ #include "aes.h" #include "cipher.h" -ERL_NIF_TERM aead_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Type,Key,Iv,AAD,In) */ + + +ERL_NIF_TERM aead_cipher(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* + (Type,Key,Iv,AAD,In,TagLen,true) + (Type,Key,Iv,AAD,In,Tag,false) + */ #if defined(HAVE_AEAD) const struct cipher_type_t *cipherp; EVP_CIPHER_CTX *ctx = NULL; const EVP_CIPHER *cipher = NULL; - ErlNifBinary key, iv, aad, in; + ErlNifBinary key, iv, aad, in, tag; unsigned int tag_len; - unsigned char *outp, *tagp; - ERL_NIF_TERM type, out, out_tag, ret; - int len, ctx_ctrl_set_ivlen, ctx_ctrl_get_tag, ctx_ctrl_set_tag; + unsigned char *outp, *tagp, *tag_data; + ERL_NIF_TERM type, out, out_tag, ret, encflg_arg; + int len, encflg; + + encflg_arg = argv[6]; + + /* Fetch the flag telling if we are going to encrypt (=true) or decrypt (=false) */ + if (encflg_arg == atom_true) + encflg = 1; + else if (encflg_arg == atom_false) + encflg = 0; + else if (encflg_arg == atom_undefined) + /* For compat funcs in crypto.erl */ + encflg = -1; + else + { + ret = EXCP_BADARG(env, "Bad enc flag"); + goto done; + } type = argv[0]; - ASSERT(argc == 6); - if (!enif_is_atom(env, type)) {ret = EXCP_BADARG(env, "non-atom cipher type"); goto done;} if (!enif_inspect_iolist_as_binary(env, argv[1], &key)) {ret = EXCP_BADARG(env, "non-binary key"); goto done;} - if (!enif_inspect_binary(env, argv[2], &iv)) + if (!enif_inspect_iolist_as_binary(env, argv[2], &iv)) {ret = EXCP_BADARG(env, "non-binary iv"); goto done;} - if (!enif_inspect_iolist_as_binary(env, argv[3], &aad)) - {ret = EXCP_BADARG(env, "non-binary AAD"); goto done;} - if (!enif_inspect_iolist_as_binary(env, argv[4], &in)) + if (!enif_inspect_iolist_as_binary(env, argv[3], &in)) {ret = EXCP_BADARG(env, "non-binary text"); goto done;} - if (!enif_get_uint(env, argv[5], &tag_len)) - {ret = EXCP_BADARG(env, ""); goto done;} + if (!enif_inspect_iolist_as_binary(env, argv[4], &aad)) + {ret = EXCP_BADARG(env, "non-binary AAD"); goto done;} + + if (encflg) { + if (!enif_get_uint(env, argv[5], &tag_len)) + {ret = EXCP_BADARG(env, "Bad Tag length"); goto done;} + tag_data = NULL; + } else { + if (!enif_inspect_iolist_as_binary(env, argv[5], &tag)) + {ret = EXCP_BADARG(env, "non-binary Tag"); goto done;} + tag_len = tag.size; + tag_data = tag.data; + } if (tag_len > INT_MAX + || key.size > INT_MAX || iv.size > INT_MAX || in.size > INT_MAX || aad.size > INT_MAX) @@ -66,167 +95,88 @@ ERL_NIF_TERM aead_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) if ((cipher = cipherp->cipher.p) == NULL) {ret = EXCP_NOTSUP(env, "Cipher not supported in this libcrypto version"); goto done;} - ctx_ctrl_set_ivlen = cipherp->extra.aead.ctx_ctrl_set_ivlen; - ctx_ctrl_get_tag = cipherp->extra.aead.ctx_ctrl_get_tag; - ctx_ctrl_set_tag = cipherp->extra.aead.ctx_ctrl_set_tag; - +#if defined(HAVE_GCM_EVP_DECRYPT_BUG) + if ( !encflg && (cipherp->flags & GCM_MODE)) + return aes_gcm_decrypt_NO_EVP(env, argc, argv); +#endif + if ((ctx = EVP_CIPHER_CTX_new()) == NULL) - {ret = EXCP_ERROR(env, ""); goto done;} + {ret = EXCP_ERROR(env, "Can't allocate ctx"); goto done;} - if (EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1) - {ret = EXCP_ERROR(env, ""); goto done;} - if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_set_ivlen, (int)iv.size, NULL) != 1) - {ret = EXCP_ERROR(env, ""); 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_ctrl(ctx, cipherp->extra.aead.ctx_ctrl_set_ivlen, (int)iv.size, NULL) != 1) + {ret = EXCP_BADARG(env, "Bad IV length"); goto done;} #if defined(HAVE_CCM) - if (type == atom_aes_ccm) { - if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_set_tag, (int)tag_len, NULL) != 1) - {ret = EXCP_ERROR(env, ""); goto done;} - if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) - {ret = EXCP_ERROR(env, ""); goto done;} - if (EVP_EncryptUpdate(ctx, NULL, &len, NULL, (int)in.size) != 1) - {ret = EXCP_ERROR(env, ""); goto done;} + if (cipherp->flags & CCM_MODE) { + if (EVP_CIPHER_CTX_ctrl(ctx, cipherp->extra.aead.ctx_ctrl_set_tag, (int)tag_len, tag_data) != 1) + {ret = EXCP_BADARG(env, "Can't set tag"); goto done;} + if (EVP_CipherInit_ex(ctx, NULL, NULL, key.data, iv.data, -1) != 1) + {ret = EXCP_BADARG(env, "Can't set key or iv"); goto done;} + if (EVP_CipherUpdate(ctx, NULL, &len, NULL, (int)in.size) != 1) + {ret = EXCP_BADARG(env, "Can't set text size"); goto done;} } else #endif { - if (EVP_EncryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) - {ret = EXCP_ERROR(env, ""); goto done;} + if (EVP_CipherInit_ex(ctx, NULL, NULL, key.data, iv.data, -1) != 1) + {ret = EXCP_BADARG(env, "Can't set key or iv"); goto done;} } - if (EVP_EncryptUpdate(ctx, NULL, &len, aad.data, (int)aad.size) != 1) - {ret = EXCP_ERROR(env, ""); goto done;} + if (EVP_CipherUpdate(ctx, NULL, &len, aad.data, (int)aad.size) != 1) + {ret = EXCP_BADARG(env, "Can't set AAD"); goto done;} if ((outp = enif_make_new_binary(env, in.size, &out)) == NULL) - {ret = EXCP_ERROR(env, ""); goto done;} - - if (EVP_EncryptUpdate(ctx, outp, &len, in.data, (int)in.size) != 1) - {ret = EXCP_ERROR(env, ""); goto done;} - if (EVP_EncryptFinal_ex(ctx, outp/*+len*/, &len) != 1) - {ret = EXCP_ERROR(env, ""); goto done;} - - if ((tagp = enif_make_new_binary(env, tag_len, &out_tag)) == NULL) - {ret = EXCP_ERROR(env, ""); goto done;} + {ret = EXCP_ERROR(env, "Can't make 'Out' binary"); goto done;} - if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_get_tag, (int)tag_len, tagp) != 1) - {ret = EXCP_ERROR(env, ""); goto done;} - - CONSUME_REDS(env, in); - ret = enif_make_tuple2(env, out, out_tag); - - done: - if (ctx) - EVP_CIPHER_CTX_free(ctx); - return ret; - -#else - return EXCP_NOTSUP(env, ""); -#endif -} - -ERL_NIF_TERM aead_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (Type,Key,Iv,AAD,In,Tag) */ -#if defined(HAVE_AEAD) - const struct cipher_type_t *cipherp; - EVP_CIPHER_CTX *ctx = NULL; - const EVP_CIPHER *cipher = NULL; - ErlNifBinary key, iv, aad, in, tag; - unsigned char *outp; - ERL_NIF_TERM type, out, ret; - int len, ctx_ctrl_set_ivlen, ctx_ctrl_set_tag; - - ASSERT(argc == 6); - - type = argv[0]; -#if defined(HAVE_GCM_EVP_DECRYPT_BUG) - if (type == atom_aes_gcm) - return aes_gcm_decrypt_NO_EVP(env, argc, argv); -#endif - - if (!enif_is_atom(env, type)) - {ret = EXCP_BADARG(env, "non-atom cipher type"); goto done;} - if (!enif_inspect_iolist_as_binary(env, argv[1], &key)) - {ret = EXCP_BADARG(env, "non-binary key"); goto done;} - if (!enif_inspect_binary(env, argv[2], &iv)) - {ret = EXCP_BADARG(env, "non-binary iv"); goto done;} - if (!enif_inspect_iolist_as_binary(env, argv[3], &aad)) - {ret = EXCP_BADARG(env, "non-binary AAD"); goto done;} - if (!enif_inspect_iolist_as_binary(env, argv[4], &in)) - {ret = EXCP_BADARG(env, ""); goto done;} - if (!enif_inspect_iolist_as_binary(env, argv[5], &tag)) - {ret = EXCP_BADARG(env, "non-binary text"); goto done;} - - if (tag.size > INT_MAX - || key.size > INT_MAX - || iv.size > INT_MAX - || in.size > INT_MAX - || aad.size > INT_MAX) - {ret = EXCP_BADARG(env, "binary too long"); goto done;} - - if ((cipherp = get_cipher_type(type, key.size)) == NULL) - {ret = EXCP_BADARG(env, "Unknown cipher"); goto done;} - if (cipherp->flags & NON_EVP_CIPHER) - {ret = EXCP_BADARG(env, "Bad cipher"); goto done;} - if ( !(cipherp->flags & AEAD_CIPHER) ) - {ret = EXCP_BADARG(env, "Not aead cipher"); goto done;} - if ((cipher = cipherp->cipher.p) == NULL) - {ret = EXCP_NOTSUP(env, "Cipher not supported in this libcrypto version"); goto done;} + if (EVP_CipherUpdate(ctx, outp, &len, in.data, (int)in.size) != 1) + { + if (encflg) + ret = EXCP_BADARG(env, "Can't set in-text"); + else + /* Decrypt error */ + ret = atom_error; + goto done; + } - ctx_ctrl_set_ivlen = cipherp->extra.aead.ctx_ctrl_set_ivlen; - ctx_ctrl_set_tag = cipherp->extra.aead.ctx_ctrl_set_tag; + if (encflg) + { + if (EVP_CipherFinal_ex(ctx, outp/*+len*/, &len) != 1) + {ret = EXCP_ERROR(env, "Encrypt error"); goto done;} - if ((outp = enif_make_new_binary(env, in.size, &out)) == NULL) - {ret = EXCP_ERROR(env, ""); goto done;} + if ((tagp = enif_make_new_binary(env, tag_len, &out_tag)) == NULL) + {ret = EXCP_ERROR(env, "Can't make 'Out' binary"); goto done;} - if ((ctx = EVP_CIPHER_CTX_new()) == NULL) - {ret = EXCP_ERROR(env, ""); goto done;} - if (EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL) != 1) - {ret = EXCP_ERROR(env, ""); goto done;} - if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_set_ivlen, (int)iv.size, NULL) != 1) - {ret = EXCP_ERROR(env, ""); goto done;} + if (EVP_CIPHER_CTX_ctrl(ctx, cipherp->extra.aead.ctx_ctrl_get_tag, (int)tag_len, tagp) != 1) + {ret = EXCP_ERROR(env, "Can't get Tag"); goto done;} -#if defined(HAVE_CCM) - if (type == atom_aes_ccm) { - if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_set_tag, (int)tag.size, tag.data) != 1) - {ret = EXCP_ERROR(env, ""); goto done;} - if (EVP_DecryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) - {ret = EXCP_ERROR(env, ""); goto done;} - if (EVP_DecryptUpdate(ctx, NULL, &len, NULL, (int)in.size) != 1) - {ret = EXCP_ERROR(env, ""); goto done;} - } + ret = enif_make_tuple2(env, out, out_tag); + } else -#endif { - if (EVP_DecryptInit_ex(ctx, NULL, NULL, key.data, iv.data) != 1) - {ret = EXCP_ERROR(env, ""); goto done;} - } - - if (EVP_DecryptUpdate(ctx, NULL, &len, aad.data, (int)aad.size) != 1) - {ret = EXCP_ERROR(env, ""); goto done;} - if (EVP_DecryptUpdate(ctx, outp, &len, in.data, (int)in.size) != 1) - {ret = EXCP_ERROR(env, ""); goto done;} - #if defined(HAVE_GCM) - if (type == atom_aes_gcm) { - if (EVP_CIPHER_CTX_ctrl(ctx, ctx_ctrl_set_tag, (int)tag.size, tag.data) != 1) - goto err; - if (EVP_DecryptFinal_ex(ctx, outp+len, &len) != 1) - goto err; - } + if (cipherp->flags & GCM_MODE) { + if (EVP_CIPHER_CTX_ctrl(ctx, cipherp->extra.aead.ctx_ctrl_set_tag, (int)tag_len, tag.data) != 1) + /* Decrypt error */ + {ret = atom_error; goto done;} + if (EVP_DecryptFinal_ex(ctx, outp+len, &len) != 1) + /* Decrypt error */ + {ret = atom_error; goto done;} + } #endif - CONSUME_REDS(env, in); - ret = out; - goto done; + ret = out; + } - err: - /* Decrypt failed, that is, wrong tag */ - ret = atom_error; + CONSUME_REDS(env, in); - done: +done: if (ctx) EVP_CIPHER_CTX_free(ctx); return ret; #else - return EXCP_NOTSUP(env, ""); + return EXCP_NOTSUP(env, "Unsupported Cipher"); #endif } + + diff --git a/lib/crypto/c_src/aead.h b/lib/crypto/c_src/aead.h index 54c0711535..2ec7a8a930 100644 --- a/lib/crypto/c_src/aead.h +++ b/lib/crypto/c_src/aead.h @@ -23,7 +23,6 @@ #include "common.h" -ERL_NIF_TERM aead_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -ERL_NIF_TERM aead_decrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +ERL_NIF_TERM aead_cipher(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); #endif /* E_AEAD_H__ */ diff --git a/lib/crypto/c_src/algorithms.c b/lib/crypto/c_src/algorithms.c index 1d45ed9df2..75cddeb1e9 100644 --- a/lib/crypto/c_src/algorithms.c +++ b/lib/crypto/c_src/algorithms.c @@ -80,8 +80,12 @@ void init_algorithms_types(ErlNifEnv* env) algo_pubkey_cnt = 0; algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "rsa"); +#ifdef HAVE_DSA algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "dss"); +#endif +#ifdef HAVE_DH algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "dh"); +#endif #if defined(HAVE_EC) #if !defined(OPENSSL_NO_EC2M) algo_pubkey[algo_pubkey_cnt++] = enif_make_atom(env, "ec_gf2m"); @@ -251,29 +255,66 @@ void init_algorithms_types(ErlNifEnv* env) ASSERT(algo_rsa_opts_cnt <= sizeof(algo_rsa_opts)/sizeof(ERL_NIF_TERM)); } -ERL_NIF_TERM algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) + +ERL_NIF_TERM hash_algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + unsigned int cnt = +#ifdef FIPS_SUPPORT + FIPS_mode() ? algo_hash_fips_cnt : +#endif + algo_hash_cnt; + + return enif_make_list_from_array(env, algo_hash, cnt); +} + +ERL_NIF_TERM pubkey_algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + unsigned int cnt = +#ifdef FIPS_SUPPORT + FIPS_mode() ? algo_pubkey_fips_cnt : +#endif + algo_pubkey_cnt; + + return enif_make_list_from_array(env, algo_pubkey, cnt); +} + + +ERL_NIF_TERM cipher_algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + return cipher_types_as_list(env); /* Exclude old api ciphers */ +} + +ERL_NIF_TERM mac_algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + unsigned int cnt = +#ifdef FIPS_SUPPORT + FIPS_mode() ? algo_mac_fips_cnt : +#endif + algo_mac_cnt; + + return enif_make_list_from_array(env, algo_mac, cnt); +} + + +ERL_NIF_TERM curve_algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { + unsigned int cnt = #ifdef FIPS_SUPPORT - int fips_mode = FIPS_mode(); + FIPS_mode() ? algo_curve_fips_cnt : +#endif + algo_curve_cnt; + + return enif_make_list_from_array(env, algo_curve, cnt); +} + + +ERL_NIF_TERM rsa_opts_algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ + unsigned int cnt = +#ifdef FIPS_SUPPORT + FIPS_mode() ? algo_rsa_opts_fips_cnt : +#endif + algo_rsa_opts_cnt; - unsigned int hash_cnt = fips_mode ? algo_hash_fips_cnt : algo_hash_cnt; - unsigned int pubkey_cnt = fips_mode ? algo_pubkey_fips_cnt : algo_pubkey_cnt; - unsigned int mac_cnt = fips_mode ? algo_mac_fips_cnt : algo_mac_cnt; - unsigned int curve_cnt = fips_mode ? algo_curve_fips_cnt : algo_curve_cnt; - unsigned int rsa_opts_cnt = fips_mode ? algo_rsa_opts_fips_cnt : algo_rsa_opts_cnt; -#else - unsigned int hash_cnt = algo_hash_cnt; - unsigned int pubkey_cnt = algo_pubkey_cnt; - unsigned int mac_cnt = algo_mac_cnt; - unsigned int curve_cnt = algo_curve_cnt; - unsigned int rsa_opts_cnt = algo_rsa_opts_cnt; -#endif - return enif_make_tuple6(env, - enif_make_list_from_array(env, algo_hash, hash_cnt), - enif_make_list_from_array(env, algo_pubkey, pubkey_cnt), - cipher_types_as_list(env), - enif_make_list_from_array(env, algo_mac, mac_cnt), - enif_make_list_from_array(env, algo_curve, curve_cnt), - enif_make_list_from_array(env, algo_rsa_opts, rsa_opts_cnt) - ); + return enif_make_list_from_array(env, algo_rsa_opts, cnt); } diff --git a/lib/crypto/c_src/algorithms.h b/lib/crypto/c_src/algorithms.h index 068fb661ec..4ad8b56db8 100644 --- a/lib/crypto/c_src/algorithms.h +++ b/lib/crypto/c_src/algorithms.h @@ -25,6 +25,11 @@ void init_algorithms_types(ErlNifEnv* env); -ERL_NIF_TERM algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +ERL_NIF_TERM hash_algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +ERL_NIF_TERM pubkey_algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +ERL_NIF_TERM cipher_algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +ERL_NIF_TERM mac_algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +ERL_NIF_TERM curve_algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +ERL_NIF_TERM rsa_opts_algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); #endif /* E_ALGORITHMS_H__ */ diff --git a/lib/crypto/c_src/api_ng.c b/lib/crypto/c_src/api_ng.c index 5d063c3ae4..3408ba1b88 100644 --- a/lib/crypto/c_src/api_ng.c +++ b/lib/crypto/c_src/api_ng.c @@ -27,7 +27,7 @@ * */ ERL_NIF_TERM ng_crypto_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -ERL_NIF_TERM ng_crypto_one_shot(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +ERL_NIF_TERM ng_crypto_one_time(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); #ifdef HAVE_ECB_IVEC_BUG /* <= 0.9.8l returns faulty ivec length */ @@ -93,6 +93,13 @@ static int get_init_args(ErlNifEnv* env, goto err; } + if ((*cipherp)->flags & AEAD_CIPHER) + { + *return_term = EXCP_BADARG(env, "Missing arguments for this cipher"); + goto err; + } + + if (FORBIDDEN_IN_FIPS(*cipherp)) { *return_term = EXCP_NOTSUP(env, "Forbidden in FIPS"); @@ -413,13 +420,15 @@ int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in) ERL_NIF_TERM ng_crypto_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Context, Data [, IV]) */ struct evp_cipher_ctx *ctx_res; + struct evp_cipher_ctx ctx_res_copy; ERL_NIF_TERM ret; + ctx_res_copy.ctx = NULL; + if (!enif_get_resource(env, argv[0], (ErlNifResourceType*)evp_cipher_ctx_rtype, (void**)&ctx_res)) return EXCP_BADARG(env, "Bad 1:st arg"); if (argc == 3) { - struct evp_cipher_ctx ctx_res_copy; ErlNifBinary ivec_bin; memcpy(&ctx_res_copy, ctx_res, sizeof ctx_res_copy); @@ -474,6 +483,9 @@ ERL_NIF_TERM ng_crypto_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ get_update_args(env, ctx_res, argv[1], &ret); err: + if (ctx_res_copy.ctx) + EVP_CIPHER_CTX_free(ctx_res_copy.ctx); + return ret; /* Both success and error */ } @@ -504,12 +516,17 @@ ERL_NIF_TERM ng_crypto_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM a /* One shot */ /*************************************************************************/ -ERL_NIF_TERM ng_crypto_one_shot(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +ERL_NIF_TERM ng_crypto_one_time(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Cipher, Key, IVec, Data, Encrypt) */ struct evp_cipher_ctx ctx_res; const struct cipher_type_t *cipherp; ERL_NIF_TERM ret; + ctx_res.ctx = NULL; +#if !defined(HAVE_EVP_AES_CTR) + ctx_res.env = NULL; +#endif + if (!get_init_args(env, &ctx_res, argv[0], argv[1], argv[2], argv[4], &cipherp, &ret)) goto ret; @@ -518,10 +535,17 @@ ERL_NIF_TERM ng_crypto_one_shot(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg ret: if (ctx_res.ctx) EVP_CIPHER_CTX_free(ctx_res.ctx); + +#if !defined(HAVE_EVP_AES_CTR) + if (ctx_res.env) + enif_free_env(ctx_res.env); +#endif + return ret; } -ERL_NIF_TERM ng_crypto_one_shot_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) + +ERL_NIF_TERM ng_crypto_one_time_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Cipher, Key, IVec, Data, Encrypt) % if no IV for the Cipher, set IVec = <<>> */ ErlNifBinary data_bin; @@ -536,10 +560,10 @@ ERL_NIF_TERM ng_crypto_one_shot_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM /* Run long jobs on a dirty scheduler to not block the current emulator thread */ if (data_bin.size > MAX_BYTES_TO_NIF) { - return enif_schedule_nif(env, "ng_crypto_one_shot", + return enif_schedule_nif(env, "ng_crypto_one_time", ERL_NIF_DIRTY_JOB_CPU_BOUND, - ng_crypto_one_shot, argc, argv); + ng_crypto_one_time, argc, argv); } - return ng_crypto_one_shot(env, argc, argv); + return ng_crypto_one_time(env, argc, argv); } diff --git a/lib/crypto/c_src/api_ng.h b/lib/crypto/c_src/api_ng.h index 5c7d9af3c5..aaf67524ae 100644 --- a/lib/crypto/c_src/api_ng.h +++ b/lib/crypto/c_src/api_ng.h @@ -25,6 +25,6 @@ ERL_NIF_TERM ng_crypto_init_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); ERL_NIF_TERM ng_crypto_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -ERL_NIF_TERM ng_crypto_one_shot_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +ERL_NIF_TERM ng_crypto_one_time_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); #endif /* E_AES_H__ */ diff --git a/lib/crypto/c_src/atoms.c b/lib/crypto/c_src/atoms.c index 0793ffa6ca..059c14690f 100644 --- a/lib/crypto/c_src/atoms.c +++ b/lib/crypto/c_src/atoms.c @@ -70,6 +70,7 @@ ERL_NIF_TERM atom_onbasis; ERL_NIF_TERM atom_aes_cfb8; ERL_NIF_TERM atom_aes_cfb128; +ERL_NIF_TERM atom_aes_ige256; #ifdef HAVE_GCM ERL_NIF_TERM atom_aes_gcm; #endif @@ -188,6 +189,7 @@ int init_atoms(ErlNifEnv *env, const ERL_NIF_TERM fips_mode, const ERL_NIF_TERM atom_aes_cfb8 = enif_make_atom(env, "aes_cfb8"); atom_aes_cfb128 = enif_make_atom(env, "aes_cfb128"); + atom_aes_ige256 = enif_make_atom(env, "aes_ige256"); #ifdef HAVE_GCM atom_aes_gcm = enif_make_atom(env, "aes_gcm"); #endif diff --git a/lib/crypto/c_src/atoms.h b/lib/crypto/c_src/atoms.h index 24f6dc26fd..f5913de96f 100644 --- a/lib/crypto/c_src/atoms.h +++ b/lib/crypto/c_src/atoms.h @@ -74,6 +74,7 @@ extern ERL_NIF_TERM atom_onbasis; extern ERL_NIF_TERM atom_aes_cfb8; extern ERL_NIF_TERM atom_aes_cfb128; +extern ERL_NIF_TERM atom_aes_ige256; #ifdef HAVE_GCM extern ERL_NIF_TERM atom_aes_gcm; #endif diff --git a/lib/crypto/c_src/cipher.c b/lib/crypto/c_src/cipher.c index 2652e1db4e..00072af632 100644 --- a/lib/crypto/c_src/cipher.c +++ b/lib/crypto/c_src/cipher.c @@ -20,10 +20,10 @@ #include "cipher.h" -#ifdef OPENSSL_NO_DES -#define COND_NO_DES_PTR(Ptr) (NULL) -#else +#ifdef HAVE_DES #define COND_NO_DES_PTR(Ptr) (Ptr) +#else +#define COND_NO_DES_PTR(Ptr) (NULL) #endif static struct cipher_type_t cipher_types[] = @@ -50,39 +50,30 @@ static struct cipher_type_t cipher_types[] = {{"des_ede3_cfb"}, {NULL}, 0, 0}, #endif +#ifdef HAVE_BF {{"blowfish_cbc"}, {&EVP_bf_cbc}, 0, NO_FIPS_CIPHER}, {{"blowfish_cfb64"}, {&EVP_bf_cfb64}, 0, NO_FIPS_CIPHER}, {{"blowfish_ofb64"}, {&EVP_bf_ofb}, 0, NO_FIPS_CIPHER}, {{"blowfish_ecb"}, {&EVP_bf_ecb}, 0, NO_FIPS_CIPHER | ECB_BUG_0_9_8L}, - - {{"aes_cbc"}, {&EVP_aes_128_cbc}, 16, 0}, - {{"aes_cbc"}, {&EVP_aes_192_cbc}, 24, 0}, - {{"aes_cbc"}, {&EVP_aes_256_cbc}, 32, 0}, +#else + {{"blowfish_cbc"}, {NULL}, 0, 0}, + {{"blowfish_cfb64"}, {NULL}, 0, 0}, + {{"blowfish_ofb64"}, {NULL}, 0, 0}, + {{"blowfish_ecb"}, {NULL}, 0, 0}, +#endif {{"aes_128_cbc"}, {&EVP_aes_128_cbc}, 16, 0}, {{"aes_192_cbc"}, {&EVP_aes_192_cbc}, 24, 0}, {{"aes_256_cbc"}, {&EVP_aes_256_cbc}, 32, 0}, - {{"aes_cfb8"}, {&EVP_aes_128_cfb8}, 16, NO_FIPS_CIPHER | AES_CFBx}, - {{"aes_cfb8"}, {&EVP_aes_192_cfb8}, 24, NO_FIPS_CIPHER | AES_CFBx}, - {{"aes_cfb8"}, {&EVP_aes_256_cfb8}, 32, NO_FIPS_CIPHER | AES_CFBx}, - {{"aes_128_cfb8"}, {&EVP_aes_128_cfb8}, 16, NO_FIPS_CIPHER | AES_CFBx}, {{"aes_192_cfb8"}, {&EVP_aes_192_cfb8}, 24, NO_FIPS_CIPHER | AES_CFBx}, {{"aes_256_cfb8"}, {&EVP_aes_256_cfb8}, 32, NO_FIPS_CIPHER | AES_CFBx}, - {{"aes_cfb128"}, {&EVP_aes_128_cfb128}, 16, NO_FIPS_CIPHER | AES_CFBx}, - {{"aes_cfb128"}, {&EVP_aes_192_cfb128}, 24, NO_FIPS_CIPHER | AES_CFBx}, - {{"aes_cfb128"}, {&EVP_aes_256_cfb128}, 32, NO_FIPS_CIPHER | AES_CFBx}, - {{"aes_128_cfb128"}, {&EVP_aes_128_cfb128}, 16, NO_FIPS_CIPHER | AES_CFBx}, {{"aes_192_cfb128"}, {&EVP_aes_192_cfb128}, 24, NO_FIPS_CIPHER | AES_CFBx}, {{"aes_256_cfb128"}, {&EVP_aes_256_cfb128}, 32, NO_FIPS_CIPHER | AES_CFBx}, - {{"aes_ecb"}, {&EVP_aes_128_ecb}, 16, ECB_BUG_0_9_8L}, - {{"aes_ecb"}, {&EVP_aes_192_ecb}, 24, ECB_BUG_0_9_8L}, - {{"aes_ecb"}, {&EVP_aes_256_ecb}, 32, ECB_BUG_0_9_8L}, - {{"aes_128_ecb"}, {&EVP_aes_128_ecb}, 16, ECB_BUG_0_9_8L}, {{"aes_192_ecb"}, {&EVP_aes_192_ecb}, 24, ECB_BUG_0_9_8L}, {{"aes_256_ecb"}, {&EVP_aes_256_ecb}, 32, ECB_BUG_0_9_8L}, @@ -91,16 +82,10 @@ static struct cipher_type_t cipher_types[] = {{"aes_128_ctr"}, {&EVP_aes_128_ctr}, 16, 0}, {{"aes_192_ctr"}, {&EVP_aes_192_ctr}, 24, 0}, {{"aes_256_ctr"}, {&EVP_aes_256_ctr}, 32, 0}, - {{"aes_ctr"}, {&EVP_aes_128_ctr}, 16, 0}, - {{"aes_ctr"}, {&EVP_aes_192_ctr}, 24, 0}, - {{"aes_ctr"}, {&EVP_aes_256_ctr}, 32, 0}, #else {{"aes_128_ctr"}, {NULL}, 16, AES_CTR_COMPAT}, {{"aes_192_ctr"}, {NULL}, 24, AES_CTR_COMPAT}, {{"aes_256_ctr"}, {NULL}, 32, AES_CTR_COMPAT}, - {{"aes_ctr"}, {NULL}, 16, AES_CTR_COMPAT}, - {{"aes_ctr"}, {NULL}, 24, AES_CTR_COMPAT}, - {{"aes_ctr"}, {NULL}, 32, AES_CTR_COMPAT}, #endif #if defined(HAVE_CHACHA20) @@ -117,31 +102,23 @@ static struct cipher_type_t cipher_types[] = #endif #if defined(HAVE_GCM) - {{"aes_gcm"}, {&EVP_aes_128_gcm}, 16, AEAD_CIPHER, {{EVP_CTRL_GCM_SET_IVLEN,EVP_CTRL_GCM_GET_TAG,EVP_CTRL_GCM_SET_TAG}}}, - {{"aes_gcm"}, {&EVP_aes_192_gcm}, 24, AEAD_CIPHER, {{EVP_CTRL_GCM_SET_IVLEN,EVP_CTRL_GCM_GET_TAG,EVP_CTRL_GCM_SET_TAG}}}, - {{"aes_gcm"}, {&EVP_aes_256_gcm}, 32, AEAD_CIPHER, {{EVP_CTRL_GCM_SET_IVLEN,EVP_CTRL_GCM_GET_TAG,EVP_CTRL_GCM_SET_TAG}}}, - {{"aes_128_gcm"}, {&EVP_aes_128_gcm}, 16, AEAD_CIPHER, {{EVP_CTRL_GCM_SET_IVLEN,EVP_CTRL_GCM_GET_TAG,EVP_CTRL_GCM_SET_TAG}}}, - {{"aes_192_gcm"}, {&EVP_aes_192_gcm}, 24, AEAD_CIPHER, {{EVP_CTRL_GCM_SET_IVLEN,EVP_CTRL_GCM_GET_TAG,EVP_CTRL_GCM_SET_TAG}}}, - {{"aes_256_gcm"}, {&EVP_aes_256_gcm}, 32, AEAD_CIPHER, {{EVP_CTRL_GCM_SET_IVLEN,EVP_CTRL_GCM_GET_TAG,EVP_CTRL_GCM_SET_TAG}}}, + {{"aes_128_gcm"}, {&EVP_aes_128_gcm}, 16, AEAD_CIPHER|GCM_MODE, {{EVP_CTRL_GCM_SET_IVLEN,EVP_CTRL_GCM_GET_TAG,EVP_CTRL_GCM_SET_TAG}}}, + {{"aes_192_gcm"}, {&EVP_aes_192_gcm}, 24, AEAD_CIPHER|GCM_MODE, {{EVP_CTRL_GCM_SET_IVLEN,EVP_CTRL_GCM_GET_TAG,EVP_CTRL_GCM_SET_TAG}}}, + {{"aes_256_gcm"}, {&EVP_aes_256_gcm}, 32, AEAD_CIPHER|GCM_MODE, {{EVP_CTRL_GCM_SET_IVLEN,EVP_CTRL_GCM_GET_TAG,EVP_CTRL_GCM_SET_TAG}}}, #else - {{"aes_gcm"}, {NULL}, 0, AEAD_CIPHER, {{0,0,0}}}, - {{"aes_128_gcm"}, {NULL}, 16, AEAD_CIPHER, {{0,0,0}}}, - {{"aes_192_gcm"}, {NULL}, 24, AEAD_CIPHER, {{0,0,0}}}, - {{"aes_256_gcm"}, {NULL}, 32, AEAD_CIPHER, {{0,0,0}}}, + {{"aes_128_gcm"}, {NULL}, 16, AEAD_CIPHER|GCM_MODE, {{0,0,0}}}, + {{"aes_192_gcm"}, {NULL}, 24, AEAD_CIPHER|GCM_MODE, {{0,0,0}}}, + {{"aes_256_gcm"}, {NULL}, 32, AEAD_CIPHER|GCM_MODE, {{0,0,0}}}, #endif #if defined(HAVE_CCM) - {{"aes_ccm"}, {&EVP_aes_128_ccm}, 16, AEAD_CIPHER, {{EVP_CTRL_CCM_SET_IVLEN,EVP_CTRL_CCM_GET_TAG,EVP_CTRL_CCM_SET_TAG}}}, - {{"aes_ccm"}, {&EVP_aes_192_ccm}, 24, AEAD_CIPHER, {{EVP_CTRL_CCM_SET_IVLEN,EVP_CTRL_CCM_GET_TAG,EVP_CTRL_CCM_SET_TAG}}}, - {{"aes_ccm"}, {&EVP_aes_256_ccm}, 32, AEAD_CIPHER, {{EVP_CTRL_CCM_SET_IVLEN,EVP_CTRL_CCM_GET_TAG,EVP_CTRL_CCM_SET_TAG}}}, - {{"aes_128_ccm"}, {&EVP_aes_128_ccm}, 16, AEAD_CIPHER, {{EVP_CTRL_CCM_SET_IVLEN,EVP_CTRL_CCM_GET_TAG,EVP_CTRL_CCM_SET_TAG}}}, - {{"aes_192_ccm"}, {&EVP_aes_192_ccm}, 24, AEAD_CIPHER, {{EVP_CTRL_CCM_SET_IVLEN,EVP_CTRL_CCM_GET_TAG,EVP_CTRL_CCM_SET_TAG}}}, - {{"aes_256_ccm"}, {&EVP_aes_256_ccm}, 32, AEAD_CIPHER, {{EVP_CTRL_CCM_SET_IVLEN,EVP_CTRL_CCM_GET_TAG,EVP_CTRL_CCM_SET_TAG}}}, + {{"aes_128_ccm"}, {&EVP_aes_128_ccm}, 16, AEAD_CIPHER|CCM_MODE, {{EVP_CTRL_CCM_SET_IVLEN,EVP_CTRL_CCM_GET_TAG,EVP_CTRL_CCM_SET_TAG}}}, + {{"aes_192_ccm"}, {&EVP_aes_192_ccm}, 24, AEAD_CIPHER|CCM_MODE, {{EVP_CTRL_CCM_SET_IVLEN,EVP_CTRL_CCM_GET_TAG,EVP_CTRL_CCM_SET_TAG}}}, + {{"aes_256_ccm"}, {&EVP_aes_256_ccm}, 32, AEAD_CIPHER|CCM_MODE, {{EVP_CTRL_CCM_SET_IVLEN,EVP_CTRL_CCM_GET_TAG,EVP_CTRL_CCM_SET_TAG}}}, #else - {{"aes_ccm"}, {NULL}, 0, AEAD_CIPHER, {{0,0,0}}}, - {{"aes_128_ccm"}, {NULL}, 16, AEAD_CIPHER, {{0,0,0}}}, - {{"aes_192_ccm"}, {NULL}, 24, AEAD_CIPHER, {{0,0,0}}}, - {{"aes_256_ccm"}, {NULL}, 32, AEAD_CIPHER, {{0,0,0}}}, + {{"aes_128_ccm"}, {NULL}, 16, AEAD_CIPHER|CCM_MODE, {{0,0,0}}}, + {{"aes_192_ccm"}, {NULL}, 24, AEAD_CIPHER|CCM_MODE, {{0,0,0}}}, + {{"aes_256_ccm"}, {NULL}, 32, AEAD_CIPHER|CCM_MODE, {{0,0,0}}}, #endif /*==== Specialy handled ciphers, only for inclusion in algorithm's list ====*/ @@ -352,13 +329,15 @@ ERL_NIF_TERM cipher_types_as_list(ErlNifEnv* env) prev = atom_undefined; for (p = cipher_types; (p->type.atom & (p->type.atom != atom_false)); p++) { - if ((prev != p->type.atom) && - ((p->cipher.p != NULL) || - (p->flags & (NON_EVP_CIPHER|AES_CTR_COMPAT)) ) && /* Special handling. Bad indeed... */ - ! FORBIDDEN_IN_FIPS(p) - ) - hd = enif_make_list_cell(env, p->type.atom, hd); - prev = p->type.atom; + if ((prev == p->type.atom) || + FORBIDDEN_IN_FIPS(p) ) + continue; + + if ((p->cipher.p != NULL) || + (p->type.atom == atom_aes_ige256)) /* Special handling. Bad indeed... */ + { + hd = enif_make_list_cell(env, p->type.atom, hd); + } } return hd; diff --git a/lib/crypto/c_src/cipher.h b/lib/crypto/c_src/cipher.h index b94873940f..0e51c410eb 100644 --- a/lib/crypto/c_src/cipher.h +++ b/lib/crypto/c_src/cipher.h @@ -46,6 +46,8 @@ struct cipher_type_t { #define AEAD_CIPHER 8 #define NON_EVP_CIPHER 16 #define AES_CTR_COMPAT 32 +#define CCM_MODE 64 +#define GCM_MODE 128 #ifdef FIPS_SUPPORT diff --git a/lib/crypto/c_src/common.h b/lib/crypto/c_src/common.h index 0bf7f09f4f..a7e59d5d01 100644 --- a/lib/crypto/c_src/common.h +++ b/lib/crypto/c_src/common.h @@ -38,8 +38,11 @@ /* All nif functions return a valid value or throws an exception */ #define EXCP(Env, Id, Str) enif_raise_exception((Env), \ - enif_make_tuple2((Env), \ + enif_make_tuple3((Env), \ (Id), \ + enif_make_tuple2((Env), \ + enif_make_string((Env),__FILE__,(ERL_NIF_LATIN1)), \ + enif_make_int((Env), __LINE__)), \ enif_make_string((Env),(Str),(ERL_NIF_LATIN1)) )) #define EXCP_NOTSUP(Env, Str) EXCP((Env), atom_notsup, (Str)) diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index 4aed06a489..d533cba140 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -63,7 +63,12 @@ static ErlNifFunc nif_funcs[] = { {"info_lib", 0, info_lib, 0}, {"info_fips", 0, info_fips, 0}, {"enable_fips_mode", 1, enable_fips_mode, 0}, - {"algorithms", 0, algorithms, 0}, + {"hash_algorithms", 0, hash_algorithms, 0}, + {"pubkey_algorithms", 0, pubkey_algorithms, 0}, + {"cipher_algorithms", 0, cipher_algorithms, 0}, + {"mac_algorithms", 0, mac_algorithms, 0}, + {"curve_algorithms", 0, curve_algorithms, 0}, + {"rsa_opts_algorithms", 0, rsa_opts_algorithms, 0}, {"hash_info", 1, hash_info_nif, 0}, {"hash_nif", 2, hash_nif, 0}, {"hash_init_nif", 1, hash_init_nif, 0}, @@ -81,7 +86,7 @@ static ErlNifFunc nif_funcs[] = { {"ng_crypto_init_nif", 4, ng_crypto_init_nif, 0}, {"ng_crypto_update_nif", 2, ng_crypto_update_nif, 0}, {"ng_crypto_update_nif", 3, ng_crypto_update_nif, 0}, - {"ng_crypto_one_shot_nif", 5, ng_crypto_one_shot_nif, 0}, + {"ng_crypto_one_time_nif", 5, ng_crypto_one_time_nif, 0}, {"strong_rand_bytes_nif", 1, strong_rand_bytes_nif, 0}, {"strong_rand_range_nif", 1, strong_rand_range_nif, 0}, {"rand_uniform_nif", 2, rand_uniform_nif, 0}, @@ -105,8 +110,7 @@ static ErlNifFunc nif_funcs[] = { {"rand_seed_nif", 1, rand_seed_nif, 0}, - {"aead_encrypt", 6, aead_encrypt, 0}, - {"aead_decrypt", 6, aead_decrypt, 0}, + {"aead_cipher", 7, aead_cipher, 0}, {"poly1305_nif", 2, poly1305_nif, 0}, diff --git a/lib/crypto/c_src/dh.c b/lib/crypto/c_src/dh.c index 38eb534d99..13a2336f25 100644 --- a/lib/crypto/c_src/dh.c +++ b/lib/crypto/c_src/dh.c @@ -23,6 +23,7 @@ ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (PrivKey|undefined, DHParams=[P,G], Mpint, Len|0) */ +#ifdef HAVE_DH DH *dh_params = NULL; unsigned int mpint; /* 0 or 4 */ ERL_NIF_TERM head, tail; @@ -187,10 +188,14 @@ ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar #endif return ret; +#else + return enif_raise_exception(env, atom_notsup); +#endif } ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (OthersPublicKey, MyPrivateKey, DHParams=[P,G]) */ +#ifdef HAVE_DH BIGNUM *other_pub_key = NULL; BIGNUM *dh_p = NULL; BIGNUM *dh_g = NULL; @@ -291,4 +296,7 @@ ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg DH_free(dh_priv); return ret; +#else + return enif_raise_exception(env, atom_notsup); +#endif } diff --git a/lib/crypto/c_src/dss.c b/lib/crypto/c_src/dss.c index 9bf8eb3ce0..63268f0f2b 100644 --- a/lib/crypto/c_src/dss.c +++ b/lib/crypto/c_src/dss.c @@ -21,6 +21,8 @@ #include "dss.h" #include "bn.h" +#ifdef HAVE_DSA + int get_dss_private_key(ErlNifEnv* env, ERL_NIF_TERM key, DSA *dsa) { /* key=[P,Q,G,KEY] */ @@ -142,3 +144,5 @@ int get_dss_public_key(ErlNifEnv* env, ERL_NIF_TERM key, DSA *dsa) BN_free(dsa_y); return 0; } + +#endif diff --git a/lib/crypto/c_src/dss.h b/lib/crypto/c_src/dss.h index 3275657e98..07e28ca7c5 100644 --- a/lib/crypto/c_src/dss.h +++ b/lib/crypto/c_src/dss.h @@ -23,7 +23,9 @@ #include "common.h" +#ifdef HAVE_DSA int get_dss_private_key(ErlNifEnv* env, ERL_NIF_TERM key, DSA *dsa); int get_dss_public_key(ErlNifEnv* env, ERL_NIF_TERM key, DSA *dsa); +#endif #endif /* E_DSS_H__ */ diff --git a/lib/crypto/c_src/openssl_config.h b/lib/crypto/c_src/openssl_config.h index f926f8af13..339eb5b8f4 100644 --- a/lib/crypto/c_src/openssl_config.h +++ b/lib/crypto/c_src/openssl_config.h @@ -25,9 +25,8 @@ #include <openssl/opensslconf.h> #include <openssl/crypto.h> -#ifndef OPENSSL_NO_DES #include <openssl/des.h> -#endif /* #ifndef OPENSSL_NO_DES */ + /* #include <openssl/idea.h> This is not supported on the openssl OTP requires */ #include <openssl/dsa.h> #include <openssl/rsa.h> @@ -166,6 +165,22 @@ # define HAVE_BLAKE2 #endif +#ifndef OPENSSL_NO_BF +# define HAVE_BF +#endif + +#ifndef OPENSSL_NO_DES +# define HAVE_DES +#endif + +#ifndef OPENSSL_NO_DH +# define HAVE_DH +#endif + +#ifndef OPENSSL_NO_DSA +# define HAVE_DSA +#endif + #ifndef OPENSSL_NO_MD4 # define HAVE_MD4 #endif diff --git a/lib/crypto/c_src/otp_test_engine.c b/lib/crypto/c_src/otp_test_engine.c index fd26b7cb5d..c3bd9dfb55 100644 --- a/lib/crypto/c_src/otp_test_engine.c +++ b/lib/crypto/c_src/otp_test_engine.c @@ -160,7 +160,7 @@ static int test_engine_md5_update(EVP_MD_CTX *ctx,const void *data, size_t count static int test_engine_md5_final(EVP_MD_CTX *ctx,unsigned char *md) { #ifdef OLD - fprintf(stderr, "MD5 final size of EVP_MD: %lu\r\n", sizeof(EVP_MD)); + fprintf(stderr, "MD5 final size of EVP_MD: %lu\r\n", (unsigned long)sizeof(EVP_MD)); if (!MD5_Final(md, data(ctx))) goto err; @@ -404,7 +404,7 @@ int test_rsa_sign(int dtype, } */ if ((sizeof(fake_flag) == m_len) - && bcmp(m,fake_flag,m_len) == 0) { + && memcmp(m,fake_flag,m_len) == 0) { int slen; printf("To be faked\r\n"); @@ -432,7 +432,7 @@ int test_rsa_verify(int dtype, printf("test_rsa_verify (dtype=%i) called m_len=%u siglen=%u\r\n", dtype, m_len, siglen); if ((sizeof(fake_flag) == m_len) - && bcmp(m,fake_flag,m_len) == 0) { + && memcmp(m,fake_flag,m_len) == 0) { int size; if ((size = RSA_size(rsa)) < 0) diff --git a/lib/crypto/c_src/pkey.c b/lib/crypto/c_src/pkey.c index 638bb588fa..a1e2677b34 100644 --- a/lib/crypto/c_src/pkey.c +++ b/lib/crypto/c_src/pkey.c @@ -254,7 +254,9 @@ static int get_pkey_private_key(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_ { EVP_PKEY *result = NULL; RSA *rsa = NULL; +#ifdef HAVE_DSA DSA *dsa = NULL; +#endif #if defined(HAVE_EC) EC_KEY *ec = NULL; #endif @@ -327,6 +329,7 @@ static int get_pkey_private_key(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_ return PKEY_NOTSUP; #endif } else if (algorithm == atom_dss) { +#ifdef HAVE_DSA if ((dsa = DSA_new()) == NULL) goto err; if (!get_dss_private_key(env, key, dsa)) @@ -340,9 +343,9 @@ static int get_pkey_private_key(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_ dsa = NULL; } else { +#endif return PKEY_BADARG; } - goto done; err: @@ -357,8 +360,10 @@ static int get_pkey_private_key(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_ enif_free(id); if (rsa) RSA_free(rsa); +#ifdef HAVE_DSA if (dsa) DSA_free(dsa); +#endif #ifdef HAVE_EC if (ec) EC_KEY_free(ec); @@ -377,7 +382,9 @@ static int get_pkey_public_key(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_T { EVP_PKEY *result = NULL; RSA *rsa = NULL; +#ifdef HAVE_DSA DSA *dsa = NULL; +#endif #if defined(HAVE_EC) EC_KEY *ec = NULL; #endif @@ -449,6 +456,7 @@ static int get_pkey_public_key(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_T return PKEY_NOTSUP; #endif } else if (algorithm == atom_dss) { +#ifdef HAVE_DSA if ((dsa = DSA_new()) == NULL) goto err; @@ -461,7 +469,9 @@ static int get_pkey_public_key(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_T goto err; /* On success, result owns dsa */ dsa = NULL; - +#else + return PKEY_NOTSUP; +#endif } else { return PKEY_BADARG; } @@ -480,8 +490,10 @@ static int get_pkey_public_key(ErlNifEnv *env, ERL_NIF_TERM algorithm, ERL_NIF_T enif_free(id); if (rsa) RSA_free(rsa); +#ifdef HAVE_DSA if (dsa) DSA_free(dsa); +#endif #ifdef HAVE_EC if (ec) EC_KEY_free(ec); @@ -518,7 +530,9 @@ ERL_NIF_TERM pkey_sign_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) unsigned char *tbs; /* data to be signed */ size_t tbslen; RSA *rsa = NULL; +#ifdef HAVE_DSA DSA *dsa = NULL; +#endif #if defined(HAVE_EC) EC_KEY *ec = NULL; #endif @@ -706,8 +720,10 @@ enif_get_atom(env,argv[1],buf,1024,ERL_NIF_LATIN1); printf("hash=%s ",buf); enif_release_binary(&sig_bin); if (rsa) RSA_free(rsa); +#ifdef HAVE_DSA if (dsa) DSA_free(dsa); +#endif #ifdef HAVE_EC if (ec) EC_KEY_free(ec); @@ -744,7 +760,9 @@ ERL_NIF_TERM pkey_verify_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[] size_t tbslen; ERL_NIF_TERM ret; RSA *rsa = NULL; +#ifdef HAVE_DSA DSA *dsa = NULL; +#endif #ifdef HAVE_EC EC_KEY *ec = NULL; #endif @@ -890,8 +908,10 @@ ERL_NIF_TERM pkey_verify_nif(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[] EVP_PKEY_free(pkey); if (rsa) RSA_free(rsa); +#ifdef HAVE_DSA if (dsa) DSA_free(dsa); +#endif #ifdef HAVE_EC if (ec) EC_KEY_free(ec); @@ -1358,7 +1378,9 @@ ERL_NIF_TERM privkey_to_pubkey_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ERL_NIF_TERM ret; EVP_PKEY *pkey = NULL; RSA *rsa = NULL; +#ifdef HAVE_DSA DSA *dsa = NULL; +#endif ERL_NIF_TERM result[8]; ASSERT(argc == 2); @@ -1383,6 +1405,7 @@ ERL_NIF_TERM privkey_to_pubkey_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ret = enif_make_list_from_array(env, result, 2); +#ifdef HAVE_DSA } else if (argv[0] == atom_dss) { const BIGNUM *p = NULL, *q = NULL, *g = NULL, *pub_key = NULL; @@ -1402,7 +1425,7 @@ ERL_NIF_TERM privkey_to_pubkey_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM goto err; ret = enif_make_list_from_array(env, result, 4); - +#endif } else if (argv[0] == atom_ecdsa) { #if defined(HAVE_EC) /* not yet implemented @@ -1452,8 +1475,10 @@ ERL_NIF_TERM privkey_to_pubkey_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM done: if (rsa) RSA_free(rsa); +#ifdef HAVE_DSA if (dsa) DSA_free(dsa); +#endif if (pkey) EVP_PKEY_free(pkey); diff --git a/lib/crypto/doc/src/Makefile b/lib/crypto/doc/src/Makefile index cbcafb7375..8da494dad6 100644 --- a/lib/crypto/doc/src/Makefile +++ b/lib/crypto/doc/src/Makefile @@ -39,7 +39,8 @@ XML_REF3_FILES = crypto.xml XML_REF6_FILES = crypto_app.xml XML_PART_FILES = usersguide.xml -XML_CHAPTER_FILES = notes.xml licenses.xml fips.xml engine_load.xml engine_keys.xml algorithm_details.xml +XML_CHAPTER_FILES = notes.xml licenses.xml fips.xml engine_load.xml engine_keys.xml \ + algorithm_details.xml new_api.xml BOOK_FILES = book.xml diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml index 8a4fad67de..d1d1252f29 100644 --- a/lib/crypto/doc/src/crypto.xml +++ b/lib/crypto/doc/src/crypto.xml @@ -42,7 +42,7 @@ <item> <url href="https://www.nist.gov/publications/sha-3-standard-permutation-based-hash-and-extendable-output-functions?pub_id=919061"> SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions [FIPS PUB 202] - </url> + </url> </item> <tag>BLAKE2</tag> <item> @@ -190,70 +190,101 @@ </description> <datatypes> - <datatype_title>Ciphers</datatype_title> + <datatype_title>Ciphers, new API</datatype_title> <datatype> <name name="cipher"/> - <name name="stream_cipher"/> - <name name="block_cipher"/> <desc> - <p>Ciphers known byt the CRYPTO application. Note that this list might be reduced if the - underlying libcrypto does not support all of them.</p> </desc> </datatype> - <datatype> - <name name="stream_cipher_iv"/> - <name name="stream_cipher_no_iv"/> + <name name="cipher_no_iv"/> <desc> - <p>Stream ciphers for - <seealso marker="#stream_init-3">stream_init/3</seealso> and - <seealso marker="#stream_init-2">stream_init/2</seealso> . - </p> + </desc> + </datatype> + <datatype> + <name name="cipher_iv"/> + <desc> + </desc> + </datatype> + <datatype> + <name name="cipher_aead"/> + <desc> + <p>Ciphers known by the CRYPTO application when using the + <seealso marker="crypto:new_api#the-new-api">new API</seealso>.</p> + <p>Note that this list might be reduced if the underlying libcrypto does not support all of them.</p> </desc> </datatype> + <datatype_title>Ciphers, old API</datatype_title> + <datatype> + <name name="block_cipher_with_iv"/> + <desc> + </desc> + </datatype> + <datatype> + <name name="block_cipher_without_iv"/> + <desc> + </desc> + </datatype> + <datatype> + <name name="stream_cipher"/> + <desc> + </desc> + </datatype> + <datatype> + <name name="aead_cipher"/> + <desc> + </desc> + </datatype> <datatype> - <name name="block_cipher_iv"/> <name name="cbc_cipher"/> + <desc> + </desc> + </datatype> + <datatype> <name name="cfb_cipher"/> <desc> - <p>Block ciphers with initialization vector for - <seealso marker="#block_encrypt-4">block_encrypt/4</seealso> and - <seealso marker="#block_decrypt-4">block_decrypt/4</seealso> . - </p> </desc> </datatype> - <datatype> - <name name="alias_cfb"/> - <name name="alias_cbc"/> + <name name="ctr_cipher"/> <desc> - <p>Names that are replaced by more common names. They may deprecated in futer releases.</p> - <p><c>des3_cbc</c> and <c>des_ede3</c> should be replaced by <c>des_ede3_cbc</c></p> - <p><c>des_ede3_cbf</c>, <c>des3_cbf</c> and <c>des3_cfb</c> should be replaced by <c>des_ede3_cfb</c>.</p> - <p><c>aes_cbc128</c> should be replaced by <c>aes_128_cbc</c>.</p> - <p><c>aes_cbc256</c> should be replaced by <c>aes_256_cbc</c>.</p> </desc> </datatype> - <datatype> - <name name="block_cipher_no_iv"/> <name name="ecb_cipher"/> <desc> - <p>Block ciphers without initialization vector for - <seealso marker="#block_encrypt-3">block_encrypt/3</seealso> and - <seealso marker="#block_decrypt-3">block_decrypt/3</seealso> . - </p> + <p>Ciphers known by the CRYPTO application when using the + <seealso marker="crypto:new_api#the-old-api">old API</seealso>.</p> + <p>Note that this list might be reduced if the underlying libcrypto does not support all of them.</p> </desc> </datatype> <datatype> - <name name="aead_cipher"/> + <name name="retired_cbc_cipher_aliases"/> + <desc> + </desc> + </datatype> + <datatype> + <name name="retired_cfb_cipher_aliases"/> <desc> - <p>Ciphers with simultaneous MAC-calculation or MAC-checking. - <seealso marker="#block_encrypt-4">block_encrypt/4</seealso> and - <seealso marker="#block_decrypt-4">block_decrypt/4</seealso> . + </desc> + </datatype> + <datatype> + <name name="retired_ctr_cipher_aliases"/> + <desc> + </desc> + </datatype> + <datatype> + <name name="retired_ecb_cipher_aliases"/> + <desc> + <p>Alternative, old names of ciphers known by the CRYPTO application when using the + <seealso marker="crypto:new_api#the-old-api">old API</seealso>. + See <seealso marker="crypto:new_api#retired-cipher-names">Retired cipher names</seealso> for names to + use instead to be prepared for an easy convertion to the + <seealso marker="crypto:new_api#the-new-api">new API</seealso>. </p> + <p>Note that this list might be reduced if the underlying libcrypto does not support all of them.</p> </desc> </datatype> @@ -547,6 +578,7 @@ <name name="stream_state"/> <name name="hmac_state"/> <name name="hash_state"/> + <name name="crypto_state"/> <desc> <p>Contexts with an internal state that should not be manipulated but passed between function calls. </p> @@ -575,117 +607,190 @@ <p>This is a more developed variant of the older <seealso marker="#type-run_time_error">run_time_error()</seealso>. </p> + <p>The exception is:</p> + <pre> + {Tag, {C_FileName,LineNumber}, Description} + + Tag = badarg | notsup | error + C_FileName = string() + LineNumber = integer() + Description = string() + </pre> + <p>It is like the older type an exception of the <c>error</c> class. In addition they contain a descriptive text in English. That text is targeted to a developer. Examples are "Bad key size" or "Cipher id is not an atom". </p> - <p>The exceptions are:</p> + <p>The exception tags are:</p> <taglist> - <tag><c>{badarg, Description::string()}</c></tag> + <tag><c>badarg</c></tag> <item><p>Signifies that one or more arguments are of wrong data type or are otherwise badly formed.</p> </item> - <tag><c>{notsup, Description::string()}</c></tag> + <tag><c>notsup</c></tag> <item><p>Signifies that the algorithm is known but is not supported by current underlying libcrypto or explicitly disabled when building that one.</p> </item> - <tag><c>{error, Description::string()}</c></tag> + <tag><c>error</c></tag> <item><p>An error condition that should not occur, for example a memory allocation failed or the underlying cryptolib returned an error code, for example "Can't initialize context, step 1". Thoose text usually needs searching the C-code to be understood.</p> </item> </taglist> + <p>To catch the exception, use for example:</p> + <code> + try crypto:crypto_init(Ciph, Key, IV, true) + catch + error:{Tag, {C_FileName,LineNumber}, Description} -> + do_something(......) + ..... + end + </code> </desc> </datatype> </datatypes> <!--================ FUNCTIONS ================--> + <section> + <title>New API</title> + </section> + <funcs> <func> - <name name="block_encrypt" arity="3" since="OTP 18.0"/> - <fsummary>Encrypt <c>PlainText</c> according to <c>Type</c> block cipher</fsummary> + <name name="crypto_init" arity="3" since="OTP 22.0"/> + <fsummary>Initializes a series of encryptions or decryptions</fsummary> <desc> - <p>Encrypt <c>PlainText</c> according to <c>Type</c> block cipher.</p> - <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c> - is not supported by the underlying libcrypto implementation.</p> - <p>For keylengths and blocksizes see the - <seealso marker="crypto:algorithm_details#ciphers">User's Guide</seealso>. + <p>As <seealso marker="#crypto_init/4">crypto_init/4</seealso> but for ciphers without IVs.</p> + </desc> + </func> + + <func> + <name name="crypto_init" arity="4" since="OTP 22.0"/> + <fsummary>Initializes a series of encryptions or decryptions</fsummary> + <desc> + <p>Part of the <seealso marker="crypto:new_api#the-new-api">new API</seealso>. + Initializes a series of encryptions or decryptions and creates an internal state + with a reference that is returned. + The actual encryption or decryption is done by + <seealso marker="crypto#crypto_update/2">crypto_update/2</seealso>. + </p> + <p>For encryption, set the <c>EncryptFlag</c> to <c>true</c>. For decryption, set it to <c>false</c>. + </p> + <p>See <seealso marker="crypto:new_api#examples-of-crypto_init-4-and-crypto_update-2"> + examples in the User's Guide.</seealso> </p> </desc> </func> <func> - <name name="block_decrypt" arity="3" since="OTP 18.0"/> - <fsummary>Decrypt <c>CipherText</c> according to <c>Type</c> block cipher</fsummary> + <name name="crypto_update" arity="2" since="OTP 22.0"/> + <fsummary>Do an actual crypto operation on a part of the full text</fsummary> <desc> - <p>Decrypt <c>CipherText</c> according to <c>Type</c> block cipher.</p> - <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c> - is not supported by the underlying libcrypto implementation.</p> - <p>For keylengths and blocksizes see the - <seealso marker="crypto:algorithm_details#ciphers">User's Guide</seealso>. + <p>Part of the <seealso marker="crypto:new_api#the-new-api">new API</seealso>. + It does an actual crypto operation on a part of the full text. If the part is less + than a number of full blocks, only the full blocks (possibly none) are encrypted + or decrypted and the remaining bytes are saved to the next <c>crypto_update</c> operation. + The <c>State</c> should be created with + <seealso marker="crypto#crypto_init/3">crypto_init/3</seealso> + or + <seealso marker="crypto#crypto_init/4">crypto_init/4</seealso>. + </p> + <p>See <seealso marker="crypto:new_api#examples-of-crypto_init-4-and-crypto_update-2"> + examples in the User's Guide.</seealso> </p> </desc> </func> <func> - <name since="OTP R16B01">block_encrypt(Type, Key, Ivec, PlainText) -> CipherText | Error</name> - <name since="OTP R16B01">block_encrypt(AeadType, Key, Ivec, {AAD, PlainText}) -> {CipherText, CipherTag} | Error</name> - <name since="OTP R16B01">block_encrypt(aes_gcm | aes_ccm, Key, Ivec, {AAD, PlainText, TagLength}) -> {CipherText, CipherTag} | Error </name> - <fsummary>Encrypt <c>PlainText</c> according to <c>Type</c> block cipher</fsummary> - <type> - <v>Type = <seealso marker="#type-block_cipher_iv">block_cipher_iv()</seealso></v> - <v>AeadType = <seealso marker="#type-aead_cipher">aead_cipher()</seealso></v> - <v>Key = <seealso marker="#type-key">key()</seealso> | <seealso marker="#type-des3_key">des3_key()</seealso></v> - <v>PlainText = iodata()</v> - <v>AAD = IVec = CipherText = CipherTag = binary()</v> - <v>TagLength = 1..16</v> - <v>Error = <seealso marker="#type-run_time_error">run_time_error()</seealso></v> - </type> + <name name="crypto_dyn_iv_init" arity="3" since="OTP 22.0"/> + <fsummary>Initializes a series of encryptions or decryptions where the IV is provided later</fsummary> <desc> - <p>Encrypt <c>PlainText</c> according to <c>Type</c> block cipher. - <c>IVec</c> is an arbitrary initializing vector.</p> - <p>In AEAD (Authenticated Encryption with Associated Data) mode, encrypt - <c>PlainText</c>according to <c>Type</c> block cipher and calculate - <c>CipherTag</c> that also authenticates the <c>AAD</c> (Associated Authenticated Data).</p> - <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c> - is not supported by the underlying libcrypto implementation.</p> - <p>For keylengths, iv-sizes and blocksizes see the - <seealso marker="crypto:algorithm_details#ciphers">User's Guide</seealso>. + <p>Part of the <seealso marker="crypto:new_api#the-new-api">new API</seealso>. + Initializes a series of encryptions or decryptions where the IV is provided later. + The actual encryption or decryption is done by + <seealso marker="crypto#crypto_dyn_iv_update/3">crypto_dyn_iv_update/3</seealso>. + </p> + <p>For encryption, set the <c>EncryptFlag</c> to <c>true</c>. For decryption, set it to <c>false</c>. </p> </desc> </func> <func> - <name since="OTP R16B01">block_decrypt(Type, Key, Ivec, CipherText) -> PlainText | Error</name> - <name since="OTP R16B01">block_decrypt(AeadType, Key, Ivec, {AAD, CipherText, CipherTag}) -> PlainText | Error</name> - <fsummary>Decrypt <c>CipherText</c> according to <c>Type</c> block cipher</fsummary> - <type> - <v>Type = <seealso marker="#type-block_cipher_iv">block_cipher_iv()</seealso></v> - <v>AeadType = <seealso marker="#type-aead_cipher">aead_cipher()</seealso></v> - <v>Key = <seealso marker="#type-key">key()</seealso> | <seealso marker="#type-des3_key">des3_key()</seealso></v> - <v>PlainText = iodata()</v> - <v>AAD = IVec = CipherText = CipherTag = binary()</v> - <v>Error = BadTag | <seealso marker="#type-run_time_error">run_time_error()</seealso></v> - <v>BadTag = error</v> - </type> + <name name="crypto_dyn_iv_update" arity="3" since="OTP 22.0"/> + <fsummary>Do an actual crypto operation on a part of the full text and the IV is supplied for each part</fsummary> <desc> - <p>Decrypt <c>CipherText</c> according to <c>Type</c> block cipher. - <c>IVec</c> is an arbitrary initializing vector.</p> - <p>In AEAD (Authenticated Encryption with Associated Data) mode, decrypt - <c>CipherText</c>according to <c>Type</c> block cipher and check the authenticity - the <c>PlainText</c> and <c>AAD</c> (Associated Authenticated Data) using the - <c>CipherTag</c>. May return <c>error</c> if the decryption or validation fail's</p> - <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c> - is not supported by the underlying libcrypto implementation.</p> - <p>For keylengths, iv-sizes and blocksizes see the - <seealso marker="crypto:algorithm_details#ciphers">User's Guide</seealso>. + <p>Part of the <seealso marker="crypto:new_api#the-new-api">new API</seealso>. + Do an actual crypto operation on a part of the full text and the IV is supplied for each part. + The <c>State</c> should be created with + <seealso marker="crypto#crypto_dyn_iv_init/3">crypto_dyn_iv_init/3</seealso>. </p> </desc> </func> - <func> + <func> + <name name="crypto_one_time" arity="4" since="OTP 22.0"/> + <fsummary>Do a complete encrypt or decrypt of the full text</fsummary> + <desc> + <p>As <seealso marker="#crypto_one_time/5">crypto_one_time/5</seealso> but for ciphers without IVs.</p> + </desc> + </func> + + <func> + <name name="crypto_one_time" arity="5" since="OTP 22.0"/> + <fsummary>Do a complete encrypt or decrypt of the full text</fsummary> + <desc> + <p>Part of the <seealso marker="crypto:new_api#the-new-api">new API</seealso>. + Do a complete encrypt or decrypt of the full text in the argument <c>Data</c>. + </p> + <p>For encryption, set the <c>EncryptFlag</c> to <c>true</c>. For decryption, set it to <c>false</c>. + </p> + <p>See <seealso marker="crypto:new_api#example-of-crypto_one_time-5">examples in the User's Guide.</seealso> + </p> + </desc> + </func> + + <func> + <name name="crypto_one_time_aead" arity="6" since="OTP 22.0"/> + <name name="crypto_one_time_aead" arity="7" since="OTP 22.0"/> + <fsummary>Do a complete encrypt or decrypt with an AEAD cipher of the full text</fsummary> + <desc> + <p>Part of the <seealso marker="crypto:new_api#the-new-api">new API</seealso>. + Do a complete encrypt or decrypt with an AEAD cipher of the full text. + </p> + <p>For encryption, set the <c>EncryptFlag</c> to <c>true</c> and set the <c>TagOrTagLength</c> + to the wanted size of the tag, that is, the tag length. If the default length is wanted, the + <c>crypto_aead/6</c> form may be used. + </p> + <p>For decryption, set the <c>EncryptFlag</c> to <c>false</c> and put the tag to be checked + in the argument <c>TagOrTagLength</c>. + </p> + <p>See <seealso marker="crypto:new_api#example-of-crypto_one_time_aead-6">examples in the User's Guide.</seealso> + </p> + </desc> + </func> + + <func> + <name name="supports" arity="1" since="OTP 22.0"/> + <fsummary>Provide a list of available crypto algorithms.</fsummary> + <desc> + <p> Can be used to determine which crypto algorithms that are supported + by the underlying libcrypto library</p> + <p>See <seealso marker="#hash_info-1">hash_info/1</seealso> and <seealso marker="#cipher_info-1">cipher_info/1</seealso> + for information about the hash and cipher algorithms. + </p> + </desc> + </func> + + </funcs> + + <section> + <title>API kept from previous versions</title> + </section> + + <funcs> + <func> <name name="bytes_to_integer" arity="1" since="OTP R16B01"/> <fsummary>Convert binary representation, of an integer, to an Erlang integer.</fsummary> <desc> @@ -928,7 +1033,7 @@ cipher algorithm in question. </p> <note> - <p>The ciphers <c>aes_cbc</c>, <c>aes_cfb8</c>, <c>aes_cfb128</c>, <c>aes_ctr</c>, + <p>The ciphers <c>aes_cbc</c>, <c>aes_cfb8</c>, <c>aes_cfb128</c>, <c>aes_ctr</c>, <c>aes_ecb</c>, <c>aes_gcm</c> and <c>aes_ccm</c> has no keylength in the <c>Type</c> as opposed to for example <c>aes_128_ctr</c>. They adapt to the length of the key provided in the encrypt and decrypt function. Therefor it is impossible to return a valid keylength @@ -1094,7 +1199,7 @@ <seealso marker="#rand_seed_s-0">rand_seed_s/0</seealso>. </p> <p> - When using the state object from this function the + When using the state object from this function the <seealso marker="stdlib:rand">rand</seealso> functions using it may raise exception <c>error:low_entropy</c> in case the random generator failed due to lack of secure "randomness". @@ -1120,7 +1225,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre> <seealso marker="stdlib:rand#seed_s-1">rand:seed_s/1</seealso>. </p> <p> - When using the state object from this function the + When using the state object from this function the <seealso marker="stdlib:rand">rand</seealso> functions using it may raise exception <c>error:low_entropy</c> in case the random generator failed due to lack of secure "randomness". @@ -1129,7 +1234,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre> <p> The state returned from this function cannot be used to get a reproducable random sequence as from - the other + the other <seealso marker="stdlib:rand">rand</seealso> functions, since reproducability does not match cryptographically safe. @@ -1160,7 +1265,7 @@ _FloatValue = rand:uniform(). % [0.0; 1.0[</pre> <seealso marker="#rand_seed_alg_s-1">rand_seed_alg_s/1</seealso>. </p> <p> - When using the state object from this function the + When using the state object from this function the <seealso marker="stdlib:rand">rand</seealso> functions using it may raise exception <c>error:low_entropy</c> in case the random generator failed due to lack of secure "randomness". @@ -1227,7 +1332,7 @@ FloatValue = rand:uniform(). % again of 56 bits that makes calculations fast on 64 bit machines. </p> <p> - When using the state object from this function the + When using the state object from this function the <seealso marker="stdlib:rand">rand</seealso> functions using it may raise exception <c>error:low_entropy</c> in case the random generator failed due to lack of secure "randomness". @@ -1248,7 +1353,7 @@ FloatValue = rand:uniform(). % again <p> The state returned from this function cannot be used to get a reproducable random sequence as from - the other + the other <seealso marker="stdlib:rand">rand</seealso> functions, since reproducability does not match cryptographically safe. @@ -1332,68 +1437,6 @@ FloatValue = rand:uniform(). % again </func> <func> - <name name="stream_init" arity="2" since="OTP R16B01"/> - <fsummary></fsummary> - <desc> - <p>Initializes the state for use in RC4 stream encryption - <seealso marker="#stream_encrypt-2">stream_encrypt</seealso> and - <seealso marker="#stream_decrypt-2">stream_decrypt</seealso></p> - <p>For keylengths see the - <seealso marker="crypto:algorithm_details#stream-ciphers">User's Guide</seealso>. - </p> - </desc> - </func> - - <func> - <name name="stream_init" arity="3" since="OTP R16B01"/> - <fsummary></fsummary> - <desc> - <p>Initializes the state for use in streaming AES encryption using Counter mode (CTR). - <c>Key</c> is the AES key and must be either 128, 192, or 256 bits long. <c>IVec</c> is - an arbitrary initializing vector of 128 bits (16 bytes). This state is for use with - <seealso marker="#stream_encrypt-2">stream_encrypt</seealso> and - <seealso marker="#stream_decrypt-2">stream_decrypt</seealso>.</p> - <p>For keylengths and iv-sizes see the - <seealso marker="crypto:algorithm_details#stream-ciphers">User's Guide</seealso>. - </p> - </desc> - </func> - - <func> - <name name="stream_encrypt" arity="2" since="OTP R16B01"/> - <fsummary></fsummary> - <desc> - <p>Encrypts <c>PlainText</c> according to the stream cipher <c>Type</c> specified in stream_init/3. - <c>Text</c> can be any number of bytes. The initial <c>State</c> is created using - <seealso marker="#stream_init-2">stream_init</seealso>. - <c>NewState</c> must be passed into the next call to <c>stream_encrypt</c>.</p> - </desc> - </func> - - <func> - <name name="stream_decrypt" arity="2" since="OTP R16B01"/> - <fsummary></fsummary> - <desc> - <p>Decrypts <c>CipherText</c> according to the stream cipher <c>Type</c> specified in stream_init/3. - <c>PlainText</c> can be any number of bytes. The initial <c>State</c> is created using - <seealso marker="#stream_init-2">stream_init</seealso>. - <c>NewState</c> must be passed into the next call to <c>stream_decrypt</c>.</p> - </desc> - </func> - - <func> - <name name="supports" arity="0" since="OTP R16B01"/> - <fsummary>Provide a list of available crypto algorithms.</fsummary> - <desc> - <p> Can be used to determine which crypto algorithms that are supported - by the underlying libcrypto library</p> - <p>See <seealso marker="#hash_info-1">hash_info/1</seealso> and <seealso marker="#cipher_info-1">cipher_info/1</seealso> - for information about the hash and cipher algorithms. - </p> - </desc> - </func> - - <func> <name name="ec_curves" arity="0" since="OTP 17.0"/> <fsummary>Provide a list of available named elliptic curves.</fsummary> <desc> @@ -1440,6 +1483,12 @@ FloatValue = rand:uniform(). % again </desc> </func> + </funcs> + <section> + <title>Engine API</title> + </section> + + <funcs> <!-- Engine functions --> <func> <name name="privkey_to_pubkey" arity="2" since="OTP 20.2"/> @@ -1752,5 +1801,167 @@ FloatValue = rand:uniform(). % again </funcs> +<section> + <title>Old API</title> +</section> + + <funcs> + <func> + <name name="block_encrypt" arity="3" since="OTP 18.0"/> + <fsummary>Encrypt <c>PlainText</c> according to <c>Type</c> block cipher</fsummary> + <desc> + <dont><p>Don't use this function for new programs! Use <seealso marker="crypto:new_api">the-new-api</seealso>.</p></dont> + <p>Encrypt <c>PlainText</c> according to <c>Type</c> block cipher.</p> + <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c> + is not supported by the underlying libcrypto implementation.</p> + <p>For keylengths and blocksizes see the + <seealso marker="crypto:algorithm_details#ciphers">User's Guide</seealso>. + </p> + </desc> + </func> + + <func> + <name name="block_decrypt" arity="3" since="OTP 18.0"/> + <fsummary>Decrypt <c>CipherText</c> according to <c>Type</c> block cipher</fsummary> + <desc> + <dont><p>Don't use this function for new programs! Use <seealso marker="crypto:new_api">the new api</seealso>.</p></dont> + <p>Decrypt <c>CipherText</c> according to <c>Type</c> block cipher.</p> + <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c> + is not supported by the underlying libcrypto implementation.</p> + <p>For keylengths and blocksizes see the + <seealso marker="crypto:algorithm_details#ciphers">User's Guide</seealso>. + </p> + </desc> + </func> + + <func> + <name since="OTP R16B01">block_encrypt(Type, Key, Ivec, PlainText) -> CipherText | Error</name> + <name since="OTP R16B01">block_encrypt(AeadType, Key, Ivec, {AAD, PlainText}) -> {CipherText, CipherTag} | Error</name> + <name since="OTP R16B01">block_encrypt(aes_gcm | aes_ccm, Key, Ivec, {AAD, PlainText, TagLength}) -> {CipherText, CipherTag} | Error </name> + <fsummary>Encrypt <c>PlainText</c> according to <c>Type</c> block cipher</fsummary> + <type> + <v>Type = <seealso marker="#type-block_cipher_with_iv">block_cipher_with_iv()</seealso></v> + <v>AeadType = <seealso marker="#type-aead_cipher">aead_cipher()</seealso></v> + <v>Key = <seealso marker="#type-key">key()</seealso> | <seealso marker="#type-des3_key">des3_key()</seealso></v> + <v>PlainText = iodata()</v> + <v>AAD = IVec = CipherText = CipherTag = binary()</v> + <v>TagLength = 1..16</v> + <v>Error = <seealso marker="#type-run_time_error">run_time_error()</seealso></v> + </type> + <desc> + <dont><p>Don't use this function for new programs! Use <seealso marker="crypto:new_api">the new api</seealso>.</p></dont> + <p>Encrypt <c>PlainText</c> according to <c>Type</c> block cipher. + <c>IVec</c> is an arbitrary initializing vector.</p> + <p>In AEAD (Authenticated Encryption with Associated Data) mode, encrypt + <c>PlainText</c>according to <c>Type</c> block cipher and calculate + <c>CipherTag</c> that also authenticates the <c>AAD</c> (Associated Authenticated Data).</p> + <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c> + is not supported by the underlying libcrypto implementation.</p> + <p>For keylengths, iv-sizes and blocksizes see the + <seealso marker="crypto:algorithm_details#ciphers">User's Guide</seealso>. + </p> + </desc> + </func> + + <func> + <name since="OTP R16B01">block_decrypt(Type, Key, Ivec, CipherText) -> PlainText | Error</name> + <name since="OTP R16B01">block_decrypt(AeadType, Key, Ivec, {AAD, CipherText, CipherTag}) -> PlainText | Error</name> + <fsummary>Decrypt <c>CipherText</c> according to <c>Type</c> block cipher</fsummary> + <type> + <v>Type = <seealso marker="#type-block_cipher_with_iv">block_cipher_with_iv()</seealso></v> + <v>AeadType = <seealso marker="#type-aead_cipher">aead_cipher()</seealso></v> + <v>Key = <seealso marker="#type-key">key()</seealso> | <seealso marker="#type-des3_key">des3_key()</seealso></v> + <v>PlainText = iodata()</v> + <v>AAD = IVec = CipherText = CipherTag = binary()</v> + <v>Error = BadTag | <seealso marker="#type-run_time_error">run_time_error()</seealso></v> + <v>BadTag = error</v> + </type> + <desc> + <dont><p>Don't use this function for new programs! Use <seealso marker="crypto:new_api">the new api</seealso>.</p></dont> + <p>Decrypt <c>CipherText</c> according to <c>Type</c> block cipher. + <c>IVec</c> is an arbitrary initializing vector.</p> + <p>In AEAD (Authenticated Encryption with Associated Data) mode, decrypt + <c>CipherText</c>according to <c>Type</c> block cipher and check the authenticity + the <c>PlainText</c> and <c>AAD</c> (Associated Authenticated Data) using the + <c>CipherTag</c>. May return <c>error</c> if the decryption or validation fail's</p> + <p>May raise exception <c>error:notsup</c> in case the chosen <c>Type</c> + is not supported by the underlying libcrypto implementation.</p> + <p>For keylengths, iv-sizes and blocksizes see the + <seealso marker="crypto:algorithm_details#ciphers">User's Guide</seealso>. + </p> + </desc> + </func> + + <func> + <name name="stream_init" arity="2" since="OTP R16B01"/> + <fsummary></fsummary> + <desc> + <dont><p>Don't use this function for new programs! Use <seealso marker="crypto:new_api">the new api</seealso>.</p></dont> + <p>Initializes the state for use in RC4 stream encryption + <seealso marker="#stream_encrypt-2">stream_encrypt</seealso> and + <seealso marker="#stream_decrypt-2">stream_decrypt</seealso></p> + <p>For keylengths see the + <seealso marker="crypto:algorithm_details#stream-ciphers">User's Guide</seealso>. + </p> + </desc> + </func> + + <func> + <name name="stream_init" arity="3" since="OTP R16B01"/> + <fsummary></fsummary> + <desc> + <dont><p>Don't use this function for new programs! Use <seealso marker="crypto:new_api">the new api</seealso>.</p></dont> + <p>Initializes the state for use in streaming AES encryption using Counter mode (CTR). + <c>Key</c> is the AES key and must be either 128, 192, or 256 bits long. <c>IVec</c> is + an arbitrary initializing vector of 128 bits (16 bytes). This state is for use with + <seealso marker="#stream_encrypt-2">stream_encrypt</seealso> and + <seealso marker="#stream_decrypt-2">stream_decrypt</seealso>.</p> + <p>For keylengths and iv-sizes see the + <seealso marker="crypto:algorithm_details#stream-ciphers">User's Guide</seealso>. + </p> + </desc> + </func> + + <func> + <name name="stream_encrypt" arity="2" since="OTP R16B01"/> + <fsummary></fsummary> + <desc> + <dont><p>Don't use this function for new programs! Use <seealso marker="crypto:new_api">the new api</seealso>.</p></dont> + <p>Encrypts <c>PlainText</c> according to the stream cipher <c>Type</c> specified in stream_init/3. + <c>Text</c> can be any number of bytes. The initial <c>State</c> is created using + <seealso marker="#stream_init-2">stream_init</seealso>. + <c>NewState</c> must be passed into the next call to <c>stream_encrypt</c>.</p> + </desc> + </func> + + <func> + <name name="stream_decrypt" arity="2" since="OTP R16B01"/> + <fsummary></fsummary> + <desc> + <dont><p>Don't use this function for new programs! Use <seealso marker="crypto:new_api">the new api</seealso>.</p></dont> + <p>Decrypts <c>CipherText</c> according to the stream cipher <c>Type</c> specified in stream_init/3. + <c>PlainText</c> can be any number of bytes. The initial <c>State</c> is created using + <seealso marker="#stream_init-2">stream_init</seealso>. + <c>NewState</c> must be passed into the next call to <c>stream_decrypt</c>.</p> + </desc> + </func> + + <func> + <name name="supports" arity="0" since="OTP R16B01"/> + <fsummary>Provide a list of available crypto algorithms.</fsummary> + <desc> + <dont><p>Don't use this function for new programs! Use + <seealso marker="crypto#supports-1">supports/1</seealso> in + <seealso marker="crypto:new_api">the new api</seealso>.</p></dont> + <p> Can be used to determine which crypto algorithms that are supported + by the underlying libcrypto library</p> + <p>See <seealso marker="#hash_info-1">hash_info/1</seealso> and <seealso marker="#cipher_info-1">cipher_info/1</seealso> + for information about the hash and cipher algorithms. + </p> + </desc> + </func> + + </funcs> + </erlref> diff --git a/lib/crypto/doc/src/new_api.xml b/lib/crypto/doc/src/new_api.xml new file mode 100644 index 0000000000..bd2334ac9f --- /dev/null +++ b/lib/crypto/doc/src/new_api.xml @@ -0,0 +1,260 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>2014</year><year>2019</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + </legalnotice> + + <title>New and Old API</title> + <prepared>Hans Nilsson</prepared> + <docno></docno> + <date>2019-08-22</date> + <rev>A</rev> + <file>new_api.xml</file> + </header> + <p> + This chapter describes the new api to encryption and decryption. + </p> + + <section> + <title>Background</title> + <p>The CRYPTO app has evolved during its lifetime. Since also the OpenSSL cryptolib has changed the + API several times, there are parts of the CRYPTO app that uses a very old one internally and + other parts that uses the latest one. The internal definitions of e.g cipher names was a bit hard + to maintain. + </p> + <p>It turned out that using the old api in the new way (more about that later), and still keep it + backwards compatible, was not possible. Specially as more precision in the error messages was wanted + it could not be combined with the old standard. + </p> + <p>Therefore the old api (see next section) is kept for now but internally implemented with new primitives. + </p> + </section> + + <section> + <title>The old API</title> + <p>The old functions - not recommended for new programs - are:</p> + <list> + <item><seealso marker="crypto#block_encrypt-3">block_encrypt/3</seealso></item> + <item><seealso marker="crypto#block_encrypt-4">block_encrypt/4</seealso></item> + <item><seealso marker="crypto#block_decrypt-3">block_decrypt/3</seealso></item> + <item><seealso marker="crypto#block_decrypt-4">block_decrypt/4</seealso></item> + <item><seealso marker="crypto#stream_init-2">stream_init/2</seealso></item> + <item><seealso marker="crypto#stream_init-2">stream_init/3</seealso></item> + <item><seealso marker="crypto#stream_encrypt-2">stream_encrypt/2</seealso></item> + <item><seealso marker="crypto#stream_decrypt-2">stream_decrypt/2</seealso></item> + <item><seealso marker="crypto#supports-0">supports/0</seealso></item> + </list> + <p>They are not deprecated for now, but may be in a future release. + </p> + </section> + + <section> + <title>The new API</title> + <p>The new functions for encrypting or decrypting one single binary are: + </p> + <list> + <item><seealso marker="crypto#crypto_one_time/4">crypto_one_time/4</seealso></item> + <item><seealso marker="crypto#crypto_one_time/5">crypto_one_time/5</seealso></item> + <item><seealso marker="crypto#crypto_one_time_aead/6">crypto_one_time_aead/6</seealso></item> + <item><seealso marker="crypto#crypto_one_time_aead/7">crypto_one_time_aead/7</seealso></item> + </list> + <p>In those functions the internal crypto state is first created and initialized + with the cipher type, the key and possibly other data. Then the single binary is encrypted + or decrypted, + the crypto state is de-allocated and the result of the crypto operation is returned. + </p> + <p>The <c>crypto_one_time_aead</c> functions are for the ciphers of mode <c>ccm</c> or + <c>gcm</c>, and for the cipher <c>chacha20-poly1305</c>. + </p> + <p>For repeated encryption or decryption of a text divided in parts, where the internal + crypto state is initialized once, and then many binaries are encrypted or decrypted with + the same state, the functions are: + </p> + <list> + <item><seealso marker="crypto#crypto_init/4">crypto_init/4</seealso></item> + <item><seealso marker="crypto#crypto_init/3">crypto_init/3</seealso></item> + <item><seealso marker="crypto#crypto_update/2">crypto_update/2</seealso></item> + </list> + <p>The <c>crypto_init</c> initialies an internal cipher state, and one or more calls of + <c>crypto_update</c> does the acual encryption or decryption. Note that AEAD ciphers + can't be handled this way due to their nature. + </p> + <p>For repeated encryption or decryption of a text divided in parts where the + same cipher and same key is used, but a new initialization vector (nounce) should be applied + for each part, the functions are: + </p> + <list> + <item><seealso marker="crypto#crypto_dyn_iv_init/3">crypto_dyn_iv_init/3</seealso></item> + <item><seealso marker="crypto#crypto_dyn_iv_update/3">crypto_dyn_iv_update/3</seealso></item> + </list> + <p>An example of where those functions are needed, is when handling the TLS protocol.</p> + <p>For information about available algorithms, use: + </p> + <list> + <item><seealso marker="crypto#supports-1">supports/1</seealso></item> + <item><seealso marker="crypto#hash_info-1">hash_info/1</seealso></item> + <item><seealso marker="crypto#cipher_info-1">cipher_info/1</seealso></item> + </list> + + <section> + <title>Examples of crypto_init/4 and crypto_update/2</title> + <p>The functions <seealso marker="crypto#crypto_init/4">crypto_init/4</seealso> + and <seealso marker="crypto#crypto_update/2">crypto_update/2</seealso> are intended + to be used for encrypting or decrypting a sequence of blocks. First one call of + <c>crypto_init/4</c> initialises the crypto context. One or more calls <c>crypto_update/2</c> + does the actual encryption or decryption for each block. + </p> + <p>This example shows first the encryption of two blocks and then decryptions of the cipher + text, but divided into three blocks just to show that it is possible to divide the plain text and + cipher text differently for some ciphers:</p> + <code type="erl"> + 1> crypto:start(). + ok + 2> Key = <<1:128>>. + <<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>> + 3> IV = <<0:128>>. + <<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>> + 4> StateEnc = crypto:crypto_init(aes_128_ctr, Key, IV, true). % encrypt -> true + #Ref<0.3768901617.1128660993.124047> + 5> crypto:crypto_update(StateEnc, <<"First bytes">>). + <<67,44,216,166,25,130,203,5,66,6,162>> + 6> crypto:crypto_update(StateEnc, <<"Second bytes">>). + <<16,79,94,115,234,197,94,253,16,144,151,41>> + 7> + 7> StateDec = crypto:crypto_init(aes_128_ctr, Key, IV, false). % decrypt -> false + #Ref<0.3768901617.1128660994.124255> + 8> crypto:crypto_update(StateDec, <<67,44,216,166,25,130,203>>). + <<"First b">> + 9> crypto:crypto_update(StateDec, <<5,66,6,162,16,79,94,115,234,197, + 94,253,16,144,151>>). + <<"ytesSecond byte">> + 10> crypto:crypto_update(StateDec, <<41>>). + <<"s">> + 11> + </code> + <p>Note that the internal data that the <c>StateEnc</c> and <c>StateDec</c> references are + destructivly updated by the calls to <seealso marker="crypto#crypto_update/2">crypto_update/2</seealso>. + This is to gain time in the calls of the nifs interfacing the cryptolib. In a loop where the + state is saved in the loop's state, it also saves one update of the loop state per crypto operation. + </p> + <p>For example, a simple server receiving text parts to encrypt and send the result back to the + one who sent them (the <c>Requester</c>): + </p> + <code type="erl"> + encode(Crypto, Key, IV) -> + crypto_loop(crypto:crypto_init(Crypto, Key, IV, true)). + + crypto_loop(State) -> + receive + {Text, Requester} -> + Requester ! crypto:crypto_update(State, Text), + loop(State) + end. + </code> + </section> + + <section> + <title>Example of crypto_one_time/5</title> + <p>The same example as in the + <seealso marker="#examples-of-crypto_init-4-and-crypto_update-2">previous section</seealso>, + but now with one call to <seealso marker="crypto#crypto_one_time/5">crypto_one_time/5</seealso>: + </p> + <code> + 1> Key = <<1:128>>. + <<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>> + 2> IV = <<0:128>>. + <<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>> + 3> Txt = [<<"First bytes">>,<<"Second bytes">>]. + [<<"First bytes">>,<<"Second bytes">>] + 4> crypto:crypto_one_time(aes_128_ctr, Key, IV, Txt, true). + <<67,44,216,166,25,130,203,5,66,6,162,16,79,94,115,234, + 197,94,253,16,144,151,41>> + 5> + </code> + <p>The <c>[<<"First bytes">>,<<"Second bytes">>]</c> could of course have been one + single binary: <c><<"First bytesSecond bytes">></c>. + </p> + </section> + + <section> + <title>Example of crypto_one_time_aead/6</title> + <p>The same example as in the + <seealso marker="#example-of-crypto_one_time-5">previous section</seealso>, + but now with one call to <seealso marker="crypto#crypto_one_time_aead/6">crypto_one_time_aead/6</seealso>: + </p> + <code> + 1> Key = <<1:128>>. + <<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1>> + 2> IV = <<0:128>>. + <<0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>> + 3> Txt = [<<"First bytes">>,<<"Second bytes">>]. + [<<"First bytes">>,<<"Second bytes">>] + 4> AAD = <<"Some bytes">>. + <<"Some bytes">> + 5> crypto:crypto_one_time_aead(aes_128_gcm, Key, IV, Txt, AAD, true). + {<<240,130,38,96,130,241,189,52,3,190,179,213,132,1,72, + 192,103,176,90,104,15,71,158>>, + <<131,47,45,91,142,85,9,244,21,141,214,71,31,135,2,155>>} + 9> + </code> + <p>The <c>[<<"First bytes">>,<<"Second bytes">>]</c> could of course have been one + single binary: <c><<"First bytesSecond bytes">></c>. + </p> + </section> + + </section> + + <section> + <title>Retired cipher names</title> + <p>This table lists the retired cipher names in the first column and suggests names to replace them with + in the second column. + </p> + <p>The new names follows the OpenSSL libcrypto names. The format is ALGORITM_KEYSIZE_MODE. + </p> + <p>Examples of algorithms are aes, chacha20 and des. The keysize is the number of bits + and examples of the mode are cbc, ctr and gcm. The mode may be followed by a number depending + on the mode. An example is the ccm mode which has a variant called ccm8 where the so called tag + has a length of eight bits. + </p> + <p>The old names had by time lost any common naming which the new names now introduces. The new names include + the key length which improves the error checking in the lower levels of the crypto application. + </p> + + <table> + <row><cell><strong>Instead of:</strong></cell> <cell><strong>Use:</strong> </cell></row> + + <row><cell><c>aes_cbc128</c> </cell> <cell> <c>aes_128_cbc</c> </cell></row> + <row><cell><c>aes_cbc256</c> </cell> <cell> <c>aes_256_cbc</c> </cell></row> + <row><cell><c>aes_cbc</c> </cell> <cell> <c>aes_128_cbc, aes_192_cbc, aes_256_cbc</c></cell></row> + <row><cell><c>aes_ccm</c> </cell> <cell> <c>aes_128_ccm, aes_192_ccm, aes_256_ccm</c></cell></row> + <row><cell><c>aes_cfb128</c> </cell> <cell> <c>aes_128_cfb128, aes_192_cfb128, aes_256_cfb128</c></cell></row> + <row><cell><c>aes_cfb8</c> </cell> <cell> <c>aes_128_cfb8, aes_192_cfb8, aes_256_cfb8</c></cell></row> + <row><cell><c>aes_ctr</c> </cell> <cell> <c>aes_128_ctr, aes_192_ctr, aes_256_ctr</c></cell></row> + <row><cell><c>aes_gcm</c> </cell> <cell> <c>aes_128_gcm, aes_192_gcm, aes_256_gcm</c></cell></row> + <row><cell><c>des3_cbc</c> </cell> <cell> <c>des_ede3_cbc</c></cell></row> + <row><cell><c>des3_cbf</c> </cell> <cell> <c>des_ede3_cfb</c></cell></row> + <row><cell><c>des3_cfb</c> </cell> <cell> <c>des_ede3_cfb</c></cell></row> + <row><cell><c>des_ede3</c> </cell> <cell> <c>des_ede3_cbc</c></cell></row> + <row><cell><c>des_ede3_cbf</c> </cell> <cell> <c>des_ede3_cfb</c></cell></row> + <tcaption></tcaption> + </table> + </section> + +</chapter> diff --git a/lib/crypto/doc/src/notes.xml b/lib/crypto/doc/src/notes.xml index c0b302734e..195c9d029d 100644 --- a/lib/crypto/doc/src/notes.xml +++ b/lib/crypto/doc/src/notes.xml @@ -31,6 +31,22 @@ </header> <p>This document describes the changes made to the Crypto application.</p> +<section><title>Crypto 4.4.2</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fixed build link error on Windows. Unresolved symbol + 'bcmp'.</p> + <p> + Own Id: OTP-15750 Aux Id: ERL-905 </p> + </item> + </list> + </section> + +</section> + <section><title>Crypto 4.4.1</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/crypto/doc/src/usersguide.xml b/lib/crypto/doc/src/usersguide.xml index 2dfc966609..134f900d4c 100644 --- a/lib/crypto/doc/src/usersguide.xml +++ b/lib/crypto/doc/src/usersguide.xml @@ -51,4 +51,5 @@ <xi:include href="engine_load.xml"/> <xi:include href="engine_keys.xml"/> <xi:include href="algorithm_details.xml"/> + <xi:include href="new_api.xml"/> </part> diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index fd13481951..8ffdde2b90 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -58,9 +58,11 @@ %% New interface -export([crypto_init/4, crypto_init/3, crypto_update/2, - crypto_one_shot/5, - crypto_init_dyn_iv/3, - crypto_update_dyn_iv/3 + crypto_one_time/4, crypto_one_time/5, + crypto_one_time_aead/6, crypto_one_time_aead/7, + crypto_dyn_iv_init/3, + crypto_dyn_iv_update/3, + supports/1 ]). @@ -276,48 +278,153 @@ -type edwards_curve_ed() :: ed25519 | ed448 . -%%% --type cipher() :: block_cipher() - | stream_cipher() - | aead_cipher() . +%%%---------------------------------------------------------------- +%%% New cipher schema +%%% +-type cipher() :: cipher_no_iv() + | cipher_iv() + | cipher_aead() . --type block_cipher() :: block_cipher_iv() | block_cipher_no_iv() . +-type cipher_no_iv() :: aes_128_ecb + | aes_192_ecb + | aes_256_ecb --type block_cipher_iv() :: cbc_cipher() - | cfb_cipher() - | aes_ige256 - | blowfish_ofb64 - | rc2_cbc . + | blowfish_ecb + | des_ecb + | rc4 . --type cbc_cipher() :: des_cbc | des_ede3_cbc - | blowfish_cbc - | aes_cbc | aes_128_cbc | aes_192_cbc | aes_256_cbc - | alias_cbc() . --type alias_cbc() :: des3_cbc | des_ede3 - | aes_cbc128 | aes_cbc256 . +-type cipher_iv() :: aes_128_cbc + | aes_192_cbc + | aes_256_cbc + + | aes_128_cfb128 + | aes_192_cfb128 + | aes_256_cfb128 + + | aes_128_cfb8 + | aes_192_cfb8 + | aes_256_cfb8 + + | aes_128_ctr + | aes_192_ctr + | aes_256_ctr + + | aes_ige256 --type aead_cipher() :: aes_gcm + | blowfish_cbc + | blowfish_cfb64 + | blowfish_ofb64 + | chacha20 + | des_ede3_cbc + | des_ede3_cfb + + | des_cbc + | des_cfb + | rc2_cbc . + + +-type cipher_aead() :: aes_128_ccm + | aes_192_ccm + | aes_256_ccm + | aes_128_gcm | aes_192_gcm | aes_256_gcm - | aes_ccm - | aes_128_ccm - | aes_192_ccm - | aes_256_ccm + | chacha20_poly1305 . --type cfb_cipher() :: aes_cfb8 - | aes_cfb128 - | blowfish_cfb64 - | des_cfb - | des_ede3_cfb - | alias_cfb() . --type alias_cfb() :: des_ede3_cbf | des3_cbf - | des3_cfb . +%% -type retired_cipher_no_iv_aliases() :: aes_ecb . + +%% -type retired_cipher_iv_aliases() :: aes_cbc +%% | aes_cbc128 % aes_128_cbc +%% | aes_cbc256 % aes_256_cbc +%% | aes_cfb128 +%% | aes_cfb8 +%% | aes_ctr +%% | des3_cbc % des_ede3_cbc +%% | des_ede3 % des_ede3_cbc +%% | des_ede3_cbf % des_ede3_cfb +%% | des3_cbf % des_ede3_cfb +%% | des3_cfb . % des_ede3_cfb + +%% -type retired_cipher_aead_aliases() :: aes_ccm +%% | aes_gcm . --type block_cipher_no_iv() :: ecb_cipher() . --type ecb_cipher() :: des_ecb | blowfish_ecb | aes_ecb . +%%%---------------------------------------------------------------- +%%% Old cipher scheme +%%% +%%% +-type block_cipher_without_iv() :: ecb_cipher() . + +-type block_cipher_with_iv() :: cbc_cipher() + | cfb_cipher() + | blowfish_ofb64 + | aes_ige256 . + +-type stream_cipher() :: ctr_cipher() + | chacha20 + | rc4 . + + +%%%---- +-type cbc_cipher() :: aes_128_cbc + | aes_192_cbc + | aes_256_cbc + | blowfish_cbc + | des_cbc + | des_ede3_cbc + | rc2_cbc + | retired_cbc_cipher_aliases() . + +-type retired_cbc_cipher_aliases() :: aes_cbc % aes_*_cbc + | aes_cbc128 % aes_128_cbc + | aes_cbc256 % aes_256_cbc + | des3_cbc % des_ede3_cbc + | des_ede3 . % des_ede3_cbc + +%%%---- +-type cfb_cipher() :: aes_128_cfb128 + | aes_192_cfb128 + | aes_256_cfb128 + | aes_128_cfb8 + | aes_192_cfb8 + | aes_256_cfb8 + | blowfish_cfb64 + | des_cfb + | des_ede3_cfb + | retired_cfb_cipher_aliases() . + +-type retired_cfb_cipher_aliases() :: aes_cfb8 % aes_*_cfb8 + | aes_cfb128 % aes_*_cfb128 + | des3_cbf % des_ede3_cfb, cfb misspelled + | des3_cfb % des_ede3_cfb + | des_ede3_cbf .% cfb misspelled + + +%%%---- +-type ctr_cipher() :: aes_128_ctr + | aes_192_ctr + | aes_256_ctr + | retired_ctr_cipher_aliases() . + +-type retired_ctr_cipher_aliases() :: aes_ctr . % aes_*_ctr + +%%%---- +-type ecb_cipher() :: aes_128_ecb + | aes_192_ecb + | aes_256_ecb + | blowfish_ecb + | retired_ecb_cipher_aliases() . + +-type retired_ecb_cipher_aliases() :: aes_ecb . + +%%%---- +-type aead_cipher() :: aes_gcm | aes_ccm | chacha20_poly1305 . + + +%%%----- end old cipher schema ------------------------------------ +%%%---------------------------------------------------------------- -type key() :: iodata(). -type des3_key() :: [key()]. @@ -393,15 +500,43 @@ stop() -> Macs :: [hmac | cmac | poly1305], Curves :: [ec_named_curve() | edwards_curve_dh() | edwards_curve_ed()], RSAopts :: [rsa_sign_verify_opt() | rsa_opt()] . -supports()-> - {Hashs, PubKeys, Ciphers, Macs, Curves, RsaOpts} = algorithms(), - [{hashs, Hashs}, - {ciphers, prepend_cipher_aliases(Ciphers)}, - {public_keys, PubKeys}, - {macs, Macs}, - {curves, Curves}, - {rsa_opts, RsaOpts} - ]. +supports() -> + [{hashs, hash_algorithms()}, + {ciphers, prepend_old_aliases( cipher_algorithms())}, + {public_keys, pubkey_algorithms()}, + {macs, mac_algorithms()}, + {curves, curve_algorithms()}, + {rsa_opts, rsa_opts_algorithms()} + ]. + + +-spec supports(Type) -> Support + when Type :: hashs + | ciphers + | public_keys + | macs + | curves + | rsa_opts, + Support :: Hashs + | Ciphers + | PKs + | Macs + | Curves + | RSAopts, + Hashs :: [sha1() | sha2() | sha3() | blake2() | ripemd160 | compatibility_only_hash()], + Ciphers :: [cipher()], + PKs :: [rsa | dss | ecdsa | dh | ecdh | ec_gf2m], + Macs :: [hmac | cmac | poly1305], + Curves :: [ec_named_curve() | edwards_curve_dh() | edwards_curve_ed()], + RSAopts :: [rsa_sign_verify_opt() | rsa_opt()] . + +supports(hashs) -> hash_algorithms(); +supports(public_keys) -> pubkey_algorithms(); +supports(ciphers) -> cipher_algorithms(); +supports(macs) -> mac_algorithms(); +supports(curves) -> curve_algorithms(); +supports(rsa_opts) -> rsa_opts_algorithms(). + -spec info_lib() -> [{Name,VerNum,VerStr}] when Name :: binary(), VerNum :: integer(), @@ -564,9 +699,9 @@ poly1305(Key, Data) -> -define(COMPAT(CALL), try begin CALL end catch - error:{error,_} -> + error:{error, {_File,_Line}, _Reason} -> error(badarg); - error:{E,_Reason} when E==notsup ; E==badarg -> + error:{E, {_File,_Line}, _Reason} when E==notsup ; E==badarg -> error(E) end). @@ -594,7 +729,7 @@ poly1305(Key, Data) -> | xts_mode . -%% These ciphers are not available via the EVP interface on older cryptolibs. +%% %% These ciphers are not available via the EVP interface on older cryptolibs. cipher_info(aes_ctr) -> #{block_size => 1,iv_length => 16,key_length => 32,mode => ctr_mode,type => undefined}; cipher_info(aes_128_ctr) -> @@ -603,15 +738,42 @@ cipher_info(aes_192_ctr) -> #{block_size => 1,iv_length => 16,key_length => 24,mode => ctr_mode,type => undefined}; cipher_info(aes_256_ctr) -> #{block_size => 1,iv_length => 16,key_length => 32,mode => ctr_mode,type => undefined}; -%% This cipher is handled specialy. +%% %% This cipher is handled specialy. cipher_info(aes_ige256) -> #{block_size => 16,iv_length => 32,key_length => 16,mode => ige_mode,type => undefined}; +%% %% These ciphers belong to the "old" interface: +%% cipher_info(aes_cbc) -> +%% #{block_size => 16,iv_length => 16,key_length => 24,mode => cbc_mode,type => 423}; +%% cipher_info(aes_cbc128) -> +%% #{block_size => 16,iv_length => 16,key_length => 16,mode => cbc_mode,type => 419}; +%% cipher_info(aes_cbc256) -> +%% #{block_size => 16,iv_length => 16,key_length => 32,mode => cbc_mode,type => 427}; +%% cipher_info(aes_ccm) -> +%% #{block_size => 1,iv_length => 12,key_length => 24,mode => ccm_mode,type => 899}; +%% cipher_info(aes_cfb128) -> +%% #{block_size => 1,iv_length => 16,key_length => 32,mode => cfb_mode,type => 429}; +%% cipher_info(aes_cfb8) -> +%% #{block_size => 1,iv_length => 16,key_length => 32,mode => cfb_mode,type => 429}; +%% cipher_info(aes_ecb) -> +%% #{block_size => 16,iv_length => 0,key_length => 24,mode => ecb_mode,type => 422}; +%% cipher_info(aes_gcm) -> +%% #{block_size => 1,iv_length => 12,key_length => 24,mode => gcm_mode,type => 898}; +%% cipher_info(des3_cbc) -> +%% #{block_size => 8,iv_length => 8,key_length => 24,mode => cbc_mode,type => 44}; +%% cipher_info(des3_cbf) -> +%% #{block_size => 1,iv_length => 8,key_length => 24,mode => cfb_mode,type => 30}; +%% cipher_info(des3_cfb) -> +%% #{block_size => 1,iv_length => 8,key_length => 24,mode => cfb_mode,type => 30}; +%% cipher_info(des_ede3) -> +%% #{block_size => 8,iv_length => 8,key_length => 24,mode => cbc_mode,type => 44}; +%% cipher_info(des_ede3_cbf) -> +%% #{block_size => 1,iv_length => 8,key_length => 24,mode => cfb_mode,type => 30}; cipher_info(Type) -> cipher_info_nif(alias(Type)). %%%---- Block ciphers %%%---------------------------------------------------------------- --spec block_encrypt(Type::block_cipher_iv(), Key::key()|des3_key(), Ivec::binary(), PlainText::iodata()) -> +-spec block_encrypt(Type::block_cipher_with_iv(), Key::key()|des3_key(), Ivec::binary(), PlainText::iodata()) -> binary() | run_time_error(); (Type::aead_cipher(), Key::iodata(), Ivec::binary(), {AAD::binary(), PlainText::iodata()}) -> {binary(), binary()} | run_time_error(); @@ -627,34 +789,24 @@ block_encrypt(Type, Key0, Ivec, Data) -> ?COMPAT( case Data of {AAD, PlainText} -> - aead_encrypt(alias(Type,Key), Key, Ivec, AAD, PlainText, aead_tag_len(Type)); + crypto_one_time_aead(alias(Type,Key), Key, Ivec, PlainText, AAD, true); {AAD, PlainText, TagLength} -> - aead_encrypt(alias(Type,Key), Key, Ivec, AAD, PlainText, TagLength); + crypto_one_time_aead(alias(Type,Key), Key, Ivec, PlainText, AAD, TagLength, true); PlainText -> - crypto_one_shot(alias(Type,Key), Key, Ivec, PlainText, true) + crypto_one_time(alias(Type,Key), Key, Ivec, PlainText, true) end). --spec block_encrypt(Type::block_cipher_no_iv(), Key::key(), PlainText::iodata()) -> +-spec block_encrypt(Type::block_cipher_without_iv(), Key::key(), PlainText::iodata()) -> binary() | run_time_error(). block_encrypt(Type, Key0, PlainText) -> Key = iolist_to_binary(Key0), - ?COMPAT(crypto_one_shot(alias(Type,Key), Key, <<>>, PlainText, true)). + ?COMPAT(crypto_one_time(alias(Type,Key), Key, PlainText, true)). -aead_tag_len(chacha20_poly1305) -> 16; -aead_tag_len(aes_ccm) -> 12; -aead_tag_len(aes_128_ccm) -> 12; -aead_tag_len(aes_192_ccm) -> 12; -aead_tag_len(aes_256_ccm) -> 12; -aead_tag_len(aes_gcm) -> 16; -aead_tag_len(aes_128_gcm) -> 16; -aead_tag_len(aes_192_gcm) -> 16; -aead_tag_len(aes_256_gcm) -> 16. - %%%---------------------------------------------------------------- %%%---------------------------------------------------------------- --spec block_decrypt(Type::block_cipher_iv(), Key::key()|des3_key(), Ivec::binary(), Data::iodata()) -> +-spec block_decrypt(Type::block_cipher_with_iv(), Key::key()|des3_key(), Ivec::binary(), Data::iodata()) -> binary() | run_time_error(); (Type::aead_cipher(), Key::iodata(), Ivec::binary(), {AAD::binary(), Data::iodata(), Tag::binary()}) -> @@ -668,18 +820,18 @@ block_decrypt(Type, Key0, Ivec, Data) -> ?COMPAT( case Data of {AAD, CryptoText, Tag} -> - aead_decrypt(alias(Type,Key), Key, Ivec, AAD, CryptoText, Tag); + crypto_one_time_aead(alias(Type,Key), Key, Ivec, CryptoText, AAD, Tag, false); CryptoText -> - crypto_one_shot(alias(Type,Key), Key, Ivec, CryptoText, false) + crypto_one_time(alias(Type,Key), Key, Ivec, CryptoText, false) end). --spec block_decrypt(Type::block_cipher_no_iv(), Key::key(), Data::iodata()) -> +-spec block_decrypt(Type::block_cipher_without_iv(), Key::key(), Data::iodata()) -> binary() | run_time_error(). block_decrypt(Type, Key0, CryptoText) -> Key = iolist_to_binary(Key0), - ?COMPAT(crypto_one_shot(alias(Type,Key), Key, <<>>, CryptoText, false)). + ?COMPAT(crypto_one_time(alias(Type,Key), Key, CryptoText, false)). %%%-------- Stream ciphers API @@ -687,17 +839,9 @@ block_decrypt(Type, Key0, CryptoText) -> crypto_state() | {crypto_state(),flg_undefined} }. --type stream_cipher() :: stream_cipher_iv() | stream_cipher_no_iv() . --type stream_cipher_no_iv() :: rc4 . --type stream_cipher_iv() :: aes_ctr - | aes_128_ctr - | aes_192_ctr - | aes_256_ctr - | chacha20 . - %%%---- stream_init -spec stream_init(Type, Key, IVec) -> State | run_time_error() - when Type :: stream_cipher_iv(), + when Type :: stream_cipher(), Key :: iodata(), IVec ::binary(), State :: stream_state() . @@ -711,7 +855,7 @@ stream_init(Type, Key0, IVec) when is_binary(IVec) -> -spec stream_init(Type, Key) -> State | run_time_error() - when Type :: stream_cipher_no_iv(), + when Type :: rc4, Key :: iodata(), State :: stream_state() . stream_init(rc4 = Type, Key0) -> @@ -792,38 +936,35 @@ next_iv(Type, Data, _Ivec) -> %%% -spec crypto_init(Cipher, Key, EncryptFlag) -> State | descriptive_error() - when Cipher :: block_cipher_no_iv() - | stream_cipher_no_iv(), + when Cipher :: cipher_no_iv(), Key :: iodata(), EncryptFlag :: boolean(), State :: crypto_state() . crypto_init(Cipher, Key, EncryptFlag) -> %% The IV is supposed to be supplied by calling crypto_update/3 - ng_crypto_init_nif(alias(Cipher), iolist_to_binary(Key), <<>>, EncryptFlag). + ng_crypto_init_nif(Cipher, iolist_to_binary(Key), <<>>, EncryptFlag). -spec crypto_init(Cipher, Key, IV, EncryptFlag) -> State | descriptive_error() - when Cipher :: stream_cipher_iv() - | block_cipher_iv(), + when Cipher :: cipher_iv(), Key :: iodata(), IV :: iodata(), EncryptFlag :: boolean(), State :: crypto_state() . crypto_init(Cipher, Key, IV, EncryptFlag) -> - ng_crypto_init_nif(alias(Cipher), iolist_to_binary(Key), iolist_to_binary(IV), EncryptFlag). + ng_crypto_init_nif(Cipher, iolist_to_binary(Key), iolist_to_binary(IV), EncryptFlag). %%%---------------------------------------------------------------- --spec crypto_init_dyn_iv(Cipher, Key, EncryptFlag) -> State | descriptive_error() - when Cipher :: stream_cipher_iv() - | block_cipher_iv(), +-spec crypto_dyn_iv_init(Cipher, Key, EncryptFlag) -> State | descriptive_error() + when Cipher :: cipher_iv(), Key :: iodata(), EncryptFlag :: boolean(), State :: crypto_state() . -crypto_init_dyn_iv(Cipher, Key, EncryptFlag) -> +crypto_dyn_iv_init(Cipher, Key, EncryptFlag) -> %% The IV is supposed to be supplied by calling crypto_update/3 - ng_crypto_init_nif(alias(Cipher), iolist_to_binary(Key), undefined, EncryptFlag). + ng_crypto_init_nif(Cipher, iolist_to_binary(Key), undefined, EncryptFlag). %%%---------------------------------------------------------------- %%% @@ -846,12 +987,12 @@ crypto_update(State, Data0) -> %%%---------------------------------------------------------------- --spec crypto_update_dyn_iv(State, Data, IV) -> Result | descriptive_error() +-spec crypto_dyn_iv_update(State, Data, IV) -> Result | descriptive_error() when State :: crypto_state(), Data :: iodata(), IV :: iodata(), Result :: binary() . -crypto_update_dyn_iv(State, Data0, IV) -> +crypto_dyn_iv_update(State, Data0, IV) -> %% When State is from State = crypto_init(Cipher, Key, undefined, EncryptFlag) case iolist_to_binary(Data0) of <<>> -> @@ -866,29 +1007,86 @@ crypto_update_dyn_iv(State, Data0, IV) -> %%% The size must be an integer multiple of the crypto's blocksize. %%% --spec crypto_one_shot(Cipher, Key, IV, Data, EncryptFlag) -> +-spec crypto_one_time(Cipher, Key, Data, EncryptFlag) -> Result | descriptive_error() - when Cipher :: stream_cipher() - | block_cipher(), + when Cipher :: cipher_no_iv(), Key :: iodata(), - IV :: iodata() | undefined, Data :: iodata(), EncryptFlag :: boolean(), Result :: binary() . -crypto_one_shot(Cipher, Key, undefined, Data, EncryptFlag) -> - crypto_one_shot(Cipher, Key, <<>>, Data, EncryptFlag); +crypto_one_time(Cipher, Key, Data, EncryptFlag) -> + crypto_one_time(Cipher, Key, <<>>, Data, EncryptFlag). + +-spec crypto_one_time(Cipher, Key, IV, Data, EncryptFlag) -> + Result | descriptive_error() + when Cipher :: cipher_iv(), + Key :: iodata(), + IV :: iodata(), + Data :: iodata(), + EncryptFlag :: boolean(), + Result :: binary() . -crypto_one_shot(Cipher, Key, IV, Data0, EncryptFlag) -> +crypto_one_time(Cipher, Key, IV, Data0, EncryptFlag) -> case iolist_to_binary(Data0) of <<>> -> <<>>; % Known to fail on OpenSSL 0.9.8h Data -> - ng_crypto_one_shot_nif(alias(Cipher), + ng_crypto_one_time_nif(Cipher, iolist_to_binary(Key), iolist_to_binary(IV), Data, EncryptFlag) end. + +-spec crypto_one_time_aead(Cipher, Key, IV, InText, AAD, EncFlag::true) -> + Result | descriptive_error() + when Cipher :: cipher_aead(), + Key :: iodata(), + IV :: iodata(), + InText :: iodata(), + AAD :: iodata(), + Result :: EncryptResult, + EncryptResult :: {OutCryptoText, OutTag}, + OutCryptoText :: binary(), + OutTag :: binary(). + +crypto_one_time_aead(Cipher, Key, IV, PlainText, AAD, true) -> + crypto_one_time_aead(Cipher, Key, IV, PlainText, AAD, aead_tag_len(Cipher), true). + + +-spec crypto_one_time_aead(Cipher, Key, IV, InText, AAD, TagOrTagLength, EncFlag) -> + Result | descriptive_error() + when Cipher :: cipher_aead(), + Key :: iodata(), + IV :: iodata(), + InText :: iodata(), + AAD :: iodata(), + TagOrTagLength :: EncryptTagLength | DecryptTag, + EncryptTagLength :: non_neg_integer(), % or pos_integer() 1.. + DecryptTag :: iodata(), + EncFlag :: boolean(), + Result :: EncryptResult | DecryptResult, + EncryptResult :: {OutCryptoText, OutTag}, + DecryptResult :: OutPlainText | error, + OutCryptoText :: binary(), + OutTag :: binary(), + OutPlainText :: binary(). + +crypto_one_time_aead(Cipher, Key, IV, TextIn, AAD, TagOrTagLength, EncFlg) -> + aead_cipher(Cipher, Key, IV, TextIn, AAD, TagOrTagLength, EncFlg). + + +aead_tag_len(chacha20_poly1305) -> 16; +aead_tag_len(aes_ccm ) -> 12; +aead_tag_len(aes_128_ccm) -> 12; +aead_tag_len(aes_192_ccm) -> 12; +aead_tag_len(aes_256_ccm) -> 12; +aead_tag_len(aes_gcm ) -> 16; +aead_tag_len(aes_128_gcm) -> 16; +aead_tag_len(aes_192_gcm) -> 16; +aead_tag_len(aes_256_gcm) -> 16; +aead_tag_len(_) -> error({badarg, "Not an AEAD cipher"}). + %%%---------------------------------------------------------------- %%% NIFs @@ -909,15 +1107,42 @@ ng_crypto_update_nif(_State, _Data) -> ?nif_stub. ng_crypto_update_nif(_State, _Data, _IV) -> ?nif_stub. --spec ng_crypto_one_shot_nif(atom(), binary(), binary(), binary(), boolean() ) -> +-spec ng_crypto_one_time_nif(atom(), binary(), binary(), binary(), boolean() ) -> binary() | descriptive_error(). -ng_crypto_one_shot_nif(_Cipher, _Key, _IVec, _Data, _EncryptFlg) -> ?nif_stub. +ng_crypto_one_time_nif(_Cipher, _Key, _IVec, _Data, _EncryptFlg) -> ?nif_stub. %%%---------------------------------------------------------------- %%% Cipher aliases %%% -prepend_cipher_aliases(L) -> - [des3_cbc, des_ede3, des_ede3_cbf, des3_cbf, des3_cfb, aes_cbc128, aes_cbc256 | L]. +-define(if_also(Cipher, Ciphers, AliasCiphers), + case lists:member(Cipher, Ciphers) of + true -> + AliasCiphers; + false -> + Ciphers + end). + + +prepend_old_aliases(L0) -> + L1 = ?if_also(des_ede3_cbc, L0, + [des3_cbc, des_ede3, des_ede3_cbf, des3_cbf, des3_cfb | L0]), + L2 = ?if_also(aes_128_cbc, L1, + [aes_cbc, aes_cbc128, aes_cbc256 | L1]), + L3 = ?if_also(aes_128_ctr, L2, + [aes_ctr | L2]), + L4 = ?if_also(aes_128_ccm, L3, + [aes_ccm | L3]), + L5 = ?if_also(aes_128_gcm, L4, + [aes_gcm | L4]), + L6 = ?if_also(aes_128_cfb8, L5, + [aes_cfb8 | L5]), + L7 = ?if_also(aes_128_cfb128, L6, + [aes_cfb128 | L6]), + L8 = ?if_also(aes_128_ecb, L7, + [aes_ecb | L7]), + L8. + + %%%---- des_ede3_cbc alias(des3_cbc) -> des_ede3_cbc; @@ -933,42 +1158,37 @@ alias(aes_cbc256) -> aes_256_cbc; alias(Alg) -> Alg. -%%%---- des_ede3_cbc -alias(des3_cbc, _) -> des_ede3_cbc; -alias(des_ede3, _) -> des_ede3_cbc; -%%%---- des_ede3_cfb -alias(des_ede3_cbf,_ ) -> des_ede3_cfb; -alias(des3_cbf, _) -> des_ede3_cfb; -alias(des3_cfb, _) -> des_ede3_cfb; -%%%---- aes_*_cbc -alias(aes_cbc128, _) -> aes_128_cbc; -alias(aes_cbc256, _) -> aes_256_cbc; +alias(Ciph, Key) -> alias2(alias(Ciph), Key). -alias(aes_cbc, Key) when size(Key)==128 -> aes_128_cbc; -alias(aes_cbc, Key) when size(Key)==192 -> aes_192_cbc; -alias(aes_cbc, Key) when size(Key)==256 -> aes_256_cbc; +alias2(aes_cbc, Key) when size(Key)==16 -> aes_128_cbc; +alias2(aes_cbc, Key) when size(Key)==24 -> aes_192_cbc; +alias2(aes_cbc, Key) when size(Key)==32 -> aes_256_cbc; -alias(aes_cfb8, Key) when size(Key)==128 -> aes_128_cfb8; -alias(aes_cfb8, Key) when size(Key)==192 -> aes_192_cfb8; -alias(aes_cfb8, Key) when size(Key)==256 -> aes_256_cfb8; +alias2(aes_cfb8, Key) when size(Key)==16 -> aes_128_cfb8; +alias2(aes_cfb8, Key) when size(Key)==24 -> aes_192_cfb8; +alias2(aes_cfb8, Key) when size(Key)==32 -> aes_256_cfb8; -alias(aes_cfb128, Key) when size(Key)==128 -> aes_128_cfb128; -alias(aes_cfb128, Key) when size(Key)==192 -> aes_192_cfb128; -alias(aes_cfb128, Key) when size(Key)==256 -> aes_256_cfb128; +alias2(aes_cfb128, Key) when size(Key)==16 -> aes_128_cfb128; +alias2(aes_cfb128, Key) when size(Key)==24 -> aes_192_cfb128; +alias2(aes_cfb128, Key) when size(Key)==32 -> aes_256_cfb128; -alias(aes_ctr, Key) when size(Key)==128 -> aes_128_ctr; -alias(aes_ctr, Key) when size(Key)==192 -> aes_192_ctr; -alias(aes_ctr, Key) when size(Key)==256 -> aes_256_ctr; +alias2(aes_ctr, Key) when size(Key)==16 -> aes_128_ctr; +alias2(aes_ctr, Key) when size(Key)==24 -> aes_192_ctr; +alias2(aes_ctr, Key) when size(Key)==32 -> aes_256_ctr; -alias(aes_gcm, Key) when size(Key)==128 -> aes_128_gcm; -alias(aes_gcm, Key) when size(Key)==192 -> aes_192_gcm; -alias(aes_gcm, Key) when size(Key)==256 -> aes_256_gcm; +alias2(aes_ecb, Key) when size(Key)==16 -> aes_128_ecb; +alias2(aes_ecb, Key) when size(Key)==24 -> aes_192_ecb; +alias2(aes_ecb, Key) when size(Key)==32 -> aes_256_ecb; -alias(aes_ccm, Key) when size(Key)==128 -> aes_128_ccm; -alias(aes_ccm, Key) when size(Key)==192 -> aes_192_ccm; -alias(aes_ccm, Key) when size(Key)==256 -> aes_256_ccm; +alias2(aes_gcm, Key) when size(Key)==16 -> aes_128_gcm; +alias2(aes_gcm, Key) when size(Key)==24 -> aes_192_gcm; +alias2(aes_gcm, Key) when size(Key)==32 -> aes_256_gcm; -alias(Alg, _) -> Alg. +alias2(aes_ccm, Key) when size(Key)==16 -> aes_128_ccm; +alias2(aes_ccm, Key) when size(Key)==24 -> aes_192_ccm; +alias2(aes_ccm, Key) when size(Key)==32 -> aes_256_ccm; + +alias2(Alg, _) -> Alg. %%%================================================================ %%% @@ -2060,8 +2280,7 @@ cipher_info_nif(_Type) -> ?nif_stub. %% AES - in Galois/Counter Mode (GCM) %% %% The default tag length is EVP_GCM_TLS_TAG_LEN(16), -aead_encrypt(_Type, _Key, _Ivec, _AAD, _In, _TagLength) -> ?nif_stub. -aead_decrypt(_Type, _Key, _Ivec, _AAD, _In, _Tag) -> ?nif_stub. +aead_cipher(_Type, _Key, _Ivec, _AAD, _In, _TagOrTagLength, _EncFlg) -> ?nif_stub. %% %% AES - with 256 bit key in infinite garble extension mode (IGE) @@ -2233,7 +2452,13 @@ exor(Data1, Data2, _Size, MaxByts, Acc) -> do_exor(_A, _B) -> ?nif_stub. -algorithms() -> ?nif_stub. +hash_algorithms() -> ?nif_stub. +pubkey_algorithms() -> ?nif_stub. +cipher_algorithms() -> ?nif_stub. +mac_algorithms() -> ?nif_stub. +curve_algorithms() -> ?nif_stub. +rsa_opts_algorithms() -> ?nif_stub. + int_to_bin(X) when X < 0 -> int_to_bin_neg(X, []); int_to_bin(X) -> int_to_bin_pos(X, []). diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl index ce5097de47..56691223c4 100644 --- a/lib/crypto/test/crypto_SUITE.erl +++ b/lib/crypto/test/crypto_SUITE.erl @@ -45,6 +45,42 @@ all() -> hash_info ]. +-define(NEW_CIPHER_TYPE_SCHEMA, + {group, des_ede3_cbc}, + {group, des_ede3_cfb}, + {group, aes_128_cbc}, + {group, aes_192_cbc}, + {group, aes_256_cbc}, + {group, aes_128_ctr}, + {group, aes_192_ctr}, + {group, aes_256_ctr}, + {group, aes_128_ccm}, + {group, aes_192_ccm}, + {group, aes_256_ccm}, + {group, aes_128_ecb}, + {group, aes_192_ecb}, + {group, aes_256_ecb}, + {group, aes_128_gcm}, + {group, aes_192_gcm}, + {group, aes_256_gcm}, + {group, des_ede3_cbc}, + {group, des_ede3_cfb} + ). + +-define(RETIRED_TYPE_ALIASES, + {group, aes_cbc}, + {group, aes_cbc128}, + {group, aes_cbc256}, + {group, aes_ccm}, + {group, aes_ctr}, + {group, aes_gcm}, + {group, aes_ecb}, + {group, des3_cfb}, + {group, des3_cbc}, + {group, des3_cbf}, + {group, des_ede3} + ). + groups() -> [{non_fips, [], [ {group, blake2b}, @@ -67,35 +103,35 @@ groups() -> {group, sha3_512}, {group, sha512}, {group, sha}, + {group, poly1305}, {group, dh}, {group, ecdh}, {group, srp}, - {group, aes_cbc}, - {group, aes_ccm}, - {group, aes_gcm}, {group, chacha20_poly1305}, {group, chacha20}, - {group, des3_cfb}, - {group, aes_cbc128}, - {group, aes_cbc256}, - {group, aes_cfb128}, - {group, aes_cfb8}, - {group, aes_ctr}, - {group, aes_ige256}, {group, blowfish_cbc}, {group, blowfish_cfb64}, {group, blowfish_ecb}, {group, blowfish_ofb64}, - {group, des3_cbc}, - {group, des3_cbf}, + + {group, aes_ige256}, {group, des_cbc}, {group, des_cfb}, - {group, des_ede3}, - {group, poly1305}, {group, rc2_cbc}, - {group, rc4} + {group, rc4}, + + ?NEW_CIPHER_TYPE_SCHEMA, + {group, aes_128_cfb128}, + {group, aes_192_cfb128}, + {group, aes_256_cfb128}, + {group, aes_128_cfb8}, + {group, aes_192_cfb8}, + {group, aes_256_cfb8}, + ?RETIRED_TYPE_ALIASES, + {group, aes_cfb128}, + {group, aes_cfb8} ]}, {fips, [], [ {group, no_blake2b}, @@ -114,123 +150,148 @@ groups() -> {group, sha256}, {group, sha384}, {group, sha512}, + {group, no_poly1305}, {group, dh}, {group, ecdh}, {group, no_srp}, - {group, aes_cbc}, - {group, aes_ccm}, - {group, aes_gcm}, {group, no_chacha20_poly1305}, {group, no_chacha20}, - {group, des3_cfb}, - {group, aes_cbc128}, - {group, aes_cbc256}, - {group, no_aes_cfb128}, - {group, no_aes_cfb8}, - {group, aes_ctr}, - {group, no_aes_ige256}, {group, no_blowfish_cbc}, {group, no_blowfish_cfb64}, {group, no_blowfish_ecb}, {group, no_blowfish_ofb64}, - {group, des3_cbc}, - {group, des3_cbf}, + + {group, no_aes_cfb128}, + {group, no_aes_cfb8}, + {group, no_aes_ige256}, {group, no_des_cbc}, {group, no_des_cfb}, - {group, des_ede3}, - {group, no_poly1305}, {group, no_rc2_cbc}, - {group, no_rc4} + {group, no_rc4}, + + ?NEW_CIPHER_TYPE_SCHEMA, + ?RETIRED_TYPE_ALIASES ]}, - {md4, [], [hash]}, - {md5, [], [hash, hmac]}, - {ripemd160, [], [hash]}, - {sha, [], [hash, hmac]}, - {sha224, [], [hash, hmac]}, - {sha256, [], [hash, hmac]}, - {sha384, [], [hash, hmac]}, - {sha512, [], [hash, hmac]}, - {sha3_224, [], [hash, hmac]}, - {sha3_256, [], [hash, hmac]}, - {sha3_384, [], [hash, hmac]}, - {sha3_512, [], [hash, hmac]}, - {blake2b, [], [hash, hmac]}, - {blake2s, [], [hash, hmac]}, - {no_blake2b, [], [no_hash, no_hmac]}, - {no_blake2s, [], [no_hash, no_hmac]}, - {rsa, [], [sign_verify, - public_encrypt, - private_encrypt, - generate - ]}, - {dss, [], [sign_verify - %% Does not work yet: ,public_encrypt, private_encrypt - ]}, - {ecdsa, [], [sign_verify - %% Does not work yet: ,public_encrypt, private_encrypt - ]}, - {ed25519, [], [sign_verify - %% Does not work yet: ,public_encrypt, private_encrypt - ]}, - {ed448, [], [sign_verify - %% Does not work yet: ,public_encrypt, private_encrypt - ]}, - {dh, [], [generate_compute, - compute_bug]}, - {ecdh, [], [use_all_elliptic_curves, compute, generate]}, - {srp, [], [generate_compute]}, - {des_cbc, [], [block, api_ng, api_ng_one_shot, api_ng_tls]}, - {des_cfb, [], [block, api_ng, api_ng_one_shot, api_ng_tls]}, - {des3_cbc,[], [block, api_ng, api_ng_one_shot, api_ng_tls]}, - {des_ede3,[], [block, api_ng, api_ng_one_shot, api_ng_tls]}, - {des3_cbf,[], [block, api_ng, api_ng_one_shot, api_ng_tls]}, - {des3_cfb,[], [block, api_ng, api_ng_one_shot, api_ng_tls]}, - {rc2_cbc,[], [block, api_ng, api_ng_one_shot, api_ng_tls]}, - {aes_cbc128,[], [block, api_ng, api_ng_one_shot, api_ng_tls, cmac]}, - {aes_cfb8,[], [block, api_ng, api_ng_one_shot, api_ng_tls]}, - {aes_cfb128,[], [block, api_ng, api_ng_one_shot, api_ng_tls]}, - {aes_cbc256,[], [block, api_ng, api_ng_one_shot, api_ng_tls, cmac]}, - {aes_ecb,[], [block, api_ng, api_ng_one_shot, api_ng_tls]}, - {aes_ige256,[], [block]}, - {blowfish_cbc, [], [block, api_ng, api_ng_one_shot, api_ng_tls]}, - {blowfish_ecb, [], [block, api_ng, api_ng_one_shot, api_ng_tls]}, - {blowfish_cfb64, [], [block, api_ng, api_ng_one_shot, api_ng_tls]}, - {blowfish_ofb64,[], [block, api_ng, api_ng_one_shot, api_ng_tls]}, - {rc4, [], [stream, api_ng, api_ng_one_shot, api_ng_tls]}, - {aes_ctr, [], [stream, api_ng, api_ng_one_shot, api_ng_tls]}, - {aes_ccm, [], [aead]}, - {aes_gcm, [], [aead]}, - {chacha20_poly1305, [], [aead]}, - {chacha20, [], [stream, api_ng, api_ng_one_shot, api_ng_tls]}, - {poly1305, [], [poly1305]}, - {no_poly1305, [], [no_poly1305]}, - {aes_cbc, [], [block, api_ng, api_ng_one_shot, api_ng_tls]}, - {no_aes_cfb8,[], [no_support, no_block]}, - {no_aes_cfb128,[], [no_support, no_block]}, - {no_md4, [], [no_support, no_hash]}, - {no_md5, [], [no_support, no_hash, no_hmac]}, - {no_ed25519, [], [no_support, no_sign_verify - %% Does not work yet: ,public_encrypt, private_encrypt - ]}, - {no_ed448, [], [no_support, no_sign_verify - %% Does not work yet: ,public_encrypt, private_encrypt - ]}, - {no_ripemd160, [], [no_support, no_hash]}, - {no_srp, [], [no_support, no_generate_compute]}, - {no_des_cbc, [], [no_support, no_block]}, - {no_des_cfb, [], [no_support, no_block]}, - {no_blowfish_cbc, [], [no_support, no_block]}, - {no_blowfish_ecb, [], [no_support, no_block]}, - {no_blowfish_cfb64, [], [no_support, no_block]}, - {no_blowfish_ofb64, [], [no_support, no_block]}, - {no_aes_ige256, [], [no_support, no_block]}, + + {md4, [], [hash]}, + {md5, [], [hash, hmac]}, + {ripemd160, [], [hash]}, + {sha, [], [hash, hmac]}, + {sha224, [], [hash, hmac]}, + {sha256, [], [hash, hmac]}, + {sha384, [], [hash, hmac]}, + {sha512, [], [hash, hmac]}, + {sha3_224, [], [hash, hmac]}, + {sha3_256, [], [hash, hmac]}, + {sha3_384, [], [hash, hmac]}, + {sha3_512, [], [hash, hmac]}, + {blake2b, [], [hash, hmac]}, + {blake2s, [], [hash, hmac]}, + {no_blake2b, [], [no_hash, no_hmac]}, + {no_blake2s, [], [no_hash, no_hmac]}, + {rsa, [], [sign_verify, + public_encrypt, + private_encrypt, + generate + ]}, + {dss, [], [sign_verify + %% Does not work yet: ,public_encrypt, private_encrypt + ]}, + {ecdsa, [], [sign_verify + %% Does not work yet: ,public_encrypt, private_encrypt + ]}, + {ed25519, [], [sign_verify + %% Does not work yet: ,public_encrypt, private_encrypt + ]}, + {ed448, [], [sign_verify + %% Does not work yet: ,public_encrypt, private_encrypt + ]}, + {dh, [], [generate_compute, compute_bug]}, + {ecdh, [], [use_all_elliptic_curves, compute, generate]}, + {srp, [], [generate_compute]}, + {des_cbc, [], [block, api_ng, api_ng_one_shot, api_ng_tls]}, + {des_cfb, [], [block, api_ng, api_ng_one_shot, api_ng_tls]}, + {des_ede3_cbc, [], [block, api_ng, api_ng_one_shot, api_ng_tls]}, + {des_ede3_cfb, [], [block, api_ng, api_ng_one_shot, api_ng_tls]}, + {rc2_cbc, [], [block, api_ng, api_ng_one_shot, api_ng_tls]}, + {aes_cfb8, [], [block]}, + {aes_128_cfb8, [], [block, api_ng, api_ng_one_shot, api_ng_tls]}, + {aes_192_cfb8, [], [block, api_ng, api_ng_one_shot, api_ng_tls]}, + {aes_256_cfb8, [], [block, api_ng, api_ng_one_shot, api_ng_tls]}, + {no_aes_cfb8, [], [no_support, no_block]}, + {aes_cfb128, [], [block]}, + {aes_128_cfb128, [], [block, api_ng, api_ng_one_shot, api_ng_tls]}, + {aes_192_cfb128, [], [block, api_ng, api_ng_one_shot, api_ng_tls]}, + {aes_256_cfb128, [], [block, api_ng, api_ng_one_shot, api_ng_tls]}, + {no_aes_cfb128, [], [no_support, no_block]}, + {aes_ige256, [], [block]}, + {no_aes_ige256, [], [no_support, no_block]}, + {blowfish_cbc, [], [block, api_ng, api_ng_one_shot, api_ng_tls]}, + {blowfish_ecb, [], [block, api_ng, api_ng_one_shot]}, + {blowfish_cfb64, [], [block, api_ng, api_ng_one_shot, api_ng_tls]}, + {blowfish_ofb64, [], [block, api_ng, api_ng_one_shot, api_ng_tls]}, + {rc4, [], [stream, api_ng, api_ng_one_shot, api_ng_tls]}, + {aes_ctr, [], [stream]}, + {chacha20_poly1305, [], [aead]}, + {chacha20, [], [stream, api_ng, api_ng_one_shot, api_ng_tls]}, + {poly1305, [], [poly1305]}, + {no_poly1305, [], [no_poly1305]}, + {no_aes_cfb128, [], [no_support, no_block]}, + {no_md4, [], [no_support, no_hash]}, + {no_md5, [], [no_support, no_hash, no_hmac]}, + {no_ed25519, [], [no_support, no_sign_verify + %% Does not work yet: ,public_encrypt, private_encrypt + ]}, + {no_ed448, [], [no_support, no_sign_verify + %% Does not work yet: ,public_encrypt, private_encrypt + ]}, + {no_ripemd160, [], [no_support, no_hash]}, + {no_srp, [], [no_support, no_generate_compute]}, + {no_des_cbc, [], [no_support, no_block]}, + {no_des_cfb, [], [no_support, no_block]}, + {no_blowfish_cbc, [], [no_support, no_block]}, + {no_blowfish_ecb, [], [no_support, no_block]}, + {no_blowfish_cfb64, [], [no_support, no_block]}, + {no_blowfish_ofb64, [], [no_support, no_block]}, + {no_aes_ige256, [], [no_support, no_block]}, {no_chacha20_poly1305, [], [no_support, no_aead]}, - {no_chacha20, [], [no_support, no_stream_ivec]}, - {no_rc2_cbc, [], [no_support, no_block]}, - {no_rc4, [], [no_support, no_stream]}, - {api_errors, [], [api_errors_ecdh]} + {no_chacha20, [], [no_support, no_stream_ivec]}, + {no_rc2_cbc, [], [no_support, no_block]}, + {no_rc4, [], [no_support, no_stream]}, + {api_errors, [], [api_errors_ecdh]}, + + %% New cipher nameing schema + {des_ede3_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls]}, + {des_ede3_cfb, [], [api_ng, api_ng_one_shot, api_ng_tls]}, + {aes_128_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls]}, + {aes_192_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls]}, + {aes_256_cbc, [], [api_ng, api_ng_one_shot, api_ng_tls]}, + {aes_128_ctr, [], [api_ng, api_ng_one_shot, api_ng_tls]}, + {aes_192_ctr, [], [api_ng, api_ng_one_shot, api_ng_tls]}, + {aes_256_ctr, [], [api_ng, api_ng_one_shot, api_ng_tls]}, + {aes_128_ccm, [], [aead]}, + {aes_192_ccm, [], [aead]}, + {aes_256_ccm, [], [aead]}, + {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]}, + {aes_192_gcm, [], [aead]}, + {aes_256_gcm, [], [aead]}, + + %% Retired aliases + {aes_cbc, [], [block]}, + {aes_cbc128, [], [block]}, + {aes_cbc256, [], [block]}, + {aes_ccm, [], [aead]}, + {aes_ecb, [], [block]}, + {aes_gcm, [], [aead]}, + {des3_cbc, [], [block]}, + {des_ede3, [], [block]}, + {des3_cbf, [], [block]}, + {des3_cfb, [], [block]} ]. %%------------------------------------------------------------------- @@ -429,8 +490,7 @@ poly1305(Config) -> %%-------------------------------------------------------------------- no_poly1305() -> [{doc, "Test disabled poly1305 function"}]. -no_poly1305(Config) -> - Type = ?config(type, Config), +no_poly1305(_Config) -> Key = <<133,214,190,120,87,85,109,51,127,68,82,254,66,213,6,168,1, 3,128,138,251,13,178,253,74,191,246,175,65,73,245,27>>, Txt = <<"Cryptographic Forum Research Group">>, @@ -440,7 +500,7 @@ no_poly1305(Config) -> block() -> [{doc, "Test block ciphers"}]. block(Config) when is_list(Config) -> - Blocks = lazy_eval(proplists:get_value(block, Config)), + [_|_] = Blocks = lazy_eval(proplists:get_value(cipher, Config)), lists:foreach(fun block_cipher/1, Blocks), lists:foreach(fun block_cipher/1, block_iolistify(Blocks)), lists:foreach(fun block_cipher_increment/1, block_iolistify(Blocks)). @@ -449,7 +509,7 @@ block(Config) when is_list(Config) -> no_block() -> [{doc, "Test disabled block ciphers"}]. no_block(Config) when is_list(Config) -> - Blocks = lazy_eval(proplists:get_value(block, Config)), + [_|_] = Blocks = lazy_eval(proplists:get_value(cipher, Config)), Args = case Blocks of [{_Type, _Key, _PlainText} = A | _] -> tuple_to_list(A); @@ -466,10 +526,8 @@ api_ng() -> [{doc, "Test new api"}]. api_ng(Config) when is_list(Config) -> - Blocks = lazy_eval(proplists:get_value(block, Config, [])), - Streams = lazy_eval(proplists:get_value(stream, Config, [])), - lists:foreach(fun api_ng_cipher_increment/1, Blocks++Streams). - + [_|_] = Ciphers = lazy_eval(proplists:get_value(cipher, Config, [])), + lists:foreach(fun api_ng_cipher_increment/1, Ciphers). api_ng_cipher_increment({Type, Key, PlainTexts}=_X) -> ct:log("~p",[_X]), @@ -523,9 +581,8 @@ api_ng_one_shot() -> [{doc, "Test new api"}]. api_ng_one_shot(Config) when is_list(Config) -> - Blocks = lazy_eval(proplists:get_value(block, Config, [])), - Streams = lazy_eval(proplists:get_value(stream, Config, [])), - lists:foreach(fun do_api_ng_one_shot/1, Blocks++Streams). + [_|_] = Ciphers = lazy_eval(proplists:get_value(cipher, Config, [])), + lists:foreach(fun do_api_ng_one_shot/1, Ciphers). do_api_ng_one_shot({Type, Key, PlainTexts}=_X) -> ct:log("~p",[_X]), @@ -537,8 +594,8 @@ do_api_ng_one_shot({Type, Key, IV, PlainTexts}=_X) -> do_api_ng_one_shot({Type, Key, IV, PlainText0, ExpectedEncText}=_X) -> ct:log("~p",[_X]), - PlainText = iolist_to_binary(PlainText0), - EncTxt = crypto:crypto_one_shot(Type, Key, IV, PlainText, true), + PlainText = iolist_to_binary(lazy_eval(PlainText0)), + EncTxt = crypto:crypto_one_time(Type, Key, IV, PlainText, true), case ExpectedEncText of undefined -> ok; @@ -546,14 +603,14 @@ do_api_ng_one_shot({Type, Key, IV, PlainText0, ExpectedEncText}=_X) -> ok; _ -> ct:log("encode~nIn: ~p~nExpected: ~p~nEnc: ~p~n", [{Type,Key,IV,PlainText}, ExpectedEncText, EncTxt]), - ct:fail("api_ng_one_shot (encode)",[]) + ct:fail("api_ng_one_time (encode)",[]) end, - case crypto:crypto_one_shot(Type, Key, IV, EncTxt, false) of + case crypto:crypto_one_time(Type, Key, IV, EncTxt, false) of PlainText -> ok; OtherPT -> ct:log("decode~nIn: ~p~nExpected: ~p~nDec: ~p~n", [{Type,Key,IV,EncTxt}, PlainText, OtherPT]), - ct:fail("api_ng_one_shot (decode)",[]) + ct:fail("api_ng_one_time (decode)",[]) end. %%-------------------------------------------------------------------- @@ -561,9 +618,8 @@ api_ng_tls() -> [{doc, "Test special tls api"}]. api_ng_tls(Config) when is_list(Config) -> - Blocks = lazy_eval(proplists:get_value(block, Config, [])), - Streams = lazy_eval(proplists:get_value(stream, Config, [])), - lists:foreach(fun do_api_ng_tls/1, Blocks++Streams). + [_|_] = Ciphers = lazy_eval(proplists:get_value(cipher, Config, [])), + lists:foreach(fun do_api_ng_tls/1, Ciphers). do_api_ng_tls({Type, Key, PlainTexts}=_X) -> @@ -576,16 +632,16 @@ do_api_ng_tls({Type, Key, IV, PlainTexts}=_X) -> do_api_ng_tls({Type, Key, IV, PlainText0, ExpectedEncText}=_X) -> ct:log("~p",[_X]), - PlainText = iolist_to_binary(PlainText0), - Renc = crypto:crypto_init_dyn_iv(Type, Key, true), - Rdec = crypto:crypto_init_dyn_iv(Type, Key, false), - EncTxt = crypto:crypto_update_dyn_iv(Renc, PlainText, IV), + PlainText = iolist_to_binary(lazy_eval(PlainText0)), + Renc = crypto:crypto_dyn_iv_init(Type, Key, true), + Rdec = crypto:crypto_dyn_iv_init(Type, Key, false), + EncTxt = crypto:crypto_dyn_iv_update(Renc, PlainText, IV), case ExpectedEncText of undefined -> ok; EncTxt -> %% Now check that the state is NOT updated: - case crypto:crypto_update_dyn_iv(Renc, PlainText, IV) of + case crypto:crypto_dyn_iv_update(Renc, PlainText, IV) of EncTxt -> ok; EncTxt2 -> @@ -596,10 +652,10 @@ do_api_ng_tls({Type, Key, IV, PlainText0, ExpectedEncText}=_X) -> ct:log("1st encode~nIn: ~p~nExpected: ~p~nEnc: ~p~n", [{Type,Key,IV,PlainText}, ExpectedEncText, OtherEnc]), ct:fail("api_ng_tls (encode)",[]) end, - case crypto:crypto_update_dyn_iv(Rdec, EncTxt, IV) of + case crypto:crypto_dyn_iv_update(Rdec, EncTxt, IV) of PlainText -> %% Now check that the state is NOT updated: - case crypto:crypto_update_dyn_iv(Rdec, EncTxt, IV) of + case crypto:crypto_dyn_iv_update(Rdec, EncTxt, IV) of PlainText -> ok; PlainText2 -> @@ -616,7 +672,7 @@ no_aead() -> [{doc, "Test disabled aead ciphers"}]. no_aead(Config) when is_list(Config) -> EncArg4 = - case lazy_eval(proplists:get_value(aead, Config)) of + case lazy_eval(proplists:get_value(cipher, Config)) of [{Type, Key, PlainText, Nonce, AAD, CipherText, CipherTag, TagLen, _Info} | _] -> {AAD, PlainText, TagLen}; [{Type, Key, PlainText, Nonce, AAD, CipherText, CipherTag, _Info} | _] -> @@ -631,7 +687,7 @@ no_aead(Config) when is_list(Config) -> stream() -> [{doc, "Test stream ciphers"}]. stream(Config) when is_list(Config) -> - Streams = lazy_eval(proplists:get_value(stream, Config)), + [_|_] = Streams = lazy_eval(proplists:get_value(cipher, Config)), lists:foreach(fun stream_cipher/1, Streams), lists:foreach(fun stream_cipher/1, stream_iolistify(Streams)), @@ -654,8 +710,7 @@ no_stream_ivec(Config) when is_list(Config) -> aead() -> [{doc, "Test AEAD ciphers"}]. aead(Config) when is_list(Config) -> - AEADs = lazy_eval(proplists:get_value(aead, Config)), - + [_|_] = AEADs = lazy_eval(proplists:get_value(cipher, Config)), FilteredAEADs = case proplists:get_bool(fips, Config) of false -> @@ -668,7 +723,6 @@ aead(Config) when is_list(Config) -> IVLen >= 12 end, AEADs) end, - lists:foreach(fun aead_cipher/1, FilteredAEADs). %%-------------------------------------------------------------------- @@ -847,8 +901,24 @@ cipher_info(Config) when is_list(Config) -> #{type := _,key_length := _,iv_length := _, block_size := _,mode := _} = crypto:cipher_info(aes_128_cbc), {'EXIT',_} = (catch crypto:cipher_info(not_a_cipher)), - lists:foreach(fun(C) -> crypto:cipher_info(C) end, - proplists:get_value(ciphers, crypto:supports())). + case lists:foldl(fun(C,Ok) -> + try crypto:cipher_info(C) + of + _ -> Ok + catch Cls:Exc -> + ct:pal("~p:~p ~p",[Cls,Exc,C]), + false + end + end, + true, +crypto:supports(ciphers)) of +%% proplists:get_value(ciphers, crypto:supports())) of + true -> + ok; + false -> + ct:fail('Cipher unsupported',[]) + end. + %%-------------------------------------------------------------------- hash_info() -> @@ -985,13 +1055,27 @@ block_cipher({Type, Key, IV, PlainText, CipherText}) -> ct:fail({{crypto, block_decrypt, [Type, Key, IV, CipherText]}, {expected, Plain}, {got, Other1}}) end. -block_cipher_increment({Type, Key, IV, PlainTexts}) - when Type == des_cbc; Type == aes_cbc; Type == des3_cbc -> +block_cipher_increment({Type, Key, IV, PlainTexts}) when Type == des_cbc ; + Type == des3_cbc ; + Type == aes_128_cbc ; + Type == aes_192_cbc ; + Type == aes_256_cbc + -> block_cipher_increment(Type, Key, IV, IV, PlainTexts, iolist_to_binary(PlainTexts), []); -block_cipher_increment({Type, Key, IV, PlainTexts, CipherText}) - when Type == des_cbc; Type == des3_cbc -> +block_cipher_increment({Type, Key, IV, PlainTexts, CipherText}) when Type == des_cbc; + Type == des_ede3_cbc ; + Type == des3_cbc ; + Type == des_ede3 ; + Type == des_ede3_cfb ; + Type == des_ede3_cbf ; + Type == des3_cbf ; + Type == des3_cfb + -> block_cipher_increment(Type, Key, IV, IV, PlainTexts, iolist_to_binary(PlainTexts), CipherText, []); -block_cipher_increment({Type, Key, IV, PlainTexts, _CipherText}) when Type == aes_cbc -> +block_cipher_increment({Type, Key, IV, PlainTexts, _CipherText}) when Type == aes_128_cbc ; + Type == aes_192_cbc ; + Type == aes_256_cbc + -> Plain = iolist_to_binary(PlainTexts), Blocks = [iolistify(Block) || << Block:128/bitstring >> <= Plain], block_cipher_increment(Type, Key, IV, IV, Blocks, Plain, []); @@ -1025,8 +1109,9 @@ block_cipher_increment(Type, Key, IV0, IV, [PlainText | PlainTexts], Plain, Ciph NextIV = crypto:next_iv(Type, CT), block_cipher_increment(Type, Key, IV0, NextIV, PlainTexts, Plain, CipherText, [CT | Acc]). -stream_cipher({Type, Key, PlainText}) -> - Plain = iolist_to_binary(PlainText), +stream_cipher({Type, Key, PlainText0}) -> + PlainText = lazy_eval(PlainText0), + Plain = iolist_to_binary(lazy_eval(PlainText)), StateE = crypto:stream_init(Type, Key), StateD = crypto:stream_init(Type, Key), {_, CipherText} = crypto:stream_encrypt(StateE, PlainText), @@ -1036,7 +1121,8 @@ stream_cipher({Type, Key, PlainText}) -> Other -> ct:fail({{crypto, stream_decrypt, [StateD, CipherText]}, {expected, PlainText}, {got, Other}}) end; -stream_cipher({Type, Key, IV, PlainText}) -> +stream_cipher({Type, Key, IV, PlainText0}) -> + PlainText = lazy_eval(PlainText0), Plain = iolist_to_binary(PlainText), StateE = crypto:stream_init(Type, Key, IV), StateD = crypto:stream_init(Type, Key, IV), @@ -1047,7 +1133,8 @@ stream_cipher({Type, Key, IV, PlainText}) -> Other -> ct:fail({{crypto, stream_decrypt, [StateD, CipherText]}, {expected, PlainText}, {got, Other}}) end; -stream_cipher({Type, Key, IV, PlainText, CipherText}) -> +stream_cipher({Type, Key, IV, PlainText0, CipherText}) -> + PlainText = lazy_eval(PlainText0), Plain = iolist_to_binary(PlainText), StateE = crypto:stream_init(Type, Key, IV), StateD = crypto:stream_init(Type, Key, IV), @@ -1112,7 +1199,7 @@ aead_cipher({Type, Key, PlainText, IV, AAD, CipherText, CipherTag, Info}) -> aead_cipher({Type, Key, PlainText, IV, AAD, CipherText, CipherTag, TagLen, Info}) -> <<TruncatedCipherTag:TagLen/binary, _/binary>> = CipherTag, Plain = iolist_to_binary(PlainText), - case crypto:block_encrypt(Type, Key, IV, {AAD, Plain, TagLen}) of + try crypto:block_encrypt(Type, Key, IV, {AAD, Plain, TagLen}) of {CipherText, TruncatedCipherTag} -> ok; Other0 -> @@ -1121,6 +1208,18 @@ aead_cipher({Type, Key, PlainText, IV, AAD, CipherText, CipherTag, TagLen, Info} [{info,Info}, {key,Key}, {pt,PlainText}, {iv,IV}, {aad,AAD}, {ct,CipherText}, {tag,CipherTag}, {taglen,TagLen}]}, {expected, {CipherText, TruncatedCipherTag}}, {got, Other0}}) + catch + error:E -> + ct:log("~p",[{Type, Key, PlainText, IV, AAD, CipherText, CipherTag, TagLen, Info}]), + try crypto:crypto_one_time_aead(Type, Key, IV, PlainText, AAD, TagLen, true) + of + RR -> + ct:log("Works: ~p",[RR]) + catch + CC:EE -> + ct:log("~p:~p", [CC,EE]) + end, + ct:fail("~p",[E]) end, case crypto:block_decrypt(Type, Key, IV, {AAD, CipherText, TruncatedCipherTag}) of Plain -> @@ -1369,16 +1468,15 @@ do_stream_iolistify({Type, Key, IV, PlainText}) -> {Type, iolistify(Key), IV, iolistify(PlainText)}; do_stream_iolistify({Type, Key, IV, PlainText, CipherText}) -> {Type, iolistify(Key), IV, iolistify(PlainText), CipherText}. - -do_block_iolistify({des_cbc = Type, Key, IV, PlainText}) -> - {Type, Key, IV, des_iolistify(PlainText)}; -do_block_iolistify({des3_cbc = Type, Key, IV, PlainText}) -> - {Type, Key, IV, des_iolistify(PlainText)}; -do_block_iolistify({des3_cbf = Type, Key, IV, PlainText}) -> - {Type, Key, IV, des_iolistify(PlainText)}; -do_block_iolistify({des3_cfb = Type, Key, IV, PlainText}) -> - {Type, Key, IV, des_iolistify(PlainText)}; -do_block_iolistify({des_ede3 = Type, Key, IV, PlainText}) -> +do_block_iolistify({Type, Key, IV, PlainText}) when Type == des_cbc ; + Type == des_ede3_cbc ; + Type == des3_cbc ; + Type == des_ede3 ; + Type == des_ede3_cfb ; + Type == des_ede3_cbf ; + Type == des3_cbf ; + Type == des3_cfb + -> {Type, Key, IV, des_iolistify(PlainText)}; do_block_iolistify({Type, Key, PlainText}) -> {Type, iolistify(Key), iolistify(PlainText)}; @@ -1387,10 +1485,13 @@ do_block_iolistify({Type, Key, IV, PlainText}) -> do_block_iolistify({Type, Key, IV, PlainText, CipherText}) -> {Type, iolistify(Key), IV, iolistify(PlainText), CipherText}. -iolistify(<<"Test With Truncation">>)-> +iolistify(X) -> + iolistify1(lazy_eval(X)). + +iolistify1(<<"Test With Truncation">>)-> %% Do not iolistify as it spoils this special case <<"Test With Truncation">>; -iolistify(Msg) when is_binary(Msg) -> +iolistify1(Msg) when is_binary(Msg) -> Length = erlang:byte_size(Msg), Split = Length div 2, List0 = binary_to_list(Msg), @@ -1400,8 +1501,8 @@ iolistify(Msg) when is_binary(Msg) -> {List1, List2}-> [List1, List2] end; -iolistify(Msg) -> - iolistify(list_to_binary(Msg)). +iolistify1(Msg) when is_list(Msg) -> + iolistify1(list_to_binary(Msg)). des_iolistify(Msg) -> des_iolist(erlang:byte_size(Msg) div 8, Msg, []). @@ -1480,7 +1581,7 @@ rand_uniform_aux_test(N) -> rand_uniform_aux_test(N-1). crypto_rand_uniform(L,H) -> - R1 = crypto:rand_uniform(L, H), + R1 = (L-1) + rand:uniform(H-L), case (R1 >= L) and (R1 < H) of true -> ok; @@ -1710,7 +1811,6 @@ group_config(dss = Type, Config) -> MsgPubEnc = <<"7896345786348 Asldi">>, PubPrivEnc = [{dss, Public, Private, MsgPubEnc, []}], [{sign_verify, SignVerify}, {pub_priv_encrypt, PubPrivEnc} | Config]; - group_config(ecdsa = Type, Config) -> {Private, Public} = ec_key_named(), Msg = ec_msg(), @@ -1722,15 +1822,13 @@ group_config(ecdsa = Type, Config) -> MsgPubEnc = <<"7896345786348 Asldi">>, PubPrivEnc = [{ecdsa, Public, Private, MsgPubEnc, []}], [{sign_verify, SignVerify}, {pub_priv_encrypt, PubPrivEnc} | Config]; - group_config(Type, Config) when Type == ed25519 ; Type == ed448 -> TestVectors = eddsa(Type), [{sign_verify,TestVectors} | Config]; - - group_config(srp, Config) -> GenerateCompute = [srp3(), srp6(), srp6a(), srp6a_smaller_prime()], [{generate_compute, GenerateCompute} | Config]; + group_config(ecdh, Config) -> Compute = ecdh(), Generate = ecc(), @@ -1738,77 +1836,19 @@ group_config(ecdh, Config) -> group_config(dh, Config) -> GenerateCompute = [dh()], [{generate_compute, GenerateCompute} | Config]; -group_config(des_cbc, Config) -> - Block = des_cbc(), - [{block, Block} | Config]; -group_config(des_cfb, Config) -> - Block = des_cfb(), - [{block, Block} | Config]; -group_config(des3_cbc, Config) -> - Block = des3_cbc(), - [{block, Block} | Config]; -group_config(des3_cbf, Config) -> - Block = des3_cbf(), - [{block, Block} | Config]; -group_config(des3_cfb, Config) -> - Block = des3_cfb(), - [{block, Block} | Config]; -group_config(des_ede3, Config) -> - Block = des_ede3(), - [{block, Block} | Config]; -group_config(rc2_cbc, Config) -> - Block = rc2_cbc(), - [{block, Block} | Config]; + group_config(aes_cbc128 = Type, Config) -> Block = fun() -> aes_cbc128(Config) end, Pairs = fun() -> cmac_nist(Config, Type) end, - [{block, Block}, {cmac, Pairs} | Config]; + [{cipher, Block}, {cmac, Pairs} | Config]; group_config(aes_cbc256 = Type, Config) -> Block = fun() -> aes_cbc256(Config) end, Pairs = fun() -> cmac_nist(Config, Type) end, - [{block, Block}, {cmac, Pairs} | Config]; -group_config(aes_ecb, Config) -> - Block = fun() -> aes_ecb(Config) end, - [{block, Block} | Config]; -group_config(aes_ige256, Config) -> - Block = aes_ige256(), - [{block, Block} | Config]; -group_config(aes_cfb8, Config) -> - Block = fun() -> aes_cfb8(Config) end, - [{block, Block} | Config]; -group_config(aes_cfb128, Config) -> - Block = fun() -> aes_cfb128(Config) end, - [{block, Block} | Config]; -group_config(blowfish_cbc, Config) -> - Block = blowfish_cbc(), - [{block, Block} | Config]; -group_config(blowfish_ecb, Config) -> - Block = blowfish_ecb(), - [{block, Block} | Config]; -group_config(blowfish_cfb64, Config) -> - Block = blowfish_cfb64(), - [{block, Block} | Config]; -group_config(blowfish_ofb64, Config) -> - Block = blowfish_ofb64(), - [{block, Block} | Config]; -group_config(rc4, Config) -> - Stream = rc4(), - [{stream, Stream} | Config]; -group_config(aes_ctr, Config) -> - Stream = aes_ctr(), - [{stream, Stream} | Config]; -group_config(aes_ccm, Config) -> - AEAD = fun() -> aes_ccm(Config) end, - [{aead, AEAD} | Config]; -group_config(aes_gcm, Config) -> - AEAD = fun() -> aes_gcm(Config) end, - [{aead, AEAD} | Config]; + [{cipher, Block}, {cmac, Pairs} | Config]; group_config(chacha20_poly1305, Config) -> - AEAD = chacha20_poly1305(), - [{aead, AEAD} | Config]; -group_config(chacha20, Config) -> - Stream = chacha20(), - [{stream, Stream} | Config]; + AEAD = chacha20_poly1305(Config), + [{cipher, AEAD} | Config]; + group_config(poly1305, Config) -> V = [%% {Key, Txt, Expect} {%% RFC7539 2.5.2 @@ -1818,11 +1858,12 @@ group_config(poly1305, Config) -> } ], [{poly1305,V} | Config]; -group_config(aes_cbc, Config) -> - Block = aes_cbc(Config), - [{block, Block} | Config]; -group_config(_, Config) -> - Config. + +group_config(F, Config) -> + TestVectors = fun() -> ?MODULE:F(Config) end, + [{cipher, TestVectors} | Config]. + + rsa_sign_verify_tests(Config, Msg, Public, Private, PublicS, PrivateS, OptsToTry) -> case ?config(fips, Config) of @@ -2413,19 +2454,19 @@ rfc4231_hmac_sha512() -> "debd71f8867289865df5a32d20cdc944" "b6022cac3c4982b10d5eeb55c3e4de15" "134676fb6de0446065c97440fa8c6a58")]. -des_cbc() -> +des_cbc(_) -> [{des_cbc, hexstr2bin("0123456789abcdef"), hexstr2bin("1234567890abcdef"), <<"Now is the time for all ">> }]. -des_cfb() -> +des_cfb(_) -> [{des_cfb, hexstr2bin("0123456789abcdef"), hexstr2bin("1234567890abcdef"), <<"Now is the">>}]. -des3_cbc() -> +des3_cbc(_) -> [{des3_cbc, [hexstr2bin("0123456789abcdef"), hexstr2bin("fedcba9876543210"), @@ -2434,7 +2475,7 @@ des3_cbc() -> <<"Now is the time for all ">> }]. -des_ede3() -> +des_ede3(_) -> [{des_ede3, [hexstr2bin("8000000000000000"), hexstr2bin("4000000000000000"), @@ -2443,7 +2484,23 @@ des_ede3() -> hexstr2bin("0000000000000000") }]. -des3_cbf() -> +des_ede3_cbc(_) -> + [{des_ede3_cbc, + [hexstr2bin("0123456789abcdef"), + hexstr2bin("fedcba9876543210"), + hexstr2bin("0f2d4b6987a5c3e1")], + hexstr2bin("1234567890abcdef"), + <<"Now is the time for all ">> + }, + {des_ede3_cbc, + [hexstr2bin("8000000000000000"), + hexstr2bin("4000000000000000"), + hexstr2bin("2000000000000000")], + hexstr2bin("7AD16FFB79C45926"), + hexstr2bin("0000000000000000") + }]. + +des3_cbf(_) -> [{des3_cbf, [hexstr2bin("0123456789abcdef"), hexstr2bin("fedcba9876543210"), @@ -2452,7 +2509,7 @@ des3_cbf() -> <<"Now is the time for all ">> }]. -des3_cfb() -> +des3_cfb(_) -> [{des3_cfb, [hexstr2bin("0123456789abcdef"), hexstr2bin("fedcba9876543210"), @@ -2461,7 +2518,16 @@ des3_cfb() -> <<"Now is the time for all ">> }]. -rc2_cbc() -> +des_ede3_cfb(_) -> + [{des_ede3_cfb, + [hexstr2bin("0123456789abcdef"), + hexstr2bin("fedcba9876543210"), + hexstr2bin("0f2d4b6987a5c3e1")], + hexstr2bin("1234567890abcdef"), + <<"Now is the time for all ">> + }]. + +rc2_cbc(_) -> [{rc2_cbc, <<146,210,160,124,215,227,153,239,227,17,222,140,3,93,27,191>>, <<72,91,135,182,25,42,35,210>>, @@ -2470,7 +2536,8 @@ rc2_cbc() -> %% AES CBC test vectors from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf aes_cbc(Config) -> - read_rsp(Config, aes_cbc, + %% RETIRED aes_*_cbc + read_rsp(Config, aes_cbc, ["CBCVarTxt128.rsp", "CBCVarKey128.rsp", "CBCGFSbox128.rsp", "CBCKeySbox128.rsp", "CBCVarTxt192.rsp", "CBCVarKey192.rsp", "CBCGFSbox192.rsp", "CBCKeySbox192.rsp", "CBCVarTxt256.rsp", "CBCVarKey256.rsp", "CBCGFSbox256.rsp", "CBCKeySbox256.rsp", @@ -2478,15 +2545,32 @@ aes_cbc(Config) -> ]). aes_cbc128(Config) -> + %% RETIRED aes_128_cbc read_rsp(Config, aes_cbc128, ["CBCVarTxt128.rsp", "CBCVarKey128.rsp", "CBCGFSbox128.rsp", "CBCKeySbox128.rsp", "CBCMMT128.rsp"]). aes_cbc256(Config) -> + %% RETIRED aes_256_cbc read_rsp(Config, aes_cbc256, ["CBCVarTxt256.rsp", "CBCVarKey256.rsp", "CBCGFSbox256.rsp", "CBCKeySbox256.rsp", "CBCMMT256.rsp"]). +aes_128_cbc(Config) -> + read_rsp(Config, aes_128_cbc, + ["CBCVarTxt128.rsp", "CBCVarKey128.rsp", "CBCGFSbox128.rsp", "CBCKeySbox128.rsp", + "CBCMMT128.rsp"]). + +aes_192_cbc(Config) -> + read_rsp(Config, aes_192_cbc, + ["CBCVarTxt192.rsp", "CBCVarKey192.rsp", "CBCGFSbox192.rsp", "CBCKeySbox192.rsp", + "CBCMMT192.rsp"]). + +aes_256_cbc(Config) -> + read_rsp(Config, aes_256_cbc, + ["CBCVarTxt256.rsp", "CBCVarKey256.rsp", "CBCGFSbox256.rsp", "CBCKeySbox256.rsp", + "CBCMMT256.rsp"]). + aes_ecb(Config) -> read_rsp(Config, aes_ecb, ["ECBVarTxt128.rsp", "ECBVarKey128.rsp", "ECBGFSbox128.rsp", "ECBKeySbox128.rsp", @@ -2494,7 +2578,22 @@ aes_ecb(Config) -> "ECBVarTxt256.rsp", "ECBVarKey256.rsp", "ECBGFSbox256.rsp", "ECBKeySbox256.rsp", "ECBMMT128.rsp", "ECBMMT192.rsp", "ECBMMT256.rsp"]). -aes_ige256() -> +aes_128_ecb(Config) -> + read_rsp(Config, aes_128_ecb, + ["ECBVarTxt128.rsp", "ECBVarKey128.rsp", "ECBGFSbox128.rsp", "ECBKeySbox128.rsp", + "ECBMMT128.rsp"]). + +aes_192_ecb(Config) -> + read_rsp(Config, aes_192_ecb, + ["ECBVarTxt192.rsp", "ECBVarKey192.rsp", "ECBGFSbox192.rsp", "ECBKeySbox192.rsp", + "ECBMMT192.rsp"]). + +aes_256_ecb(Config) -> + read_rsp(Config, aes_256_ecb, + ["ECBVarTxt256.rsp", "ECBVarKey256.rsp", "ECBGFSbox256.rsp", "ECBKeySbox256.rsp", + "ECBMMT256.rsp"]). + +aes_ige256(_) -> [{aes_ige256, hexstr2bin("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"), hexstr2bin("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F"), @@ -2520,6 +2619,22 @@ aes_cfb8(Config) -> "CFB8VarTxt256.rsp", "CFB8VarKey256.rsp", "CFB8GFSbox256.rsp", "CFB8KeySbox256.rsp", "CFB8MMT128.rsp", "CFB8MMT192.rsp", "CFB8MMT256.rsp"]). +aes_128_cfb8(Config) -> + read_rsp(Config, aes_128_cfb8, + ["CFB8VarTxt128.rsp", "CFB8VarKey128.rsp", "CFB8GFSbox128.rsp", "CFB8KeySbox128.rsp", + "CFB8MMT128.rsp"]). + +aes_192_cfb8(Config) -> + read_rsp(Config, aes_192_cfb8, + ["CFB8VarTxt192.rsp", "CFB8VarKey192.rsp", "CFB8GFSbox192.rsp", "CFB8KeySbox192.rsp", + "CFB8MMT192.rsp"]). + +aes_256_cfb8(Config) -> + read_rsp(Config, aes_256_cfb8, + ["CFB8VarTxt256.rsp", "CFB8VarKey256.rsp", "CFB8GFSbox256.rsp", "CFB8KeySbox256.rsp", + "CFB8MMT256.rsp"]). + + aes_cfb128(Config) -> read_rsp(Config, aes_cfb128, ["CFB128VarTxt128.rsp", "CFB128VarKey128.rsp", "CFB128GFSbox128.rsp", "CFB128KeySbox128.rsp", @@ -2527,14 +2642,30 @@ aes_cfb128(Config) -> "CFB128VarTxt256.rsp", "CFB128VarKey256.rsp", "CFB128GFSbox256.rsp", "CFB128KeySbox256.rsp", "CFB128MMT128.rsp", "CFB128MMT192.rsp", "CFB128MMT256.rsp"]). -blowfish_cbc() -> +aes_128_cfb128(Config) -> + read_rsp(Config, aes_128_cfb128, + ["CFB128VarTxt128.rsp", "CFB128VarKey128.rsp", "CFB128GFSbox128.rsp", "CFB128KeySbox128.rsp", + "CFB128MMT128.rsp"]). + +aes_192_cfb128(Config) -> + read_rsp(Config, aes_192_cfb128, + ["CFB128VarTxt192.rsp", "CFB128VarKey192.rsp", "CFB128GFSbox192.rsp", "CFB128KeySbox192.rsp", + "CFB128MMT192.rsp"]). + +aes_256_cfb128(Config) -> + read_rsp(Config, aes_256_cfb128, + ["CFB128VarTxt256.rsp", "CFB128VarKey256.rsp", "CFB128GFSbox256.rsp", "CFB128KeySbox256.rsp", + "CFB128MMT256.rsp"]). + + +blowfish_cbc(_) -> [{blowfish_cbc, hexstr2bin("0123456789ABCDEFF0E1D2C3B4A59687"), hexstr2bin("FEDCBA9876543210"), hexstr2bin("37363534333231204E6F77206973207468652074696D6520666F722000000000") }]. -blowfish_ecb() -> +blowfish_ecb(_) -> [ {blowfish_ecb, hexstr2bin("0000000000000000"), @@ -2631,26 +2762,26 @@ blowfish_ecb() -> hexstr2bin("FFFFFFFFFFFFFFFF")} ]. -blowfish_cfb64() -> +blowfish_cfb64(_) -> [{blowfish_cfb64, hexstr2bin("0123456789ABCDEFF0E1D2C3B4A59687"), hexstr2bin("FEDCBA9876543210"), hexstr2bin("37363534333231204E6F77206973207468652074696D6520666F722000") }]. -blowfish_ofb64() -> +blowfish_ofb64(_) -> [{blowfish_ofb64, hexstr2bin("0123456789ABCDEFF0E1D2C3B4A59687"), hexstr2bin("FEDCBA9876543210"), hexstr2bin("37363534333231204E6F77206973207468652074696D6520666F722000") }]. -rc4() -> +rc4(_) -> [{rc4, <<"apaapa">>, <<"Yo baby yo">>}, {rc4, <<"apaapa">>, list_to_binary(lists:seq(0, 255))}, {rc4, <<"apaapa">>, long_msg()} ]. -aes_ctr() -> +aes_ctr(_) -> [ %% F.5.3 CTR-AES192.Encrypt {aes_ctr, hexstr2bin("2b7e151628aed2a6abf7158809cf4f3c"), hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"), @@ -2699,24 +2830,109 @@ aes_ctr() -> ]. +aes_128_ctr(_) -> + [ %% F.5.3 CTR-AES192.Encrypt + {aes_128_ctr, hexstr2bin("2b7e151628aed2a6abf7158809cf4f3c"), + hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"), + hexstr2bin("6bc1bee22e409f96e93d7e117393172a")}, + {aes_128_ctr, hexstr2bin("2b7e151628aed2a6abf7158809cf4f3c"), + hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdff00"), + hexstr2bin("ae2d8a571e03ac9c9eb76fac45af8e51")}, + {aes_128_ctr, hexstr2bin("2b7e151628aed2a6abf7158809cf4f3c"), + hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdff01"), + hexstr2bin("30c81c46a35ce411e5fbc1191a0a52ef") }, + {aes_128_ctr, hexstr2bin("2b7e151628aed2a6abf7158809cf4f3c"), + hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdff02"), + hexstr2bin("f69f2445df4f9b17ad2b417be66c3710")} + ]. + +aes_192_ctr(_) -> + [ %% F.5.3 CTR-AES192.Encrypt + {aes_192_ctr, hexstr2bin("8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"), + hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"), + hexstr2bin("6bc1bee22e409f96e93d7e117393172a")}, + {aes_192_ctr, hexstr2bin("8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"), + hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdff00"), + hexstr2bin("ae2d8a571e03ac9c9eb76fac45af8e51")}, + {aes_192_ctr, hexstr2bin("8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"), + hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdff01"), + hexstr2bin("30c81c46a35ce411e5fbc1191a0a52ef")}, + {aes_192_ctr, hexstr2bin("8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"), + hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdff02"), + hexstr2bin("f69f2445df4f9b17ad2b417be66c3710")} + ]. + +aes_256_ctr(_) -> + [ %% F.5.5 CTR-AES256.Encrypt + {aes_256_ctr, hexstr2bin("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"), + hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"), + hexstr2bin("6bc1bee22e409f96e93d7e117393172a")}, + {aes_256_ctr, hexstr2bin("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"), + hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdff00"), + hexstr2bin("ae2d8a571e03ac9c9eb76fac45af8e51")}, + {aes_256_ctr, hexstr2bin("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"), + hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdff01"), + hexstr2bin("30c81c46a35ce411e5fbc1191a0a52ef")}, + {aes_256_ctr, hexstr2bin("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"), + hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdff02"), + hexstr2bin("f69f2445df4f9b17ad2b417be66c3710")}, + + {aes_256_ctr, hexstr2bin("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"), + hexstr2bin("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"), + long_msg()} + ]. + + aes_gcm(Config) -> - read_rsp(Config, aes_gcm, + %% RETIRED aes_*_gcm + read_rsp(Config, aes_gcm, + ["gcmDecrypt128.rsp", + "gcmDecrypt192.rsp", + "gcmDecrypt256.rsp", + "gcmEncryptExtIV128.rsp", + "gcmEncryptExtIV192.rsp", + "gcmEncryptExtIV256.rsp"]). + +aes_128_gcm(Config) -> + read_rsp(Config, aes_128_gcm, ["gcmDecrypt128.rsp", - "gcmDecrypt192.rsp", - "gcmDecrypt256.rsp", - "gcmEncryptExtIV128.rsp", - "gcmEncryptExtIV192.rsp", + "gcmEncryptExtIV128.rsp"]). + +aes_192_gcm(Config) -> + read_rsp(Config, aes_192_gcm, + ["gcmDecrypt192.rsp", + "gcmEncryptExtIV192.rsp"]). + +aes_256_gcm(Config) -> + read_rsp(Config, aes_256_gcm, + ["gcmDecrypt256.rsp", "gcmEncryptExtIV256.rsp"]). + aes_ccm(Config) -> - read_rsp(Config, aes_ccm, - ["VADT128.rsp", "VADT192.rsp", "VADT256.rsp", - "VNT128.rsp", "VNT192.rsp", "VNT256.rsp", - "VPT128.rsp", "VPT192.rsp", "VPT256.rsp" - ]). + %% RETIRED aes_*_ccm + read_rsp(Config, aes_ccm, + ["VADT128.rsp", "VADT192.rsp", "VADT256.rsp", + "VNT128.rsp", "VNT192.rsp", "VNT256.rsp", + "VPT128.rsp", "VPT192.rsp", "VPT256.rsp" + ]). + +aes_128_ccm(Config) -> + read_rsp(Config, aes_128_ccm, + ["VADT128.rsp", "VNT128.rsp", "VPT128.rsp"]). + +aes_192_ccm(Config) -> + read_rsp(Config, aes_192_ccm, + ["VADT192.rsp", "VNT192.rsp", "VPT192.rsp"]). + +aes_256_ccm(Config) -> + read_rsp(Config, aes_256_ccm, + ["VADT256.rsp", "VNT256.rsp", "VPT256.rsp"]). + + %% https://tools.ietf.org/html/rfc7539#appendix-A.5 -chacha20_poly1305() -> +chacha20_poly1305(_) -> [ {chacha20_poly1305, hexstr2bin("1c9240a5eb55d38af333888604f6b5f0" %% Key @@ -2763,7 +2979,7 @@ chacha20_poly1305() -> ]. -chacha20() -> +chacha20(_) -> %%% chacha20 (no mode) test vectors from RFC 7539 A.2 [ %% Test Vector #1: @@ -3697,9 +3913,18 @@ parse_rsp(_Type, [], _State, Acc) -> Acc; parse_rsp(_Type, [<<"DECRYPT">>|_], _State, Acc) -> Acc; +parse_rsp(_Type, [<<"ENCRYPT">>|_], _State, Acc) -> + Acc; %% AES format parse_rsp(Type, [<<"COUNT = ", _/binary>>, <<"KEY = ", Key/binary>>, + <<"PLAINTEXT = ", PlainText/binary>>, + <<"CIPHERTEXT = ", CipherText/binary>>|Next], State, Acc) -> + parse_rsp(Type, Next, State, + [{Type, hexstr2bin(Key), + hexstr2bin(PlainText), hexstr2bin(CipherText)}|Acc]); +parse_rsp(Type, [<<"COUNT = ", _/binary>>, + <<"KEY = ", Key/binary>>, <<"IV = ", IV/binary>>, <<"PLAINTEXT = ", PlainText/binary>>, <<"CIPHERTEXT = ", CipherText/binary>>|Next], State, Acc) -> diff --git a/lib/crypto/test/engine_SUITE.erl b/lib/crypto/test/engine_SUITE.erl index 3416fbd78d..41cd132734 100644 --- a/lib/crypto/test/engine_SUITE.erl +++ b/lib/crypto/test/engine_SUITE.erl @@ -148,8 +148,21 @@ end_per_group(_, Config) -> end. %%-------------------------------------------------------------------- -init_per_testcase(_Case, Config) -> - Config. +init_per_testcase(Case, Config) -> + case string:tokens(atom_to_list(Case),"_") of + ["sign","verify",Type|_] -> + skip_if_unsup(list_to_atom(Type), Config); + + ["priv","encrypt","pub","decrypt",Type|_] -> + skip_if_unsup(list_to_atom(Type), Config); + + ["get","pub","from","priv","key",Type|_] -> + skip_if_unsup(list_to_atom(Type), Config); + + _ -> + Config + end. + end_per_testcase(_Case, _Config) -> ok. @@ -851,6 +864,19 @@ get_pub_from_priv_key_ecdsa(Config) -> %%%================================================================ %%% Help for engine_stored_pub_priv_keys* test cases %%% +skip_if_unsup(Type, Config) -> + case pkey_supported(Type) of + false -> + {skip, "Unsupported in this cryptolib"}; + true -> + Config + end. + + +pkey_supported(Type) -> + lists:member(Type, proplists:get_value(public_keys, crypto:supports(), [])). + + load_storage_engine(Config) -> load_storage_engine(Config, []). diff --git a/lib/crypto/vsn.mk b/lib/crypto/vsn.mk index deba17fb66..0a3d9f45e4 100644 --- a/lib/crypto/vsn.mk +++ b/lib/crypto/vsn.mk @@ -1 +1 @@ -CRYPTO_VSN = 4.4.1 +CRYPTO_VSN = 4.4.2 |