From c6c2e82f8b94010e78bfa5fedce7629e7fd32d58 Mon Sep 17 00:00:00 2001 From: Andreas Schultz Date: Thu, 28 Mar 2013 16:19:40 +0100 Subject: CRYPTO: add support for Elliptic Curves to crypto app Conflicts: lib/crypto/src/crypto.erl --- lib/crypto/c_src/crypto.c | 835 ++++++++++++++++++++++++++++++++++++++- lib/crypto/doc/src/crypto.xml | 149 ++++++- lib/crypto/src/crypto.erl | 107 ++++- lib/crypto/test/crypto_SUITE.erl | 67 +++- 4 files changed, 1152 insertions(+), 6 deletions(-) mode change 100755 => 100644 lib/crypto/doc/src/crypto.xml (limited to 'lib/crypto') diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index fac77308f6..1e6c2f24e7 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -74,6 +74,19 @@ # define HAVE_DES_ede3_cfb_encrypt #endif +#if OPENSSL_VERSION_NUMBER >= 0x009080ffL \ + && !defined(OPENSSL_NO_EC) \ + && !defined(OPENSSL_NO_ECDH) \ + && !defined(OPENSSL_NO_ECDSA) +# define HAVE_EC +#endif + +#if defined(HAVE_EC) +#include +#include +#include +#endif + #ifdef VALGRIND # include @@ -216,6 +229,13 @@ static ERL_NIF_TERM bf_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar static ERL_NIF_TERM bf_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM blowfish_ofb64_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM ec_key_new(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM ec_key_to_term_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM term_to_ec_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM ecdh_compute_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); /* helpers */ @@ -333,9 +353,114 @@ static ErlNifFunc nif_funcs[] = { {"bf_cfb64_crypt", 4, bf_cfb64_crypt}, {"bf_cbc_crypt", 4, bf_cbc_crypt}, {"bf_ecb_crypt", 3, bf_ecb_crypt}, - {"blowfish_ofb64_encrypt", 3, blowfish_ofb64_encrypt} + {"blowfish_ofb64_encrypt", 3, blowfish_ofb64_encrypt}, + + {"ec_key_new", 1, ec_key_new}, + {"ec_key_to_term_nif", 1, ec_key_to_term_nif}, + {"term_to_ec_key_nif", 3, term_to_ec_key_nif}, + {"ec_key_generate", 1, ec_key_generate}, + {"ecdsa_sign_nif", 3, ecdsa_sign_nif}, + {"ecdsa_verify_nif", 4, ecdsa_verify_nif}, + {"ecdh_compute_key", 2, ecdh_compute_key} }; +#if defined(HAVE_EC) +struct nid_map { + char *name; + int nid; + ERL_NIF_TERM atom; +}; + +static struct nid_map ec_curves[] = { + /* prime field curves */ + /* secg curves */ + { "secp112r1", NID_secp112r1 }, + { "secp112r2", NID_secp112r2 }, + { "secp128r1", NID_secp128r1 }, + { "secp128r2", NID_secp128r2 }, + { "secp160k1", NID_secp160k1 }, + { "secp160r1", NID_secp160r1 }, + { "secp160r2", NID_secp160r2 }, + /* SECG secp192r1 is the same as X9.62 prime192v1 */ + { "secp192r1", NID_X9_62_prime192v1 }, + { "secp192k1", NID_secp192k1 }, + { "secp224k1", NID_secp224k1 }, + { "secp224r1", NID_secp224r1 }, + { "secp256k1", NID_secp256k1 }, + /* SECG secp256r1 is the same as X9.62 prime256v1 */ + { "secp256r1", NID_X9_62_prime256v1 }, + { "secp384r1", NID_secp384r1 }, + { "secp521r1", NID_secp521r1 }, + /* X9.62 curves */ + { "prime192v1", NID_X9_62_prime192v1 }, + { "prime192v2", NID_X9_62_prime192v2 }, + { "prime192v3", NID_X9_62_prime192v3 }, + { "prime239v1", NID_X9_62_prime239v1 }, + { "prime239v2", NID_X9_62_prime239v2 }, + { "prime239v3", NID_X9_62_prime239v3 }, + { "prime256v1", NID_X9_62_prime256v1 }, + /* characteristic two field curves */ + /* NIST/SECG curves */ + { "sect113r1", NID_sect113r1 }, + { "sect113r2", NID_sect113r2 }, + { "sect131r1", NID_sect131r1 }, + { "sect131r2", NID_sect131r2 }, + { "sect163k1", NID_sect163k1 }, + { "sect163r1", NID_sect163r1 }, + { "sect163r2", NID_sect163r2 }, + { "sect193r1", NID_sect193r1 }, + { "sect193r2", NID_sect193r2 }, + { "sect233k1", NID_sect233k1 }, + { "sect233r1", NID_sect233r1 }, + { "sect239k1", NID_sect239k1 }, + { "sect283k1", NID_sect283k1 }, + { "sect283r1", NID_sect283r1 }, + { "sect409k1", NID_sect409k1 }, + { "sect409r1", NID_sect409r1 }, + { "sect571k1", NID_sect571k1 }, + { "sect571r1", NID_sect571r1 }, + /* X9.62 curves */ + { "c2pnb163v1", NID_X9_62_c2pnb163v1 }, + { "c2pnb163v2", NID_X9_62_c2pnb163v2 }, + { "c2pnb163v3", NID_X9_62_c2pnb163v3 }, + { "c2pnb176v1", NID_X9_62_c2pnb176v1 }, + { "c2tnb191v1", NID_X9_62_c2tnb191v1 }, + { "c2tnb191v2", NID_X9_62_c2tnb191v2 }, + { "c2tnb191v3", NID_X9_62_c2tnb191v3 }, + { "c2pnb208w1", NID_X9_62_c2pnb208w1 }, + { "c2tnb239v1", NID_X9_62_c2tnb239v1 }, + { "c2tnb239v2", NID_X9_62_c2tnb239v2 }, + { "c2tnb239v3", NID_X9_62_c2tnb239v3 }, + { "c2pnb272w1", NID_X9_62_c2pnb272w1 }, + { "c2pnb304w1", NID_X9_62_c2pnb304w1 }, + { "c2tnb359v1", NID_X9_62_c2tnb359v1 }, + { "c2pnb368w1", NID_X9_62_c2pnb368w1 }, + { "c2tnb431r1", NID_X9_62_c2tnb431r1 }, + /* the WAP/WTLS curves + * [unlike SECG, spec has its own OIDs for curves from X9.62] */ + { "wtls1", NID_wap_wsg_idm_ecid_wtls1 }, + { "wtls3", NID_wap_wsg_idm_ecid_wtls3 }, + { "wtls4", NID_wap_wsg_idm_ecid_wtls4 }, + { "wtls5", NID_wap_wsg_idm_ecid_wtls5 }, + { "wtls6", NID_wap_wsg_idm_ecid_wtls6 }, + { "wtls7", NID_wap_wsg_idm_ecid_wtls7 }, + { "wtls8", NID_wap_wsg_idm_ecid_wtls8 }, + { "wtls9", NID_wap_wsg_idm_ecid_wtls9 }, + { "wtls10", NID_wap_wsg_idm_ecid_wtls10 }, + { "wtls11", NID_wap_wsg_idm_ecid_wtls11 }, + { "wtls12", NID_wap_wsg_idm_ecid_wtls12 }, + /* IPSec curves */ + { "ipsec3", NID_ipsec3 }, + { "ipsec4", NID_ipsec4 } +}; + +#define EC_CURVES_CNT (sizeof(ec_curves)/sizeof(struct nid_map)) + +struct nif_ec_key { + EC_KEY *key; +}; +#endif + ERL_NIF_INIT(crypto,nif_funcs,load,NULL,upgrade,unload) @@ -386,6 +511,19 @@ static ERL_NIF_TERM atom_none; static ERL_NIF_TERM atom_notsup; static ERL_NIF_TERM atom_digest; +static ERL_NIF_TERM atom_ec; + +#if defined(HAVE_EC) +static ERL_NIF_TERM atom_prime_field; +static ERL_NIF_TERM atom_characteristic_two_field; +static ERL_NIF_TERM atom_tpbasis; +static ERL_NIF_TERM atom_ppbasis; +static ERL_NIF_TERM atom_onbasis; + +static ErlNifResourceType* res_type_ec_key; +static void ec_key_dtor(ErlNifEnv* env, void* obj); +#endif + /* #define PRINTF_ERR0(FMT) enif_fprintf(stderr, FMT "\n") #define PRINTF_ERR1(FMT, A1) enif_fprintf(stderr, FMT "\n", A1) @@ -415,6 +553,7 @@ static void error_handler(void* null, const char* errstr) static int init(ErlNifEnv* env, ERL_NIF_TERM load_info) { + int i; ErlNifSysInfo sys_info; get_crypto_callbacks_t* funcp; struct crypto_callbacks* ccb; @@ -466,6 +605,22 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info) atom_notsup = enif_make_atom(env,"notsup"); atom_digest = enif_make_atom(env,"digest"); +#if defined(HAVE_EC) + atom_ec = enif_make_atom(env,"ec"); + atom_prime_field = enif_make_atom(env,"prime_field"); + atom_characteristic_two_field = enif_make_atom(env,"characteristic_two_field"); + atom_tpbasis = enif_make_atom(env,"tpbasis"); + atom_ppbasis = enif_make_atom(env,"ppbasis"); + atom_onbasis = enif_make_atom(env,"onbasis"); + + for (i = 0; i < EC_CURVES_CNT; i++) + ec_curves[i].atom = enif_make_atom(env,ec_curves[i].name); + + res_type_ec_key = enif_open_resource_type(env,NULL,"crypto.EC_KEY", + ec_key_dtor, + ERL_NIF_RT_CREATE, NULL); +#endif + init_digest_types(env); init_algorithms_types(); @@ -549,7 +704,7 @@ static void unload(ErlNifEnv* env, void* priv_data) } static int algos_cnt; -static ERL_NIF_TERM algos[7]; /* increase when extending the list */ +static ERL_NIF_TERM algos[8]; /* increase when extending the list */ static void init_algorithms_types(void) { @@ -570,6 +725,9 @@ static void init_algorithms_types(void) #ifdef HAVE_SHA512 algos[algos_cnt++] = atom_sha512; #endif +#if defined(HAVE_EC) + algos[algos_cnt++] = atom_ec; +#endif } static ERL_NIF_TERM algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) @@ -2686,7 +2844,680 @@ static ERL_NIF_TERM blowfish_ofb64_encrypt(ErlNifEnv* env, int argc, const ERL_N return ret; } +#if defined(HAVE_EC) +static int term2curve_id(ERL_NIF_TERM nid) +{ + int i; + + for (i = 0; i < EC_CURVES_CNT; i++) + if (ec_curves[i].atom == nid) + return ec_curves[i].nid; + + return 0; +} + +static ERL_NIF_TERM curve_id2term(int nid) +{ + int i; + + for (i = 0; i < EC_CURVES_CNT; i++) + if (ec_curves[i].nid == nid) + return ec_curves[i].atom; + + return atom_undefined; +} +#endif + +static ERL_NIF_TERM ec_key_new(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ +#if defined(HAVE_EC) + EC_KEY *key = NULL; + int nid = 0; + + nid = term2curve_id(argv[0]); + if (nid == 0) + return enif_make_badarg(env); + key = EC_KEY_new_by_curve_name(nid); + + if (key) { + ERL_NIF_TERM term; + struct nif_ec_key *obj = enif_alloc_resource(res_type_ec_key, sizeof(struct nif_ec_key)); + if (!obj) + return atom_error; + obj->key = key; + term = enif_make_resource(env, obj); + enif_release_resource(obj); + + return term; + } else + return enif_make_badarg(env); +#else + return atom_notsup; +#endif +} + +#if defined(HAVE_EC) +static ERL_NIF_TERM bn2term(ErlNifEnv* env, const BIGNUM *bn) +{ + unsigned dlen; + unsigned char* ptr; + ERL_NIF_TERM ret; + + if (!bn) + return atom_undefined; + + dlen = BN_num_bytes(bn); + ptr = enif_make_new_binary(env, dlen+4, &ret); + put_int32(ptr, dlen); + BN_bn2bin(bn, ptr+4); + + return ret; +} + +static ERL_NIF_TERM point2term(ErlNifEnv* env, + const EC_GROUP *group, + const EC_POINT *point, + point_conversion_form_t form) +{ + unsigned dlen; + ErlNifBinary bin; + + dlen = EC_POINT_point2oct(group, point, form, NULL, 0, NULL); + if (dlen == 0) + return atom_undefined; + + if (!enif_alloc_binary(dlen, &bin)) + return enif_make_badarg(env); + + if (!EC_POINT_point2oct(group, point, form, bin.data, bin.size, NULL)) { + enif_release_binary(&bin); + return enif_make_badarg(env); + } + + return enif_make_binary(env, &bin); +} +#endif + +static ERL_NIF_TERM ec_key_to_term_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ +#if defined(HAVE_EC) + struct nif_ec_key *obj; + const EC_GROUP *group; + const EC_POINT *public_key; + BIGNUM *order=NULL; + const BIGNUM *priv_key = NULL; + ERL_NIF_TERM pub_key = atom_undefined; + ERL_NIF_TERM group_term = atom_undefined; + + if (!enif_get_resource(env, argv[0], res_type_ec_key, (void **)&obj)) + return enif_make_badarg(env); + + group = EC_KEY_get0_group(obj->key); + public_key = EC_KEY_get0_public_key(obj->key); + priv_key = EC_KEY_get0_private_key(obj->key); + + if (group) { + if (EC_GROUP_get_curve_name(group) != 0) { + /* named group */ + group_term = curve_id2term(EC_GROUP_get_curve_name(group)); + } else { + /* export group paramters */ + ERL_NIF_TERM field_term = atom_undefined; + ERL_NIF_TERM prime_term = atom_undefined; + ERL_NIF_TERM seed_term = atom_none; + ERL_NIF_TERM point_term = atom_none; + ERL_NIF_TERM order_term = atom_none; + ERL_NIF_TERM cofactor_term = atom_none; + + int nid = 0; + const EC_POINT *point = NULL; + BIGNUM *tmp = BN_new(); + BIGNUM *tmp_1 = BN_new(); + BIGNUM *tmp_2 = BN_new(); + + nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group)); + if (nid == NID_X9_62_prime_field) { + /* the parameters are specified by the prime number p */ + EC_GROUP_get_curve_GFp(group, tmp, tmp_1, tmp_2, NULL); + + /* {prime_field, Prime} */ + field_term = enif_make_tuple2(env, atom_prime_field, bn2term(env, tmp)); + } else { /* nid == NID_X9_62_characteristic_two_field */ + int field_type; + ERL_NIF_TERM basis_term; + ERL_NIF_TERM m_term; + + EC_GROUP_get_curve_GF2m(group, NULL, tmp_1, tmp_2, NULL); + + m_term = enif_make_long(env, (long)EC_GROUP_get_degree(group)); + + field_type = EC_GROUP_get_basis_type(group); + if (field_type == 0) { + basis_term = atom_undefined; + } else if (field_type == NID_X9_62_tpBasis) { + unsigned int k; + ERL_NIF_TERM k_term = atom_undefined; + + if (EC_GROUP_get_trinomial_basis(group, &k)) + k_term = enif_make_uint(env, k); + + basis_term = enif_make_tuple2(env, atom_tpbasis, k_term); + } else if (field_type == NID_X9_62_ppBasis) { + unsigned int k1, k2, k3; + ERL_NIF_TERM k1_term = atom_undefined; + ERL_NIF_TERM k2_term = atom_undefined; + ERL_NIF_TERM k3_term = atom_undefined; + + if (EC_GROUP_get_pentanomial_basis(group, &k1, &k2, &k3)) { + /* set k? values */ + k1_term = enif_make_uint(env, k1); + k2_term = enif_make_uint(env, k2); + k3_term = enif_make_uint(env, k3); + } + basis_term = enif_make_tuple4(env, atom_ppbasis, k1_term, k2_term, k3_term); + } else { /* field_type == NID_X9_62_onBasis */ + basis_term = atom_onbasis; + } + /* {characteristic_two_field, M, Basis} */ + field_term = enif_make_tuple3(env, atom_characteristic_two_field, m_term, basis_term); + } + + if (EC_GROUP_get0_seed(group)) { + unsigned char* ptr; + + ptr = enif_make_new_binary(env, EC_GROUP_get_seed_len(group), &seed_term); + memcpy(ptr, EC_GROUP_get0_seed(group), EC_GROUP_get_seed_len(group)); + } + + + /* set the base point */ + point = EC_GROUP_get0_generator(group); + if (point) + point_term = point2term(env, group, point, EC_GROUP_get_point_conversion_form(group)); + + /* set the order */ + if (EC_GROUP_get_order(group, tmp, NULL)) + order_term = bn2term(env, tmp); + + /* set the cofactor (optional) */ + if (EC_GROUP_get_cofactor(group, tmp, NULL)) + cofactor_term = bn2term(env, tmp); + + prime_term = enif_make_tuple3(env, bn2term(env, tmp_1), bn2term(env, tmp_2), seed_term); + group_term = enif_make_tuple5(env, field_term, prime_term, point_term, order_term, cofactor_term); + BN_free(tmp); + BN_free(tmp_1); + BN_free(tmp_2); + } + + if (public_key) + pub_key = point2term(env, group, public_key, EC_KEY_get_conv_form(obj->key)); + + if (order) BN_free(order); + } + + return enif_make_tuple3(env, group_term, bn2term(env, priv_key), pub_key); +#else + return atom_notsup; +#endif +} + +#if defined(HAVE_EC) +static int term2point(ErlNifEnv* env, ERL_NIF_TERM term, + EC_GROUP *group, EC_POINT **pptr) +{ + int ret = 0; + ErlNifBinary bin; + EC_POINT *point; + + if (!enif_inspect_binary(env,term,&bin)) { + return 0; + } + + if ((*pptr = point = EC_POINT_new(group)) == NULL) { + return 0; + } + + /* set the point conversion form */ + EC_GROUP_set_point_conversion_form(group, (point_conversion_form_t)(bin.data[0] & ~0x01)); + + /* extract the ec point */ + if (!EC_POINT_oct2point(group, point, bin.data, bin.size, NULL)) { + EC_POINT_free(point); + *pptr = NULL; + } else + ret = 1; + + return ret; +} +#endif + +static ERL_NIF_TERM term_to_ec_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ +#if defined(HAVE_EC) + ERL_NIF_TERM ret; + EC_KEY *key = NULL; + BIGNUM *priv_key = NULL; + EC_POINT *pub_key = NULL; + struct nif_ec_key *obj; + int c_arity = -1; + const ERL_NIF_TERM* curve; + ErlNifBinary seed; + BIGNUM *p = NULL; + BIGNUM *a = NULL; + BIGNUM *b = NULL; + BIGNUM *bn_order = NULL; + BIGNUM *cofactor = NULL; + EC_GROUP *group = NULL; + EC_POINT *point = NULL; + + if (!(argv[1] == atom_undefined || get_bn_from_mpint(env, argv[1], &priv_key)) + || !(argv[2] == atom_undefined || enif_is_binary(env, argv[2]))) { + printf("#1\n"); + goto out_err; + } + + if (enif_is_atom(env, argv[0])) { + int nid; + + nid = term2curve_id(argv[0]); + if (nid == 0) { + printf("#2\n"); + goto out_err; + } + + key = EC_KEY_new_by_curve_name(nid); + } + else if (enif_is_tuple(env, argv[0]) + && enif_get_tuple(env,argv[0],&c_arity,&curve) + && c_arity == 5 + && get_bn_from_mpint(env, curve[3], &bn_order) + && (curve[4] != atom_none && get_bn_from_mpint(env, curve[4], &cofactor))) { + //* {Field, Prime, Point, Order, CoFactor} = Curve */ + + int f_arity = -1; + const ERL_NIF_TERM* field; + int p_arity = -1; + const ERL_NIF_TERM* prime; + + long field_bits; + + /* {A, B, Seed} = Prime */ + if (!enif_get_tuple(env,curve[1],&p_arity,&prime) + || !get_bn_from_mpint(env, prime[0], &a) + || !get_bn_from_mpint(env, prime[1], &b)) + goto out_err; + + if (!enif_get_tuple(env,curve[0],&f_arity,&field)) + goto out_err; + + if (f_arity == 2 && field[0] == atom_prime_field) { + /* {prime_field, Prime} */ + + if (!get_bn_from_mpint(env, field[1], &p)) + goto out_err; + + if (BN_is_negative(p) || BN_is_zero(p)) + goto out_err; + + field_bits = BN_num_bits(p); + if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) + goto out_err; + + /* create the EC_GROUP structure */ + group = EC_GROUP_new_curve_GFp(p, a, b, NULL); + + } else if (f_arity == 3 && field[0] == atom_characteristic_two_field) { + /* {characteristic_two_field, M, Basis} */ + + int b_arity = -1; + const ERL_NIF_TERM* basis; + unsigned int k1, k2, k3; + + if ((p = BN_new()) == NULL) + goto out_err; + + if (!enif_get_long(env, field[1], &field_bits) + || field_bits > OPENSSL_ECC_MAX_FIELD_BITS) + goto out_err; + + if (enif_get_tuple(env,field[2],&b_arity,&basis)) { + if (b_arity == 2 + && basis[0] == atom_tpbasis + && enif_get_uint(env, basis[1], &k1)) { + /* {tpbasis, k} = Basis */ + + if (!(field_bits > k1 && k1 > 0)) + goto out_err; + + /* create the polynomial */ + if (!BN_set_bit(p, (int)field_bits) + || !BN_set_bit(p, (int)k1) + || !BN_set_bit(p, 0)) + goto out_err; + + } else if (b_arity == 4 + && basis[0] == atom_ppbasis + && enif_get_uint(env, basis[1], &k1) + && enif_get_uint(env, basis[2], &k2) + && enif_get_uint(env, basis[3], &k3)) { + /* {ppbasis, k1, k2, k3} = Basis */ + + if (!(field_bits > k3 && k3 > k2 && k2 > k1 && k1 > 0)) + goto out_err; + + /* create the polynomial */ + if (!BN_set_bit(p, (int)field_bits) + || !BN_set_bit(p, (int)k1) + || !BN_set_bit(p, (int)k2) + || !BN_set_bit(p, (int)k3) + || !BN_set_bit(p, 0)) + goto out_err; + + } else + goto out_err; + } else if (field[2] == atom_onbasis) { + /* onbasis = Basis */ + /* no parameters */ + goto out_err; + + } else + goto out_err; + + group = EC_GROUP_new_curve_GF2m(p, a, b, NULL); + } else + goto out_err; + + if (enif_inspect_binary(env, prime[2], &seed)) { + EC_GROUP_set_seed(group, seed.data, seed.size); + } + + if (!term2point(env, curve[2], group, &point)) + goto out_err; + + if (BN_is_negative(bn_order) + || BN_is_zero(bn_order) + || BN_num_bits(bn_order) > (int)field_bits + 1) + goto out_err; + + if (!EC_GROUP_set_generator(group, point, bn_order, cofactor)) + goto out_err; + + EC_GROUP_set_asn1_flag(group, 0x0); + + key = EC_KEY_new(); + if (!key) + goto out_err; + EC_KEY_set_group(key, group); + } + else { + printf("#3\n"); + goto out_err; + } + + if (!key) { + printf("#4\n"); + goto out_err; + } + + if (!group) + group = EC_GROUP_dup(EC_KEY_get0_group(key)); + + if (term2point(env, argv[2], group, &pub_key)) { + if (!EC_KEY_set_public_key(key, pub_key)) { + printf("#5\n"); + goto out_err; + } + } + if (argv[1] != atom_undefined + && !BN_is_zero(priv_key)) { + if (!EC_KEY_set_private_key(key, priv_key)) + goto out_err; + + /* calculate public key (if necessary) */ + if (EC_KEY_get0_public_key(key) == NULL) + { + /* the public key was not included in the SEC1 private + * key => calculate the public key */ + pub_key = EC_POINT_new(group); + if (pub_key == NULL + || !EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group)) + || !EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, NULL) + || !EC_KEY_set_public_key(key, pub_key)) + goto out_err; + } + } + + obj = enif_alloc_resource(res_type_ec_key, sizeof(struct nif_ec_key)); + if (!obj) + goto out_err; + + obj->key = key; + ret = enif_make_resource(env, obj); + enif_release_resource(obj); + + goto out; + +out_err: + if (key) EC_KEY_free(key); + ret = enif_make_badarg(env); + +out: + /* some OpenSSL structures are mem-dup'ed into the key, + so we have to free our copies here */ + if (priv_key) BN_clear_free(priv_key); + if (pub_key) EC_POINT_free(pub_key); + if (p) BN_free(p); + if (a) BN_free(a); + if (b) BN_free(b); + if (bn_order) BN_free(bn_order); + if (cofactor) BN_free(cofactor); + if (group) EC_GROUP_free(group); + return ret; +#else + return atom_notsup; +#endif +} + +static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ +#if defined(HAVE_EC) + struct nif_ec_key *obj; + + if (!enif_get_resource(env, argv[0], res_type_ec_key, (void **)&obj)) + return enif_make_badarg(env); + + if (EC_KEY_generate_key(obj->key)) + return atom_ok; + else + return atom_error; +#else + return atom_notsup; +#endif +} + +#if defined(HAVE_EC) +static void ec_key_dtor(ErlNifEnv* env, void* obj) +{ + struct nif_ec_key *key = (struct nif_ec_key*) obj; + EC_KEY_free(key->key); +} +#endif + +static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* (Type, Data|{digest,Digest}, Key) */ +#if defined(HAVE_EC) + ErlNifBinary data_bin, ret_bin; + unsigned char hmacbuf[SHA_DIGEST_LENGTH]; + unsigned int dsa_s_len; + struct nif_ec_key *obj; + int i; + const ERL_NIF_TERM* tpl_terms; + int tpl_arity; + struct digest_type_t *digp; + unsigned char* digest; + + digp = get_digest_type(argv[0]); + if (!digp) { + return enif_make_badarg(env); + } + if (!digp->len) { + return atom_notsup; + } + + if (!enif_get_resource(env, argv[2], res_type_ec_key, (void **)&obj)) + return enif_make_badarg(env); + + if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) { + if (tpl_arity != 2 || tpl_terms[0] != atom_digest + || !enif_inspect_binary(env, tpl_terms[1], &data_bin) + || data_bin.size != digp->len) { + + return enif_make_badarg(env); + } + digest = data_bin.data; + } + else { + if (!inspect_mpint(env,argv[1],&data_bin)) { + return enif_make_badarg(env); + } + digest = hmacbuf; + digp->funcp(data_bin.data+4, data_bin.size-4, digest); + } + + enif_alloc_binary(ECDSA_size(obj->key), &ret_bin); + + i = ECDSA_sign(digp->NID_type, digest, digp->len, + ret_bin.data, &dsa_s_len, obj->key); + if (i) { + if (dsa_s_len != ret_bin.size) { + enif_realloc_binary(&ret_bin, dsa_s_len); + } + return enif_make_binary(env, &ret_bin); + } + else { + enif_release_binary(&ret_bin); + return atom_error; + } +#else + return atom_notsup; +#endif +} + +static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{/* (Type, Data|{digest,Digest}, Signature, Key) */ +#if defined(HAVE_EC) + ErlNifBinary data_bin, sign_bin; + unsigned char hmacbuf[SHA512_LEN]; + int i; + struct nif_ec_key *obj; + const ERL_NIF_TERM type = argv[0]; + const ERL_NIF_TERM* tpl_terms; + int tpl_arity; + struct digest_type_t* digp = NULL; + unsigned char* digest = NULL; + + digp = get_digest_type(type); + if (!digp) { + return enif_make_badarg(env); + } + if (!digp->len) { + return atom_notsup; + } + + if (!inspect_mpint(env, argv[2], &sign_bin) + || !enif_get_resource(env, argv[3], res_type_ec_key, (void **)&obj)) + return enif_make_badarg(env); + + if (enif_get_tuple(env, argv[1], &tpl_arity, &tpl_terms)) { + if (tpl_arity != 2 || tpl_terms[0] != atom_digest + || !enif_inspect_binary(env, tpl_terms[1], &data_bin) + || data_bin.size != digp->len) { + + return enif_make_badarg(env); + } + digest = data_bin.data; + } + else if (inspect_mpint(env, argv[1], &data_bin)) { + digest = hmacbuf; + digp->funcp(data_bin.data+4, data_bin.size-4, digest); + } + else { + return enif_make_badarg(env); + } + + i = ECDSA_verify(digp->NID_type, digest, digp->len, + sign_bin.data+4, sign_bin.size-4, obj->key); + + return (i==1 ? atom_true : atom_false); +#else + return atom_notsup; +#endif +} + +/* + (_OthersPublicKey, _MyPrivateKey) + (_OthersPublicKey, _MyEC_Point) +*/ +static ERL_NIF_TERM ecdh_compute_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ +#if defined(HAVE_EC) + ERL_NIF_TERM ret; + unsigned char *p; + struct nif_ec_key *other_key; + int field_size = 0; + int i; + + EC_GROUP *group; + const BIGNUM *priv_key; + EC_POINT *my_ecpoint; + EC_KEY *other_ecdh = NULL; + if (!enif_get_resource(env, argv[0], res_type_ec_key, (void **)&other_key)) + return enif_make_badarg(env); + + group = EC_GROUP_dup(EC_KEY_get0_group(other_key->key)); + priv_key = EC_KEY_get0_private_key(other_key->key); + + if (!term2point(env, argv[1], group, &my_ecpoint)) { + struct nif_ec_key *my_key; + + if (!enif_get_resource(env, argv[1], res_type_ec_key, (void **)&my_key)) + goto out_err; + + if ((my_ecpoint = EC_POINT_new(group)) == NULL) + goto out_err; + EC_POINT_copy(my_ecpoint, EC_KEY_get0_public_key(my_key->key)); + } + + if ((other_ecdh = EC_KEY_new()) == NULL + || !EC_KEY_set_group(other_ecdh, group) + || !EC_KEY_set_private_key(other_ecdh, priv_key)) + goto out_err; + + field_size = EC_GROUP_get_degree(group); + if (field_size <= 0) + goto out_err; + + p = enif_make_new_binary(env, (field_size+7)/8, &ret); + i = ECDH_compute_key(p, (field_size+7)/8, my_ecpoint, other_ecdh, NULL); + + if (i < 0) + goto out_err; +out: + if (group) EC_GROUP_free(group); + if (my_ecpoint) EC_POINT_free(my_ecpoint); + if (other_ecdh) EC_KEY_free(other_ecdh); + + return ret; + +out_err: + ret = enif_make_badarg(env); + goto out; +#else + return atom_notsup; +#endif +} /* HMAC */ diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml old mode 100755 new mode 100644 index 7eca4557d9..9201d649d7 --- a/lib/crypto/doc/src/crypto.xml +++ b/lib/crypto/doc/src/crypto.xml @@ -66,8 +66,20 @@

srp: Secure Remote Password Protocol (RFC 2945)

- - + +

ecdsa: "Public Key Cryptography for the Financial + Services Industry: The Elliptic Curve Digital + Signature Standard (ECDSA)", November, 2005.

+
+ +

ec: Standards for Efficient Cryptography Group (SECG), "SEC 1: + Elliptic Curve Cryptography", Version 1.0, September 2000.

+
+ +

ecdsa: American National Standards Institute (ANSI), + ANS X9.62-2005: The Elliptic Curve Digital Signature + Algorithm (ECDSA), 2005.

+

The above publications can be found at NIST publications, at IETF.

@@ -1359,6 +1371,116 @@ Mpint() = >]]> + + ec_key_new(NamedCurve) -> ECKey + + NamedCurve = atom() + ECKey = EC key resource() + + +

Generate an new EC key from the named curve. The private key + will be initialized with random data. +

+
+
+ + + ec_key_generate(ECKey) -> ok | error + + ECKey = EC key resource() + + +

Fills in the public key if only the private key is known or generates + a new private/public key pair if only the curve parameters are known. +

+
+
+ + + ec_key_to_term(ECKey) -> ECKeyTerm. + + ECKey = EC key resource() + ECKeyTerm = EC key as Erlang term + + +

Convert a EC key from a NIF resource into an Erlang term. +

+
+
+ + + term_to_ec_key(ECKeyTerm) -> ECKey + + ECKeyTerm = EC key as Erlang term + ECKey = EC key resource() + + +

Convert a EC key an Erlang term into a NIF resource. +

+
+
+ + + ecdsa_sign(DataOrDigest, ECKey) -> Signature + ecdsa_sign(DigestType, DataOrDigest, ECKey) -> Signature + Sign the data using ecdsa with the given key. + + DataOrDigest = Data | {digest,Digest} + Data = Mpint + Digest = binary() + ECKey = EC key resource() + DigestType = md5 | sha | sha256 | sha384 | sha512 + The default DigestType is sha. + Mpint = binary() + Signature = binary() + + +

Creates a ESDSA signature with the private key Key + of a digest. The digest is either calculated as a + DigestType digest of Data or a precalculated + binary Digest.

+
+
+ + + ecdsa_verify(DataOrDigest, Signature, ECKey) -> Verified + ecdsa_verify(DigestType, DataOrDigest, Signature, ECKey) -> Verified + Verify the digest and signature using ecdsa with given public key. + + Verified = boolean() + DataOrDigest = Data | {digest|Digest} + Data, Signature = Mpint + Digest = binary() + ECKey = EC key resource() + DigestType = md5 | sha | sha256 | sha384 | sha512 + The default DigestType is sha. + Mpint = binary() + + +

Verifies that a digest matches the ECDSA signature using the + signer's public key Key. + The digest is either calculated as a DigestType + digest of Data or a precalculated binary Digest.

+

May throw exception notsup in case the chosen DigestType + is not supported by the underlying OpenSSL implementation.

+
+
+ + + ecdh_compute_key(OthersPublicKey, MyPrivateKey) -> SharedSecret + ecdh_compute_key(OthersPublicKey, MyECPoint) -> SharedSecret + Computes the shared secret + + OthersPublicKey, MyPrivateKey = ECKey() + MyPrivatePoint = binary() + SharedSecret = binary() + + +

Computes the shared secret from the private key and the other party's public key. +

+
+
+ exor(Data1, Data2) -> Result XOR data @@ -1372,6 +1494,29 @@ Mpint() = >]]> +
+ Elliptic Curve Key +

Elliptic Curve keys consist of the curve paramters and a the + private and public keys (points on the curve). Translating the + raw curve paraters into something usable for the underlying + OpenSSL implementation is a complicated process. The main cryptografic + functions therefore expect a NIF resource as input that contains the + key in an internal format. Two functions ec_key_to_term/1 + and term_to_ec_key are provided to convert between Erlang + terms and the resource format

+

Key in term form

+
+ec_named_curve() = atom()
+ec_point() = binary()
+ec_basis() = {tpbasis, K :: non_neg_integer()} | {ppbasis, K1 :: non_neg_integer(), K2 :: non_neg_integer(), K3 :: non_neg_integer()} | onbasis
+ec_field() = {prime_field, Prime :: Mpint()} | {characteristic_two_field, M :: integer(), Basis :: ec_basis()}
+ec_prime() = {A :: Mpint(), B :: Mpint(), Seed :: binary()}
+ec_curve_spec() = {Field :: ec_field(), Prime :: ec_prime(), Point :: ec_point(), Order :: Mpint(), CoFactor :: none | Mpint()}
+ec_curve() = ec_named_curve() | ec_curve_spec()
+ec_key() = {Curve :: ec_curve(), PrivKey :: Mpint() | undefined, PubKey :: ec_point() | undefined}
+    
+
+
DES in CBC mode

The Data Encryption Standard (DES) defines an algorithm for diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 1d0a9943c3..7558087d99 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -67,6 +67,8 @@ -export([aes_cbc_ivec/1]). -export([aes_ctr_encrypt/3, aes_ctr_decrypt/3]). -export([aes_ctr_stream_init/2, aes_ctr_stream_encrypt/2, aes_ctr_stream_decrypt/2]). +-export([ec_key_new/1, ec_key_to_term/1, term_to_ec_key/1, ec_key_generate/1]). +-export([ecdsa_sign/2, ecdsa_sign/3, ecdsa_verify/3, ecdsa_verify/4, ecdh_compute_key/2]). -export([dh_generate_parameters/2, dh_check/1]). %% Testing see below @@ -113,12 +115,25 @@ hmac, hmac_init, hmac_update, hmac_final, hmac_final_n, info, rc2_cbc_encrypt, rc2_cbc_decrypt, srp_generate_key, srp_compute_key, + ec_key_new, ec_key_to_term, term_to_ec_key, ec_key_generate, + ecdsa_sign, ecdsa_verify, ecdh_compute_key, info_lib, algorithms]). +-type mpint() :: binary(). -type rsa_digest_type() :: 'md5' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'. -type dss_digest_type() :: 'none' | 'sha'. +-type ecdsa_digest_type() :: 'md5' | 'sha' | 'sha256' | 'sha384' | 'sha512'. -type data_or_digest() :: binary() | {digest, binary()}. -type crypto_integer() :: binary() | integer(). +-type ec_key_res() :: any(). %% nif resource +-type ec_named_curve() :: atom(). +-type ec_point() :: binary(). +-type ec_basis() :: {tpbasis, K :: non_neg_integer()} | {ppbasis, K1 :: non_neg_integer(), K2 :: non_neg_integer(), K3 :: non_neg_integer()} | onbasis. +-type ec_field() :: {prime_field, Prime :: mpint()} | {characteristic_two_field, M :: integer(), Basis :: ec_basis()}. +-type ec_prime() :: {A :: mpint(), B :: mpint(), Seed :: binary()}. +-type ec_curve_spec() :: {Field :: ec_field(), Prime :: ec_prime(), Point :: ec_point(), Order :: mpint(), CoFactor :: none | mpint()}. +-type ec_curve() :: ec_named_curve() | ec_curve_spec(). +-type ec_key() :: {Curve :: ec_curve(), PrivKey :: mpint() | undefined, PubKey :: ec_point() | undefined}. -define(nif_stub,nif_stub_error(?LINE)). @@ -1154,6 +1169,94 @@ srp_compute_key(Verifier, Prime, ClientPublic, ServerPublic, ServerPrivate, Vers srp_server_secret_nif(Verifier, ServerPrivate, Scrambler, ClientPublic, Prime). %% +%% EC +%% +-spec ec_key_new(ec_named_curve()) -> ec_key_res(). +ec_key_new(_Curve) -> ?nif_stub. + +-spec ec_key_generate(ec_key_res()) -> ok | error. +ec_key_generate(_Key) -> ?nif_stub. + +nif_prime_to_term({prime_field, Prime}) -> + {prime_field, erlint(Prime)}; +nif_prime_to_term(PrimeField) -> + PrimeField. +nif_curve_to_term({A, B, Seed}) -> + {erlint(A), erlint(B), Seed}. +nif_curve_parameters_to_term({PrimeField, Curve, BasePoint, Order, CoFactor}) -> + {nif_prime_to_term(PrimeField), nif_curve_to_term(Curve), BasePoint, erlint(Order), erlint(CoFactor)}; +nif_curve_parameters_to_term(Curve) when is_atom(Curve) -> + %% named curve + Curve. + +-spec ec_key_to_term(ec_key_res()) -> ec_key(). +ec_key_to_term(Key) -> + case ec_key_to_term_nif(Key) of + {Curve, PrivKey, PubKey} -> + {nif_curve_parameters_to_term(Curve), erlint(PrivKey), PubKey}; + _ -> + erlang:error(conversion_failed) + end. + +ec_key_to_term_nif(_Key) -> ?nif_stub. + +term_to_nif_prime({prime_field, Prime}) -> + {prime_field, mpint(Prime)}; +term_to_nif_prime(PrimeField) -> + PrimeField. +term_to_nif_curve({A, B, Seed}) -> + {mpint(A), mpint(B), Seed}. +term_to_nif_curve_parameters({PrimeField, Curve, BasePoint, Order, CoFactor}) -> + {term_to_nif_prime(PrimeField), term_to_nif_curve(Curve), BasePoint, mpint(Order), mpint(CoFactor)}; +term_to_nif_curve_parameters(Curve) when is_atom(Curve) -> + %% named curve + Curve. + +-spec term_to_ec_key(ec_key()) -> ec_key_res(). +term_to_ec_key({Curve, undefined, PubKey}) -> + term_to_ec_key_nif(term_to_nif_curve_parameters(Curve), undefined, PubKey); +term_to_ec_key({Curve, PrivKey, PubKey}) -> + term_to_ec_key_nif(term_to_nif_curve_parameters(Curve), mpint(PrivKey), PubKey). + +term_to_ec_key_nif(_Curve, _PrivKey, _PubKey) -> ?nif_stub. + +%% +%% ECDSA - sign +%% +-spec ecdsa_sign(data_or_digest(), ec_key_res()) -> binary(). +-spec ecdsa_sign(ecdsa_digest_type(), data_or_digest(), ec_key_res()) -> binary(). + +ecdsa_sign(DataOrDigest,Key) -> + ecdsa_sign(sha, DataOrDigest, Key). +ecdsa_sign(Type, DataOrDigest, Key) -> + case ecdsa_sign_nif(Type,DataOrDigest,Key) of + error -> erlang:error(badkey, [Type,DataOrDigest,Key]); + Sign -> Sign + end. + +ecdsa_sign_nif(_Type, _DataOrDigest, _Key) -> ?nif_stub. + +%% +%% ECDSA - verify +%% +-spec ecdsa_verify(data_or_digest(), binary(), ec_key_res()) -> boolean(). +-spec ecdsa_verify(ecdsa_digest_type(), data_or_digest(), binary(), ec_key_res()) -> + boolean(). + +ecdsa_verify(Data,Signature,Key) -> + ecdsa_verify_nif(sha, Data,Signature,Key). +ecdsa_verify(Type, DataOrDigest, Signature, Key) -> + case ecdsa_verify_nif(Type, DataOrDigest, Signature, Key) of + notsup -> erlang:error(notsup); + Bool -> Bool + end. + +ecdsa_verify_nif(_Type, _DataOrDigest, _Signature, _Key) -> ?nif_stub. + +-spec ecdh_compute_key(ec_key_res(), ec_key_res() | ec_point()) -> binary(). +ecdh_compute_key(_Others, _My) -> ?nif_stub. + + %% LOCAL FUNCTIONS %% @@ -1262,7 +1365,9 @@ bin_to_int(Bin) -> erlint(<>) -> Bits= MPIntSize * 8, <> = MPIntValue, - Integer. + Integer; +erlint(undefined) -> + undefined. mpint_to_bin(<>) -> Bin. diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl index 08ecad3233..c5597be34c 100644 --- a/lib/crypto/test/crypto_SUITE.erl +++ b/lib/crypto/test/crypto_SUITE.erl @@ -76,6 +76,7 @@ rsa_encrypt_decrypt/1, dh/1, srp3/1, srp6/1, srp6a/1, + ec/1, exor_test/1, rc4_test/1, rc4_stream_test/1, @@ -105,7 +106,7 @@ groups() -> rand_uniform_test, strong_rand_test, rsa_verify_test, dsa_verify_test, rsa_sign_test, rsa_sign_hash_test, dsa_sign_test, dsa_sign_hash_test, - rsa_encrypt_decrypt, dh, srp3, srp6, srp6a, exor_test, + rsa_encrypt_decrypt, dh, srp3, srp6, srp6a, ec, exor_test, rc4_test, rc4_stream_test, mod_exp_test, blowfish_cfb64, smp]}]. @@ -1847,6 +1848,70 @@ dh(Config) when is_list(Config) -> exit(Pid, kill) end. +ec(doc) -> + ["Test ec (Ecliptic Curve) functions."]; +ec(suite) -> []; +ec(Config) when is_list(Config) -> + if_supported(ec, fun() -> ec_do() end). + +ec_do() -> + %% test for a name curve + L2 = crypto:ec_key_new(sect113r2), + crypto:ec_key_generate(L2), + + D2 = crypto:ec_key_to_term(L2), + T2 = crypto:term_to_ec_key(D2), + ?line D2 = crypto:ec_key_to_term(T2), + + %%TODO: find a published test case for a EC key + + %% test for a full specified curve and public key, + %% taken from csca-germany_013_self_signed_cer.pem + PubKey = <<16#04, 16#4a, 16#94, 16#49, 16#81, 16#77, 16#9d, 16#df, + 16#1d, 16#a5, 16#e7, 16#c5, 16#27, 16#e2, 16#7d, 16#24, + 16#71, 16#a9, 16#28, 16#eb, 16#4d, 16#7b, 16#67, 16#75, + 16#ae, 16#09, 16#0a, 16#51, 16#45, 16#19, 16#9b, 16#d4, + 16#7e, 16#a0, 16#81, 16#e5, 16#5e, 16#d4, 16#a4, 16#3f, + 16#60, 16#7c, 16#6a, 16#50, 16#ee, 16#36, 16#41, 16#8a, + 16#87, 16#ff, 16#cd, 16#a6, 16#10, 16#39, 16#ca, 16#95, + 16#76, 16#7d, 16#ae, 16#ca, 16#c3, 16#44, 16#3f, 16#e3, 16#2c>>, + <> = <<16#00, 16#a9, 16#fb, 16#57, 16#db, 16#a1, 16#ee, 16#a9, + 16#bc, 16#3e, 16#66, 16#0a, 16#90, 16#9d, 16#83, 16#8d, + 16#72, 16#6e, 16#3b, 16#f6, 16#23, 16#d5, 16#26, 16#20, + 16#28, 16#20, 16#13, 16#48, 16#1d, 16#1f, 16#6e, 16#53, 16#77>>, + <> = <<16#7d, 16#5a, 16#09, 16#75, 16#fc, 16#2c, 16#30, 16#57, + 16#ee, 16#f6, 16#75, 16#30, 16#41, 16#7a, 16#ff, 16#e7, + 16#fb, 16#80, 16#55, 16#c1, 16#26, 16#dc, 16#5c, 16#6c, + 16#e9, 16#4a, 16#4b, 16#44, 16#f3, 16#30, 16#b5, 16#d9>>, + <> = <<16#26, 16#dc, 16#5c, 16#6c, 16#e9, 16#4a, 16#4b, 16#44, + 16#f3, 16#30, 16#b5, 16#d9, 16#bb, 16#d7, 16#7c, 16#bf, + 16#95, 16#84, 16#16, 16#29, 16#5c, 16#f7, 16#e1, 16#ce, + 16#6b, 16#cc, 16#dc, 16#18, 16#ff, 16#8c, 16#07, 16#b6>>, + BasePoint = <<16#04, 16#8b, 16#d2, 16#ae, 16#b9, 16#cb, 16#7e, 16#57, + 16#cb, 16#2c, 16#4b, 16#48, 16#2f, 16#fc, 16#81, 16#b7, + 16#af, 16#b9, 16#de, 16#27, 16#e1, 16#e3, 16#bd, 16#23, + 16#c2, 16#3a, 16#44, 16#53, 16#bd, 16#9a, 16#ce, 16#32, + 16#62, 16#54, 16#7e, 16#f8, 16#35, 16#c3, 16#da, 16#c4, + 16#fd, 16#97, 16#f8, 16#46, 16#1a, 16#14, 16#61, 16#1d, + 16#c9, 16#c2, 16#77, 16#45, 16#13, 16#2d, 16#ed, 16#8e, + 16#54, 16#5c, 16#1d, 16#54, 16#c7, 16#2f, 16#04, 16#69, 16#97>>, + <> = <<16#00, 16#a9, 16#fb, 16#57, 16#db, 16#a1, 16#ee, 16#a9, + 16#bc, 16#3e, 16#66, 16#0a, 16#90, 16#9d, 16#83, 16#8d, + 16#71, 16#8c, 16#39, 16#7a, 16#a3, 16#b5, 16#61, 16#a6, + 16#f7, 16#90, 16#1e, 16#0e, 16#82, 16#97, 16#48, 16#56, 16#a7>>, + CoFactor = 1, + Curve = {{prime_field,P},{A,B,none},BasePoint, Order,CoFactor}, + CsCaKey = {Curve, undefined, PubKey}, + T3 = crypto:term_to_ec_key(CsCaKey), + ?line CsCaKey = crypto:ec_key_to_term(T3), + + Msg = <<99,234,6,64,190,237,201,99,80,248,58,40,70,45,149,218,5,246,242,63>>, + Sign = crypto:ecdsa_sign(sha, sized_binary(Msg), L2), + ?line true = crypto:ecdsa_verify(sha, sized_binary(Msg), sized_binary(Sign), L2), + ?line false = crypto:ecdsa_verify(sha, sized_binary(Msg), sized_binary(<<10,20>>), L2), + + ok. + srp3(doc) -> ["SRP-3 test vectors generated by http://srp.stanford.edu/demo/demo.html"]; srp3(suite) -> []; -- cgit v1.2.3 From 651475b0b56243e1c568e221d5401bbdcccb3a84 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Thu, 4 Apr 2013 16:31:45 +0200 Subject: crypto: Replaced all mpint's with normal binaries --- lib/crypto/c_src/crypto.c | 29 ++++++++++++++--------------- lib/crypto/src/crypto.erl | 40 ++++++++++++++++++++++++---------------- lib/crypto/test/crypto_SUITE.erl | 6 +++--- 3 files changed, 41 insertions(+), 34 deletions(-) (limited to 'lib/crypto') diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index 1e6c2f24e7..e6bbfd8c38 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -2907,9 +2907,8 @@ static ERL_NIF_TERM bn2term(ErlNifEnv* env, const BIGNUM *bn) return atom_undefined; dlen = BN_num_bytes(bn); - ptr = enif_make_new_binary(env, dlen+4, &ret); - put_int32(ptr, dlen); - BN_bn2bin(bn, ptr+4); + ptr = enif_make_new_binary(env, dlen, &ret); + BN_bn2bin(bn, ptr); return ret; } @@ -3111,7 +3110,7 @@ static ERL_NIF_TERM term_to_ec_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T EC_GROUP *group = NULL; EC_POINT *point = NULL; - if (!(argv[1] == atom_undefined || get_bn_from_mpint(env, argv[1], &priv_key)) + if (!(argv[1] == atom_undefined || get_bn_from_bin(env, argv[1], &priv_key)) || !(argv[2] == atom_undefined || enif_is_binary(env, argv[2]))) { printf("#1\n"); goto out_err; @@ -3131,8 +3130,8 @@ static ERL_NIF_TERM term_to_ec_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T else if (enif_is_tuple(env, argv[0]) && enif_get_tuple(env,argv[0],&c_arity,&curve) && c_arity == 5 - && get_bn_from_mpint(env, curve[3], &bn_order) - && (curve[4] != atom_none && get_bn_from_mpint(env, curve[4], &cofactor))) { + && get_bn_from_bin(env, curve[3], &bn_order) + && (curve[4] != atom_none && get_bn_from_bin(env, curve[4], &cofactor))) { //* {Field, Prime, Point, Order, CoFactor} = Curve */ int f_arity = -1; @@ -3144,8 +3143,8 @@ static ERL_NIF_TERM term_to_ec_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T /* {A, B, Seed} = Prime */ if (!enif_get_tuple(env,curve[1],&p_arity,&prime) - || !get_bn_from_mpint(env, prime[0], &a) - || !get_bn_from_mpint(env, prime[1], &b)) + || !get_bn_from_bin(env, prime[0], &a) + || !get_bn_from_bin(env, prime[1], &b)) goto out_err; if (!enif_get_tuple(env,curve[0],&f_arity,&field)) @@ -3154,7 +3153,7 @@ static ERL_NIF_TERM term_to_ec_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T if (f_arity == 2 && field[0] == atom_prime_field) { /* {prime_field, Prime} */ - if (!get_bn_from_mpint(env, field[1], &p)) + if (!get_bn_from_bin(env, field[1], &p)) goto out_err; if (BN_is_negative(p) || BN_is_zero(p)) @@ -3378,11 +3377,11 @@ static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM digest = data_bin.data; } else { - if (!inspect_mpint(env,argv[1],&data_bin)) { + if (!enif_inspect_binary(env,argv[1],&data_bin)) { return enif_make_badarg(env); } digest = hmacbuf; - digp->funcp(data_bin.data+4, data_bin.size-4, digest); + digp->funcp(data_bin.data, data_bin.size, digest); } enif_alloc_binary(ECDSA_size(obj->key), &ret_bin); @@ -3425,7 +3424,7 @@ static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER return atom_notsup; } - if (!inspect_mpint(env, argv[2], &sign_bin) + if (!enif_inspect_binary(env, argv[2], &sign_bin) || !enif_get_resource(env, argv[3], res_type_ec_key, (void **)&obj)) return enif_make_badarg(env); @@ -3438,16 +3437,16 @@ static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER } digest = data_bin.data; } - else if (inspect_mpint(env, argv[1], &data_bin)) { + else if (enif_inspect_binary(env, argv[1], &data_bin)) { digest = hmacbuf; - digp->funcp(data_bin.data+4, data_bin.size-4, digest); + digp->funcp(data_bin.data, data_bin.size, digest); } else { return enif_make_badarg(env); } i = ECDSA_verify(digp->NID_type, digest, digp->len, - sign_bin.data+4, sign_bin.size-4, obj->key); + sign_bin.data, sign_bin.size, obj->key); return (i==1 ? atom_true : atom_false); #else diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 7558087d99..9503d0fcaa 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -839,9 +839,17 @@ dss_verify(_Type,_Data,_Signature,_Key) -> ?nif_stub. % Key = [E,N] E=PublicExponent N=PublicModulus rsa_verify(Data,Signature,Key) -> - rsa_verify_nif(sha, Data,Signature,Key). -rsa_verify(Type, DataOrDigest, Signature, Key) -> - case rsa_verify_nif(Type, DataOrDigest, Signature, Key) of + rsa_verify(sha, Data,Signature,Key). +rsa_verify(Type, Data, Signature, Key) when is_binary(Data) -> + verify(rsa, Type, mpint_to_bin(Data), mpint_to_bin(Signature), map_mpint_to_bin(Key)); +rsa_verify(Type, Digest, Signature, Key) -> + verify(rsa, Type, Digest, mpint_to_bin(Signature), map_mpint_to_bin(Key)). + + +verify(dss, Type, Data, Signature, Key) -> + dss_verify_nif(Type, Data, Signature, map_ensure_int_as_bin(Key)); +verify(rsa, Type, DataOrDigest, Signature, Key) -> + case rsa_verify_nif(Type, DataOrDigest, Signature, map_ensure_int_as_bin(Key)) of notsup -> erlang:error(notsup); Bool -> Bool end. @@ -1178,13 +1186,13 @@ ec_key_new(_Curve) -> ?nif_stub. ec_key_generate(_Key) -> ?nif_stub. nif_prime_to_term({prime_field, Prime}) -> - {prime_field, erlint(Prime)}; + {prime_field, bin_to_int(Prime)}; nif_prime_to_term(PrimeField) -> PrimeField. nif_curve_to_term({A, B, Seed}) -> - {erlint(A), erlint(B), Seed}. + {bin_to_int(A), bin_to_int(B), Seed}. nif_curve_parameters_to_term({PrimeField, Curve, BasePoint, Order, CoFactor}) -> - {nif_prime_to_term(PrimeField), nif_curve_to_term(Curve), BasePoint, erlint(Order), erlint(CoFactor)}; + {nif_prime_to_term(PrimeField), nif_curve_to_term(Curve), BasePoint, bin_to_int(Order), bin_to_int(CoFactor)}; nif_curve_parameters_to_term(Curve) when is_atom(Curve) -> %% named curve Curve. @@ -1193,7 +1201,7 @@ nif_curve_parameters_to_term(Curve) when is_atom(Curve) -> ec_key_to_term(Key) -> case ec_key_to_term_nif(Key) of {Curve, PrivKey, PubKey} -> - {nif_curve_parameters_to_term(Curve), erlint(PrivKey), PubKey}; + {nif_curve_parameters_to_term(Curve), bin_to_int(PrivKey), PubKey}; _ -> erlang:error(conversion_failed) end. @@ -1201,13 +1209,13 @@ ec_key_to_term(Key) -> ec_key_to_term_nif(_Key) -> ?nif_stub. term_to_nif_prime({prime_field, Prime}) -> - {prime_field, mpint(Prime)}; + {prime_field, int_to_bin(Prime)}; term_to_nif_prime(PrimeField) -> PrimeField. term_to_nif_curve({A, B, Seed}) -> - {mpint(A), mpint(B), Seed}. + {int_to_bin(A), int_to_bin(B), Seed}. term_to_nif_curve_parameters({PrimeField, Curve, BasePoint, Order, CoFactor}) -> - {term_to_nif_prime(PrimeField), term_to_nif_curve(Curve), BasePoint, mpint(Order), mpint(CoFactor)}; + {term_to_nif_prime(PrimeField), term_to_nif_curve(Curve), BasePoint, int_to_bin(Order), int_to_bin(CoFactor)}; term_to_nif_curve_parameters(Curve) when is_atom(Curve) -> %% named curve Curve. @@ -1216,7 +1224,7 @@ term_to_nif_curve_parameters(Curve) when is_atom(Curve) -> term_to_ec_key({Curve, undefined, PubKey}) -> term_to_ec_key_nif(term_to_nif_curve_parameters(Curve), undefined, PubKey); term_to_ec_key({Curve, PrivKey, PubKey}) -> - term_to_ec_key_nif(term_to_nif_curve_parameters(Curve), mpint(PrivKey), PubKey). + term_to_ec_key_nif(term_to_nif_curve_parameters(Curve), int_to_bin(PrivKey), PubKey). term_to_ec_key_nif(_Curve, _PrivKey, _PubKey) -> ?nif_stub. @@ -1356,18 +1364,18 @@ int_to_bin_neg(X,Ds) -> int_to_bin_neg(X bsr 8, [(X band 255)|Ds]). -bin_to_int(Bin) -> +bin_to_int(Bin) when is_binary(Bin) -> Bits = bit_size(Bin), <> = Bin, - Integer. + Integer; +bin_to_int(undefined) -> + undefined. %% int from integer in a binary with 32bit length erlint(<>) -> Bits= MPIntSize * 8, <> = MPIntValue, - Integer; -erlint(undefined) -> - undefined. + Integer. mpint_to_bin(<>) -> Bin. diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl index c5597be34c..b8a041cf8f 100644 --- a/lib/crypto/test/crypto_SUITE.erl +++ b/lib/crypto/test/crypto_SUITE.erl @@ -1906,9 +1906,9 @@ ec_do() -> ?line CsCaKey = crypto:ec_key_to_term(T3), Msg = <<99,234,6,64,190,237,201,99,80,248,58,40,70,45,149,218,5,246,242,63>>, - Sign = crypto:ecdsa_sign(sha, sized_binary(Msg), L2), - ?line true = crypto:ecdsa_verify(sha, sized_binary(Msg), sized_binary(Sign), L2), - ?line false = crypto:ecdsa_verify(sha, sized_binary(Msg), sized_binary(<<10,20>>), L2), + Sign = crypto:ecdsa_sign(sha, Msg, L2), + ?line true = crypto:ecdsa_verify(sha, Msg, Sign, L2), + ?line false = crypto:ecdsa_verify(sha, Msg, <<10,20>>, L2), ok. -- cgit v1.2.3 From e8ef6571e929fba0081564eca45eae4ae143e50c Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 5 Apr 2013 16:10:59 +0200 Subject: crypto: Introduce generic sign() and verify() functions for rsa, dss, and new ecdsa. No mpint's accepted. --- lib/crypto/c_src/crypto.c | 72 +++++++++++++-------------- lib/crypto/src/crypto.erl | 103 +++++++++++++++++++++------------------ lib/crypto/test/crypto_SUITE.erl | 44 +++++++++++------ 3 files changed, 117 insertions(+), 102 deletions(-) (limited to 'lib/crypto') diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index e6bbfd8c38..dae48898ce 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -205,7 +205,7 @@ static ERL_NIF_TERM rand_bytes_3(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar static ERL_NIF_TERM strong_rand_mpint_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM rand_uniform_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM dss_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM dss_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM aes_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); @@ -331,7 +331,7 @@ static ErlNifFunc nif_funcs[] = { {"strong_rand_mpint_nif", 3, strong_rand_mpint_nif}, {"rand_uniform_nif", 2, rand_uniform_nif}, {"mod_exp_nif", 4, mod_exp_nif}, - {"dss_verify", 4, dss_verify}, + {"dss_verify_nif", 4, dss_verify_nif}, {"rsa_verify_nif", 4, rsa_verify_nif}, {"aes_cbc_crypt", 4, aes_cbc_crypt}, {"exor", 2, exor}, @@ -1789,13 +1789,7 @@ static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg return ret; } -static int inspect_mpint(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifBinary* bin) -{ - return enif_inspect_binary(env, term, bin) && - bin->size >= 4 && get_int32(bin->data) == bin->size-4; -} - -static ERL_NIF_TERM dss_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +static ERL_NIF_TERM dss_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (DigestType|none, Data|{digest,Digest}, Signature,Key=[P, Q, G, Y]) */ ErlNifBinary data_bin, sign_bin; BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL, *dsa_y = NULL; @@ -1818,10 +1812,10 @@ static ERL_NIF_TERM dss_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv digest = data_bin.data; } else { - if (!inspect_mpint(env, argv[1], &data_bin)) { + if (!enif_inspect_binary(env, argv[1], &data_bin)) { return enif_make_badarg(env); } - SHA1(data_bin.data+4, data_bin.size-4, hmacbuf); + SHA1(data_bin.data, data_bin.size, hmacbuf); digest = hmacbuf; } } @@ -1833,15 +1827,15 @@ static ERL_NIF_TERM dss_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv return enif_make_badarg(env); } - if (!inspect_mpint(env, argv[2], &sign_bin) + if (!enif_inspect_binary(env, argv[2], &sign_bin) || !enif_get_list_cell(env, argv[3], &head, &tail) - || !get_bn_from_mpint(env, head, &dsa_p) + || !get_bn_from_bin(env, head, &dsa_p) || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_mpint(env, head, &dsa_q) + || !get_bn_from_bin(env, head, &dsa_q) || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_mpint(env, head, &dsa_g) + || !get_bn_from_bin(env, head, &dsa_g) || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_mpint(env, head, &dsa_y) + || !get_bn_from_bin(env, head, &dsa_y) || !enif_is_empty_list(env,tail)) { if (dsa_p) BN_free(dsa_p); @@ -1858,7 +1852,7 @@ static ERL_NIF_TERM dss_verify(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv dsa->priv_key = NULL; dsa->pub_key = dsa_y; i = DSA_verify(0, digest, SHA_DIGEST_LENGTH, - sign_bin.data+4, sign_bin.size-4, dsa); + sign_bin.data, sign_bin.size, dsa); DSA_free(dsa); return(i > 0) ? atom_true : atom_false; } @@ -1984,11 +1978,11 @@ static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM rsa = RSA_new(); - if (!inspect_mpint(env, argv[2], &sign_bin) + if (!enif_inspect_binary(env, argv[2], &sign_bin) || !enif_get_list_cell(env, argv[3], &head, &tail) - || !get_bn_from_mpint(env, head, &rsa->e) + || !get_bn_from_bin(env, head, &rsa->e) || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_mpint(env, head, &rsa->n) + || !get_bn_from_bin(env, head, &rsa->n) || !enif_is_empty_list(env, tail)) { ret = enif_make_badarg(env); @@ -2004,9 +1998,9 @@ static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM } digest = data_bin.data; } - else if (inspect_mpint(env, argv[1], &data_bin)) { + else if (enif_inspect_binary(env, argv[1], &data_bin)) { digest = hmacbuf; - digp->funcp(data_bin.data+4, data_bin.size-4, digest); + digp->funcp(data_bin.data, data_bin.size, digest); } else { ret = enif_make_badarg(env); @@ -2014,7 +2008,7 @@ static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM } i = RSA_verify(digp->NID_type, digest, digp->len, - sign_bin.data+4, sign_bin.size-4, rsa); + sign_bin.data, sign_bin.size, rsa); ret = (i==1 ? atom_true : atom_false); @@ -2159,22 +2153,22 @@ static int get_rsa_private_key(ErlNifEnv* env, ERL_NIF_TERM key, RSA *rsa) ERL_NIF_TERM head, tail; if (!enif_get_list_cell(env, key, &head, &tail) - || !get_bn_from_mpint(env, head, &rsa->e) + || !get_bn_from_bin(env, head, &rsa->e) || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_mpint(env, head, &rsa->n) + || !get_bn_from_bin(env, head, &rsa->n) || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_mpint(env, head, &rsa->d) + || !get_bn_from_bin(env, head, &rsa->d) || (!enif_is_empty_list(env, tail) && (!enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_mpint(env, head, &rsa->p) + || !get_bn_from_bin(env, head, &rsa->p) || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_mpint(env, head, &rsa->q) + || !get_bn_from_bin(env, head, &rsa->q) || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_mpint(env, head, &rsa->dmp1) + || !get_bn_from_bin(env, head, &rsa->dmp1) || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_mpint(env, head, &rsa->dmq1) + || !get_bn_from_bin(env, head, &rsa->dmq1) || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_mpint(env, head, &rsa->iqmp) + || !get_bn_from_bin(env, head, &rsa->iqmp) || !enif_is_empty_list(env, tail)))) { return 0; } @@ -2211,11 +2205,11 @@ static ERL_NIF_TERM rsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar digest = data_bin.data; } else { - if (!inspect_mpint(env,argv[1],&data_bin)) { + if (!enif_inspect_binary(env,argv[1],&data_bin)) { return enif_make_badarg(env); } digest = hmacbuf; - digp->funcp(data_bin.data+4, data_bin.size-4, digest); + digp->funcp(data_bin.data, data_bin.size, digest); } rsa = RSA_new(); @@ -2270,10 +2264,10 @@ static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar digest = data_bin.data; } else { - if (!inspect_mpint(env,argv[1],&data_bin)) { + if (!enif_inspect_binary(env,argv[1],&data_bin)) { return enif_make_badarg(env); } - SHA1(data_bin.data+4, data_bin.size-4, hmacbuf); + SHA1(data_bin.data, data_bin.size, hmacbuf); digest = hmacbuf; } } @@ -2291,13 +2285,13 @@ static ERL_NIF_TERM dss_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar dsa->pub_key = NULL; if (!enif_get_list_cell(env, argv[2], &head, &tail) - || !get_bn_from_mpint(env, head, &dsa->p) + || !get_bn_from_bin(env, head, &dsa->p) || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_mpint(env, head, &dsa->q) + || !get_bn_from_bin(env, head, &dsa->q) || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_mpint(env, head, &dsa->g) + || !get_bn_from_bin(env, head, &dsa->g) || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_mpint(env, head, &dsa->priv_key) + || !get_bn_from_bin(env, head, &dsa->priv_key) || !enif_is_empty_list(env,tail)) { DSA_free(dsa); return enif_make_badarg(env); diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 9503d0fcaa..ae19755421 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -68,7 +68,7 @@ -export([aes_ctr_encrypt/3, aes_ctr_decrypt/3]). -export([aes_ctr_stream_init/2, aes_ctr_stream_encrypt/2, aes_ctr_stream_decrypt/2]). -export([ec_key_new/1, ec_key_to_term/1, term_to_ec_key/1, ec_key_generate/1]). --export([ecdsa_sign/2, ecdsa_sign/3, ecdsa_verify/3, ecdsa_verify/4, ecdh_compute_key/2]). +-export([sign/4, verify/5, ecdh_compute_key/2]). -export([dh_generate_parameters/2, dh_check/1]). %% Testing see below @@ -116,13 +116,13 @@ rc2_cbc_encrypt, rc2_cbc_decrypt, srp_generate_key, srp_compute_key, ec_key_new, ec_key_to_term, term_to_ec_key, ec_key_generate, - ecdsa_sign, ecdsa_verify, ecdh_compute_key, + sign, verify, ecdh_compute_key, info_lib, algorithms]). -type mpint() :: binary(). -type rsa_digest_type() :: 'md5' | 'sha' | 'sha224' | 'sha256' | 'sha384' | 'sha512'. -type dss_digest_type() :: 'none' | 'sha'. --type ecdsa_digest_type() :: 'md5' | 'sha' | 'sha256' | 'sha384' | 'sha512'. +%%-type ecdsa_digest_type() :: 'md5' | 'sha' | 'sha256' | 'sha384' | 'sha512'. -type data_or_digest() :: binary() | {digest, binary()}. -type crypto_integer() :: binary() | integer(). -type ec_key_res() :: any(). %% nif resource @@ -834,8 +834,12 @@ mod_exp_nif(_Base,_Exp,_Mod,_bin_hdr) -> ?nif_stub. %% Key = [P,Q,G,Y] P,Q,G=DSSParams Y=PublicKey dss_verify(Data,Signature,Key) -> - dss_verify(sha, Data, Signature, Key). -dss_verify(_Type,_Data,_Signature,_Key) -> ?nif_stub. + dss_verify(sha, Data, Signature, Key). + +dss_verify(Type,Data,Signature,Key) when is_binary(Data), Type=/=none -> + verify(dss,Type,mpint_to_bin(Data),mpint_to_bin(Signature),map_mpint_to_bin(Key)); +dss_verify(Type,Digest,Signature,Key) -> + verify(dss,Type,Digest,mpint_to_bin(Signature),map_mpint_to_bin(Key)). % Key = [E,N] E=PublicExponent N=PublicModulus rsa_verify(Data,Signature,Key) -> @@ -848,13 +852,22 @@ rsa_verify(Type, Digest, Signature, Key) -> verify(dss, Type, Data, Signature, Key) -> dss_verify_nif(Type, Data, Signature, map_ensure_int_as_bin(Key)); + verify(rsa, Type, DataOrDigest, Signature, Key) -> case rsa_verify_nif(Type, DataOrDigest, Signature, map_ensure_int_as_bin(Key)) of notsup -> erlang:error(notsup); Bool -> Bool + end; +verify(ecdsa, Type, DataOrDigest, Signature, Key) -> + case ecdsa_verify_nif(Type, DataOrDigest, Signature, map_ensure_int_as_bin(Key)) of + notsup -> erlang:error(notsup); + Bool -> Bool end. + +dss_verify_nif(_Type, _Data, _Signature, _Key) -> ?nif_stub. rsa_verify_nif(_Type, _Data, _Signature, _Key) -> ?nif_stub. +ecdsa_verify_nif(_Type, _DataOrDigest, _Signature, _Key) -> ?nif_stub. %% @@ -868,24 +881,52 @@ rsa_verify_nif(_Type, _Data, _Signature, _Key) -> ?nif_stub. dss_sign(DataOrDigest,Key) -> dss_sign(sha,DataOrDigest,Key). -dss_sign(Type, DataOrDigest, Key) -> - case dss_sign_nif(Type,DataOrDigest,Key) of - error -> erlang:error(badkey, [DataOrDigest, Key]); - Sign -> Sign - end. +dss_sign(Type, Data, Key) when is_binary(Data), Type=/=none -> + sign(dss, Type, mpint_to_bin(Data), map_mpint_to_bin(Key)); +dss_sign(Type, Digest, Key) -> + sign(dss, Type, Digest, map_mpint_to_bin(Key)). -dss_sign_nif(_Type,_Data,_Key) -> ?nif_stub. %% Key = [E,N,D] E=PublicExponent N=PublicModulus D=PrivateExponent rsa_sign(DataOrDigest,Key) -> rsa_sign(sha, DataOrDigest, Key). -rsa_sign(Type, DataOrDigest, Key) -> - case rsa_sign_nif(Type,DataOrDigest,Key) of + +rsa_sign(Type, Data, Key) when is_binary(Data) -> + sign(rsa, Type, mpint_to_bin(Data), map_mpint_to_bin(Key)); +rsa_sign(Type, Digest, Key) -> + sign(rsa, Type, Digest, map_mpint_to_bin(Key)). + +map_mpint_to_bin(List) -> + lists:map(fun(E) -> mpint_to_bin(E) end, List ). + +map_ensure_int_as_bin([H|_]=List) when is_integer(H) -> + lists:map(fun(E) -> int_to_bin(E) end, List); +map_ensure_int_as_bin(List) -> + List. + +sign(rsa, Type, DataOrDigest, Key) -> + case rsa_sign_nif(Type, DataOrDigest, map_ensure_int_as_bin(Key)) of + error -> erlang:error(badkey, [Type,DataOrDigest,Key]); + Sign -> Sign + end; +sign(dss, Type, DataOrDigest, Key) -> + case dss_sign_nif(Type, DataOrDigest, map_ensure_int_as_bin(Key)) of + error -> erlang:error(badkey, [DataOrDigest, Key]); + Sign -> Sign + end; +sign(ecdsa, Type, DataOrDigest, Key) -> + case ecdsa_sign_nif(Type, DataOrDigest, map_ensure_int_as_bin(Key)) of error -> erlang:error(badkey, [Type,DataOrDigest,Key]); Sign -> Sign end. rsa_sign_nif(_Type,_Data,_Key) -> ?nif_stub. +dss_sign_nif(_Type,_Data,_Key) -> ?nif_stub. +ecdsa_sign_nif(_Type, _DataOrDigest, _Key) -> ?nif_stub. + + + + %% @@ -914,7 +955,7 @@ rsa_public_crypt(_BinMsg, _Key, _Padding, _IsEncrypt) -> ?nif_stub. %% Binary, Key = [E,N,D] rsa_private_decrypt(BinMesg, Key, Padding) -> - case rsa_private_crypt(BinMesg, Key, Padding, false) of + case rsa_private_crypt(BinMesg, map_mpint_to_bin(Key), Padding, false) of error -> erlang:error(decrypt_failed, [BinMesg,Key, Padding]); Sign -> Sign @@ -925,7 +966,7 @@ rsa_private_crypt(_BinMsg, _Key, _Padding, _IsEncrypt) -> ?nif_stub. %% Binary, Key = [E,N,D] rsa_private_encrypt(BinMesg, Key, Padding) -> - case rsa_private_crypt(BinMesg, Key, Padding, true) of + case rsa_private_crypt(BinMesg, map_mpint_to_bin(Key), Padding, true) of error -> erlang:error(encrypt_failed, [BinMesg,Key, Padding]); Sign -> Sign @@ -1228,38 +1269,6 @@ term_to_ec_key({Curve, PrivKey, PubKey}) -> term_to_ec_key_nif(_Curve, _PrivKey, _PubKey) -> ?nif_stub. -%% -%% ECDSA - sign -%% --spec ecdsa_sign(data_or_digest(), ec_key_res()) -> binary(). --spec ecdsa_sign(ecdsa_digest_type(), data_or_digest(), ec_key_res()) -> binary(). - -ecdsa_sign(DataOrDigest,Key) -> - ecdsa_sign(sha, DataOrDigest, Key). -ecdsa_sign(Type, DataOrDigest, Key) -> - case ecdsa_sign_nif(Type,DataOrDigest,Key) of - error -> erlang:error(badkey, [Type,DataOrDigest,Key]); - Sign -> Sign - end. - -ecdsa_sign_nif(_Type, _DataOrDigest, _Key) -> ?nif_stub. - -%% -%% ECDSA - verify -%% --spec ecdsa_verify(data_or_digest(), binary(), ec_key_res()) -> boolean(). --spec ecdsa_verify(ecdsa_digest_type(), data_or_digest(), binary(), ec_key_res()) -> - boolean(). - -ecdsa_verify(Data,Signature,Key) -> - ecdsa_verify_nif(sha, Data,Signature,Key). -ecdsa_verify(Type, DataOrDigest, Signature, Key) -> - case ecdsa_verify_nif(Type, DataOrDigest, Signature, Key) of - notsup -> erlang:error(notsup); - Bool -> Bool - end. - -ecdsa_verify_nif(_Type, _DataOrDigest, _Signature, _Key) -> ?nif_stub. -spec ecdh_compute_key(ec_key_res(), ec_key_res() | ec_point()) -> binary(). ecdh_compute_key(_Others, _My) -> ?nif_stub. diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl index b8a041cf8f..6161c03240 100644 --- a/lib/crypto/test/crypto_SUITE.erl +++ b/lib/crypto/test/crypto_SUITE.erl @@ -1630,8 +1630,11 @@ dsa_verify_test(Config) when is_list(Config) -> BadArg = (catch my_dss_verify(sized_binary(Msg), <>, ValidKey)), - ?line m(element(1,element(2,BadArg)), badarg), - + badarg = case element(1,element(2,BadArg)) of + badarg -> badarg; + function_clause -> badarg; + X -> X + end, InValidKey = [crypto:mpint(P_p), crypto:mpint(Q_p), crypto:mpint(G_p), @@ -1664,20 +1667,29 @@ rsa_sign_test(Config) when is_list(Config) -> Msg = <<"7896345786348756234 Hejsan Svejsan, erlang crypto debugger" "09812312908312378623487263487623412039812 huagasd">>, - PrivKey = [crypto:mpint(PubEx), crypto:mpint(Mod), crypto:mpint(PrivEx)], - PubKey = [crypto:mpint(PubEx), crypto:mpint(Mod)], - ?line Sig1 = crypto:rsa_sign(sized_binary(Msg), PrivKey), - ?line m(crypto:rsa_verify(sized_binary(Msg), sized_binary(Sig1),PubKey), true), + PrivKey = [PubEx, Mod, PrivEx], + PubKey = [PubEx, Mod], + PubKeyMpint = map_int_to_mpint(PubKey), + Sig1 = crypto:rsa_sign(sized_binary(Msg), map_int_to_mpint(PrivKey)), + Sig1 = crypto:sign(rsa, sha, Msg, PrivKey), + true = crypto:rsa_verify(sized_binary(Msg), sized_binary(Sig1), PubKeyMpint), + true = crypto:verify(rsa, sha, Msg, Sig1, PubKey), - ?line Sig2 = crypto:rsa_sign(md5, sized_binary(Msg), PrivKey), - ?line m(crypto:rsa_verify(md5, sized_binary(Msg), sized_binary(Sig2),PubKey), true), + Sig2 = crypto:rsa_sign(md5, sized_binary(Msg), map_int_to_mpint(PrivKey)), + Sig2 = crypto:sign(rsa, md5, Msg, PrivKey), + true = crypto:rsa_verify(md5, sized_binary(Msg), sized_binary(Sig2), PubKeyMpint), + true = crypto:verify(rsa, md5, Msg, Sig2, PubKey), - ?line m(Sig1 =:= Sig2, false), - ?line m(crypto:rsa_verify(md5, sized_binary(Msg), sized_binary(Sig1),PubKey), false), - ?line m(crypto:rsa_verify(sha, sized_binary(Msg), sized_binary(Sig1),PubKey), true), - + false = (Sig1 =:= Sig2), + false = crypto:rsa_verify(md5, sized_binary(Msg), sized_binary(Sig1), PubKeyMpint), + false = crypto:verify(rsa, md5, Msg, Sig1, PubKey), + true = crypto:rsa_verify(sha, sized_binary(Msg), sized_binary(Sig1), PubKeyMpint), + true = crypto:verify(rsa, sha, Msg, Sig1, PubKey), + ok. - +map_int_to_mpint(List) -> + lists:map(fun(E) -> crypto:mpint(E) end, List). + rsa_sign_hash_test(doc) -> "rsa_sign_hash testing"; rsa_sign_hash_test(suite) -> @@ -1906,9 +1918,9 @@ ec_do() -> ?line CsCaKey = crypto:ec_key_to_term(T3), Msg = <<99,234,6,64,190,237,201,99,80,248,58,40,70,45,149,218,5,246,242,63>>, - Sign = crypto:ecdsa_sign(sha, Msg, L2), - ?line true = crypto:ecdsa_verify(sha, Msg, Sign, L2), - ?line false = crypto:ecdsa_verify(sha, Msg, <<10,20>>, L2), + Sign = crypto:sign(ecdsa, sha, Msg, L2), + ?line true = crypto:verify(ecdsa, sha, Msg, Sign, L2), + ?line false = crypto:verify(ecdsa, sha, Msg, <<10,20>>, L2), ok. -- cgit v1.2.3 From 07ba72cdef3d9b62b5be23611cfe869ec343cb87 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 9 Apr 2013 10:36:29 +0200 Subject: crypto: Allow integer keys for rsa_private/public_en/decrypt as well as mpint's for backward compatibility. --- lib/crypto/c_src/crypto.c | 4 ++-- lib/crypto/src/crypto.erl | 14 +++++++---- lib/crypto/test/crypto_SUITE.erl | 51 +++++++++++++++++++++++++++------------- 3 files changed, 47 insertions(+), 22 deletions(-) (limited to 'lib/crypto') diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index dae48898ce..a8027bb079 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -2339,9 +2339,9 @@ static ERL_NIF_TERM rsa_public_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TER if (!enif_inspect_binary(env, argv[0], &data_bin) || !enif_get_list_cell(env, argv[1], &head, &tail) - || !get_bn_from_mpint(env, head, &rsa->e) + || !get_bn_from_bin(env, head, &rsa->e) || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_mpint(env, head, &rsa->n) + || !get_bn_from_bin(env, head, &rsa->n) || !enif_is_empty_list(env,tail) || !rsa_pad(argv[2], &padding)) { diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index ae19755421..57ddf3fbac 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -904,6 +904,12 @@ map_ensure_int_as_bin([H|_]=List) when is_integer(H) -> map_ensure_int_as_bin(List) -> List. +map_to_norm_bin([H|_]=List) when is_integer(H) -> + lists:map(fun(E) -> int_to_bin(E) end, List); +map_to_norm_bin(List) -> + lists:map(fun(E) -> mpint_to_bin(E) end, List). + + sign(rsa, Type, DataOrDigest, Key) -> case rsa_sign_nif(Type, DataOrDigest, map_ensure_int_as_bin(Key)) of error -> erlang:error(badkey, [Type,DataOrDigest,Key]); @@ -945,7 +951,7 @@ ecdsa_sign_nif(_Type, _DataOrDigest, _Key) -> ?nif_stub. %% Binary, Key = [E,N] rsa_public_encrypt(BinMesg, Key, Padding) -> - case rsa_public_crypt(BinMesg, Key, Padding, true) of + case rsa_public_crypt(BinMesg, map_to_norm_bin(Key), Padding, true) of error -> erlang:error(encrypt_failed, [BinMesg,Key, Padding]); Sign -> Sign @@ -955,7 +961,7 @@ rsa_public_crypt(_BinMsg, _Key, _Padding, _IsEncrypt) -> ?nif_stub. %% Binary, Key = [E,N,D] rsa_private_decrypt(BinMesg, Key, Padding) -> - case rsa_private_crypt(BinMesg, map_mpint_to_bin(Key), Padding, false) of + case rsa_private_crypt(BinMesg, map_to_norm_bin(Key), Padding, false) of error -> erlang:error(decrypt_failed, [BinMesg,Key, Padding]); Sign -> Sign @@ -966,7 +972,7 @@ rsa_private_crypt(_BinMsg, _Key, _Padding, _IsEncrypt) -> ?nif_stub. %% Binary, Key = [E,N,D] rsa_private_encrypt(BinMesg, Key, Padding) -> - case rsa_private_crypt(BinMesg, map_mpint_to_bin(Key), Padding, true) of + case rsa_private_crypt(BinMesg, map_to_norm_bin(Key), Padding, true) of error -> erlang:error(encrypt_failed, [BinMesg,Key, Padding]); Sign -> Sign @@ -974,7 +980,7 @@ rsa_private_encrypt(BinMesg, Key, Padding) -> %% Binary, Key = [E,N] rsa_public_decrypt(BinMesg, Key, Padding) -> - case rsa_public_crypt(BinMesg, Key, Padding, false) of + case rsa_public_crypt(BinMesg, map_to_norm_bin(Key), Padding, false) of error -> erlang:error(decrypt_failed, [BinMesg,Key, Padding]); Sign -> Sign diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl index 6161c03240..09898efd49 100644 --- a/lib/crypto/test/crypto_SUITE.erl +++ b/lib/crypto/test/crypto_SUITE.erl @@ -1787,46 +1787,65 @@ rsa_encrypt_decrypt(Config) when is_list(Config) -> PrivEx = 7531712708607620783801185371644749935066152052780368689827275932079815492940396744378735701395659435842364793962992309884847527234216715366607660219930945, Mod = 7919488123861148172698919999061127847747888703039837999377650217570191053151807772962118671509138346758471459464133273114654252861270845708312601272799123, - PrivKey = [crypto:mpint(PubEx), crypto:mpint(Mod), crypto:mpint(PrivEx)], - PubKey = [crypto:mpint(PubEx), crypto:mpint(Mod)], + PrivKey = [PubEx, Mod, PrivEx], + PubKey = [PubEx, Mod], Msg = <<"7896345786348 Asldi">>, - ?line PKCS1 = crypto:rsa_public_encrypt(Msg, PubKey, rsa_pkcs1_padding), - ?line PKCS1Dec = crypto:rsa_private_decrypt(PKCS1, PrivKey, rsa_pkcs1_padding), + ?line PKCS1 = rsa_public_encrypt(Msg, PubKey, rsa_pkcs1_padding), + ?line PKCS1Dec = rsa_private_decrypt(PKCS1, PrivKey, rsa_pkcs1_padding), io:format("PKCS1Dec ~p~n",[PKCS1Dec]), ?line Msg = PKCS1Dec, - ?line OAEP = crypto:rsa_public_encrypt(Msg, PubKey, rsa_pkcs1_oaep_padding), - ?line Msg = crypto:rsa_private_decrypt(OAEP, PrivKey, rsa_pkcs1_oaep_padding), + ?line OAEP = rsa_public_encrypt(Msg, PubKey, rsa_pkcs1_oaep_padding), + ?line Msg = rsa_private_decrypt(OAEP, PrivKey, rsa_pkcs1_oaep_padding), <> = crypto:mpint(Mod), Msg2 = list_to_binary(lists:duplicate(Msg2Len-1, $X)), - ?line NoPad = crypto:rsa_public_encrypt(Msg2, PubKey, rsa_no_padding), - ?line NoPadDec = crypto:rsa_private_decrypt(NoPad, PrivKey, rsa_no_padding), + ?line NoPad = rsa_public_encrypt(Msg2, PubKey, rsa_no_padding), + ?line NoPadDec = rsa_private_decrypt(NoPad, PrivKey, rsa_no_padding), ?line NoPadDec = Msg2, - ShouldBeError = (catch crypto:rsa_public_encrypt(Msg, PubKey, rsa_no_padding)), + ShouldBeError = (catch rsa_public_encrypt(Msg, PubKey, rsa_no_padding)), ?line {'EXIT', {encrypt_failed,_}} = ShouldBeError, -%% ?line SSL = crypto:rsa_public_encrypt(Msg, PubKey, rsa_sslv23_padding), -%% ?line Msg = crypto:rsa_private_decrypt(SSL, PrivKey, rsa_sslv23_padding), +%% ?line SSL = rsa_public_encrypt(Msg, PubKey, rsa_sslv23_padding), +%% ?line Msg = rsa_private_decrypt(SSL, PrivKey, rsa_sslv23_padding), - ?line PKCS1_2 = crypto:rsa_private_encrypt(Msg, PrivKey, rsa_pkcs1_padding), - ?line PKCS1_2Dec = crypto:rsa_public_decrypt(PKCS1_2, PubKey, rsa_pkcs1_padding), + ?line PKCS1_2 = rsa_private_encrypt(Msg, PrivKey, rsa_pkcs1_padding), + ?line PKCS1_2Dec = rsa_public_decrypt(PKCS1_2, PubKey, rsa_pkcs1_padding), io:format("PKCS2Dec ~p~n",[PKCS1_2Dec]), ?line Msg = PKCS1_2Dec, - ?line PKCS1_3 = crypto:rsa_private_encrypt(Msg2, PrivKey, rsa_no_padding), - ?line PKCS1_3Dec = crypto:rsa_public_decrypt(PKCS1_3, PubKey, rsa_no_padding), + ?line PKCS1_3 = rsa_private_encrypt(Msg2, PrivKey, rsa_no_padding), + ?line PKCS1_3Dec = rsa_public_decrypt(PKCS1_3, PubKey, rsa_no_padding), io:format("PKCS2Dec ~p~n",[PKCS1_3Dec]), ?line Msg2 = PKCS1_3Dec, ?line {'EXIT', {encrypt_failed,_}} = - (catch crypto:rsa_private_encrypt(Msg, PrivKey, rsa_no_padding)), + (catch rsa_private_encrypt(Msg, PrivKey, rsa_no_padding)), ok. +rsa_public_encrypt(Msg, Key, Pad) -> + C1 = crypto:rsa_public_encrypt(Msg, Key, Pad), + C2 = crypto:rsa_public_encrypt(Msg, lists:map(fun(E) -> crypto:mpint(E) end, Key), Pad), + {C1,C2}. + +rsa_public_decrypt(Msg, Key, Pad) -> + R = crypto:rsa_public_decrypt(Msg, Key, Pad), + R = crypto:rsa_public_decrypt(Msg, lists:map(fun(E) -> crypto:mpint(E) end, Key), Pad). + +rsa_private_encrypt(Msg, Key, Pad) -> + R = crypto:rsa_private_encrypt(Msg, Key, Pad), + R = crypto:rsa_private_encrypt(Msg, lists:map(fun(E) -> crypto:mpint(E) end, Key), Pad). + +rsa_private_decrypt({C1,C2}, Key, Pad) -> + R = crypto:rsa_private_decrypt(C1, Key, Pad), + R = crypto:rsa_private_decrypt(C2, Key, Pad), + R = crypto:rsa_private_decrypt(C1, lists:map(fun(E) -> crypto:mpint(E) end, Key), Pad), + R = crypto:rsa_private_decrypt(C2, lists:map(fun(E) -> crypto:mpint(E) end, Key), Pad). + dh(doc) -> ["Test dh (Diffie-Hellman) functions."]; -- cgit v1.2.3 From 3155ca5b47149a214b101f6c0b84cdcd0400a30b Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Mon, 22 Apr 2013 21:43:44 +0200 Subject: crypto, public_key & ssl: Change API to hide resource format for EC KEY --- lib/crypto/c_src/crypto.c | 6 +++--- lib/crypto/src/crypto.erl | 27 ++++++++++++++++++++------- lib/crypto/test/crypto_SUITE.erl | 17 ++++++----------- 3 files changed, 29 insertions(+), 21 deletions(-) (limited to 'lib/crypto') diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index a8027bb079..e953eb960f 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -235,7 +235,7 @@ static ERL_NIF_TERM term_to_ec_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM ecdh_compute_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); /* helpers */ @@ -361,7 +361,7 @@ static ErlNifFunc nif_funcs[] = { {"ec_key_generate", 1, ec_key_generate}, {"ecdsa_sign_nif", 3, ecdsa_sign_nif}, {"ecdsa_verify_nif", 4, ecdsa_verify_nif}, - {"ecdh_compute_key", 2, ecdh_compute_key} + {"ecdh_compute_key_nif", 2, ecdh_compute_key_nif} }; #if defined(HAVE_EC) @@ -3452,7 +3452,7 @@ static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER (_OthersPublicKey, _MyPrivateKey) (_OthersPublicKey, _MyEC_Point) */ -static ERL_NIF_TERM ecdh_compute_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +static ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { #if defined(HAVE_EC) ERL_NIF_TERM ret; diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 57ddf3fbac..543d589d7e 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -67,8 +67,8 @@ -export([aes_cbc_ivec/1]). -export([aes_ctr_encrypt/3, aes_ctr_decrypt/3]). -export([aes_ctr_stream_init/2, aes_ctr_stream_encrypt/2, aes_ctr_stream_decrypt/2]). --export([ec_key_new/1, ec_key_to_term/1, term_to_ec_key/1, ec_key_generate/1]). --export([sign/4, verify/5, ecdh_compute_key/2]). +-export([ecdh_generate_key/1, ecdh_compute_key/2]). +-export([sign/4, verify/5]). -export([dh_generate_parameters/2, dh_check/1]). %% Testing see below @@ -115,8 +115,8 @@ hmac, hmac_init, hmac_update, hmac_final, hmac_final_n, info, rc2_cbc_encrypt, rc2_cbc_decrypt, srp_generate_key, srp_compute_key, - ec_key_new, ec_key_to_term, term_to_ec_key, ec_key_generate, - sign, verify, ecdh_compute_key, + ecdh_generate_key, ecdh_compute_key, + sign, verify, info_lib, algorithms]). -type mpint() :: binary(). @@ -859,7 +859,7 @@ verify(rsa, Type, DataOrDigest, Signature, Key) -> Bool -> Bool end; verify(ecdsa, Type, DataOrDigest, Signature, Key) -> - case ecdsa_verify_nif(Type, DataOrDigest, Signature, map_ensure_int_as_bin(Key)) of + case ecdsa_verify_nif(Type, DataOrDigest, Signature, term_to_ec_key(Key)) of notsup -> erlang:error(notsup); Bool -> Bool end. @@ -921,7 +921,7 @@ sign(dss, Type, DataOrDigest, Key) -> Sign -> Sign end; sign(ecdsa, Type, DataOrDigest, Key) -> - case ecdsa_sign_nif(Type, DataOrDigest, map_ensure_int_as_bin(Key)) of + case ecdsa_sign_nif(Type, DataOrDigest, term_to_ec_key(Key)) of error -> erlang:error(badkey, [Type,DataOrDigest,Key]); Sign -> Sign end. @@ -1229,6 +1229,16 @@ srp_compute_key(Verifier, Prime, ClientPublic, ServerPublic, ServerPrivate, Vers -spec ec_key_new(ec_named_curve()) -> ec_key_res(). ec_key_new(_Curve) -> ?nif_stub. +ecdh_generate_key(Curve) when is_atom(Curve) -> + ECKey = ec_key_new(Curve), + ec_key_generate(ECKey), + ec_key_to_term(ECKey); +ecdh_generate_key(Key) -> + ECKey = term_to_ec_key(Key), + ec_key_generate(ECKey), + ec_key_to_term(ECKey). + + -spec ec_key_generate(ec_key_res()) -> ok | error. ec_key_generate(_Key) -> ?nif_stub. @@ -1277,7 +1287,10 @@ term_to_ec_key_nif(_Curve, _PrivKey, _PubKey) -> ?nif_stub. -spec ecdh_compute_key(ec_key_res(), ec_key_res() | ec_point()) -> binary(). -ecdh_compute_key(_Others, _My) -> ?nif_stub. +ecdh_compute_key(Others, My) -> + ecdh_compute_key_nif(term_to_ec_key(Others), My). + +ecdh_compute_key_nif(_Others, _My) -> ?nif_stub. %% LOCAL FUNCTIONS diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl index 09898efd49..55db09d9dd 100644 --- a/lib/crypto/test/crypto_SUITE.erl +++ b/lib/crypto/test/crypto_SUITE.erl @@ -1887,12 +1887,7 @@ ec(Config) when is_list(Config) -> ec_do() -> %% test for a name curve - L2 = crypto:ec_key_new(sect113r2), - crypto:ec_key_generate(L2), - - D2 = crypto:ec_key_to_term(L2), - T2 = crypto:term_to_ec_key(D2), - ?line D2 = crypto:ec_key_to_term(T2), + D2 = crypto:ecdh_generate_key(sect113r2), %%TODO: find a published test case for a EC key @@ -1933,13 +1928,13 @@ ec_do() -> CoFactor = 1, Curve = {{prime_field,P},{A,B,none},BasePoint, Order,CoFactor}, CsCaKey = {Curve, undefined, PubKey}, - T3 = crypto:term_to_ec_key(CsCaKey), - ?line CsCaKey = crypto:ec_key_to_term(T3), + %%T3 = crypto:term_to_ec_key(CsCaKey), + %%?line CsCaKey = crypto:ec_key_to_term(T3), Msg = <<99,234,6,64,190,237,201,99,80,248,58,40,70,45,149,218,5,246,242,63>>, - Sign = crypto:sign(ecdsa, sha, Msg, L2), - ?line true = crypto:verify(ecdsa, sha, Msg, Sign, L2), - ?line false = crypto:verify(ecdsa, sha, Msg, <<10,20>>, L2), + Sign = crypto:sign(ecdsa, sha, Msg, D2), + ?line true = crypto:verify(ecdsa, sha, Msg, Sign, D2), + ?line false = crypto:verify(ecdsa, sha, Msg, <<10,20>>, D2), ok. -- cgit v1.2.3 From 2c1b0c61e2f6177d755e5bee9a865db646b6dca1 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 23 Apr 2013 16:51:01 +0200 Subject: crypto, public_key: Switch places of ecdh_compute_key arguments --- lib/crypto/c_src/crypto.c | 13 +++---------- lib/crypto/src/crypto.erl | 4 ++-- 2 files changed, 5 insertions(+), 12 deletions(-) (limited to 'lib/crypto') diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index e953eb960f..5781c1de78 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -3466,21 +3466,14 @@ static ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF EC_POINT *my_ecpoint; EC_KEY *other_ecdh = NULL; - if (!enif_get_resource(env, argv[0], res_type_ec_key, (void **)&other_key)) + if (!enif_get_resource(env, argv[1], res_type_ec_key, (void **)&other_key)) return enif_make_badarg(env); group = EC_GROUP_dup(EC_KEY_get0_group(other_key->key)); priv_key = EC_KEY_get0_private_key(other_key->key); - if (!term2point(env, argv[1], group, &my_ecpoint)) { - struct nif_ec_key *my_key; - - if (!enif_get_resource(env, argv[1], res_type_ec_key, (void **)&my_key)) - goto out_err; - - if ((my_ecpoint = EC_POINT_new(group)) == NULL) - goto out_err; - EC_POINT_copy(my_ecpoint, EC_KEY_get0_public_key(my_key->key)); + if (!term2point(env, argv[0], group, &my_ecpoint)) { + goto out_err; } if ((other_ecdh = EC_KEY_new()) == NULL diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 543d589d7e..6f4092ea74 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -1286,9 +1286,9 @@ term_to_ec_key({Curve, PrivKey, PubKey}) -> term_to_ec_key_nif(_Curve, _PrivKey, _PubKey) -> ?nif_stub. --spec ecdh_compute_key(ec_key_res(), ec_key_res() | ec_point()) -> binary(). +-spec ecdh_compute_key(ec_point(), ec_key_res()) -> binary(). ecdh_compute_key(Others, My) -> - ecdh_compute_key_nif(term_to_ec_key(Others), My). + ecdh_compute_key_nif(Others, term_to_ec_key(My)). ecdh_compute_key_nif(_Others, _My) -> ?nif_stub. -- cgit v1.2.3 From c47e4babacedbac46d441228b514b2e650392cf7 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Tue, 23 Apr 2013 16:54:36 +0200 Subject: crypto: Combine ec_key_new into ecdh_generate_key and remove curve from the returned tuple. --- lib/crypto/c_src/crypto.c | 439 +++++++++++++++------------------------ lib/crypto/src/crypto.erl | 29 +-- lib/crypto/test/crypto_SUITE.erl | 3 +- 3 files changed, 171 insertions(+), 300 deletions(-) (limited to 'lib/crypto') diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index 5781c1de78..99e5cb1c1f 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -229,7 +229,6 @@ static ERL_NIF_TERM bf_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar static ERL_NIF_TERM bf_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM blowfish_ofb64_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM ec_key_new(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM ec_key_to_term_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM term_to_ec_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); @@ -267,6 +266,11 @@ static void hmac_sha512(unsigned char *key, int klen, unsigned char *dbuf, int dlen, unsigned char *hmacbuf); #endif +#ifdef HAVE_EC +static EC_KEY* ec_key_new(ErlNifEnv* env, ERL_NIF_TERM curve_arg); +static int term2point(ErlNifEnv* env, ERL_NIF_TERM term, + EC_GROUP *group, EC_POINT **pptr); +#endif static int library_refc = 0; /* number of users of this dynamic library */ @@ -355,7 +359,6 @@ static ErlNifFunc nif_funcs[] = { {"bf_ecb_crypt", 3, bf_ecb_crypt}, {"blowfish_ofb64_encrypt", 3, blowfish_ofb64_encrypt}, - {"ec_key_new", 1, ec_key_new}, {"ec_key_to_term_nif", 1, ec_key_to_term_nif}, {"term_to_ec_key_nif", 3, term_to_ec_key_nif}, {"ec_key_generate", 1, ec_key_generate}, @@ -2850,249 +2853,10 @@ static int term2curve_id(ERL_NIF_TERM nid) return 0; } -static ERL_NIF_TERM curve_id2term(int nid) -{ - int i; - - for (i = 0; i < EC_CURVES_CNT; i++) - if (ec_curves[i].nid == nid) - return ec_curves[i].atom; - - return atom_undefined; -} -#endif - -static ERL_NIF_TERM ec_key_new(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +static EC_KEY* ec_key_new(ErlNifEnv* env, ERL_NIF_TERM curve_arg) { -#if defined(HAVE_EC) EC_KEY *key = NULL; int nid = 0; - - nid = term2curve_id(argv[0]); - if (nid == 0) - return enif_make_badarg(env); - key = EC_KEY_new_by_curve_name(nid); - - if (key) { - ERL_NIF_TERM term; - struct nif_ec_key *obj = enif_alloc_resource(res_type_ec_key, sizeof(struct nif_ec_key)); - if (!obj) - return atom_error; - obj->key = key; - term = enif_make_resource(env, obj); - enif_release_resource(obj); - - return term; - } else - return enif_make_badarg(env); -#else - return atom_notsup; -#endif -} - -#if defined(HAVE_EC) -static ERL_NIF_TERM bn2term(ErlNifEnv* env, const BIGNUM *bn) -{ - unsigned dlen; - unsigned char* ptr; - ERL_NIF_TERM ret; - - if (!bn) - return atom_undefined; - - dlen = BN_num_bytes(bn); - ptr = enif_make_new_binary(env, dlen, &ret); - BN_bn2bin(bn, ptr); - - return ret; -} - -static ERL_NIF_TERM point2term(ErlNifEnv* env, - const EC_GROUP *group, - const EC_POINT *point, - point_conversion_form_t form) -{ - unsigned dlen; - ErlNifBinary bin; - - dlen = EC_POINT_point2oct(group, point, form, NULL, 0, NULL); - if (dlen == 0) - return atom_undefined; - - if (!enif_alloc_binary(dlen, &bin)) - return enif_make_badarg(env); - - if (!EC_POINT_point2oct(group, point, form, bin.data, bin.size, NULL)) { - enif_release_binary(&bin); - return enif_make_badarg(env); - } - - return enif_make_binary(env, &bin); -} -#endif - -static ERL_NIF_TERM ec_key_to_term_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ -#if defined(HAVE_EC) - struct nif_ec_key *obj; - const EC_GROUP *group; - const EC_POINT *public_key; - BIGNUM *order=NULL; - const BIGNUM *priv_key = NULL; - ERL_NIF_TERM pub_key = atom_undefined; - ERL_NIF_TERM group_term = atom_undefined; - - if (!enif_get_resource(env, argv[0], res_type_ec_key, (void **)&obj)) - return enif_make_badarg(env); - - group = EC_KEY_get0_group(obj->key); - public_key = EC_KEY_get0_public_key(obj->key); - priv_key = EC_KEY_get0_private_key(obj->key); - - if (group) { - if (EC_GROUP_get_curve_name(group) != 0) { - /* named group */ - group_term = curve_id2term(EC_GROUP_get_curve_name(group)); - } else { - /* export group paramters */ - ERL_NIF_TERM field_term = atom_undefined; - ERL_NIF_TERM prime_term = atom_undefined; - ERL_NIF_TERM seed_term = atom_none; - ERL_NIF_TERM point_term = atom_none; - ERL_NIF_TERM order_term = atom_none; - ERL_NIF_TERM cofactor_term = atom_none; - - int nid = 0; - const EC_POINT *point = NULL; - BIGNUM *tmp = BN_new(); - BIGNUM *tmp_1 = BN_new(); - BIGNUM *tmp_2 = BN_new(); - - nid = EC_METHOD_get_field_type(EC_GROUP_method_of(group)); - if (nid == NID_X9_62_prime_field) { - /* the parameters are specified by the prime number p */ - EC_GROUP_get_curve_GFp(group, tmp, tmp_1, tmp_2, NULL); - - /* {prime_field, Prime} */ - field_term = enif_make_tuple2(env, atom_prime_field, bn2term(env, tmp)); - } else { /* nid == NID_X9_62_characteristic_two_field */ - int field_type; - ERL_NIF_TERM basis_term; - ERL_NIF_TERM m_term; - - EC_GROUP_get_curve_GF2m(group, NULL, tmp_1, tmp_2, NULL); - - m_term = enif_make_long(env, (long)EC_GROUP_get_degree(group)); - - field_type = EC_GROUP_get_basis_type(group); - if (field_type == 0) { - basis_term = atom_undefined; - } else if (field_type == NID_X9_62_tpBasis) { - unsigned int k; - ERL_NIF_TERM k_term = atom_undefined; - - if (EC_GROUP_get_trinomial_basis(group, &k)) - k_term = enif_make_uint(env, k); - - basis_term = enif_make_tuple2(env, atom_tpbasis, k_term); - } else if (field_type == NID_X9_62_ppBasis) { - unsigned int k1, k2, k3; - ERL_NIF_TERM k1_term = atom_undefined; - ERL_NIF_TERM k2_term = atom_undefined; - ERL_NIF_TERM k3_term = atom_undefined; - - if (EC_GROUP_get_pentanomial_basis(group, &k1, &k2, &k3)) { - /* set k? values */ - k1_term = enif_make_uint(env, k1); - k2_term = enif_make_uint(env, k2); - k3_term = enif_make_uint(env, k3); - } - basis_term = enif_make_tuple4(env, atom_ppbasis, k1_term, k2_term, k3_term); - } else { /* field_type == NID_X9_62_onBasis */ - basis_term = atom_onbasis; - } - /* {characteristic_two_field, M, Basis} */ - field_term = enif_make_tuple3(env, atom_characteristic_two_field, m_term, basis_term); - } - - if (EC_GROUP_get0_seed(group)) { - unsigned char* ptr; - - ptr = enif_make_new_binary(env, EC_GROUP_get_seed_len(group), &seed_term); - memcpy(ptr, EC_GROUP_get0_seed(group), EC_GROUP_get_seed_len(group)); - } - - - /* set the base point */ - point = EC_GROUP_get0_generator(group); - if (point) - point_term = point2term(env, group, point, EC_GROUP_get_point_conversion_form(group)); - - /* set the order */ - if (EC_GROUP_get_order(group, tmp, NULL)) - order_term = bn2term(env, tmp); - - /* set the cofactor (optional) */ - if (EC_GROUP_get_cofactor(group, tmp, NULL)) - cofactor_term = bn2term(env, tmp); - - prime_term = enif_make_tuple3(env, bn2term(env, tmp_1), bn2term(env, tmp_2), seed_term); - group_term = enif_make_tuple5(env, field_term, prime_term, point_term, order_term, cofactor_term); - BN_free(tmp); - BN_free(tmp_1); - BN_free(tmp_2); - } - - if (public_key) - pub_key = point2term(env, group, public_key, EC_KEY_get_conv_form(obj->key)); - - if (order) BN_free(order); - } - - return enif_make_tuple3(env, group_term, bn2term(env, priv_key), pub_key); -#else - return atom_notsup; -#endif -} - -#if defined(HAVE_EC) -static int term2point(ErlNifEnv* env, ERL_NIF_TERM term, - EC_GROUP *group, EC_POINT **pptr) -{ - int ret = 0; - ErlNifBinary bin; - EC_POINT *point; - - if (!enif_inspect_binary(env,term,&bin)) { - return 0; - } - - if ((*pptr = point = EC_POINT_new(group)) == NULL) { - return 0; - } - - /* set the point conversion form */ - EC_GROUP_set_point_conversion_form(group, (point_conversion_form_t)(bin.data[0] & ~0x01)); - - /* extract the ec point */ - if (!EC_POINT_oct2point(group, point, bin.data, bin.size, NULL)) { - EC_POINT_free(point); - *pptr = NULL; - } else - ret = 1; - - return ret; -} -#endif - -static ERL_NIF_TERM term_to_ec_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ -#if defined(HAVE_EC) - ERL_NIF_TERM ret; - EC_KEY *key = NULL; - BIGNUM *priv_key = NULL; - EC_POINT *pub_key = NULL; - struct nif_ec_key *obj; int c_arity = -1; const ERL_NIF_TERM* curve; ErlNifBinary seed; @@ -3104,28 +2868,17 @@ static ERL_NIF_TERM term_to_ec_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T EC_GROUP *group = NULL; EC_POINT *point = NULL; - if (!(argv[1] == atom_undefined || get_bn_from_bin(env, argv[1], &priv_key)) - || !(argv[2] == atom_undefined || enif_is_binary(env, argv[2]))) { - printf("#1\n"); - goto out_err; - } - - if (enif_is_atom(env, argv[0])) { - int nid; - - nid = term2curve_id(argv[0]); - if (nid == 0) { - printf("#2\n"); - goto out_err; - } - + if (enif_is_atom(env, curve_arg)) { + nid = term2curve_id(curve_arg); + if (nid == 0) + return NULL; key = EC_KEY_new_by_curve_name(nid); } - else if (enif_is_tuple(env, argv[0]) - && enif_get_tuple(env,argv[0],&c_arity,&curve) - && c_arity == 5 - && get_bn_from_bin(env, curve[3], &bn_order) - && (curve[4] != atom_none && get_bn_from_bin(env, curve[4], &cofactor))) { + else if (enif_is_tuple(env, curve_arg) + && enif_get_tuple(env,curve_arg,&c_arity,&curve) + && c_arity == 5 + && get_bn_from_bin(env, curve[3], &bn_order) + && (curve[4] != atom_none && get_bn_from_bin(env, curve[4], &cofactor))) { //* {Field, Prime, Point, Order, CoFactor} = Curve */ int f_arity = -1; @@ -3244,10 +2997,146 @@ static ERL_NIF_TERM term_to_ec_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T EC_KEY_set_group(key, group); } else { - printf("#3\n"); + printf("#3\n"); + goto out_err; + } + + + goto out; + +out_err: + if (key) EC_KEY_free(key); + key = NULL; + +out: + /* some OpenSSL structures are mem-dup'ed into the key, + so we have to free our copies here */ + if (p) BN_free(p); + if (a) BN_free(a); + if (b) BN_free(b); + if (bn_order) BN_free(bn_order); + if (cofactor) BN_free(cofactor); + if (group) EC_GROUP_free(group); + + return key; +} + + +static ERL_NIF_TERM bn2term(ErlNifEnv* env, const BIGNUM *bn) +{ + unsigned dlen; + unsigned char* ptr; + ERL_NIF_TERM ret; + + if (!bn) + return atom_undefined; + + dlen = BN_num_bytes(bn); + ptr = enif_make_new_binary(env, dlen, &ret); + BN_bn2bin(bn, ptr); + + return ret; +} + +static ERL_NIF_TERM point2term(ErlNifEnv* env, + const EC_GROUP *group, + const EC_POINT *point, + point_conversion_form_t form) +{ + unsigned dlen; + ErlNifBinary bin; + + dlen = EC_POINT_point2oct(group, point, form, NULL, 0, NULL); + if (dlen == 0) + return atom_undefined; + + if (!enif_alloc_binary(dlen, &bin)) + return enif_make_badarg(env); + + if (!EC_POINT_point2oct(group, point, form, bin.data, bin.size, NULL)) { + enif_release_binary(&bin); + return enif_make_badarg(env); + } + + return enif_make_binary(env, &bin); +} +#endif + +static ERL_NIF_TERM ec_key_to_term_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ +#if defined(HAVE_EC) + struct nif_ec_key *obj; + const EC_GROUP *group; + const EC_POINT *public_key; + const BIGNUM *priv_key = NULL; + ERL_NIF_TERM pub_key = atom_undefined; + + if (!enif_get_resource(env, argv[0], res_type_ec_key, (void **)&obj)) + return enif_make_badarg(env); + + group = EC_KEY_get0_group(obj->key); + public_key = EC_KEY_get0_public_key(obj->key); + priv_key = EC_KEY_get0_private_key(obj->key); + + if (group) { + if (public_key) + pub_key = point2term(env, group, public_key, EC_KEY_get_conv_form(obj->key)); + } + + return enif_make_tuple2(env, bn2term(env, priv_key), pub_key); +#else + return atom_notsup; +#endif +} + +#if defined(HAVE_EC) +static int term2point(ErlNifEnv* env, ERL_NIF_TERM term, + EC_GROUP *group, EC_POINT **pptr) +{ + int ret = 0; + ErlNifBinary bin; + EC_POINT *point; + + if (!enif_inspect_binary(env,term,&bin)) { + return 0; + } + + if ((*pptr = point = EC_POINT_new(group)) == NULL) { + return 0; + } + + /* set the point conversion form */ + EC_GROUP_set_point_conversion_form(group, (point_conversion_form_t)(bin.data[0] & ~0x01)); + + /* extract the ec point */ + if (!EC_POINT_oct2point(group, point, bin.data, bin.size, NULL)) { + EC_POINT_free(point); + *pptr = NULL; + } else + ret = 1; + + return ret; +} +#endif + +static ERL_NIF_TERM term_to_ec_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +{ +#if defined(HAVE_EC) + ERL_NIF_TERM ret; + EC_KEY *key = NULL; + BIGNUM *priv_key = NULL; + EC_POINT *pub_key = NULL; + struct nif_ec_key *obj; + EC_GROUP *group = NULL; + + if (!(argv[1] == atom_undefined || get_bn_from_bin(env, argv[1], &priv_key)) + || !(argv[2] == atom_undefined || enif_is_binary(env, argv[2]))) { + printf("#1\n"); goto out_err; } + key = ec_key_new(env, argv[0]); + if (!key) { printf("#4\n"); goto out_err; @@ -3300,11 +3189,6 @@ out: so we have to free our copies here */ if (priv_key) BN_clear_free(priv_key); if (pub_key) EC_POINT_free(pub_key); - if (p) BN_free(p); - if (a) BN_free(a); - if (b) BN_free(b); - if (bn_order) BN_free(bn_order); - if (cofactor) BN_free(cofactor); if (group) EC_GROUP_free(group); return ret; #else @@ -3315,15 +3199,20 @@ out: static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) { #if defined(HAVE_EC) - struct nif_ec_key *obj; + EC_KEY *key = ec_key_new(env, argv[0]); - if (!enif_get_resource(env, argv[0], res_type_ec_key, (void **)&obj)) - return enif_make_badarg(env); - - if (EC_KEY_generate_key(obj->key)) - return atom_ok; + if (key && EC_KEY_generate_key(key)) { + ERL_NIF_TERM term; + struct nif_ec_key *obj = enif_alloc_resource(res_type_ec_key, sizeof(struct nif_ec_key)); + if (!obj) + return atom_error; + obj->key = key; + term = enif_make_resource(env, obj); + enif_release_resource(obj); + return term; + } else - return atom_error; + return enif_make_badarg(env); #else return atom_notsup; #endif diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 6f4092ea74..999a65042d 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -1226,39 +1226,20 @@ srp_compute_key(Verifier, Prime, ClientPublic, ServerPublic, ServerPrivate, Vers %% %% EC %% --spec ec_key_new(ec_named_curve()) -> ec_key_res(). -ec_key_new(_Curve) -> ?nif_stub. -ecdh_generate_key(Curve) when is_atom(Curve) -> - ECKey = ec_key_new(Curve), - ec_key_generate(ECKey), - ec_key_to_term(ECKey); -ecdh_generate_key(Key) -> - ECKey = term_to_ec_key(Key), - ec_key_generate(ECKey), - ec_key_to_term(ECKey). +-spec ecdh_generate_key(ec_curve()) -> ec_key() | error. +ecdh_generate_key(Curve) -> + ec_key_to_term(ec_key_generate(Curve)). --spec ec_key_generate(ec_key_res()) -> ok | error. ec_key_generate(_Key) -> ?nif_stub. -nif_prime_to_term({prime_field, Prime}) -> - {prime_field, bin_to_int(Prime)}; -nif_prime_to_term(PrimeField) -> - PrimeField. -nif_curve_to_term({A, B, Seed}) -> - {bin_to_int(A), bin_to_int(B), Seed}. -nif_curve_parameters_to_term({PrimeField, Curve, BasePoint, Order, CoFactor}) -> - {nif_prime_to_term(PrimeField), nif_curve_to_term(Curve), BasePoint, bin_to_int(Order), bin_to_int(CoFactor)}; -nif_curve_parameters_to_term(Curve) when is_atom(Curve) -> - %% named curve - Curve. -spec ec_key_to_term(ec_key_res()) -> ec_key(). ec_key_to_term(Key) -> case ec_key_to_term_nif(Key) of - {Curve, PrivKey, PubKey} -> - {nif_curve_parameters_to_term(Curve), bin_to_int(PrivKey), PubKey}; + {PrivKey, PubKey} -> + {bin_to_int(PrivKey), PubKey}; _ -> erlang:error(conversion_failed) end. diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl index 55db09d9dd..384d15c68c 100644 --- a/lib/crypto/test/crypto_SUITE.erl +++ b/lib/crypto/test/crypto_SUITE.erl @@ -1887,7 +1887,8 @@ ec(Config) when is_list(Config) -> ec_do() -> %% test for a name curve - D2 = crypto:ecdh_generate_key(sect113r2), + {D2_priv, D2_pub} = crypto:ecdh_generate_key(sect113r2), + D2 = {sect113r2, D2_priv, D2_pub}, %%TODO: find a published test case for a EC key -- cgit v1.2.3 From e05c31eaa6b4f09ac220bf88d78376d7ef8722d7 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Mon, 6 May 2013 15:49:15 +0200 Subject: crypto: Fix ec_key resource to be upgradeable --- lib/crypto/c_src/crypto.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/crypto') diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index 99e5cb1c1f..08c6d4dbc5 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -621,7 +621,8 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info) res_type_ec_key = enif_open_resource_type(env,NULL,"crypto.EC_KEY", ec_key_dtor, - ERL_NIF_RT_CREATE, NULL); + ERL_NIF_RT_CREATE|ERL_NIF_RT_TAKEOVER, + NULL); #endif init_digest_types(env); -- cgit v1.2.3 From a37196319f7e62a47b43a0dc939505eede616299 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Wed, 24 Apr 2013 15:20:05 +0200 Subject: crypto: Change ecdh_compute_key to have 3 arguments --- lib/crypto/src/crypto.erl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/crypto') diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 999a65042d..894253f84d 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -67,7 +67,7 @@ -export([aes_cbc_ivec/1]). -export([aes_ctr_encrypt/3, aes_ctr_decrypt/3]). -export([aes_ctr_stream_init/2, aes_ctr_stream_encrypt/2, aes_ctr_stream_decrypt/2]). --export([ecdh_generate_key/1, ecdh_compute_key/2]). +-export([ecdh_generate_key/1, ecdh_compute_key/3]). -export([sign/4, verify/5]). -export([dh_generate_parameters/2, dh_check/1]). %% Testing see below @@ -1267,9 +1267,9 @@ term_to_ec_key({Curve, PrivKey, PubKey}) -> term_to_ec_key_nif(_Curve, _PrivKey, _PubKey) -> ?nif_stub. --spec ecdh_compute_key(ec_point(), ec_key_res()) -> binary(). -ecdh_compute_key(Others, My) -> - ecdh_compute_key_nif(Others, term_to_ec_key(My)). +-spec ecdh_compute_key(ec_point(), binary(), ec_curve()) -> binary(). +ecdh_compute_key(Others, My, Curve) -> + ecdh_compute_key_nif(Others, term_to_ec_key({Curve,My,undefined})). ecdh_compute_key_nif(_Others, _My) -> ?nif_stub. -- cgit v1.2.3 From 7bbfc0d715d2023cc27a7819c108d47ab812b89e Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Wed, 24 Apr 2013 18:00:56 +0200 Subject: crypto: Add generic functions generate_key and compute_key and remove corresponding specific functions for srp and ecdh but leave dh_ functions for backward compatibility. --- lib/crypto/c_src/crypto.c | 70 +++++++------- lib/crypto/src/crypto.erl | 197 +++++++++++++++++---------------------- lib/crypto/test/crypto_SUITE.erl | 53 ++++++----- 3 files changed, 150 insertions(+), 170 deletions(-) (limited to 'lib/crypto') diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index 08c6d4dbc5..c5d181ea25 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -222,8 +222,8 @@ static ERL_NIF_TERM dh_check(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] static ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM srp_value_B_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM srp_client_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); -static ERL_NIF_TERM srp_server_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM srp_user_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); +static ERL_NIF_TERM srp_host_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM bf_cfb64_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM bf_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); static ERL_NIF_TERM bf_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); @@ -349,11 +349,11 @@ static ErlNifFunc nif_funcs[] = { {"rsa_private_crypt", 4, rsa_private_crypt}, {"dh_generate_parameters_nif", 2, dh_generate_parameters_nif}, {"dh_check", 1, dh_check}, - {"dh_generate_key_nif", 2, dh_generate_key_nif}, + {"dh_generate_key_nif", 3, dh_generate_key_nif}, {"dh_compute_key_nif", 3, dh_compute_key_nif}, {"srp_value_B_nif", 5, srp_value_B_nif}, - {"srp_client_secret_nif", 7, srp_client_secret_nif}, - {"srp_server_secret_nif", 5, srp_server_secret_nif}, + {"srp_user_secret_nif", 7, srp_user_secret_nif}, + {"srp_host_secret_nif", 5, srp_host_secret_nif}, {"bf_cfb64_crypt", 4, bf_cfb64_crypt}, {"bf_cbc_crypt", 4, bf_cbc_crypt}, {"bf_ecb_crypt", 3, bf_ecb_crypt}, @@ -2442,14 +2442,12 @@ static ERL_NIF_TERM dh_generate_parameters_nif(ErlNifEnv* env, int argc, const E } p_len = BN_num_bytes(dh_params->p); g_len = BN_num_bytes(dh_params->g); - p_ptr = enif_make_new_binary(env, p_len+4, &ret_p); - g_ptr = enif_make_new_binary(env, g_len+4, &ret_g); - put_int32(p_ptr, p_len); - put_int32(g_ptr, g_len); - BN_bn2bin(dh_params->p, p_ptr+4); - BN_bn2bin(dh_params->g, g_ptr+4); - ERL_VALGRIND_MAKE_MEM_DEFINED(p_ptr+4, p_len); - ERL_VALGRIND_MAKE_MEM_DEFINED(g_ptr+4, g_len); + p_ptr = enif_make_new_binary(env, p_len, &ret_p); + g_ptr = enif_make_new_binary(env, g_len, &ret_g); + BN_bn2bin(dh_params->p, p_ptr); + BN_bn2bin(dh_params->g, g_ptr); + ERL_VALGRIND_MAKE_MEM_DEFINED(p_ptr, p_len); + ERL_VALGRIND_MAKE_MEM_DEFINED(g_ptr, g_len); DH_free(dh_params); return enif_make_list2(env, ret_p, ret_g); } @@ -2461,9 +2459,9 @@ static ERL_NIF_TERM dh_check(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] ERL_NIF_TERM ret, head, tail; if (!enif_get_list_cell(env, argv[0], &head, &tail) - || !get_bn_from_mpint(env, head, &dh_params->p) + || !get_bn_from_bin(env, head, &dh_params->p) || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_mpint(env, head, &dh_params->g) + || !get_bn_from_bin(env, head, &dh_params->g) || !enif_is_empty_list(env,tail)) { DH_free(dh_params); @@ -2485,19 +2483,21 @@ static ERL_NIF_TERM dh_check(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[] } static ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{/* (PrivKey, DHParams=[P,G]) */ +{/* (PrivKey, DHParams=[P,G], Mpint) */ DH* dh_params = DH_new(); int pub_len, prv_len; unsigned char *pub_ptr, *prv_ptr; ERL_NIF_TERM ret, ret_pub, ret_prv, head, tail; + int mpint; /* 0 or 4 */ - if (!(get_bn_from_mpint(env, argv[0], &dh_params->priv_key) + if (!(get_bn_from_bin(env, argv[0], &dh_params->priv_key) || argv[0] == atom_undefined) || !enif_get_list_cell(env, argv[1], &head, &tail) - || !get_bn_from_mpint(env, head, &dh_params->p) + || !get_bn_from_bin(env, head, &dh_params->p) || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_mpint(env, head, &dh_params->g) - || !enif_is_empty_list(env, tail)) { + || !get_bn_from_bin(env, head, &dh_params->g) + || !enif_is_empty_list(env, tail) + || !enif_get_int(env, argv[2], &mpint) || (mpint & ~4)) { DH_free(dh_params); return enif_make_badarg(env); } @@ -2505,14 +2505,16 @@ static ERL_NIF_TERM dh_generate_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_ if (DH_generate_key(dh_params)) { pub_len = BN_num_bytes(dh_params->pub_key); prv_len = BN_num_bytes(dh_params->priv_key); - pub_ptr = enif_make_new_binary(env, pub_len+4, &ret_pub); - prv_ptr = enif_make_new_binary(env, prv_len+4, &ret_prv); - put_int32(pub_ptr, pub_len); - put_int32(prv_ptr, prv_len); - BN_bn2bin(dh_params->pub_key, pub_ptr+4); - BN_bn2bin(dh_params->priv_key, prv_ptr+4); - ERL_VALGRIND_MAKE_MEM_DEFINED(pub_ptr+4, pub_len); - ERL_VALGRIND_MAKE_MEM_DEFINED(prv_ptr+4, prv_len); + pub_ptr = enif_make_new_binary(env, pub_len+mpint, &ret_pub); + prv_ptr = enif_make_new_binary(env, prv_len+mpint, &ret_prv); + if (mpint) { + put_int32(pub_ptr, pub_len); pub_ptr += 4; + put_int32(prv_ptr, prv_len); prv_ptr += 4; + } + BN_bn2bin(dh_params->pub_key, pub_ptr); + BN_bn2bin(dh_params->priv_key, prv_ptr); + ERL_VALGRIND_MAKE_MEM_DEFINED(pub_ptr, pub_len); + ERL_VALGRIND_MAKE_MEM_DEFINED(prv_ptr, prv_len); ret = enif_make_tuple2(env, ret_pub, ret_prv); } else { @@ -2530,12 +2532,12 @@ static ERL_NIF_TERM dh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T ErlNifBinary ret_bin; ERL_NIF_TERM ret, head, tail; - if (!get_bn_from_mpint(env, argv[0], &pubkey) - || !get_bn_from_mpint(env, argv[1], &dh_params->priv_key) + if (!get_bn_from_bin(env, argv[0], &pubkey) + || !get_bn_from_bin(env, argv[1], &dh_params->priv_key) || !enif_get_list_cell(env, argv[2], &head, &tail) - || !get_bn_from_mpint(env, head, &dh_params->p) + || !get_bn_from_bin(env, head, &dh_params->p) || !enif_get_list_cell(env, tail, &head, &tail) - || !get_bn_from_mpint(env, head, &dh_params->g) + || !get_bn_from_bin(env, head, &dh_params->g) || !enif_is_empty_list(env, tail)) { ret = enif_make_badarg(env); @@ -2613,7 +2615,7 @@ static ERL_NIF_TERM srp_value_B_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM return ret; } -static ERL_NIF_TERM srp_client_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +static ERL_NIF_TERM srp_user_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (a, u, B, Multiplier, Prime, Exponent, Generator) */ /* = (B - (k * g^x)) ^ (a + (u * x)) % N @@ -2693,7 +2695,7 @@ static ERL_NIF_TERM srp_client_secret_nif(ErlNifEnv* env, int argc, const ERL_NI return ret; } -static ERL_NIF_TERM srp_server_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) +static ERL_NIF_TERM srp_host_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Verifier, b, u, A, Prime) */ /* = (A * v^u) ^ b % N diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 894253f84d..76e4ac620c 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -58,8 +58,6 @@ -export([rand_bytes/1, rand_bytes/3, rand_uniform/2]). -export([strong_rand_bytes/1, strong_rand_mpint/3]). -export([mod_exp/3, mod_exp_prime/3, mpint/1, erlint/1]). --export([srp_generate_key/4, srp_generate_key/3, - srp_generate_key/5, srp_compute_key/6, srp_compute_key/7, srp_compute_key/8]). %% -export([idea_cbc_encrypt/3, idea_cbc_decrypt/3]). -export([aes_cbc_128_encrypt/3, aes_cbc_128_decrypt/3]). @@ -67,8 +65,9 @@ -export([aes_cbc_ivec/1]). -export([aes_ctr_encrypt/3, aes_ctr_decrypt/3]). -export([aes_ctr_stream_init/2, aes_ctr_stream_encrypt/2, aes_ctr_stream_decrypt/2]). --export([ecdh_generate_key/1, ecdh_compute_key/3]). -export([sign/4, verify/5]). +-export([generate_key/2, generate_key/3, compute_key/4]). + -export([dh_generate_parameters/2, dh_check/1]). %% Testing see below @@ -114,9 +113,7 @@ hash, hash_init, hash_update, hash_final, hmac, hmac_init, hmac_update, hmac_final, hmac_final_n, info, rc2_cbc_encrypt, rc2_cbc_decrypt, - srp_generate_key, srp_compute_key, - ecdh_generate_key, ecdh_compute_key, - sign, verify, + sign, verify, generate_key, compute_key, info_lib, algorithms]). -type mpint() :: binary(). @@ -1122,118 +1119,98 @@ dh_check([_Prime,_Gen]) -> ?nif_stub. {binary(),binary()}. dh_generate_key(DHParameters) -> - dh_generate_key(undefined, DHParameters). + dh_generate_key_nif(undefined, map_mpint_to_bin(DHParameters), 4). dh_generate_key(PrivateKey, DHParameters) -> - case dh_generate_key_nif(PrivateKey, DHParameters) of - error -> erlang:error(generation_failed, [PrivateKey,DHParameters]); - Res -> Res - end. + dh_generate_key_nif(mpint_to_bin(PrivateKey), map_mpint_to_bin(DHParameters), 4). -dh_generate_key_nif(_PrivateKey, _DHParameters) -> ?nif_stub. +dh_generate_key_nif(_PrivateKey, _DHParameters, _Mpint) -> ?nif_stub. %% DHParameters = [P (Prime)= mpint(), G(Generator) = mpint()] -%% MyPrivKey, OthersPublicKey = mpint() +%% MyPrivKey, OthersPublicKey = mpint() -spec dh_compute_key(binary(), binary(), [binary()]) -> binary(). dh_compute_key(OthersPublicKey, MyPrivateKey, DHParameters) -> - case dh_compute_key_nif(OthersPublicKey,MyPrivateKey,DHParameters) of - error -> erlang:error(computation_failed, [OthersPublicKey,MyPrivateKey,DHParameters]); - Ret -> Ret - end. + compute_key(dh, mpint_to_bin(OthersPublicKey), mpint_to_bin(MyPrivateKey), + map_mpint_to_bin(DHParameters)). + dh_compute_key_nif(_OthersPublicKey, _MyPrivateKey, _DHParameters) -> ?nif_stub. +generate_key(Type, Params) -> + generate_key(Type, Params, undefined). + +generate_key(dh, DHParameters, PrivateKey) -> + dh_generate_key_nif(PrivateKey, DHParameters, 0); + +generate_key(srp, {host, [Verifier, Generator, Prime, Version]}, PrivArg) + when is_binary(Verifier), is_binary(Generator), is_binary(Prime), is_atom(Version) -> + Private = case PrivArg of + undefined -> random_bytes(32); + _ -> PrivArg + end, + host_srp_gen_key(Private, Verifier, Generator, Prime, Version); + +generate_key(srp, {user, [Generator, Prime, Version]}, PrivateArg) + when is_binary(Generator), is_binary(Prime), is_atom(Version) -> + Private = case PrivateArg of + undefined -> random_bytes(32); + _ -> PrivateArg + end, + user_srp_gen_key(Private, Generator, Prime); + +generate_key(ecdh, Curve, undefined) -> + ec_key_to_term(ec_key_generate(Curve)). + + +ec_key_generate(_Key) -> ?nif_stub. + + +compute_key(dh, OthersPublicKey, MyPrivateKey, DHParameters) -> + case dh_compute_key_nif(OthersPublicKey,MyPrivateKey,DHParameters) of + error -> erlang:error(computation_failed, + [OthersPublicKey,MyPrivateKey,DHParameters]); + Ret -> Ret + end; -%%% SRP --spec srp_generate_key(binary(), binary(), atom() | binary(), atom() | binary() ) -> {Public::binary(), Private::binary()}. -srp_generate_key(Verifier, Generator, Prime, Version) when is_binary(Verifier), - is_binary(Generator), - is_binary(Prime), - is_atom(Version) -> - Private = random_bytes(32), - server_srp_gen_key(Private, Verifier, Generator, Prime, Version); - -srp_generate_key(Generator, Prime, Version, Private) when is_binary(Generator), - is_binary(Prime), - is_atom(Version), - is_binary(Private) -> - client_srp_gen_key(Private, Generator, Prime). - --spec srp_generate_key(binary(), binary(), binary(), atom(), binary()) -> {Public::binary(), Private::binary()}. -srp_generate_key(Verifier, Generator, Prime, Version, Private) when is_binary(Verifier), - is_binary(Generator), - is_binary(Prime), - is_atom(Version), - is_binary(Private) - -> - server_srp_gen_key(Private, Verifier, Generator, Prime, Version). - --spec srp_generate_key(binary(), binary(), atom()) -> {Public::binary(), Private::binary()}. -srp_generate_key(Generator, Prime, Version) when is_binary(Generator), - is_binary(Prime), - is_atom(Version) -> - Private = random_bytes(32), - client_srp_gen_key(Private, Generator, Prime). - --spec srp_compute_key(binary(), binary(), binary(), binary(), binary(), atom()| binary(), atom() | binary() ) -> binary(). -srp_compute_key(DerivedKey, Prime, Generator, ClientPublic, ClientPrivate, ServerPublic, Version) when - is_binary(Prime), +compute_key(srp, HostPublic, {UserPublic, UserPrivate}, + {user, [DerivedKey, Prime, Generator, Version | ScramblerArg]}) when + is_binary(Prime), is_binary(Generator), - is_binary(ClientPublic), - is_binary(ClientPrivate), - is_binary(ServerPublic), + is_binary(UserPublic), + is_binary(UserPrivate), + is_binary(HostPublic), is_atom(Version) -> Multiplier = srp_multiplier(Version, Generator, Prime), - Scrambler = srp_scrambler(Version, ClientPublic, ServerPublic, Prime), - srp_client_secret_nif(ClientPrivate, Scrambler, ServerPublic, Multiplier, - Generator, DerivedKey, Prime); - -srp_compute_key(Verifier, Prime, ClientPublic, ServerPublic, ServerPrivate, Version, Scrambler) when - is_binary(Verifier), - is_binary(Prime), - is_binary(ClientPublic), - is_binary(ServerPublic), - is_binary(ServerPrivate), - is_atom(Version), - is_binary(Scrambler) -> - srp_server_secret_nif(Verifier, ServerPrivate, Scrambler, ClientPublic, Prime). - --spec srp_compute_key(binary(), binary(), binary(), binary(), binary(), binary(), atom(), binary()) -> binary(). -srp_compute_key(DerivedKey, Prime, Generator, ClientPublic, ClientPrivate, - ServerPublic, Version, Scrambler) when is_binary(DerivedKey), - is_binary(Prime), - is_binary(Generator), - is_binary(ClientPublic), - is_binary(ClientPrivate), - is_binary(ServerPublic), - is_atom(Version), - is_binary(Scrambler) -> - Multiplier = srp_multiplier(Version, Generator, Prime), - srp_client_secret_nif(ClientPrivate, Scrambler, ServerPublic, Multiplier, - Generator, DerivedKey, Prime). - --spec srp_compute_key(binary(), binary(), binary(), binary(), binary(), atom()) -> binary(). -srp_compute_key(Verifier, Prime, ClientPublic, ServerPublic, ServerPrivate, Version) when + Scrambler = case ScramblerArg of + [] -> srp_scrambler(Version, UserPublic, HostPublic, Prime); + [S] -> S + end, + srp_user_secret_nif(UserPrivate, Scrambler, HostPublic, Multiplier, + Generator, DerivedKey, Prime); + +compute_key(srp, UserPublic, {HostPublic, HostPrivate}, + {host,[Verifier, Prime, Version | ScramblerArg]}) when is_binary(Verifier), - is_binary(Prime), - is_binary(ClientPublic), - is_binary(ServerPublic), - is_binary(ServerPrivate), + is_binary(Prime), + is_binary(UserPublic), + is_binary(HostPublic), + is_binary(HostPrivate), is_atom(Version) -> - Scrambler = srp_scrambler(Version, ClientPublic, ServerPublic, Prime), - srp_server_secret_nif(Verifier, ServerPrivate, Scrambler, ClientPublic, Prime). + Scrambler = case ScramblerArg of + [] -> srp_scrambler(Version, UserPublic, HostPublic, Prime); + [S] -> S + end, + srp_host_secret_nif(Verifier, HostPrivate, Scrambler, UserPublic, Prime); -%% -%% EC -%% - --spec ecdh_generate_key(ec_curve()) -> ec_key() | error. -ecdh_generate_key(Curve) -> - ec_key_to_term(ec_key_generate(Curve)). +compute_key(ecdh, Others, My, Curve) -> + ecdh_compute_key_nif(Others, term_to_ec_key({Curve,My,undefined})). +ecdh_compute_key_nif(_Others, _My) -> ?nif_stub. -ec_key_generate(_Key) -> ?nif_stub. +%% +%% EC +%% -spec ec_key_to_term(ec_key_res()) -> ec_key(). ec_key_to_term(Key) -> @@ -1267,17 +1244,11 @@ term_to_ec_key({Curve, PrivKey, PubKey}) -> term_to_ec_key_nif(_Curve, _PrivKey, _PubKey) -> ?nif_stub. --spec ecdh_compute_key(ec_point(), binary(), ec_curve()) -> binary(). -ecdh_compute_key(Others, My, Curve) -> - ecdh_compute_key_nif(Others, term_to_ec_key({Curve,My,undefined})). - -ecdh_compute_key_nif(_Others, _My) -> ?nif_stub. - %% LOCAL FUNCTIONS %% -client_srp_gen_key(Private, Generator, Prime) -> +user_srp_gen_key(Private, Generator, Prime) -> case mod_exp_prime(Generator, Private, Prime) of error -> error; @@ -1285,7 +1256,7 @@ client_srp_gen_key(Private, Generator, Prime) -> {Public, Private} end. -server_srp_gen_key(Private, Verifier, Generator, Prime, Version) -> +host_srp_gen_key(Private, Verifier, Generator, Prime, Version) -> Multiplier = srp_multiplier(Version, Generator, Prime), case srp_value_B_nif(Multiplier, Verifier, Generator, Private, Prime) of error -> @@ -1305,17 +1276,17 @@ srp_multiplier('6', _, _) -> srp_multiplier('3', _, _) -> <<1/integer>>. -srp_scrambler(Version, ClientPublic, ServerPublic, Prime) when Version == '6'; Version == '6a'-> +srp_scrambler(Version, UserPublic, HostPublic, Prime) when Version == '6'; Version == '6a'-> %% SHA1(PAD(A) | PAD(B)) from http://srp.stanford.edu/design.html PadLength = erlang:byte_size(Prime), C0 = sha_init(), - C1 = sha_update(C0, srp_pad_to(PadLength, ClientPublic)), - C2 = sha_update(C1, srp_pad_to(PadLength, ServerPublic)), + C1 = sha_update(C0, srp_pad_to(PadLength, UserPublic)), + C2 = sha_update(C1, srp_pad_to(PadLength, HostPublic)), sha_final(C2); -srp_scrambler('3', _, ServerPublic, _Prime) -> +srp_scrambler('3', _, HostPublic, _Prime) -> %% The parameter u is a 32-bit unsigned integer which takes its value %% from the first 32 bits of the SHA1 hash of B, MSB first. - <> = sha(ServerPublic), + <> = sha(HostPublic), U. srp_pad_length(Width, Length) -> @@ -1327,9 +1298,9 @@ srp_pad_to(Width, Binary) -> N -> << 0:(N*8), Binary/binary>> end. -srp_server_secret_nif(_Verifier, _B, _U, _A, _Prime) -> ?nif_stub. +srp_host_secret_nif(_Verifier, _B, _U, _A, _Prime) -> ?nif_stub. -srp_client_secret_nif(_A, _U, _B, _Multiplier, _Generator, _Exponent, _Prime) -> ?nif_stub. +srp_user_secret_nif(_A, _U, _B, _Multiplier, _Generator, _Exponent, _Prime) -> ?nif_stub. srp_value_B_nif(_Multiplier, _Verifier, _Generator, _Exponent, _Prime) -> ?nif_stub. diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl index 384d15c68c..473609778c 100644 --- a/lib/crypto/test/crypto_SUITE.erl +++ b/lib/crypto/test/crypto_SUITE.erl @@ -1864,13 +1864,16 @@ dh(Config) when is_list(Config) -> {param, DHPs} -> timer:sleep(100), io:format("DHP ~p~n", [DHPs]), - ?line {Pub1,Priv1} = crypto:dh_generate_key(DHPs), + DHPs_mpint = lists:map(fun(E) -> sized_binary(E) end, DHPs), + ?line {Pub1,Priv1} = crypto:generate_key(dh, DHPs), io:format("Key1:~n~p~n~p~n~n", [Pub1,Priv1]), - ?line {Pub2,Priv2} = crypto:dh_generate_key(DHPs), + ?line {Pub2,Priv2} = crypto:dh_generate_key(DHPs_mpint), io:format("Key2:~n~p~n~p~n~n", [Pub2,Priv2]), - ?line A = crypto:dh_compute_key(Pub1, Priv2, DHPs), + ?line A = crypto:compute_key(dh, Pub1, unsized_binary(Priv2), DHPs), + ?line A = crypto:dh_compute_key(sized_binary(Pub1), Priv2, DHPs_mpint), timer:sleep(100), %% Get another thread see if that triggers problem - ?line B = crypto:dh_compute_key(Pub2, Priv1, DHPs), + ?line B = crypto:compute_key(dh, unsized_binary(Pub2), Priv1, DHPs), + ?line B = crypto:dh_compute_key(Pub2, sized_binary(Priv1), DHPs_mpint), io:format("A ~p~n",[A]), io:format("B ~p~n",[B]), ?line A = B @@ -1879,6 +1882,7 @@ dh(Config) when is_list(Config) -> exit(Pid, kill) end. + ec(doc) -> ["Test ec (Ecliptic Curve) functions."]; ec(suite) -> []; @@ -1887,7 +1891,7 @@ ec(Config) when is_list(Config) -> ec_do() -> %% test for a name curve - {D2_priv, D2_pub} = crypto:ecdh_generate_key(sect113r2), + {D2_priv, D2_pub} = crypto:generate_key(ecdh, sect113r2), D2 = {sect113r2, D2_priv, D2_pub}, %%TODO: find a published test case for a EC key @@ -1985,12 +1989,12 @@ srp3(Config) when is_list(Config) -> Verifier = crypto:mod_exp_prime(Generator, UserPassHash, Prime), ClientPublic = crypto:mod_exp_prime(Generator, ClientPrivate, Prime), - {ClientPublic, ClientPrivate} = crypto:srp_generate_key(Generator, Prime, Version, ClientPrivate), - {ServerPublic, ServerPrivate} = crypto:srp_generate_key(Verifier, Generator, Prime, Version, ServerPrivate), - SessionKey = crypto:srp_compute_key(UserPassHash, Prime, Generator, ClientPublic, - ClientPrivate, ServerPublic, Version, Scrambler), - SessionKey = crypto:srp_compute_key(Verifier, Prime, ClientPublic, - ServerPublic, ServerPrivate, Version, Scrambler). + {ClientPublic, ClientPrivate} = crypto:generate_key(srp, {user, [Generator, Prime, Version]}, ClientPrivate), + {ServerPublic, ServerPrivate} = crypto:generate_key(srp, {host, [Verifier, Generator, Prime, Version]}, ServerPrivate), + SessionKey = crypto:compute_key(srp, ServerPublic, {ClientPublic, ClientPrivate}, + {user, [UserPassHash, Prime, Generator, Version, Scrambler]}), + SessionKey = crypto:compute_key(srp, ClientPublic, {ServerPublic, ServerPrivate}, + {host, [Verifier, Prime, Version, Scrambler]}). srp6(doc) -> ["SRP-6 test vectors generated by http://srp.stanford.edu/demo/demo.html"]; @@ -2036,12 +2040,12 @@ srp6(Config) when is_list(Config) -> Verifier = crypto:mod_exp_prime(Generator, UserPassHash, Prime), ClientPublic = crypto:mod_exp_prime(Generator, ClientPrivate, Prime), - {ClientPublic, ClientPrivate} = crypto:srp_generate_key(Generator, Prime, Version, ClientPrivate), - {ServerPublic, ServerPrivate} = crypto:srp_generate_key(Verifier, Generator, Prime, Version, ServerPrivate), - SessionKey = crypto:srp_compute_key(UserPassHash, Prime, Generator, ClientPublic, - ClientPrivate, ServerPublic, Version, Scrambler), - SessionKey = crypto:srp_compute_key(Verifier, Prime, ClientPublic, - ServerPublic, ServerPrivate, Version, Scrambler). + {ClientPublic, ClientPrivate} = crypto:generate_key(srp, {user, [Generator, Prime, Version]}, ClientPrivate), + {ServerPublic, ServerPrivate} = crypto:generate_key(srp, {host, [Verifier, Generator, Prime, Version]}, ServerPrivate), + SessionKey = crypto:compute_key(srp, ServerPublic, {ClientPublic, ClientPrivate}, + {user, [UserPassHash, Prime, Generator, Version, Scrambler]}), + SessionKey = crypto:compute_key(srp, ClientPublic, {ServerPublic, ServerPrivate}, + {host, [Verifier, Prime, Version, Scrambler]}). srp6a(doc) -> ["SRP-6a test vectors from RFC5054."]; @@ -2086,13 +2090,13 @@ srp6a(Config) when is_list(Config) -> UserPassHash = crypto:sha([Salt, crypto:sha([Username, <<$:>>, Password])]), Verifier = crypto:mod_exp_prime(Generator, UserPassHash, Prime), - {ClientPublic, ClientPrivate} = crypto:srp_generate_key(Generator, Prime, Version, ClientPrivate), - {ServerPublic, ServerPrivate} = crypto:srp_generate_key(Verifier, Generator, Prime, Version, ServerPrivate), + {ClientPublic, ClientPrivate} = crypto:generate_key(srp, {user, [Generator, Prime, Version]}, ClientPrivate), + {ServerPublic, ServerPrivate} = crypto:generate_key(srp, {host, [Verifier, Generator, Prime, Version]}, ServerPrivate), - SessionKey = crypto:srp_compute_key(UserPassHash, Prime, Generator, ClientPublic, - ClientPrivate, ServerPublic, Version, Scrambler), - SessionKey = crypto:srp_compute_key(Verifier, Prime, ClientPublic, - ServerPublic, ServerPrivate, Version, Scrambler). + SessionKey = crypto:compute_key(srp, ServerPublic, {ClientPublic, ClientPrivate}, + {user, [UserPassHash, Prime, Generator, Version, Scrambler]}), + SessionKey = crypto:compute_key(srp, ClientPublic, {ServerPublic, ServerPrivate}, + {host, [Verifier, Prime, Version, Scrambler]}). %% %% @@ -2287,6 +2291,9 @@ sized_binary(Binary) when is_binary(Binary) -> sized_binary(List) -> sized_binary(list_to_binary(List)). +unsized_binary(<>) -> + Binary. + xor_bytes(Bin1, Bin2) when is_binary(Bin1), is_binary(Bin2) -> L1 = binary_to_list(Bin1), L2 = binary_to_list(Bin2), -- cgit v1.2.3 From dad86c51e920d015da390ec6bef3da24924fa063 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Thu, 25 Apr 2013 11:04:36 +0200 Subject: ssl, public_key, crypto: General generate_key and compute_key functions --- lib/crypto/src/crypto.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/crypto') diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 76e4ac620c..43ea1d48fd 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -1140,7 +1140,7 @@ generate_key(Type, Params) -> generate_key(Type, Params, undefined). generate_key(dh, DHParameters, PrivateKey) -> - dh_generate_key_nif(PrivateKey, DHParameters, 0); + dh_generate_key_nif(PrivateKey, map_ensure_int_as_bin(DHParameters), 0); generate_key(srp, {host, [Verifier, Generator, Prime, Version]}, PrivArg) when is_binary(Verifier), is_binary(Generator), is_binary(Prime), is_atom(Version) -> @@ -1166,7 +1166,7 @@ ec_key_generate(_Key) -> ?nif_stub. compute_key(dh, OthersPublicKey, MyPrivateKey, DHParameters) -> - case dh_compute_key_nif(OthersPublicKey,MyPrivateKey,DHParameters) of + case dh_compute_key_nif(OthersPublicKey,MyPrivateKey, map_ensure_int_as_bin(DHParameters)) of error -> erlang:error(computation_failed, [OthersPublicKey,MyPrivateKey,DHParameters]); Ret -> Ret -- cgit v1.2.3 From badb8f14e9829ce0a797b56702997aa355cdd9ba Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Thu, 25 Apr 2013 14:51:19 +0200 Subject: ssl, crypto: Eliminate remaining mpint and EC resource key from API --- lib/crypto/src/crypto.erl | 17 +++++++++++------ lib/crypto/test/crypto_SUITE.erl | 13 +++++-------- 2 files changed, 16 insertions(+), 14 deletions(-) (limited to 'lib/crypto') diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 43ea1d48fd..f87644b3fe 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -855,8 +855,8 @@ verify(rsa, Type, DataOrDigest, Signature, Key) -> notsup -> erlang:error(notsup); Bool -> Bool end; -verify(ecdsa, Type, DataOrDigest, Signature, Key) -> - case ecdsa_verify_nif(Type, DataOrDigest, Signature, term_to_ec_key(Key)) of +verify(ecdsa, Type, DataOrDigest, Signature, [Key, Curve]) -> + case ecdsa_verify_nif(Type, DataOrDigest, Signature, term_to_ec_key({Curve, undefined, Key})) of notsup -> erlang:error(notsup); Bool -> Bool end. @@ -901,6 +901,11 @@ map_ensure_int_as_bin([H|_]=List) when is_integer(H) -> map_ensure_int_as_bin(List) -> List. +ensure_int_as_bin(Int) when is_integer(Int) -> + int_to_bin(Int); +ensure_int_as_bin(Bin) -> + Bin. + map_to_norm_bin([H|_]=List) when is_integer(H) -> lists:map(fun(E) -> int_to_bin(E) end, List); map_to_norm_bin(List) -> @@ -917,8 +922,8 @@ sign(dss, Type, DataOrDigest, Key) -> error -> erlang:error(badkey, [DataOrDigest, Key]); Sign -> Sign end; -sign(ecdsa, Type, DataOrDigest, Key) -> - case ecdsa_sign_nif(Type, DataOrDigest, term_to_ec_key(Key)) of +sign(ecdsa, Type, DataOrDigest, [Key, Curve]) -> + case ecdsa_sign_nif(Type, DataOrDigest, term_to_ec_key({Curve, Key, undefined})) of error -> erlang:error(badkey, [Type,DataOrDigest,Key]); Sign -> Sign end. @@ -1228,9 +1233,9 @@ term_to_nif_prime({prime_field, Prime}) -> term_to_nif_prime(PrimeField) -> PrimeField. term_to_nif_curve({A, B, Seed}) -> - {int_to_bin(A), int_to_bin(B), Seed}. + {ensure_int_as_bin(A), ensure_int_as_bin(B), Seed}. term_to_nif_curve_parameters({PrimeField, Curve, BasePoint, Order, CoFactor}) -> - {term_to_nif_prime(PrimeField), term_to_nif_curve(Curve), BasePoint, int_to_bin(Order), int_to_bin(CoFactor)}; + {term_to_nif_prime(PrimeField), term_to_nif_curve(Curve), ensure_int_as_bin(BasePoint), int_to_bin(Order), int_to_bin(CoFactor)}; term_to_nif_curve_parameters(Curve) when is_atom(Curve) -> %% named curve Curve. diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl index 473609778c..3ebe10866c 100644 --- a/lib/crypto/test/crypto_SUITE.erl +++ b/lib/crypto/test/crypto_SUITE.erl @@ -1892,8 +1892,8 @@ ec(Config) when is_list(Config) -> ec_do() -> %% test for a name curve {D2_priv, D2_pub} = crypto:generate_key(ecdh, sect113r2), - D2 = {sect113r2, D2_priv, D2_pub}, - + PrivECDH = [D2_priv, sect113r2], + PubECDH = [D2_pub, sect113r2], %%TODO: find a published test case for a EC key %% test for a full specified curve and public key, @@ -1932,14 +1932,11 @@ ec_do() -> 16#f7, 16#90, 16#1e, 16#0e, 16#82, 16#97, 16#48, 16#56, 16#a7>>, CoFactor = 1, Curve = {{prime_field,P},{A,B,none},BasePoint, Order,CoFactor}, - CsCaKey = {Curve, undefined, PubKey}, - %%T3 = crypto:term_to_ec_key(CsCaKey), - %%?line CsCaKey = crypto:ec_key_to_term(T3), Msg = <<99,234,6,64,190,237,201,99,80,248,58,40,70,45,149,218,5,246,242,63>>, - Sign = crypto:sign(ecdsa, sha, Msg, D2), - ?line true = crypto:verify(ecdsa, sha, Msg, Sign, D2), - ?line false = crypto:verify(ecdsa, sha, Msg, <<10,20>>, D2), + Sign = crypto:sign(ecdsa, sha, Msg, PrivECDH), + ?line true = crypto:verify(ecdsa, sha, Msg, Sign, PubECDH), + ?line false = crypto:verify(ecdsa, sha, Msg, <<10,20>>, PubECDH), ok. -- cgit v1.2.3 From 7c901c92f5936ca2f212300d2f13f899b7a222e0 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Fri, 26 Apr 2013 18:08:48 +0200 Subject: crypto: Deprecate functions, update doc and specs --- lib/crypto/doc/src/crypto.xml | 1442 +++++++++++++------------------------ lib/crypto/doc/src/crypto_app.xml | 47 +- lib/crypto/src/crypto.erl | 99 ++- lib/crypto/test/crypto_SUITE.erl | 86 ++- 4 files changed, 594 insertions(+), 1080 deletions(-) (limited to 'lib/crypto') diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml index 9201d649d7..c4e6993460 100644 --- a/lib/crypto/doc/src/crypto.xml +++ b/lib/crypto/doc/src/crypto.xml @@ -22,100 +22,115 @@ crypto - Peter Högfeldt - - 2000-06-20 - B crypto Crypto Functions

This module provides a set of cryptographic functions.

-

References:

-

md4: The MD4 Message Digest Algorithm (RFC 1320)

-
- -

md5: The MD5 Message Digest Algorithm (RFC 1321)

-
- -

sha: Secure Hash Standard (FIPS 180-2)

-
- -

hmac: Keyed-Hashing for Message Authentication (RFC 2104)

-
- -

des: Data Encryption Standard (FIPS 46-3)

-
- -

aes: Advanced Encryption Standard (AES) (FIPS 197)

+

Hash functions - The MD4 Message Digest Algorithm (RFC 1320), + The MD5 Message Digest Algorithm (RFC 1321) and + Secure Hash Standard +

-

ecb, cbc, cfb, ofb, ctr: Recommendation for Block Cipher Modes - of Operation (NIST SP 800-38A).

+

Hmac functions - Keyed-Hashing for Message Authentication (RFC 2104)

-

rsa: Recommendation for Block Cipher Modes of Operation - (NIST 800-38A)

+

Block ciphers - DES and AES and + and Block Cipher Modes - ECB, CBC, CFB, OFB and CTR

-

dss: Digital Signature Standard (FIPS 186-2)

+

RSA encryption RFC 1321

-

srp: Secure Remote Password Protocol (RFC 2945)

+

Digital signatures Digital Signature Standard (DSS) and Elliptic Curve Digital + Signature Algorithm (ECDSA)

-

ecdsa: "Public Key Cryptography for the Financial - Services Industry: The Elliptic Curve Digital - Signature Standard (ECDSA)", November, 2005.

+

Secure Remote Password Protocol (SRP - RFC 2945)

- -

ec: Standards for Efficient Cryptography Group (SECG), "SEC 1: - Elliptic Curve Cryptography", Version 1.0, September 2000.

-
- -

ecdsa: American National Standards Institute (ANSI), - ANS X9.62-2005: The Elliptic Curve Digital Signature - Algorithm (ECDSA), 2005.

-
-

The above publications can be found at NIST publications, at IETF. -

-

Types

-
-byte() = 0 ... 255
-ioelem() = byte() | binary() | iolist()
-iolist() = [ioelem()]
-Mpint() = >]]>
-    
-

+ +
+ DATA TYPES + +

byte() = 0 ... 255

+ +

ioelem() = byte() | binary() | iolist()

+ +

iolist() = [ioelem()]

+ +

key_value() = integer() | binary()

+ +

rsa_public() = [key_value()] = [E, N]

+

Where E is the public exponent and N is public modulus.

+ +

rsa_private() = [key_value()] = [E, N, D] | [E, N, D, P1, P2, E1, E2, C]

+

Where E is the public exponent, N is public modulus and D is + the private exponent.The longer key format contains redundant + information that will make the calculation faster. P1,P2 are first + and second prime factors. E1,E2 are first and second exponents. C + is the CRT coefficient. Terminology is taken from RFC 3447.

+ +

dss_public() = [key_value()] = [P, Q, G, Y]

+

Where P, Q and G are the dss parameters and Y is the public key.

+ +

dss_private() = [key_value()] = [P, Q, G, X]

+

Where P, Q and G are the dss parameters and X is the private key.

+ +

dss_public() = [key_value()] =[P, Q, G, Y]

+ +

srp_public() = key_value()

+

Where is A or B from SRP design

+ +

srp_private() = key_value()

+

Where is a or b from SRP design

+ +

srp_params() = {user, [Generator::binary(), Prime::binary(), Version::atom()]} | + {host, [Verifier::binary(), Generator::binary(), Prime::binary(), Version::atom()]} + | {user, [DerivedKey::binary(), Prime::binary(), Generator::binary(), Version::atom() | [Scrambler:binary()]]} + | {host,[Verifier::binary(), Prime::binary(), Version::atom() | [Scrambler::binary]]}

+ +

Where Verifier is v, Generator is g and Prime is N, DerivedKey is X, and Scrambler is + u (optional will be genrated if not provided) from SRP design + Version = '3' | '6' | '6a' +

+ +

dh_public() = key_value()

+ +

dh_private() = key_value()

+ +

dh_params() = [key_value()] = [P, G]

+ +

ecdh_public() = key_value()

+ +

ecdh_private() = key_value()

+ +

ecdh_params() = ec_named_curve() | + {ec_field(), Prime :: key_value(), Point :: key_value(), Order :: integer(), CoFactor :: none | integer()}

+ +

ec_field() = {prime_field, Prime :: integer()} | + {characteristic_two_field, M :: integer(), Basis :: ec_basis()}

+ +

ec_basis() = {tpbasis, K :: non_neg_integer()} | + {ppbasis, K1 :: non_neg_integer(), K2 :: non_neg_integer(), K3 :: non_neg_integer()} | + onbasis

+ +

ec_named_curve() -> + sect571r1| sect571k1| sect409r1| sect409k1| secp521r1| secp384r1| secp224r1| secp224k1| + secp192k1| secp160r2| secp128r2| secp128r1| sect233r1| sect233k1| sect193r2| sect193r1| + sect131r2| sect131r1| sect283r1| sect283k1| sect163r2| secp256k1| secp160k1| secp160r1| + secp112r2| secp112r1| sect113r2| sect113r1| sect239k1| sect163r1| sect163k1| secp256r1| + secp192r1

+ +
+ - - start() -> ok - Start the crypto server. - -

Starts the crypto server.

-
-
- - stop() -> ok - Stop the crypto server. - -

Stops the crypto server.

-
-
- - info() -> [atom()] - Provide a list of available crypto functions. - -

Provides the available crypto functions in terms of a list - of atoms.

-
-
- + algorithms() -> [atom()] Provide a list of available crypto algorithms. @@ -123,170 +138,52 @@ Mpint() = >]]> of atoms.

+ - info_lib() -> [{Name,VerNum,VerStr}] - Provides information about the libraries used by crypto. - - Name = binary() - VerNum = integer() - VerStr = binary() - - -

Provides the name and version of the libraries used by crypto.

-

Name is the name of the library. VerNum is - the numeric version according to the library's own versioning - scheme. VerStr contains a text variant of the version.

-
-> info_lib().
-[{<<"OpenSSL">>,9469983,<<"OpenSSL 0.9.8a 11 Oct 2005">>}]
-        
-

- From OTP R16 the numeric version represents the version of the OpenSSL - header files (openssl/opensslv.h) used when crypto was compiled. - The text variant represents the OpenSSL library used at runtime. - In earlier OTP versions both numeric and text was taken from the library. -

-
-
- - md4(Data) -> Digest - Compute an MD4message digest from Data - - Data = iolist() | binary() - Digest = binary() - - -

Computes an MD4 message digest from Data, where - the length of the digest is 128 bits (16 bytes).

-
-
- - md4_init() -> Context - Creates an MD4 context - - Context = binary() - - -

Creates an MD4 context, to be used in subsequent calls to - md4_update/2.

-
-
- - md4_update(Context, Data) -> NewContext - Update an MD4 Contextwith Data, and return a NewContext - - Data = iolist() | binary() - Context = NewContext = binary() - - -

Updates an MD4 Context with Data, and returns - a NewContext.

-
-
- - md4_final(Context) -> Digest - Finish the update of an MD4 Contextand return the computed MD4message digest - - Context = Digest = binary() - - -

Finishes the update of an MD4 Context and returns - the computed MD4 message digest.

-
-
- - md5(Data) -> Digest - Compute an MD5message digest from Data - - Data = iolist() | binary() - Digest = binary() - - -

Computes an MD5 message digest from Data, where - the length of the digest is 128 bits (16 bytes).

-
-
- - md5_init() -> Context - Creates an MD5 context - - Context = binary() - - -

Creates an MD5 context, to be used in subsequent calls to - md5_update/2.

-
-
- - md5_update(Context, Data) -> NewContext - Update an MD5 Contextwith Data, and return a NewContext - - Data = iolist() | binary() - Context = NewContext = binary() - - -

Updates an MD5 Context with Data, and returns - a NewContext.

-
-
- - md5_final(Context) -> Digest - Finish the update of an MD5 Contextand return the computed MD5message digest - - Context = Digest = binary() - - -

Finishes the update of an MD5 Context and returns - the computed MD5 message digest.

-
-
- - sha(Data) -> Digest - Compute an SHAmessage digest from Data - - Data = iolist() | binary() - Digest = binary() - - -

Computes an SHA message digest from Data, where - the length of the digest is 160 bits (20 bytes).

-
-
- - sha_init() -> Context - Create an SHA context + compute_key(Type, OthersPublicKey, MyPrivateKey, Params) -> SharedSecret + Computes the shared secret - Context = binary() + Type = dh | ecdh | srp + OthersPublicKey = dh_public() | ecdh_public() | srp_public() + MyPrivate = dh_private() | ecdh_private() | srp_private() + Params = dh_params() | edhc_params() | srp_params() + SharedSecret = binary() -

Creates an SHA context, to be used in subsequent calls to - sha_update/2.

+

Computes the shared secret from the private key and the other party's public key. +

+ - sha_update(Context, Data) -> NewContext - Update an SHA context + exor(Data1, Data2) -> Result + XOR data - Data = iolist() | binary() - Context = NewContext = binary() + Data1, Data2 = iolist() | binary() + Result = binary() -

Updates an SHA Context with Data, and returns - a NewContext.

+

Performs bit-wise XOR (exclusive or) on the data supplied.

- - sha_final(Context) -> Digest - Finish the update of an SHA context + + + generate_key(Type, Params) -> {PublicKey, PrivateKey} + generate_key(Type, Params, PrivateKey) -> {PublicKey, PrivateKey} + Generates a public keys of type Type - Context = Digest = binary() + Type = dh | ecdh | srp + Params = dh_params() | edhc_params() | srp_params() + PublicKey = dh_public() | ecdh_public() | srp_public() + PrivateKey = dh_private() | ecdh_private() | srp_private() -

Finishes the update of an SHA Context and returns - the computed SHA message digest.

+

Generates public keys of type Type. +

- + + hash(Type, Data) -> Digest @@ -300,6 +197,7 @@ Mpint() = >]]> is not supported by the underlying OpenSSL implementation.

+ hash_init(Type) -> Context @@ -314,6 +212,7 @@ Mpint() = >]]> is not supported by the underlying OpenSSL implementation.

+ hash_update(Context, Data) -> NewContext @@ -341,32 +240,7 @@ Mpint() = >]]> function used to generate it.

- - md5_mac(Key, Data) -> Mac - Compute an MD5 MACmessage authentification code - - Key = Data = iolist() | binary() - Mac = binary() - - -

Computes an MD5 MAC message authentification code - from Key and Data, where the the length of the - Mac is 128 bits (16 bytes).

-
-
- - md5_mac_96(Key, Data) -> Mac - Compute an MD5 MACmessage authentification code - - Key = Data = iolist() | binary() - Mac = binary() - - -

Computes an MD5 MAC message authentification code - from Key and Data, where the length of the Mac - is 96 bits (12 bytes).

-
-
+ hmac(Type, Key, Data) -> Mac hmac(Type, Key, Data, MacLength) -> Mac @@ -384,6 +258,7 @@ Mpint() = >]]> will limit the size of the resultant Mac. + hmac_init(Type, Key) -> Context @@ -398,6 +273,7 @@ Mpint() = >]]> key. The key can be any length.

+ hmac_update(Context, Data) -> NewContext @@ -412,6 +288,7 @@ Mpint() = >]]> must be passed into the next call to hmac_update.

+ hmac_final(Context) -> Mac @@ -423,6 +300,7 @@ Mpint() = >]]> determined by the type of hash function used to generate it.

+ hmac_final_n(Context, HashLen) -> Mac @@ -435,318 +313,143 @@ Mpint() = >]]> zero. Mac will be a binary with at most HashLen bytes. Note that if HashLen is greater than the actual number of bytes returned from the underlying hash, the returned hash will have fewer than HashLen bytes.

+ + + info() -> [atom()] + Provide a list of available crypto functions. + +

Provides the available crypto functions in terms of a list + of atoms.

+
+
+ - sha_mac(Key, Data) -> Mac - sha_mac(Key, Data, MacLength) -> Mac - Compute an MD5 MACmessage authentification code + info_lib() -> [{Name,VerNum,VerStr}] + Provides information about the libraries used by crypto. - Key = Data = iolist() | binary() - Mac = binary() - MacLenength = integer() =< 20 + Name = binary() + VerNum = integer() + VerStr = binary() -

Computes an SHA MAC message authentification code - from Key and Data, where the default length of the Mac - is 160 bits (20 bytes).

+

Provides the name and version of the libraries used by crypto.

+

Name is the name of the library. VerNum is + the numeric version according to the library's own versioning + scheme. VerStr contains a text variant of the version.

+
+> info_lib().
+[{<<"OpenSSL">>,9469983,<<"OpenSSL 0.9.8a 11 Oct 2005">>}]
+        
+

+ From OTP R16 the numeric version represents the version of the OpenSSL + header files (openssl/opensslv.h) used when crypto was compiled. + The text variant represents the OpenSSL library used at runtime. + In earlier OTP versions both numeric and text was taken from the library. +

+ - sha_mac_96(Key, Data) -> Mac - Compute an SHA MACmessage authentification code + mod_exp_prime(N, P, M) -> Result + Computes the function: N^P mod M - Key = Data = iolist() | binary() - Mac = binary() + N, P, M = binary() + Result = binary() | error -

Computes an SHA MAC message authentification code - from Key and Data, where the length of the Mac - is 96 bits (12 bytes).

+

Computes the function N^P mod M.

+ - des_cbc_encrypt(Key, IVec, Text) -> Cipher - Encrypt Textaccording to DES in CBC mode + rand_bytes(N) -> binary() + Generate a binary of random bytes - Key = Text = iolist() | binary() - IVec = Cipher = binary() + N = integer() -

Encrypts Text according to DES in CBC - mode. Text must be a multiple of 64 bits (8 - bytes). Key is the DES key, and IVec is an - arbitrary initializing vector. The lengths of Key and - IVec must be 64 bits (8 bytes).

+

Generates N bytes randomly uniform 0..255, and returns the + result in a binary. Uses the crypto library pseudo-random + number generator.

- - des_cbc_decrypt(Key, IVec, Cipher) -> Text - Decrypt Cipheraccording to DES in CBC mode + + + rand_uniform(Lo, Hi) -> N + Generate a random number - Key = Cipher = iolist() | binary() - IVec = Text = binary() + Lo, Hi, N = integer() -

Decrypts Cipher according to DES in CBC mode. - Key is the DES key, and IVec is an arbitrary - initializing vector. Key and IVec must have - the same values as those used when encrypting. Cipher - must be a multiple of 64 bits (8 bytes). The lengths of - Key and IVec must be 64 bits (8 bytes).

+

Generate a random number Uses the + crypto library pseudo-random number generator. + Hi must be larger than Lo.

+ - des_cbc_ivec(Data) -> IVec - Get IVec to be used in next iteration of - des_cbc_[ecrypt|decrypt] + sign(Algorithm, DigestType, Msg, Key) -> binary() + Create digital signature. - Data = iolist() | binary() - IVec = binary() + Algorithm = rsa | dss | ecdsa + Msg = binary() | {digest,binary()} + The msg is either the binary "plain text" data to be + signed or it is the hashed value of "plain text" i.e. the + digest. + DigestType = digest_type() + Key = rsa_private_key() | dsa_private_key() | ec_private_key() -

Returns the IVec to be used in a next iteration of - des_cbc_[encrypt|decrypt]. Data is the encrypted - data from the previous iteration step.

-
-
- - des_cfb_encrypt(Key, IVec, Text) -> Cipher - Encrypt Textaccording to DES in CFB mode - - Key = Text = iolist() | binary() - IVec = Cipher = binary() - - -

Encrypts Text according to DES in 8-bit CFB - mode. Key is the DES key, and IVec is an - arbitrary initializing vector. The lengths of Key and - IVec must be 64 bits (8 bytes).

-
-
- - des_cfb_decrypt(Key, IVec, Cipher) -> Text - Decrypt Cipheraccording to DES in CFB mode - - Key = Cipher = iolist() | binary() - IVec = Text = binary() - - -

Decrypts Cipher according to DES in 8-bit CFB mode. - Key is the DES key, and IVec is an arbitrary - initializing vector. Key and IVec must have - the same values as those used when encrypting. The lengths of - Key and IVec must be 64 bits (8 bytes).

-
-
- - des_cfb_ivec(IVec, Data) -> NextIVec - Get IVec to be used in next iteration of - des_cfb_[ecrypt|decrypt] - - IVec = iolist() | binary() - Data = iolist() | binary() - NextIVec = binary() - - -

Returns the IVec to be used in a next iteration of - des_cfb_[encrypt|decrypt]. IVec is the vector - used in the previous iteration step. Data is the encrypted - data from the previous iteration step.

-
-
- - des3_cbc_encrypt(Key1, Key2, Key3, IVec, Text) -> Cipher - Encrypt Textaccording to DES3 in CBC mode - - Key1 =Key2 = Key3 Text = iolist() | binary() - IVec = Cipher = binary() - - -

Encrypts Text according to DES3 in CBC - mode. Text must be a multiple of 64 bits (8 - bytes). Key1, Key2, Key3, are the DES - keys, and IVec is an arbitrary initializing - vector. The lengths of each of Key1, Key2, - Key3 and IVec must be 64 bits (8 bytes).

-
-
- - des3_cbc_decrypt(Key1, Key2, Key3, IVec, Cipher) -> Text - Decrypt Cipheraccording to DES3 in CBC mode - - Key1 = Key2 = Key3 = Cipher = iolist() | binary() - IVec = Text = binary() - - -

Decrypts Cipher according to DES3 in CBC mode. - Key1, Key2, Key3 are the DES key, and - IVec is an arbitrary initializing vector. - Key1, Key2, Key3 and IVec must - and IVec must have the same values as those used when - encrypting. Cipher must be a multiple of 64 bits (8 - bytes). The lengths of Key1, Key2, - Key3, and IVec must be 64 bits (8 bytes).

-
-
- - des3_cfb_encrypt(Key1, Key2, Key3, IVec, Text) -> Cipher - Encrypt Textaccording to DES3 in CFB mode - - Key1 =Key2 = Key3 Text = iolist() | binary() - IVec = Cipher = binary() - - -

Encrypts Text according to DES3 in 8-bit CFB - mode. Key1, Key2, Key3, are the DES - keys, and IVec is an arbitrary initializing - vector. The lengths of each of Key1, Key2, - Key3 and IVec must be 64 bits (8 bytes).

-

May throw exception notsup for old OpenSSL - versions (0.9.7) that does not support this encryption mode.

-
-
- - des3_cfb_decrypt(Key1, Key2, Key3, IVec, Cipher) -> Text - Decrypt Cipheraccording to DES3 in CFB mode - - Key1 = Key2 = Key3 = Cipher = iolist() | binary() - IVec = Text = binary() - - -

Decrypts Cipher according to DES3 in 8-bit CFB mode. - Key1, Key2, Key3 are the DES key, and - IVec is an arbitrary initializing vector. - Key1, Key2, Key3 and IVec must - and IVec must have the same values as those used when - encrypting. The lengths of Key1, Key2, - Key3, and IVec must be 64 bits (8 bytes).

-

May throw exception notsup for old OpenSSL - versions (0.9.7) that does not support this encryption mode.

-
-
- - - des_ecb_encrypt(Key, Text) -> Cipher - Encrypt Textaccording to DES in ECB mode - - Key = Text = iolist() | binary() - Cipher = binary() - - -

Encrypts Text according to DES in ECB mode. - Key is the DES key. The lengths of Key and - Text must be 64 bits (8 bytes).

-
-
- - des_ecb_decrypt(Key, Cipher) -> Text - Decrypt Cipheraccording to DES in ECB mode - - Key = Cipher = iolist() | binary() - Text = binary() - - -

Decrypts Cipher according to DES in ECB mode. - Key is the DES key. The lengths of Key and - Cipher must be 64 bits (8 bytes).

-
-
- - - blowfish_ecb_encrypt(Key, Text) -> Cipher - Encrypt the first 64 bits of Text using Blowfish in ECB mode - - Key = Text = iolist() | binary() - Cipher = binary() - - -

Encrypts the first 64 bits of Text using Blowfish in ECB mode. Key is the Blowfish key. The length of Text must be at least 64 bits (8 bytes).

-
-
- - blowfish_ecb_decrypt(Key, Text) -> Cipher - Decrypt the first 64 bits of Text using Blowfish in ECB mode - - Key = Text = iolist() | binary() - Cipher = binary() - - -

Decrypts the first 64 bits of Text using Blowfish in ECB mode. Key is the Blowfish key. The length of Text must be at least 64 bits (8 bytes).

+

Creates a digital signature.

- blowfish_cbc_encrypt(Key, IVec, Text) -> Cipher - Encrypt Text using Blowfish in CBC mode - - Key = Text = iolist() | binary() - IVec = Cipher = binary() - + start() -> ok + Equivalent to application:start(crypto). -

Encrypts Text using Blowfish in CBC mode. Key is the Blowfish key, and IVec is an - arbitrary initializing vector. The length of IVec - must be 64 bits (8 bytes). The length of Text must be a multiple of 64 bits (8 bytes).

+

Equivalent to application:start(crypto).

- blowfish_cbc_decrypt(Key, IVec, Text) -> Cipher - Decrypt Text using Blowfish in CBC mode - - Key = Text = iolist() | binary() - IVec = Cipher = binary() - + stop() -> ok + Equivalent to application:stop(crypto). -

Decrypts Text using Blowfish in CBC mode. Key is the Blowfish key, and IVec is an - arbitrary initializing vector. The length of IVec - must be 64 bits (8 bytes). The length of Text must be a multiple 64 bits (8 bytes).

+

Equivalent to application:stop(crypto).

- blowfish_cfb64_encrypt(Key, IVec, Text) -> Cipher - Encrypt Textusing Blowfish in CFB mode with 64 - bit feedback - - Key = Text = iolist() | binary() - IVec = Cipher = binary() - - -

Encrypts Text using Blowfish in CFB mode with 64 bit - feedback. Key is the Blowfish key, and IVec is an - arbitrary initializing vector. The length of IVec - must be 64 bits (8 bytes).

-
-
- - blowfish_cfb64_decrypt(Key, IVec, Text) -> Cipher - Decrypt Textusing Blowfish in CFB mode with 64 - bit feedback + strong_rand_bytes(N) -> binary() + Generate a binary of random bytes - Key = Text = iolist() | binary() - IVec = Cipher = binary() + N = integer() -

Decrypts Text using Blowfish in CFB mode with 64 bit - feedback. Key is the Blowfish key, and IVec is an - arbitrary initializing vector. The length of IVec - must be 64 bits (8 bytes).

+

Generates N bytes randomly uniform 0..255, and returns the + result in a binary. Uses a cryptographically secure prng seeded and + periodically mixed with operating system provided entropy. By default + this is the RAND_bytes method from OpenSSL.

+

May throw exception low_entropy in case the random generator + failed due to lack of secure "randomness".

- - blowfish_ofb64_encrypt(Key, IVec, Text) -> Cipher - Encrypt Textusing Blowfish in OFB mode with 64 - bit feedback + verify(Algorithm, DigestType, Msg, Signature, Key) -> boolean() + Verifies a digital signature. - Key = Text = iolist() | binary() - IVec = Cipher = binary() + Algorithm = rsa | dss | ecdsa + Msg = binary() | {digest,binary()} + The msg is either the binary "plain text" data + or it is the hashed value of "plain text" i.e. the digest. + DigestType = digest_type() + Signature = binary() + Key = rsa_public_key() | dsa_public_key() | ec_public_key() -

Encrypts Text using Blowfish in OFB mode with 64 bit - feedback. Key is the Blowfish key, and IVec is an - arbitrary initializing vector. The length of IVec - must be 64 bits (8 bytes).

+

Verifies a digital signature

-
+
aes_cfb_128_encrypt(Key, IVec, Text) -> Cipher @@ -763,6 +466,7 @@ Mpint() = >]]> (16 bytes).

+ aes_cfb_128_decrypt(Key, IVec, Cipher) -> Text Decrypt Cipheraccording to AES in Cipher Feedback mode @@ -778,6 +482,7 @@ Mpint() = >]]> Key and IVec must be 128 bits (16 bytes).

+ aes_cbc_128_encrypt(Key, IVec, Text) -> Cipher Encrypt Textaccording to AES in Cipher Block Chaining mode @@ -794,6 +499,7 @@ Mpint() = >]]> (16 bytes).

+ aes_cbc_128_decrypt(Key, IVec, Cipher) -> Text Decrypt Cipheraccording to AES in Cipher Block Chaining mode @@ -811,6 +517,7 @@ Mpint() = >]]> Key and IVec must be 128 bits (16 bytes).

+ aes_cbc_ivec(Data) -> IVec Get IVec to be used in next iteration of @@ -825,6 +532,7 @@ Mpint() = >]]> data from the previous iteration step.

+ aes_ctr_encrypt(Key, IVec, Text) -> Cipher Encrypt Textaccording to AES in Counter mode @@ -839,6 +547,7 @@ Mpint() = >]]> (16 bytes).

+ aes_ctr_decrypt(Key, IVec, Cipher) -> Text Decrypt Cipheraccording to AES in Counter mode @@ -853,6 +562,7 @@ Mpint() = >]]> (16 bytes).

+ aes_ctr_stream_init(Key, IVec) -> State @@ -870,6 +580,7 @@ Mpint() = >]]> aes_ctr_stream_decrypt.

+ aes_ctr_stream_encrypt(State, Text) -> { NewState, Cipher} @@ -886,6 +597,7 @@ Mpint() = >]]> Cipher is the encrypted cipher text.

+ aes_ctr_stream_decrypt(State, Cipher) -> { NewState, Text } @@ -902,620 +614,446 @@ Mpint() = >]]> Text is the decrypted data.

- - erlint(Mpint) -> N - mpint(N) -> Mpint - Convert between binary multi-precision integer and erlang big integer - - Mpint = binary() - N = integer() + + + blowfish_ecb_encrypt(Key, Text) -> Cipher + Encrypt the first 64 bits of Text using Blowfish in ECB mode + + Key = Text = iolist() | binary() + Cipher = binary() -

Convert a binary multi-precision integer Mpint to and from - an erlang big integer. A multi-precision integer is a binary - with the following form: - >]]> where both - ByteLen and Bytes are big-endian. Mpints are used in - some of the functions in crypto and are not translated - in the API for performance reasons.

+

Encrypts the first 64 bits of Text using Blowfish in ECB mode. Key is the Blowfish key. The length of Text must be at least 64 bits (8 bytes).

+ - rand_bytes(N) -> binary() - Generate a binary of random bytes + blowfish_ecb_decrypt(Key, Text) -> Cipher + Decrypt the first 64 bits of Text using Blowfish in ECB mode - N = integer() + Key = Text = iolist() | binary() + Cipher = binary() -

Generates N bytes randomly uniform 0..255, and returns the - result in a binary. Uses the crypto library pseudo-random - number generator.

-
-
- - strong_rand_bytes(N) -> binary() - Generate a binary of random bytes - - N = integer() - - -

Generates N bytes randomly uniform 0..255, and returns the - result in a binary. Uses a cryptographically secure prng seeded and - periodically mixed with operating system provided entropy. By default - this is the RAND_bytes method from OpenSSL.

-

May throw exception low_entropy in case the random generator - failed due to lack of secure "randomness".

+

Decrypts the first 64 bits of Text using Blowfish in ECB mode. Key is the Blowfish key. The length of Text must be at least 64 bits (8 bytes).

+ - rand_uniform(Lo, Hi) -> N - Generate a random number + blowfish_cbc_encrypt(Key, IVec, Text) -> Cipher + Encrypt Text using Blowfish in CBC mode - Lo, Hi, N = Mpint | integer() - Mpint = binary() + Key = Text = iolist() | binary() + IVec = Cipher = binary() -

Generate a random number Uses the - crypto library pseudo-random number generator. The - arguments (and result) can be either erlang integers or binary - multi-precision integers. Hi must be larger than Lo.

+

Encrypts Text using Blowfish in CBC mode. Key is the Blowfish key, and IVec is an + arbitrary initializing vector. The length of IVec + must be 64 bits (8 bytes). The length of Text must be a multiple of 64 bits (8 bytes).

- strong_rand_mpint(N, Top, Bottom) -> Mpint - Generate an N bit random number + blowfish_cbc_decrypt(Key, IVec, Text) -> Cipher + Decrypt Text using Blowfish in CBC mode - N = non_neg_integer() - Top = -1 | 0 | 1 - Bottom = 0 | 1 - Mpint = binary() + Key = Text = iolist() | binary() + IVec = Cipher = binary() -

Generate an N bit random number using OpenSSL's - cryptographically strong pseudo random number generator - BN_rand.

-

The parameter Top places constraints on the most - significant bits of the generated number. If Top is 1, then the - two most significant bits will be set to 1, if Top is 0, the - most significant bit will be 1, and if Top is -1 then no - constraints are applied and thus the generated number may be less than - N bits long.

-

If Bottom is 1, then the generated number is - constrained to be odd.

-

May throw exception low_entropy in case the random generator - failed due to lack of secure "randomness".

+

Decrypts Text using Blowfish in CBC mode. Key is the Blowfish key, and IVec is an + arbitrary initializing vector. The length of IVec + must be 64 bits (8 bytes). The length of Text must be a multiple 64 bits (8 bytes).

+ - mod_exp(N, P, M) -> Result - Perform N ^ P mod M + blowfish_cfb64_encrypt(Key, IVec, Text) -> Cipher + Encrypt Textusing Blowfish in CFB mode with 64 + bit feedback - N, P, M, Result = Mpint - Mpint = binary() + Key = Text = iolist() | binary() + IVec = Cipher = binary() -

This function performs the exponentiation N ^ P mod M, - using the crypto library.

+

Encrypts Text using Blowfish in CFB mode with 64 bit + feedback. Key is the Blowfish key, and IVec is an + arbitrary initializing vector. The length of IVec + must be 64 bits (8 bytes).

+ - mod_exp_prime(N, P, M) -> Result - Computes the function: N^P mod M + blowfish_cfb64_decrypt(Key, IVec, Text) -> Cipher + Decrypt Textusing Blowfish in CFB mode with 64 + bit feedback - N, P, M = binary() - Result = binary() | error + Key = Text = iolist() | binary() + IVec = Cipher = binary() -

Computes the function N^P mod M.

+

Decrypts Text using Blowfish in CFB mode with 64 bit + feedback. Key is the Blowfish key, and IVec is an + arbitrary initializing vector. The length of IVec + must be 64 bits (8 bytes).

+ - rsa_sign(DataOrDigest, Key) -> Signature - rsa_sign(DigestType, DataOrDigest, Key) -> Signature - Sign the data using rsa with the given key. + blowfish_ofb64_encrypt(Key, IVec, Text) -> Cipher + Encrypt Textusing Blowfish in OFB mode with 64 + bit feedback - DataOrDigest = Data | {digest,Digest} - Data = Mpint - Digest = binary() - Key = [E, N, D] | [E, N, D, P1, P2, E1, E2, C] - E, N, D = Mpint - Where E is the public exponent, N is public modulus and - D is the private exponent. - P1, P2, E1, E2, C = Mpint - The longer key format contains redundant information that will make - the calculation faster. P1,P2 are first and second prime factors. - E1,E2 are first and second exponents. C is the CRT coefficient. - Terminology is taken from RFC 3447. - DigestType = md5 | sha | sha224 | sha256 | sha384 | sha512 - The default DigestType is sha. - Mpint = binary() - Signature = binary() + Key = Text = iolist() | binary() + IVec = Cipher = binary() -

Creates a RSA signature with the private key Key - of a digest. The digest is either calculated as a - DigestType digest of Data or a precalculated - binary Digest.

+

Encrypts Text using Blowfish in OFB mode with 64 bit + feedback. Key is the Blowfish key, and IVec is an + arbitrary initializing vector. The length of IVec + must be 64 bits (8 bytes).

- rsa_verify(DataOrDigest, Signature, Key) -> Verified - rsa_verify(DigestType, DataOrDigest, Signature, Key) -> Verified - Verify the digest and signature using rsa with given public key. + des_cbc_encrypt(Key, IVec, Text) -> Cipher + Encrypt Textaccording to DES in CBC mode - Verified = boolean() - DataOrDigest = Data | {digest|Digest} - Data, Signature = Mpint - Digest = binary() - Key = [E, N] - E, N = Mpint - Where E is the public exponent and N is public modulus. - DigestType = md5 | sha | sha224 | sha256 | sha384 | sha512 - The default DigestType is sha. - Mpint = binary() + Key = Text = iolist() | binary() + IVec = Cipher = binary() -

Verifies that a digest matches the RSA signature using the - signer's public key Key. - The digest is either calculated as a DigestType - digest of Data or a precalculated binary Digest.

-

May throw exception notsup in case the chosen DigestType - is not supported by the underlying OpenSSL implementation.

+

Encrypts Text according to DES in CBC + mode. Text must be a multiple of 64 bits (8 + bytes). Key is the DES key, and IVec is an + arbitrary initializing vector. The lengths of Key and + IVec must be 64 bits (8 bytes).

- + - rsa_public_encrypt(PlainText, PublicKey, Padding) -> ChipherText - Encrypts Msg using the public Key. + des_cbc_decrypt(Key, IVec, Cipher) -> Text + Decrypt Cipheraccording to DES in CBC mode - PlainText = binary() - PublicKey = [E, N] - E, N = Mpint - Where E is the public exponent and N is public modulus. - Padding = rsa_pkcs1_padding | rsa_pkcs1_oaep_padding | rsa_no_padding - ChipherText = binary() + Key = Cipher = iolist() | binary() + IVec = Text = binary() -

Encrypts the PlainText (usually a session key) using the PublicKey - and returns the cipher. The Padding decides what padding mode is used, - rsa_pkcs1_padding is PKCS #1 v1.5 currently the most - used mode and rsa_pkcs1_oaep_padding is EME-OAEP as - defined in PKCS #1 v2.0 with SHA-1, MGF1 and an empty encoding - parameter. This mode is recommended for all new applications. - The size of the Msg must be less - than byte_size(N)-11 if - rsa_pkcs1_padding is used, byte_size(N)-41 if - rsa_pkcs1_oaep_padding is used and byte_size(N) if rsa_no_padding - is used. - Where byte_size(N) is the size part of an Mpint-1. -

+

Decrypts Cipher according to DES in CBC mode. + Key is the DES key, and IVec is an arbitrary + initializing vector. Key and IVec must have + the same values as those used when encrypting. Cipher + must be a multiple of 64 bits (8 bytes). The lengths of + Key and IVec must be 64 bits (8 bytes).

- rsa_private_decrypt(ChipherText, PrivateKey, Padding) -> PlainText - Decrypts ChipherText using the private Key. + des_cbc_ivec(Data) -> IVec + Get IVec to be used in next iteration of + des_cbc_[ecrypt|decrypt] - ChipherText = binary() - PrivateKey = [E, N, D] | [E, N, D, P1, P2, E1, E2, C] - E, N, D = Mpint - Where E is the public exponent, N is public modulus and - D is the private exponent. - P1, P2, E1, E2, C = Mpint - The longer key format contains redundant information that will make - the calculation faster. P1,P2 are first and second prime factors. - E1,E2 are first and second exponents. C is the CRT coefficient. - Terminology is taken from RFC 3447. - Padding = rsa_pkcs1_padding | rsa_pkcs1_oaep_padding | rsa_no_padding - PlainText = binary() + Data = iolist() | binary() + IVec = binary() -

Decrypts the ChipherText (usually a session key encrypted with - rsa_public_encrypt/3) - using the PrivateKey and returns the - message. The Padding is the padding mode that was - used to encrypt the data, - see rsa_public_encrypt/3. -

+

Returns the IVec to be used in a next iteration of + des_cbc_[encrypt|decrypt]. Data is the encrypted + data from the previous iteration step.

+ - rsa_private_encrypt(PlainText, PrivateKey, Padding) -> ChipherText - Encrypts Msg using the private Key. + des_cfb_encrypt(Key, IVec, Text) -> Cipher + Encrypt Textaccording to DES in CFB mode - PlainText = binary() - PrivateKey = [E, N, D] | [E, N, D, P1, P2, E1, E2, C] - E, N, D = Mpint - Where E is the public exponent, N is public modulus and - D is the private exponent. - P1, P2, E1, E2, C = Mpint - The longer key format contains redundant information that will make - the calculation faster. P1,P2 are first and second prime factors. - E1,E2 are first and second exponents. C is the CRT coefficient. - Terminology is taken from RFC 3447. - Padding = rsa_pkcs1_padding | rsa_no_padding - ChipherText = binary() + Key = Text = iolist() | binary() + IVec = Cipher = binary() -

Encrypts the PlainText using the PrivateKey - and returns the cipher. The Padding decides what padding mode is used, - rsa_pkcs1_padding is PKCS #1 v1.5 currently the most - used mode. - The size of the Msg must be less than byte_size(N)-11 if - rsa_pkcs1_padding is used, and byte_size(N) if rsa_no_padding - is used. Where byte_size(N) is the size part of an Mpint-1. -

+

Encrypts Text according to DES in 8-bit CFB + mode. Key is the DES key, and IVec is an + arbitrary initializing vector. The lengths of Key and + IVec must be 64 bits (8 bytes).

- rsa_public_decrypt(ChipherText, PublicKey, Padding) -> PlainText - Decrypts ChipherText using the public Key. + des_cfb_decrypt(Key, IVec, Cipher) -> Text + Decrypt Cipheraccording to DES in CFB mode - ChipherText = binary() - PublicKey = [E, N] - E, N = Mpint - Where E is the public exponent and N is public modulus - Padding = rsa_pkcs1_padding | rsa_no_padding - PlainText = binary() + Key = Cipher = iolist() | binary() + IVec = Text = binary() -

Decrypts the ChipherText (encrypted with - rsa_private_encrypt/3) - using the PrivateKey and returns the - message. The Padding is the padding mode that was - used to encrypt the data, - see rsa_private_encrypt/3. -

+

Decrypts Cipher according to DES in 8-bit CFB mode. + Key is the DES key, and IVec is an arbitrary + initializing vector. Key and IVec must have + the same values as those used when encrypting. The lengths of + Key and IVec must be 64 bits (8 bytes).

- + - dss_sign(DataOrDigest, Key) -> Signature - dss_sign(DigestType, DataOrDigest, Key) -> Signature - Sign the data using dsa with given private key. + des_cfb_ivec(IVec, Data) -> NextIVec + Get IVec to be used in next iteration of + des_cfb_[ecrypt|decrypt] - DigestType = sha - DataOrDigest = Mpint | {digest,Digest} - Key = [P, Q, G, X] - P, Q, G, X = Mpint - Where P, Q and G are the dss - parameters and X is the private key. - Digest = binary() with length 20 bytes - Signature = binary() + IVec = iolist() | binary() + Data = iolist() | binary() + NextIVec = binary() -

Creates a DSS signature with the private key Key of - a digest. The digest is either calculated as a SHA1 - digest of Data or a precalculated binary Digest.

-

A deprecated feature is having DigestType = 'none' - in which case DataOrDigest is a precalculated SHA1 - digest.

+

Returns the IVec to be used in a next iteration of + des_cfb_[encrypt|decrypt]. IVec is the vector + used in the previous iteration step. Data is the encrypted + data from the previous iteration step.

- dss_verify(DataOrDigest, Signature, Key) -> Verified - dss_verify(DigestType, DataOrDigest, Signature, Key) -> Verified - Verify the data and signature using dsa with given public key. + des3_cbc_encrypt(Key1, Key2, Key3, IVec, Text) -> Cipher + Encrypt Textaccording to DES3 in CBC mode - Verified = boolean() - DigestType = sha - DataOrDigest = Mpint | {digest,Digest} - Data = Mpint | ShaDigest - Signature = Mpint - Key = [P, Q, G, Y] - P, Q, G, Y = Mpint - Where P, Q and G are the dss - parameters and Y is the public key. - Digest = binary() with length 20 bytes + Key1 =Key2 = Key3 Text = iolist() | binary() + IVec = Cipher = binary() -

Verifies that a digest matches the DSS signature using the - public key Key. The digest is either calculated as a SHA1 - digest of Data or is a precalculated binary Digest.

-

A deprecated feature is having DigestType = 'none' - in which case DataOrDigest is a precalculated SHA1 - digest binary.

+

Encrypts Text according to DES3 in CBC + mode. Text must be a multiple of 64 bits (8 + bytes). Key1, Key2, Key3, are the DES + keys, and IVec is an arbitrary initializing + vector. The lengths of each of Key1, Key2, + Key3 and IVec must be 64 bits (8 bytes).

- rc2_cbc_encrypt(Key, IVec, Text) -> Cipher - Encrypt Textaccording to RC2 in CBC mode + des3_cbc_decrypt(Key1, Key2, Key3, IVec, Cipher) -> Text + Decrypt Cipheraccording to DES3 in CBC mode - Key = Text = iolist() | binary() - Ivec = Cipher = binary() + Key1 = Key2 = Key3 = Cipher = iolist() | binary() + IVec = Text = binary() -

Encrypts Text according to RC2 in CBC mode.

+

Decrypts Cipher according to DES3 in CBC mode. + Key1, Key2, Key3 are the DES key, and + IVec is an arbitrary initializing vector. + Key1, Key2, Key3 and IVec must + and IVec must have the same values as those used when + encrypting. Cipher must be a multiple of 64 bits (8 + bytes). The lengths of Key1, Key2, + Key3, and IVec must be 64 bits (8 bytes).

- rc2_cbc_decrypt(Key, IVec, Cipher) -> Text - Decrypts Cipheraccording to RC2 in CBC mode + des3_cfb_encrypt(Key1, Key2, Key3, IVec, Text) -> Cipher + Encrypt Textaccording to DES3 in CFB mode - Key = Text = iolist() | binary() - Ivec = Cipher = binary() + Key1 =Key2 = Key3 Text = iolist() | binary() + IVec = Cipher = binary() -

Decrypts Cipher according to RC2 in CBC mode.

+

Encrypts Text according to DES3 in 8-bit CFB + mode. Key1, Key2, Key3, are the DES + keys, and IVec is an arbitrary initializing + vector. The lengths of each of Key1, Key2, + Key3 and IVec must be 64 bits (8 bytes).

+

May throw exception notsup for old OpenSSL + versions (0.9.7) that does not support this encryption mode.

- + - rc4_encrypt(Key, Data) -> Result - Encrypt data using RC4 + des3_cfb_decrypt(Key1, Key2, Key3, IVec, Cipher) -> Text + Decrypt Cipheraccording to DES3 in CFB mode - Key, Data = iolist() | binary() - Result = binary() + Key1 = Key2 = Key3 = Cipher = iolist() | binary() + IVec = Text = binary() -

Encrypts the data with RC4 symmetric stream encryption. - Since it is symmetric, the same function is used for - decryption.

+

Decrypts Cipher according to DES3 in 8-bit CFB mode. + Key1, Key2, Key3 are the DES key, and + IVec is an arbitrary initializing vector. + Key1, Key2, Key3 and IVec must + and IVec must have the same values as those used when + encrypting. The lengths of Key1, Key2, + Key3, and IVec must be 64 bits (8 bytes).

+

May throw exception notsup for old OpenSSL + versions (0.9.7) that does not support this encryption mode.

- dh_generate_key(DHParams) -> {PublicKey,PrivateKey} - dh_generate_key(PrivateKey, DHParams) -> {PublicKey,PrivateKey} - Generates a Diffie-Hellman public key + des_ecb_encrypt(Key, Text) -> Cipher + Encrypt Textaccording to DES in ECB mode - DHParameters = [P, G] - P, G = Mpint - Where P is the shared prime number and G is the shared generator. - PublicKey, PrivateKey = Mpint() + Key = Text = iolist() | binary() + Cipher = binary() -

Generates a Diffie-Hellman PublicKey and PrivateKey (if not given). -

+

Encrypts Text according to DES in ECB mode. + Key is the DES key. The lengths of Key and + Text must be 64 bits (8 bytes).

- - dh_compute_key(OthersPublicKey, MyPrivateKey, DHParams) -> SharedSecret - Computes the shared secret + des_ecb_decrypt(Key, Cipher) -> Text + Decrypt Cipheraccording to DES in ECB mode - DHParameters = [P, G] - P, G = Mpint - Where P is the shared prime number and G is the shared generator. - OthersPublicKey, MyPrivateKey = Mpint() - SharedSecret = binary() + Key = Cipher = iolist() | binary() + Text = binary() -

Computes the shared secret from the private key and the other party's public key. -

+

Decrypts Cipher according to DES in ECB mode. + Key is the DES key. The lengths of Key and + Cipher must be 64 bits (8 bytes).

- - - srp_generate_key(Generator, Prime, Version) -> {PublicKey, PrivateKey} - srp_generate_key(Generator, Prime, Version, Private) -> {PublicKey, PrivateKey} - srp_generate_key(Verifier, Generator, Prime, Version) -> {PublicKey, PrivateKey} - srp_generate_key(Verifier, Generator, Prime, Version, Private) -> {PublicKey, PrivateKey} - Generates SRP public keys + + rc2_cbc_encrypt(Key, IVec, Text) -> Cipher + Encrypt Textaccording to RC2 in CBC mode - Verifier = binary() - Parameter v from SRP design - - Generator = binary() - Parameter g from SRP design - - Prime = binary() - Parameter N from SRP design - - Version = '3' | '6' | '6a' - SRP version, TLS SRP cipher suites uses '6a'. - PublicKey = binary() - Parameter A or B from SRP design - Private = PrivateKey = binary() - generated if not supplied - Parameter a or b from SRP design + Key = Text = iolist() | binary() + Ivec = Cipher = binary() -

Generates SRP public keys for the client side (first argument is Generator) - or for the server side (first argument is Verifier).

+

Encrypts Text according to RC2 in CBC mode.

- srp_compute_key(DerivedKey, Prime, Generator, - ClientPublic, ClientPrivate, ServerPublic, Version) -> SessionKey - srp_compute_key(DerivedKey, Prime, Generator, - ClientPublic, ClientPrivate, ServerPublic, Version, Scrambler) -> SessionKey - srp_compute_key(Verifier, Prime, - ClientPublic, ServerPublic, ServerPrivate, Version, Scrambler)-> SessionKey - srp_compute_key(Verifier, Prime, - ClientPublic, ServerPublic, ServerPrivate, Version) -> SessionKey - - Computes SRP session key + rc2_cbc_decrypt(Key, IVec, Cipher) -> Text + Decrypts Cipheraccording to RC2 in CBC mode - DerivedKey = binary() - Parameter x from SRP design - - Verifier = binary() - Parameter v from SRP design - - Prime = binary() - Parameter N from SRP design - - Generator = binary() - Parameter g from SRP design - - ClientPublic = binary() - Parameter A from SRP design - - ClientPrivate = binary() - Parameter a from SRP design - - ServerPublic = binary() - Parameter B from SRP design - - ServerPrivate = binary() - Parameter b from SRP design - - Version = '3' | '6' | '6a' - SRP version, TLS SRP cipher suites uses '6a'. - SessionKey = binary() - Result K from SRP design - + Key = Text = iolist() | binary() + Ivec = Cipher = binary() -

- Computes the SRP session key (shared secret) for the client side (first argument is DerivedKey) - or for the server side (first argument is Verifier). Also used - as premaster secret by TLS-SRP cipher suites. -

+

Decrypts Cipher according to RC2 in CBC mode.

- ec_key_new(NamedCurve) -> ECKey + rc4_encrypt(Key, Data) -> Result + Encrypt data using RC4 - NamedCurve = atom() - ECKey = EC key resource() + Key, Data = iolist() | binary() + Result = binary() -

Generate an new EC key from the named curve. The private key - will be initialized with random data. -

+

Encrypts the data with RC4 symmetric stream encryption. + Since it is symmetric, the same function is used for + decryption.

- - ec_key_generate(ECKey) -> ok | error - - ECKey = EC key resource() - - -

Fills in the public key if only the private key is known or generates - a new private/public key pair if only the curve parameters are known. -

-
-
- ec_key_to_term(ECKey) -> ECKeyTerm. + rsa_public_encrypt(PlainText, PublicKey, Padding) -> ChipherText + Encrypts Msg using the public Key. - ECKey = EC key resource() - ECKeyTerm = EC key as Erlang term + PlainText = binary() + PublicKey = [E, N] + E, N = integer() + Where E is the public exponent and N is public modulus. + Padding = rsa_pkcs1_padding | rsa_pkcs1_oaep_padding | rsa_no_padding + ChipherText = binary() -

Convert a EC key from a NIF resource into an Erlang term. +

Encrypts the PlainText (usually a session key) using the PublicKey + and returns the cipher. The Padding decides what padding mode is used, + rsa_pkcs1_padding is PKCS #1 v1.5 currently the most + used mode and rsa_pkcs1_oaep_padding is EME-OAEP as + defined in PKCS #1 v2.0 with SHA-1, MGF1 and an empty encoding + parameter. This mode is recommended for all new applications. + The size of the Msg must be less + than byte_size(N)-11 if + rsa_pkcs1_padding is used, byte_size(N)-41 if + rsa_pkcs1_oaep_padding is used and byte_size(N) if rsa_no_padding + is used.

- term_to_ec_key(ECKeyTerm) -> ECKey + rsa_private_decrypt(ChipherText, PrivateKey, Padding) -> PlainText + Decrypts ChipherText using the private Key. - ECKeyTerm = EC key as Erlang term - ECKey = EC key resource() + ChipherText = binary() + PrivateKey = [E, N, D] | [E, N, D, P1, P2, E1, E2, C] + E, N, D = integer() + Where E is the public exponent, N is public modulus and + D is the private exponent. + P1, P2, E1, E2, C = integer() + The longer key format contains redundant information that will make + the calculation faster. P1,P2 are first and second prime factors. + E1,E2 are first and second exponents. C is the CRT coefficient. + Terminology is taken from RFC 3447. + Padding = rsa_pkcs1_padding | rsa_pkcs1_oaep_padding | rsa_no_padding + PlainText = binary() -

Convert a EC key an Erlang term into a NIF resource. +

Decrypts the ChipherText (usually a session key encrypted with + rsa_public_encrypt/3) + using the PrivateKey and returns the + message. The Padding is the padding mode that was + used to encrypt the data, + see rsa_public_encrypt/3.

- ecdsa_sign(DataOrDigest, ECKey) -> Signature - ecdsa_sign(DigestType, DataOrDigest, ECKey) -> Signature - Sign the data using ecdsa with the given key. - - DataOrDigest = Data | {digest,Digest} - Data = Mpint - Digest = binary() - ECKey = EC key resource() - DigestType = md5 | sha | sha256 | sha384 | sha512 - The default DigestType is sha. - Mpint = binary() - Signature = binary() - - -

Creates a ESDSA signature with the private key Key - of a digest. The digest is either calculated as a - DigestType digest of Data or a precalculated - binary Digest.

-
-
- - - ecdsa_verify(DataOrDigest, Signature, ECKey) -> Verified - ecdsa_verify(DigestType, DataOrDigest, Signature, ECKey) -> Verified - Verify the digest and signature using ecdsa with given public key. - - Verified = boolean() - DataOrDigest = Data | {digest|Digest} - Data, Signature = Mpint - Digest = binary() - ECKey = EC key resource() - DigestType = md5 | sha | sha256 | sha384 | sha512 - The default DigestType is sha. - Mpint = binary() - - -

Verifies that a digest matches the ECDSA signature using the - signer's public key Key. - The digest is either calculated as a DigestType - digest of Data or a precalculated binary Digest.

-

May throw exception notsup in case the chosen DigestType - is not supported by the underlying OpenSSL implementation.

-
-
- - - ecdh_compute_key(OthersPublicKey, MyPrivateKey) -> SharedSecret - ecdh_compute_key(OthersPublicKey, MyECPoint) -> SharedSecret - Computes the shared secret + rsa_private_encrypt(PlainText, PrivateKey, Padding) -> ChipherText + Encrypts Msg using the private Key. - OthersPublicKey, MyPrivateKey = ECKey() - MyPrivatePoint = binary() - SharedSecret = binary() + PlainText = binary() + PrivateKey = [E, N, D] | [E, N, D, P1, P2, E1, E2, C] + E, N, D = integer() + Where E is the public exponent, N is public modulus and + D is the private exponent. + P1, P2, E1, E2, C = integer() + The longer key format contains redundant information that will make + the calculation faster. P1,P2 are first and second prime factors. + E1,E2 are first and second exponents. C is the CRT coefficient. + Terminology is taken from RFC 3447. + Padding = rsa_pkcs1_padding | rsa_no_padding + ChipherText = binary() -

Computes the shared secret from the private key and the other party's public key. +

Encrypts the PlainText using the PrivateKey + and returns the cipher. The Padding decides what padding mode is used, + rsa_pkcs1_padding is PKCS #1 v1.5 currently the most + used mode. + The size of the Msg must be less than byte_size(N)-11 if + rsa_pkcs1_padding is used, and byte_size(N) if rsa_no_padding + is used.

- - exor(Data1, Data2) -> Result - XOR data + rsa_public_decrypt(ChipherText, PublicKey, Padding) -> PlainText + Decrypts ChipherText using the public Key. - Data1, Data2 = iolist() | binary() - Result = binary() + ChipherText = binary() + PublicKey = [E, N] + E, N = integer() + Where E is the public exponent and N is public modulus + Padding = rsa_pkcs1_padding | rsa_no_padding + PlainText = binary() -

Performs bit-wise XOR (exclusive or) on the data supplied.

+

Decrypts the ChipherText (encrypted with + rsa_private_encrypt/3) + using the PrivateKey and returns the + message. The Padding is the padding mode that was + used to encrypt the data, + see rsa_private_encrypt/3. +

-
- -
- Elliptic Curve Key -

Elliptic Curve keys consist of the curve paramters and a the - private and public keys (points on the curve). Translating the - raw curve paraters into something usable for the underlying - OpenSSL implementation is a complicated process. The main cryptografic - functions therefore expect a NIF resource as input that contains the - key in an internal format. Two functions ec_key_to_term/1 - and term_to_ec_key are provided to convert between Erlang - terms and the resource format

-

Key in term form

-
-ec_named_curve() = atom()
-ec_point() = binary()
-ec_basis() = {tpbasis, K :: non_neg_integer()} | {ppbasis, K1 :: non_neg_integer(), K2 :: non_neg_integer(), K3 :: non_neg_integer()} | onbasis
-ec_field() = {prime_field, Prime :: Mpint()} | {characteristic_two_field, M :: integer(), Basis :: ec_basis()}
-ec_prime() = {A :: Mpint(), B :: Mpint(), Seed :: binary()}
-ec_curve_spec() = {Field :: ec_field(), Prime :: ec_prime(), Point :: ec_point(), Order :: Mpint(), CoFactor :: none | Mpint()}
-ec_curve() = ec_named_curve() | ec_curve_spec()
-ec_key() = {Curve :: ec_curve(), PrivKey :: Mpint() | undefined, PubKey :: ec_point() | undefined}
-    
-
+
DES in CBC mode diff --git a/lib/crypto/doc/src/crypto_app.xml b/lib/crypto/doc/src/crypto_app.xml index 8371db1ff2..20f4ed5c45 100644 --- a/lib/crypto/doc/src/crypto_app.xml +++ b/lib/crypto/doc/src/crypto_app.xml @@ -1,4 +1,4 @@ - + @@ -24,23 +24,14 @@ crypto - Peter Högfeldt - Peter Högfeldt - - Peter Högfeldt - Peter Högfeldt - 2003-06-01 - B crypto_app.sgml crypto The Crypto Application -

The purpose of the Crypto application is to provide message - digest and DES encryption for SMNPv3. It provides computation of - message digests MD5 and SHA, and CBC-DES encryption and - decryption.

-

+

The purpose of the Crypto application is to provide erlang + acess to crypto graphic functions in openssl. +

@@ -68,36 +59,6 @@

Source releases of OpenSSL can be downloaded from the OpenSSL project home page, or mirror sites listed there.

-

The same URL also contains links to some compiled binaries and - libraries of OpenSSL (see the Related/Binaries menu) of - which the Shining Light Productions Win32 and OpenSSL pages are of - interest for the Win32 user. -

-

For some Unix flavours there are binary packages available - on the net. -

-

If you cannot find a suitable binary OpenSSL package, you - have to fetch an OpenSSL source release and compile it. -

-

You then have to compile and install the library - libcrypto.so (Unix), or the library libeay32.dll - (Win32). -

-

For Unix The crypto_drv dynamic driver is delivered linked - to OpenSSL libraries in /usr/local/lib, but the default - dynamic linking will also accept libraries in /lib and - /usr/lib. -

-

If that is not applicable to the particular Unix operating - system used, the example Makefile in the Crypto - priv/obj directory, should be used as a basis for - relinking the final version of the port program. -

-

For Win32 it is only required that the library can be - found from the PATH environment variable, or that they - reside in the appropriate SYSTEM32 directory; hence no - particular relinking is need. Hence no example Makefile - for Win32 is provided.

diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index f87644b3fe..2b5ccb6ef4 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -23,19 +23,13 @@ -export([start/0, stop/0, info/0, info_lib/0, algorithms/0, version/0]). -export([hash/2, hash_init/1, hash_update/2, hash_final/1]). --export([md4/1, md4_init/0, md4_update/2, md4_final/1]). --export([md5/1, md5_init/0, md5_update/2, md5_final/1]). --export([sha/1, sha_init/0, sha_update/2, sha_final/1]). --export([sha224/1, sha224_init/0, sha224_update/2, sha224_final/1]). --export([sha256/1, sha256_init/0, sha256_update/2, sha256_final/1]). --export([sha384/1, sha384_init/0, sha384_update/2, sha384_final/1]). --export([sha512/1, sha512_init/0, sha512_update/2, sha512_final/1]). --export([md5_mac/2, md5_mac_96/2, sha_mac/2, sha_mac/3, sha_mac_96/2]). --export([sha224_mac/2, sha224_mac/3]). --export([sha256_mac/2, sha256_mac/3]). --export([sha384_mac/2, sha384_mac/3]). --export([sha512_mac/2, sha512_mac/3]). +-export([sign/4, verify/5]). +-export([generate_key/2, generate_key/3, compute_key/4]). -export([hmac/3, hmac/4, hmac_init/2, hmac_update/2, hmac_final/1, hmac_final_n/2]). +-export([exor/2]). +-export([strong_rand_bytes/1, mod_exp_prime/3]). +-export([rand_bytes/1, rand_bytes/3, rand_uniform/2]). + -export([des_cbc_encrypt/3, des_cbc_decrypt/3, des_cbc_ivec/1]). -export([des_ecb_encrypt/2, des_ecb_decrypt/2]). -export([des_cfb_encrypt/3, des_cfb_decrypt/3, des_cfb_ivec/2]). @@ -47,41 +41,69 @@ -export([blowfish_ofb64_encrypt/3]). -export([des_ede3_cbc_encrypt/5, des_ede3_cbc_decrypt/5]). -export([aes_cfb_128_encrypt/3, aes_cfb_128_decrypt/3]). --export([exor/2]). -export([rc4_encrypt/2, rc4_set_key/1, rc4_encrypt_with_state/2]). -export([rc2_cbc_encrypt/3, rc2_cbc_decrypt/3, rc2_40_cbc_encrypt/3, rc2_40_cbc_decrypt/3]). --export([dss_verify/3, dss_verify/4, rsa_verify/3, rsa_verify/4]). --export([dss_sign/2, dss_sign/3, rsa_sign/2, rsa_sign/3]). -export([rsa_public_encrypt/3, rsa_private_decrypt/3]). -export([rsa_private_encrypt/3, rsa_public_decrypt/3]). --export([dh_generate_key/1, dh_generate_key/2, dh_compute_key/3]). --export([rand_bytes/1, rand_bytes/3, rand_uniform/2]). --export([strong_rand_bytes/1, strong_rand_mpint/3]). --export([mod_exp/3, mod_exp_prime/3, mpint/1, erlint/1]). - -%% -export([idea_cbc_encrypt/3, idea_cbc_decrypt/3]). -export([aes_cbc_128_encrypt/3, aes_cbc_128_decrypt/3]). -export([aes_cbc_256_encrypt/3, aes_cbc_256_decrypt/3]). -export([aes_cbc_ivec/1]). -export([aes_ctr_encrypt/3, aes_ctr_decrypt/3]). -export([aes_ctr_stream_init/2, aes_ctr_stream_encrypt/2, aes_ctr_stream_decrypt/2]). --export([sign/4, verify/5]). --export([generate_key/2, generate_key/3, compute_key/4]). +-export([dh_generate_parameters/2, dh_check/1]). %% Testing see + +%% DEPRECATED +-export([md4/1, md4_init/0, md4_update/2, md4_final/1]). +-export([md5/1, md5_init/0, md5_update/2, md5_final/1]). +-export([sha/1, sha_init/0, sha_update/2, sha_final/1]). +-deprecated({md4, 1, next_major_release}). +-deprecated({md5, 1, next_major_release}). +-deprecated({sha, 1, next_major_release}). +-deprecated({md4_init, 0, next_major_release}). +-deprecated({md5_init, 0, next_major_release}). +-deprecated({sha_init, 0, next_major_release}). +-deprecated({md4_update, 2, next_major_release}). +-deprecated({md5_update, 2, next_major_release}). +-deprecated({sha_update, 2, next_major_release}). +-deprecated({md4_final, 1, next_major_release}). +-deprecated({md5_final, 1, next_major_release}). +-deprecated({sha_final, 1, next_major_release}). + +-export([md5_mac/2, md5_mac_96/2, sha_mac/2, sha_mac/3, sha_mac_96/2]). +-deprecated({md5_mac, 2, next_major_release}). +-deprecated({md5_mac_96, 2, next_major_release}). +-deprecated({sha_mac, 2, next_major_release}). +-deprecated({sha_mac, 3, next_major_release}). +-deprecated({sha_mac_96, 2, next_major_release}). --export([dh_generate_parameters/2, dh_check/1]). %% Testing see below +-export([dss_verify/3, dss_verify/4, rsa_verify/3, rsa_verify/4]). +-export([dss_sign/2, dss_sign/3, rsa_sign/2, rsa_sign/3]). +-deprecated({dss_verify, 3, next_major_release}). +-deprecated({dss_verify, 4, next_major_release}). +-deprecated({rsa_verify, 3, next_major_release}). +-deprecated({rsa_verify, 4, next_major_release}). +-deprecated({dss_sign, 2, next_major_release}). +-deprecated({dss_sign, 3, next_major_release}). +-deprecated({rsa_sign, 2, next_major_release}). +-deprecated({rsa_sign, 3, next_major_release}). +-export([dh_generate_key/1, dh_generate_key/2, dh_compute_key/3]). +-deprecated({dh_generate_key, 1, next_major_release}). +-deprecated({dh_generate_key, 2, next_major_release}). +-deprecated({dh_compute_key, 3, next_major_release}). + +-export([mod_exp/3, mpint/1, erlint/1, strong_rand_mpint/3]). +-deprecated({mod_exp, 3, next_major_release}). +-deprecated({mpint, 1, next_major_release}). +-deprecated({erlint, 1, next_major_release}). +-deprecated({strong_rand_mpint, 3, next_major_release}). -define(FUNC_LIST, [md4, md4_init, md4_update, md4_final, md5, md5_init, md5_update, md5_final, sha, sha_init, sha_update, sha_final, - sha224, sha224_init, sha224_update, sha224_final, - sha256, sha256_init, sha256_update, sha256_final, - sha384, sha384_init, sha384_update, sha384_final, - sha512, sha512_init, sha512_update, sha512_final, md5_mac, md5_mac_96, sha_mac, sha_mac_96, - sha224_mac, sha256_mac, sha384_mac, sha512_mac, des_cbc_encrypt, des_cbc_decrypt, des_cfb_encrypt, des_cfb_decrypt, des_ecb_encrypt, des_ecb_decrypt, @@ -102,7 +124,6 @@ exor, rc4_encrypt, rc4_set_key, rc4_encrypt_with_state, rc2_40_cbc_encrypt, rc2_40_cbc_decrypt, - %% idea_cbc_encrypt, idea_cbc_decrypt, aes_cbc_256_encrypt, aes_cbc_256_decrypt, aes_ctr_encrypt, aes_ctr_decrypt, aes_ctr_stream_init, aes_ctr_stream_encrypt, aes_ctr_stream_decrypt, @@ -124,13 +145,13 @@ -type crypto_integer() :: binary() | integer(). -type ec_key_res() :: any(). %% nif resource -type ec_named_curve() :: atom(). --type ec_point() :: binary(). +-type ec_point() :: crypto_integer(). -type ec_basis() :: {tpbasis, K :: non_neg_integer()} | {ppbasis, K1 :: non_neg_integer(), K2 :: non_neg_integer(), K3 :: non_neg_integer()} | onbasis. --type ec_field() :: {prime_field, Prime :: mpint()} | {characteristic_two_field, M :: integer(), Basis :: ec_basis()}. --type ec_prime() :: {A :: mpint(), B :: mpint(), Seed :: binary()}. --type ec_curve_spec() :: {Field :: ec_field(), Prime :: ec_prime(), Point :: ec_point(), Order :: mpint(), CoFactor :: none | mpint()}. +-type ec_field() :: {prime_field, Prime :: integer()} | {characteristic_two_field, M :: integer(), Basis :: ec_basis()}. +-type ec_prime() :: {A :: crypto_integer(), B :: crypto_integer(), Seed :: binary() | none}. +-type ec_curve_spec() :: {Field :: ec_field(), Prime :: ec_prime(), Point :: crypto_integer(), Order :: integer(), CoFactor :: none | integer()}. -type ec_curve() :: ec_named_curve() | ec_curve_spec(). --type ec_key() :: {Curve :: ec_curve(), PrivKey :: mpint() | undefined, PubKey :: ec_point() | undefined}. +-type ec_key() :: {Curve :: ec_curve(), PrivKey :: binary() | undefined, PubKey :: ec_point() | undefined}. -define(nif_stub,nif_stub_error(?LINE)). @@ -944,11 +965,11 @@ ecdsa_sign_nif(_Type, _DataOrDigest, _Key) -> ?nif_stub. -spec rsa_public_encrypt(binary(), [binary()], rsa_padding()) -> binary(). --spec rsa_public_decrypt(binary(), [binary()], rsa_padding()) -> +-spec rsa_public_decrypt(binary(), [integer() | mpint()], rsa_padding()) -> binary(). --spec rsa_private_encrypt(binary(), [binary()], rsa_padding()) -> +-spec rsa_private_encrypt(binary(), [integer() | mpint()], rsa_padding()) -> binary(). --spec rsa_private_decrypt(binary(), [binary()], rsa_padding()) -> +-spec rsa_private_decrypt(binary(), [integer() | mpint()], rsa_padding()) -> binary(). %% Binary, Key = [E,N] @@ -1216,8 +1237,6 @@ ecdh_compute_key_nif(_Others, _My) -> ?nif_stub. %% %% EC %% - --spec ec_key_to_term(ec_key_res()) -> ec_key(). ec_key_to_term(Key) -> case ec_key_to_term_nif(Key) of {PrivKey, PubKey} -> diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl index 3ebe10866c..eff0f8a878 100644 --- a/lib/crypto/test/crypto_SUITE.erl +++ b/lib/crypto/test/crypto_SUITE.erl @@ -360,7 +360,7 @@ hmac_update_sha(Config) when is_list(Config) -> ?line Ctx2 = crypto:hmac_update(Ctx, Data), ?line Ctx3 = crypto:hmac_update(Ctx2, Data2), ?line Mac = crypto:hmac_final(Ctx3), - ?line Exp = crypto:sha_mac(Key, lists:flatten([Data, Data2])), + ?line Exp = crypto:hmac(sha, Key, lists:flatten([Data, Data2])), ?line m(Exp, Mac). hmac_update_sha256(doc) -> @@ -382,7 +382,7 @@ hmac_update_sha256_do() -> ?line Ctx2 = crypto:hmac_update(Ctx, Data), ?line Ctx3 = crypto:hmac_update(Ctx2, Data2), ?line Mac = crypto:hmac_final(Ctx3), - ?line Exp = crypto:sha256_mac(Key, lists:flatten([Data, Data2])), + ?line Exp = crypto:hmac(sha256, Key, lists:flatten([Data, Data2])), ?line m(Exp, Mac). hmac_update_sha512(doc) -> @@ -404,7 +404,7 @@ hmac_update_sha512_do() -> ?line Ctx2 = crypto:hmac_update(Ctx, Data), ?line Ctx3 = crypto:hmac_update(Ctx2, Data2), ?line Mac = crypto:hmac_final(Ctx3), - ?line Exp = crypto:sha512_mac(Key, lists:flatten([Data, Data2])), + ?line Exp = crypto:hmac(sha512, Key, lists:flatten([Data, Data2])), ?line m(Exp, Mac). hmac_update_md5(doc) -> @@ -619,68 +619,64 @@ hmac_rfc4231_sha512(suite) -> hmac_rfc4231_sha512(Config) when is_list(Config) -> if_supported(sha512, fun() -> hmac_rfc4231_sha512_do() end). -hmac_rfc4231_case(Hash, HashFun, case1, Exp) -> +hmac_rfc4231_case(Hash, case1, Exp) -> %% Test 1 Key = binary:copy(<<16#0b>>, 20), Data = <<"Hi There">>, - hmac_rfc4231_case(Hash, HashFun, Key, Data, Exp); + hmac_rfc4231_case(Hash, Key, Data, Exp); -hmac_rfc4231_case(Hash, HashFun, case2, Exp) -> +hmac_rfc4231_case(Hash, case2, Exp) -> %% Test 2 Key = <<"Jefe">>, Data = <<"what do ya want for nothing?">>, - hmac_rfc4231_case(Hash, HashFun, Key, Data, Exp); + hmac_rfc4231_case(Hash, Key, Data, Exp); -hmac_rfc4231_case(Hash, HashFun, case3, Exp) -> +hmac_rfc4231_case(Hash, case3, Exp) -> %% Test 3 Key = binary:copy(<<16#aa>>, 20), Data = binary:copy(<<16#dd>>, 50), - hmac_rfc4231_case(Hash, HashFun, Key, Data, Exp); + hmac_rfc4231_case(Hash, Key, Data, Exp); -hmac_rfc4231_case(Hash, HashFun, case4, Exp) -> +hmac_rfc4231_case(Hash, case4, Exp) -> %% Test 4 Key = list_to_binary(lists:seq(1, 16#19)), Data = binary:copy(<<16#cd>>, 50), - hmac_rfc4231_case(Hash, HashFun, Key, Data, Exp); + hmac_rfc4231_case(Hash, Key, Data, Exp); -hmac_rfc4231_case(Hash, HashFun, case5, Exp) -> +hmac_rfc4231_case(Hash, case5, Exp) -> %% Test 5 Key = binary:copy(<<16#0c>>, 20), Data = <<"Test With Truncation">>, - hmac_rfc4231_case(Hash, HashFun, Key, Data, 16, Exp); + hmac_rfc4231_case(Hash, Key, Data, 16, Exp); -hmac_rfc4231_case(Hash, HashFun, case6, Exp) -> +hmac_rfc4231_case(Hash, case6, Exp) -> %% Test 6 Key = binary:copy(<<16#aa>>, 131), Data = <<"Test Using Larger Than Block-Size Key - Hash Key First">>, - hmac_rfc4231_case(Hash, HashFun, Key, Data, Exp); + hmac_rfc4231_case(Hash, Key, Data, Exp); -hmac_rfc4231_case(Hash, HashFun, case7, Exp) -> +hmac_rfc4231_case(Hash, case7, Exp) -> %% Test Case 7 Key = binary:copy(<<16#aa>>, 131), Data = <<"This is a test using a larger than block-size key and a larger t", "han block-size data. The key needs to be hashed before being use", "d by the HMAC algorithm.">>, - hmac_rfc4231_case(Hash, HashFun, Key, Data, Exp). + hmac_rfc4231_case(Hash, Key, Data, Exp). -hmac_rfc4231_case(Hash, HashFun, Key, Data, Exp) -> +hmac_rfc4231_case(Hash, Key, Data, Exp) -> ?line Ctx = crypto:hmac_init(Hash, Key), ?line Ctx2 = crypto:hmac_update(Ctx, Data), ?line Mac1 = crypto:hmac_final(Ctx2), - ?line Mac2 = crypto:HashFun(Key, Data), ?line Mac3 = crypto:hmac(Hash, Key, Data), ?line m(Exp, Mac1), - ?line m(Exp, Mac2), ?line m(Exp, Mac3). -hmac_rfc4231_case(Hash, HashFun, Key, Data, Trunc, Exp) -> +hmac_rfc4231_case(Hash, Key, Data, Trunc, Exp) -> ?line Ctx = crypto:hmac_init(Hash, Key), ?line Ctx2 = crypto:hmac_update(Ctx, Data), ?line Mac1 = crypto:hmac_final_n(Ctx2, Trunc), - ?line Mac2 = crypto:HashFun(Key, Data, Trunc), ?line Mac3 = crypto:hmac(Hash, Key, Data, Trunc), ?line m(Exp, Mac1), - ?line m(Exp, Mac2), ?line m(Exp, Mac3). hmac_rfc4231_sha224_do() -> @@ -697,7 +693,7 @@ hmac_rfc4231_sha224_do() -> "d499f112f2d2b7273fa6870e"), Case7 = hexstr2bin("3a854166ac5d9f023f54d517d0b39dbd" "946770db9c2b95c9f6f565d1"), - hmac_rfc4231_cases_do(sha224, sha224_mac, [Case1, Case2, Case3, Case4, Case5, Case6, Case7]). + hmac_rfc4231_cases_do(sha224, [Case1, Case2, Case3, Case4, Case5, Case6, Case7]). hmac_rfc4231_sha256_do() -> Case1 = hexstr2bin("b0344c61d8db38535ca8afceaf0bf12b" @@ -713,7 +709,7 @@ hmac_rfc4231_sha256_do() -> "8e0bc6213728c5140546040f0ee37f54"), Case7 = hexstr2bin("9b09ffa71b942fcb27635fbcd5b0e944" "bfdc63644f0713938a7f51535c3a35e2"), - hmac_rfc4231_cases_do(sha256, sha256_mac, [Case1, Case2, Case3, Case4, Case5, Case6, Case7]). + hmac_rfc4231_cases_do(sha256, [Case1, Case2, Case3, Case4, Case5, Case6, Case7]). hmac_rfc4231_sha384_do() -> Case1 = hexstr2bin("afd03944d84895626b0825f4ab46907f" @@ -735,7 +731,7 @@ hmac_rfc4231_sha384_do() -> Case7 = hexstr2bin("6617178e941f020d351e2f254e8fd32c" "602420feb0b8fb9adccebb82461e99c5" "a678cc31e799176d3860e6110c46523e"), - hmac_rfc4231_cases_do(sha384, sha384_mac, [Case1, Case2, Case3, Case4, Case5, Case6, Case7]). + hmac_rfc4231_cases_do(sha384, [Case1, Case2, Case3, Case4, Case5, Case6, Case7]). hmac_rfc4231_sha512_do() -> Case1 = hexstr2bin("87aa7cdea5ef619d4ff0b4241a1d6cb0" @@ -763,16 +759,16 @@ hmac_rfc4231_sha512_do() -> "debd71f8867289865df5a32d20cdc944" "b6022cac3c4982b10d5eeb55c3e4de15" "134676fb6de0446065c97440fa8c6a58"), - hmac_rfc4231_cases_do(sha512, sha512_mac, [Case1, Case2, Case3, Case4, Case5, Case6, Case7]). + hmac_rfc4231_cases_do(sha512, [Case1, Case2, Case3, Case4, Case5, Case6, Case7]). -hmac_rfc4231_cases_do(Hash, HashFun, CasesData) -> - hmac_rfc4231_cases_do(Hash, HashFun, [case1, case2, case3, case4, case5, case6, case7], CasesData). +hmac_rfc4231_cases_do(Hash, CasesData) -> + hmac_rfc4231_cases_do(Hash, [case1, case2, case3, case4, case5, case6, case7], CasesData). -hmac_rfc4231_cases_do(_Hash, _HashFun, _, []) -> +hmac_rfc4231_cases_do(_Hash, _, []) -> ok; -hmac_rfc4231_cases_do(Hash, HashFun, [C|Cases], [D|CasesData]) -> - hmac_rfc4231_case(Hash, HashFun, C, D), - hmac_rfc4231_cases_do(Hash, HashFun, Cases, CasesData). +hmac_rfc4231_cases_do(Hash, [C|Cases], [D|CasesData]) -> + hmac_rfc4231_case(Hash, C, D), + hmac_rfc4231_cases_do(Hash, Cases, CasesData). hmac_update_md5_io(doc) -> ["Generate an MD5 HMAC using hmac_init, hmac_update, and hmac_final. " @@ -859,10 +855,10 @@ sha256(Config) when is_list(Config) -> if_supported(sha256, fun() -> sha256_do() end). sha256_do() -> - ?line m(crypto:sha256("abc"), + ?line m(crypto:hash(sha256, "abc"), hexstr2bin("BA7816BF8F01CFEA4141" "40DE5DAE2223B00361A396177A9CB410FF61F20015AD")), - ?line m(crypto:sha256("abcdbcdecdefdefgefghfghighijhijkijkljklmklm" + ?line m(crypto:hash(sha256, "abcdbcdecdefdefgefghfghighijhijkijkljklmklm" "nlmnomnopnopq"), hexstr2bin("248D6A61D20638B8" "E5C026930C3E6039A33CE45964FF2167F6ECEDD419DB06C1")). @@ -878,10 +874,10 @@ sha256_update(Config) when is_list(Config) -> if_supported(sha256, fun() -> sha256_update_do() end). sha256_update_do() -> - ?line Ctx = crypto:sha256_init(), - ?line Ctx1 = crypto:sha256_update(Ctx, "abcdbcdecdefdefgefghfghighi"), - ?line Ctx2 = crypto:sha256_update(Ctx1, "jhijkijkljklmklmnlmnomnopnopq"), - ?line m(crypto:sha256_final(Ctx2), + ?line Ctx = crypto:hash_init(sha256), + ?line Ctx1 = crypto:hash_update(Ctx, "abcdbcdecdefdefgefghfghighi"), + ?line Ctx2 = crypto:hash_update(Ctx1, "jhijkijkljklmklmnlmnomnopnopq"), + ?line m(crypto:hash_final(Ctx2), hexstr2bin("248D6A61D20638B8" "E5C026930C3E6039A33CE45964FF2167F6ECEDD419DB06C1")). @@ -897,11 +893,11 @@ sha512(Config) when is_list(Config) -> if_supported(sha512, fun() -> sha512_do() end). sha512_do() -> - ?line m(crypto:sha512("abc"), + ?line m(crypto:hash(sha512, "abc"), hexstr2bin("DDAF35A193617ABACC417349AE20413112E6FA4E89A97EA2" "0A9EEEE64B55D39A2192992A274FC1A836BA3C23A3FEEBBD" "454D4423643CE80E2A9AC94FA54CA49F")), - ?line m(crypto:sha512("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" + ?line m(crypto:hash(sha512, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"), hexstr2bin("8E959B75DAE313DA8CF4F72814FC143F8F7779C6EB9F7FA1" "7299AEADB6889018501D289E4900F7E4331B99DEC4B5433A" @@ -918,10 +914,10 @@ sha512_update(Config) when is_list(Config) -> if_supported(sha512, fun() -> sha512_update_do() end). sha512_update_do() -> - ?line Ctx = crypto:sha512_init(), - ?line Ctx1 = crypto:sha512_update(Ctx, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"), - ?line Ctx2 = crypto:sha512_update(Ctx1, "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"), - ?line m(crypto:sha512_final(Ctx2), + ?line Ctx = crypto:hash_init(sha512), + ?line Ctx1 = crypto:hash_update(Ctx, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"), + ?line Ctx2 = crypto:hash_update(Ctx1, "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"), + ?line m(crypto:hash_final(Ctx2), hexstr2bin("8E959B75DAE313DA8CF4F72814FC143F8F7779C6EB9F7FA1" "7299AEADB6889018501D289E4900F7E4331B99DEC4B5433A" "C7D329EEB6DD26545E96E55B874BE909")). -- cgit v1.2.3 From 50605d756a9fc0a247e19922dff53b4a9d639a59 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Tue, 30 Apr 2013 13:13:48 +0200 Subject: crypto: New API for ciphers --- lib/crypto/doc/src/crypto.xml | 929 ++++++++++++--------------------------- lib/crypto/src/crypto.erl | 305 +++++++++++-- lib/crypto/test/crypto_SUITE.erl | 16 +- 3 files changed, 544 insertions(+), 706 deletions(-) (limited to 'lib/crypto') diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml index c4e6993460..0fb53346ca 100644 --- a/lib/crypto/doc/src/crypto.xml +++ b/lib/crypto/doc/src/crypto.xml @@ -127,15 +127,65 @@ secp112r2| secp112r1| sect113r2| sect113r1| sect239k1| sect163r1| sect163k1| secp256r1| secp192r1

+

stream_cipher() = rc4 | aes_ctr

+ +

block_cipher() = aes_cbc128 | aes_cfb128 | blowfish_cbc | + blowfish_cfb64 | des_cbc | des_cfb | des3_cbc | des3_cbf + | des_ede3 | rc2_cbc

+ +

stream_key() = aes_key() | rc4_key()

+ +

block_key() = aes_key() | blowfish_key() | des_key()| des3_key()

+ +

aes_key() = binary() Key length is 128, 192 or 256 bits

+ +

rc4_key() = binary() Variable key length from 8 bits up to 2048 bits (usually between 40 and 256)

+ +

blowfish_key() = binary() Variable key length from 32 bits up to 448 bits

+ +

des_key() = binary() Key length is 64 bits (in CBC mod only 8 bits are used)

+ +

des3_key() = [binary(), binary(), binary()] Each key part is 64 bits (in CBC mod only 8 bits are used)

- + algorithms() -> [atom()] Provide a list of available crypto algorithms.

Provides the available crypto algorithms in terms of a list - of atoms.

+ of atoms. This is interesting as older versions of the openssl + crypto library may not support all algorithms used in the crypto API.

+
+
+ + + block_encrypt(Type, Key, Ivec, PlainText) -> CipherText + Encrypt PlainTextaccording to Type block cipher + + Key = block_key() + PlainText = iodata() | binary() + IVec = CipherText = binary() + + +

Encrypt PlainTextaccording to Type block cipher. + IVec is an arbitrary initializing vector. +

+
+
+ + + block_decrypt(Type, Key, Ivec, CipherText) -> PlainText + Decrypt CipherTextaccording to Type block cipher + + Key = block_key() + PlainText = iodata() | binary() + IVec = CipherText = binary() + + +

Decrypt CipherTextaccording to Type block cipher. + IVec is an arbitrary initializing vector. +

@@ -314,15 +364,6 @@
- - info() -> [atom()] - Provide a list of available crypto functions. - -

Provides the available crypto functions in terms of a list - of atoms.

-
-
- info_lib() -> [{Name,VerNum,VerStr}] Provides information about the libraries used by crypto. @@ -361,6 +402,109 @@ + + next_iv(Type, Data) -> + + + Type = des_cbc | aes_cbc + Data = iodata() + + +

Returns the initialization vector to be used in the next + iteration of encrypt/decrypt of type Type. Data is the + encrypted data from the previous iteration step.

+
+
+ + + private_decrypt(Type, ChipherText, PrivateKey, Padding) -> PlainText + Decrypts ChipherText using the private Key. + + Type = rsa + ChipherText = binary() + PrivateKey = rsa_private() + Padding = rsa_pkcs1_padding | rsa_pkcs1_oaep_padding | rsa_no_padding + PlainText = binary() + + +

Decrypts the ChipherText (usually a session key encrypted with + public_encrypt/3) + using the PrivateKey and returns the + message. The Padding is the padding mode that was + used to encrypt the data, + see public_encrypt/3. +

+
+
+ + + private_encrypt(Type, PlainText, PrivateKey, Padding) -> ChipherText + Encrypts Msg using the private Key. + + Type = rsa + PlainText = binary() + PrivateKey = rsa_private() + Padding = rsa_pkcs1_padding | rsa_no_padding + ChipherText = binary() + + +

Encrypts the PlainText using the PrivateKey + and returns the cipher. The Padding decides what padding mode is used, + rsa_pkcs1_padding is PKCS #1 v1.5 currently the most + used mode. + The size of the Msg must be less than byte_size(N)-11 if + rsa_pkcs1_padding is used, and byte_size(N) if rsa_no_padding + is used. +

+
+
+ + public_decrypt(Type, ChipherText, PublicKey, Padding) -> PlainText + Decrypts ChipherText using the public Key. + + Type = rsa + ChipherText = binary() + PublicKey = rsa_public() + Padding = rsa_pkcs1_padding | rsa_no_padding + PlainText = binary() + + +

Decrypts the ChipherText (encrypted with + private_encrypt/3) + using the PrivateKey and returns the + message. The Padding is the padding mode that was + used to encrypt the data, + see private_encrypt/3. +

+
+
+ + + public_encrypt(Type, PlainText, PublicKey, Padding) -> ChipherText + Encrypts Msg using the public Key. + + Type = rsa + PlainText = binary() + PublicKey = rsa_public() + Padding = rsa_pkcs1_padding | rsa_pkcs1_oaep_padding | rsa_no_padding + ChipherText = binary() + + +

Encrypts the PlainText (usually a session key) using the PublicKey + and returns the CipherText. The Padding decides what padding mode is used, + rsa_pkcs1_padding is PKCS #1 v1.5 currently the most + used mode and rsa_pkcs1_oaep_padding is EME-OAEP as + defined in PKCS #1 v2.0 with SHA-1, MGF1 and an empty encoding + parameter. This mode is recommended for all new applications. + The size of the Msg must be less + than byte_size(N)-11 if + rsa_pkcs1_padding is used, byte_size(N)-41 if + rsa_pkcs1_oaep_padding is used and byte_size(N) if rsa_no_padding + is used. +

+
+
+ rand_bytes(N) -> binary() Generate a binary of random bytes @@ -435,695 +579,162 @@ - verify(Algorithm, DigestType, Msg, Signature, Key) -> boolean() - Verifies a digital signature. - - Algorithm = rsa | dss | ecdsa - Msg = binary() | {digest,binary()} - The msg is either the binary "plain text" data - or it is the hashed value of "plain text" i.e. the digest. - DigestType = digest_type() - Signature = binary() - Key = rsa_public_key() | dsa_public_key() | ec_public_key() - - -

Verifies a digital signature

-
-
- - - aes_cfb_128_encrypt(Key, IVec, Text) -> Cipher - Encrypt Textaccording to AES in Cipher Feedback mode - - Key = Text = iolist() | binary() - IVec = Cipher = binary() - - -

Encrypts Text according to AES in Cipher Feedback - mode (CFB). Key is the - AES key, and IVec is an arbitrary initializing vector. - The lengths of Key and IVec must be 128 bits - (16 bytes).

-
-
- - - aes_cfb_128_decrypt(Key, IVec, Cipher) -> Text - Decrypt Cipheraccording to AES in Cipher Feedback mode - - Key = Cipher = iolist() | binary() - IVec = Text = binary() - - -

Decrypts Cipher according to AES in Cipher Feedback Mode (CFB). - Key is the AES key, and IVec is an arbitrary - initializing vector. Key and IVec must have - the same values as those used when encrypting. The lengths of - Key and IVec must be 128 bits (16 bytes).

-
-
- - - aes_cbc_128_encrypt(Key, IVec, Text) -> Cipher - Encrypt Textaccording to AES in Cipher Block Chaining mode - - Key = Text = iolist() | binary() - IVec = Cipher = binary() - - -

Encrypts Text according to AES in Cipher Block Chaining - mode (CBC). Text - must be a multiple of 128 bits (16 bytes). Key is the - AES key, and IVec is an arbitrary initializing vector. - The lengths of Key and IVec must be 128 bits - (16 bytes).

-
-
- - - aes_cbc_128_decrypt(Key, IVec, Cipher) -> Text - Decrypt Cipheraccording to AES in Cipher Block Chaining mode - - Key = Cipher = iolist() | binary() - IVec = Text = binary() - - -

Decrypts Cipher according to AES in Cipher Block - Chaining mode (CBC). - Key is the AES key, and IVec is an arbitrary - initializing vector. Key and IVec must have - the same values as those used when encrypting. Cipher - must be a multiple of 128 bits (16 bytes). The lengths of - Key and IVec must be 128 bits (16 bytes).

-
-
- - - aes_cbc_ivec(Data) -> IVec - Get IVec to be used in next iteration of - aes_cbc_*_[ecrypt|decrypt] + stream_init(Type, Key) -> State + - Data = iolist() | binary() + Type rc4 + State = opaque() + Key = iodata() IVec = binary() -

Returns the IVec to be used in a next iteration of - aes_cbc_*_[encrypt|decrypt]. Data is the encrypted - data from the previous iteration step.

+

Initializes the state for use in RC4 stream encryption + stream_encrypt and + stream_decrypt

- - aes_ctr_encrypt(Key, IVec, Text) -> Cipher - Encrypt Textaccording to AES in Counter mode - - Key = Text = iolist() | binary() - IVec = Cipher = binary() - - -

Encrypts Text according to AES in Counter mode (CTR). Text - can be any number of bytes. Key is the AES key and must be either - 128, 192 or 256 bits long. IVec is an arbitrary initializing vector of 128 bits - (16 bytes).

-
-
- - - aes_ctr_decrypt(Key, IVec, Cipher) -> Text - Decrypt Cipheraccording to AES in Counter mode - - Key = Cipher = iolist() | binary() - IVec = Text = binary() - - -

Decrypts Cipher according to AES in Counter mode (CTR). Cipher - can be any number of bytes. Key is the AES key and must be either - 128, 192 or 256 bits long. IVec is an arbitrary initializing vector of 128 bits - (16 bytes).

-
-
- - - aes_ctr_stream_init(Key, IVec) -> State + + stream_init(Type, Key, IVec) -> State - State = { K, I, E, C } - Key = K = iolist() - IVec = I = E = binary() - C = integer() + Type aes_ctr + State = opaque() + Key = iodata() + IVec = binary()

Initializes the state for use in streaming AES encryption using Counter mode (CTR). Key is the AES key and must be either 128, 192, or 256 bts long. IVec is an arbitrary initializing vector of 128 bits (16 bytes). This state is for use with - aes_ctr_stream_encrypt and - aes_ctr_stream_decrypt.

+ stream_encrypt and + stream_decrypt.

- aes_ctr_stream_encrypt(State, Text) -> { NewState, Cipher} + stream_encrypt(Type, State, PlainText) -> { NewState, CipherText} + Type = stream_cipher() Text = iolist() | binary() - Cipher = binary() + CipherText = binary() -

Encrypts Text according to AES in Counter mode (CTR). This function can be - used to encrypt a stream of text using a series of calls instead of requiring all - text to be in memory. Text can be any number of bytes. State is initialized using - aes_ctr_stream_init. NewState is the new streaming - encryption state that must be passed to the next call to aes_ctr_stream_encrypt. - Cipher is the encrypted cipher text.

+

Encrypts PlainText according to the stream cipher Type. + Text can be any number of bytes. State is initialized using + stream_init on + the next invocation of this function the returned State shall be + given as input and so on until the end of the stream is reached.

- aes_ctr_stream_decrypt(State, Cipher) -> { NewState, Text } + stream_decrypt(Type, State, CipherText) -> { NewState, PlainText } - Cipher = iolist() | binary() - Text = binary() - - -

Decrypts Cipher according to AES in Counter mode (CTR). This function can be - used to decrypt a stream of ciphertext using a series of calls instead of requiring all - ciphertext to be in memory. Cipher can be any number of bytes. State is initialized using - aes_ctr_stream_init. NewState is the new streaming - encryption state that must be passed to the next call to aes_ctr_stream_encrypt. - Text is the decrypted data.

-
-
- - - blowfish_ecb_encrypt(Key, Text) -> Cipher - Encrypt the first 64 bits of Text using Blowfish in ECB mode - - Key = Text = iolist() | binary() - Cipher = binary() - - -

Encrypts the first 64 bits of Text using Blowfish in ECB mode. Key is the Blowfish key. The length of Text must be at least 64 bits (8 bytes).

-
-
- - - blowfish_ecb_decrypt(Key, Text) -> Cipher - Decrypt the first 64 bits of Text using Blowfish in ECB mode - - Key = Text = iolist() | binary() - Cipher = binary() - - -

Decrypts the first 64 bits of Text using Blowfish in ECB mode. Key is the Blowfish key. The length of Text must be at least 64 bits (8 bytes).

-
-
- - - blowfish_cbc_encrypt(Key, IVec, Text) -> Cipher - Encrypt Text using Blowfish in CBC mode - - Key = Text = iolist() | binary() - IVec = Cipher = binary() - - -

Encrypts Text using Blowfish in CBC mode. Key is the Blowfish key, and IVec is an - arbitrary initializing vector. The length of IVec - must be 64 bits (8 bytes). The length of Text must be a multiple of 64 bits (8 bytes).

-
-
- - blowfish_cbc_decrypt(Key, IVec, Text) -> Cipher - Decrypt Text using Blowfish in CBC mode - - Key = Text = iolist() | binary() - IVec = Cipher = binary() - - -

Decrypts Text using Blowfish in CBC mode. Key is the Blowfish key, and IVec is an - arbitrary initializing vector. The length of IVec - must be 64 bits (8 bytes). The length of Text must be a multiple 64 bits (8 bytes).

-
-
- - - blowfish_cfb64_encrypt(Key, IVec, Text) -> Cipher - Encrypt Textusing Blowfish in CFB mode with 64 - bit feedback - - Key = Text = iolist() | binary() - IVec = Cipher = binary() - - -

Encrypts Text using Blowfish in CFB mode with 64 bit - feedback. Key is the Blowfish key, and IVec is an - arbitrary initializing vector. The length of IVec - must be 64 bits (8 bytes).

-
-
- - - blowfish_cfb64_decrypt(Key, IVec, Text) -> Cipher - Decrypt Textusing Blowfish in CFB mode with 64 - bit feedback - - Key = Text = iolist() | binary() - IVec = Cipher = binary() - - -

Decrypts Text using Blowfish in CFB mode with 64 bit - feedback. Key is the Blowfish key, and IVec is an - arbitrary initializing vector. The length of IVec - must be 64 bits (8 bytes).

-
-
- - - blowfish_ofb64_encrypt(Key, IVec, Text) -> Cipher - Encrypt Textusing Blowfish in OFB mode with 64 - bit feedback - - Key = Text = iolist() | binary() - IVec = Cipher = binary() - - -

Encrypts Text using Blowfish in OFB mode with 64 bit - feedback. Key is the Blowfish key, and IVec is an - arbitrary initializing vector. The length of IVec - must be 64 bits (8 bytes).

-
-
- - - des_cbc_encrypt(Key, IVec, Text) -> Cipher - Encrypt Textaccording to DES in CBC mode - - Key = Text = iolist() | binary() - IVec = Cipher = binary() - - -

Encrypts Text according to DES in CBC - mode. Text must be a multiple of 64 bits (8 - bytes). Key is the DES key, and IVec is an - arbitrary initializing vector. The lengths of Key and - IVec must be 64 bits (8 bytes).

-
-
- - - des_cbc_decrypt(Key, IVec, Cipher) -> Text - Decrypt Cipheraccording to DES in CBC mode - - Key = Cipher = iolist() | binary() - IVec = Text = binary() - - -

Decrypts Cipher according to DES in CBC mode. - Key is the DES key, and IVec is an arbitrary - initializing vector. Key and IVec must have - the same values as those used when encrypting. Cipher - must be a multiple of 64 bits (8 bytes). The lengths of - Key and IVec must be 64 bits (8 bytes).

-
-
- - - des_cbc_ivec(Data) -> IVec - Get IVec to be used in next iteration of - des_cbc_[ecrypt|decrypt] - - Data = iolist() | binary() - IVec = binary() - - -

Returns the IVec to be used in a next iteration of - des_cbc_[encrypt|decrypt]. Data is the encrypted - data from the previous iteration step.

-
-
- - - des_cfb_encrypt(Key, IVec, Text) -> Cipher - Encrypt Textaccording to DES in CFB mode - - Key = Text = iolist() | binary() - IVec = Cipher = binary() - - -

Encrypts Text according to DES in 8-bit CFB - mode. Key is the DES key, and IVec is an - arbitrary initializing vector. The lengths of Key and - IVec must be 64 bits (8 bytes).

-
-
- - - des_cfb_decrypt(Key, IVec, Cipher) -> Text - Decrypt Cipheraccording to DES in CFB mode - - Key = Cipher = iolist() | binary() - IVec = Text = binary() - - -

Decrypts Cipher according to DES in 8-bit CFB mode. - Key is the DES key, and IVec is an arbitrary - initializing vector. Key and IVec must have - the same values as those used when encrypting. The lengths of - Key and IVec must be 64 bits (8 bytes).

-
-
- - - des_cfb_ivec(IVec, Data) -> NextIVec - Get IVec to be used in next iteration of - des_cfb_[ecrypt|decrypt] - - IVec = iolist() | binary() - Data = iolist() | binary() - NextIVec = binary() - - -

Returns the IVec to be used in a next iteration of - des_cfb_[encrypt|decrypt]. IVec is the vector - used in the previous iteration step. Data is the encrypted - data from the previous iteration step.

-
-
- - - des3_cbc_encrypt(Key1, Key2, Key3, IVec, Text) -> Cipher - Encrypt Textaccording to DES3 in CBC mode - - Key1 =Key2 = Key3 Text = iolist() | binary() - IVec = Cipher = binary() - - -

Encrypts Text according to DES3 in CBC - mode. Text must be a multiple of 64 bits (8 - bytes). Key1, Key2, Key3, are the DES - keys, and IVec is an arbitrary initializing - vector. The lengths of each of Key1, Key2, - Key3 and IVec must be 64 bits (8 bytes).

-
-
- - - des3_cbc_decrypt(Key1, Key2, Key3, IVec, Cipher) -> Text - Decrypt Cipheraccording to DES3 in CBC mode - - Key1 = Key2 = Key3 = Cipher = iolist() | binary() - IVec = Text = binary() - - -

Decrypts Cipher according to DES3 in CBC mode. - Key1, Key2, Key3 are the DES key, and - IVec is an arbitrary initializing vector. - Key1, Key2, Key3 and IVec must - and IVec must have the same values as those used when - encrypting. Cipher must be a multiple of 64 bits (8 - bytes). The lengths of Key1, Key2, - Key3, and IVec must be 64 bits (8 bytes).

-
-
- - - des3_cfb_encrypt(Key1, Key2, Key3, IVec, Text) -> Cipher - Encrypt Textaccording to DES3 in CFB mode - - Key1 =Key2 = Key3 Text = iolist() | binary() - IVec = Cipher = binary() - - -

Encrypts Text according to DES3 in 8-bit CFB - mode. Key1, Key2, Key3, are the DES - keys, and IVec is an arbitrary initializing - vector. The lengths of each of Key1, Key2, - Key3 and IVec must be 64 bits (8 bytes).

-

May throw exception notsup for old OpenSSL - versions (0.9.7) that does not support this encryption mode.

-
-
- - - des3_cfb_decrypt(Key1, Key2, Key3, IVec, Cipher) -> Text - Decrypt Cipheraccording to DES3 in CFB mode - - Key1 = Key2 = Key3 = Cipher = iolist() | binary() - IVec = Text = binary() - - -

Decrypts Cipher according to DES3 in 8-bit CFB mode. - Key1, Key2, Key3 are the DES key, and - IVec is an arbitrary initializing vector. - Key1, Key2, Key3 and IVec must - and IVec must have the same values as those used when - encrypting. The lengths of Key1, Key2, - Key3, and IVec must be 64 bits (8 bytes).

-

May throw exception notsup for old OpenSSL - versions (0.9.7) that does not support this encryption mode.

-
-
- - - des_ecb_encrypt(Key, Text) -> Cipher - Encrypt Textaccording to DES in ECB mode - - Key = Text = iolist() | binary() - Cipher = binary() - - -

Encrypts Text according to DES in ECB mode. - Key is the DES key. The lengths of Key and - Text must be 64 bits (8 bytes).

-
-
- - des_ecb_decrypt(Key, Cipher) -> Text - Decrypt Cipheraccording to DES in ECB mode - - Key = Cipher = iolist() | binary() - Text = binary() - - -

Decrypts Cipher according to DES in ECB mode. - Key is the DES key. The lengths of Key and - Cipher must be 64 bits (8 bytes).

-
-
- - rc2_cbc_encrypt(Key, IVec, Text) -> Cipher - Encrypt Textaccording to RC2 in CBC mode - - Key = Text = iolist() | binary() - Ivec = Cipher = binary() - - -

Encrypts Text according to RC2 in CBC mode.

-
-
- - - rc2_cbc_decrypt(Key, IVec, Cipher) -> Text - Decrypts Cipheraccording to RC2 in CBC mode - - Key = Text = iolist() | binary() - Ivec = Cipher = binary() - - -

Decrypts Cipher according to RC2 in CBC mode.

-
-
- - - rc4_encrypt(Key, Data) -> Result - Encrypt data using RC4 - - Key, Data = iolist() | binary() - Result = binary() - - -

Encrypts the data with RC4 symmetric stream encryption. - Since it is symmetric, the same function is used for - decryption.

-
-
- - - - rsa_public_encrypt(PlainText, PublicKey, Padding) -> ChipherText - Encrypts Msg using the public Key. - - PlainText = binary() - PublicKey = [E, N] - E, N = integer() - Where E is the public exponent and N is public modulus. - Padding = rsa_pkcs1_padding | rsa_pkcs1_oaep_padding | rsa_no_padding - ChipherText = binary() - - -

Encrypts the PlainText (usually a session key) using the PublicKey - and returns the cipher. The Padding decides what padding mode is used, - rsa_pkcs1_padding is PKCS #1 v1.5 currently the most - used mode and rsa_pkcs1_oaep_padding is EME-OAEP as - defined in PKCS #1 v2.0 with SHA-1, MGF1 and an empty encoding - parameter. This mode is recommended for all new applications. - The size of the Msg must be less - than byte_size(N)-11 if - rsa_pkcs1_padding is used, byte_size(N)-41 if - rsa_pkcs1_oaep_padding is used and byte_size(N) if rsa_no_padding - is used. -

-
-
- - - rsa_private_decrypt(ChipherText, PrivateKey, Padding) -> PlainText - Decrypts ChipherText using the private Key. - - ChipherText = binary() - PrivateKey = [E, N, D] | [E, N, D, P1, P2, E1, E2, C] - E, N, D = integer() - Where E is the public exponent, N is public modulus and - D is the private exponent. - P1, P2, E1, E2, C = integer() - The longer key format contains redundant information that will make - the calculation faster. P1,P2 are first and second prime factors. - E1,E2 are first and second exponents. C is the CRT coefficient. - Terminology is taken from RFC 3447. - Padding = rsa_pkcs1_padding | rsa_pkcs1_oaep_padding | rsa_no_padding + Type = stream_cipher() + CipherText = iodata() | binary() PlainText = binary() -

Decrypts the ChipherText (usually a session key encrypted with - rsa_public_encrypt/3) - using the PrivateKey and returns the - message. The Padding is the padding mode that was - used to encrypt the data, - see rsa_public_encrypt/3. -

+

Decrypts CipherText according to the stream cipher Type. + PlainText can be any number of bytes. State is initialized using + stream_init on + the next invocation of this function the returned State shall be + given as input and so on until the end of the stream is reached.

- - rsa_private_encrypt(PlainText, PrivateKey, Padding) -> ChipherText - Encrypts Msg using the private Key. - - PlainText = binary() - PrivateKey = [E, N, D] | [E, N, D, P1, P2, E1, E2, C] - E, N, D = integer() - Where E is the public exponent, N is public modulus and - D is the private exponent. - P1, P2, E1, E2, C = integer() - The longer key format contains redundant information that will make - the calculation faster. P1,P2 are first and second prime factors. - E1,E2 are first and second exponents. C is the CRT coefficient. - Terminology is taken from RFC 3447. - Padding = rsa_pkcs1_padding | rsa_no_padding - ChipherText = binary() - - -

Encrypts the PlainText using the PrivateKey - and returns the cipher. The Padding decides what padding mode is used, - rsa_pkcs1_padding is PKCS #1 v1.5 currently the most - used mode. - The size of the Msg must be less than byte_size(N)-11 if - rsa_pkcs1_padding is used, and byte_size(N) if rsa_no_padding - is used. -

-
-
- - rsa_public_decrypt(ChipherText, PublicKey, Padding) -> PlainText - Decrypts ChipherText using the public Key. + + verify(Algorithm, DigestType, Msg, Signature, Key) -> boolean() + Verifies a digital signature. - ChipherText = binary() - PublicKey = [E, N] - E, N = integer() - Where E is the public exponent and N is public modulus - Padding = rsa_pkcs1_padding | rsa_no_padding - PlainText = binary() + Algorithm = rsa | dss | ecdsa + Msg = binary() | {digest,binary()} + The msg is either the binary "plain text" data + or it is the hashed value of "plain text" i.e. the digest. + DigestType = digest_type() + Signature = binary() + Key = rsa_public_key() | dsa_public_key() | ec_public_key() -

Decrypts the ChipherText (encrypted with - rsa_private_encrypt/3) - using the PrivateKey and returns the - message. The Padding is the padding mode that was - used to encrypt the data, - see rsa_private_encrypt/3. -

+

Verifies a digital signature

+
-
- DES in CBC mode -

The Data Encryption Standard (DES) defines an algorithm for - encrypting and decrypting an 8 byte quantity using an 8 byte key - (actually only 56 bits of the key is used). -

-

When it comes to encrypting and decrypting blocks that are - multiples of 8 bytes various modes are defined (NIST SP - 800-38A). One of those modes is the Cipher Block Chaining (CBC) - mode, where the encryption of an 8 byte segment depend not only - of the contents of the segment itself, but also on the result of - encrypting the previous segment: the encryption of the previous - segment becomes the initializing vector of the encryption of the - current segment. -

-

Thus the encryption of every segment depends on the encryption - key (which is secret) and the encryption of the previous - segment, except the first segment which has to be provided with - an initial initializing vector. That vector could be chosen at - random, or be a counter of some kind. It does not have to be - secret. -

-

The following example is drawn from the old FIPS 81 standard - (replaced by NIST SP 800-38A), where both the plain text and the - resulting cipher text is settled. The following code fragment - returns `true'. -

-
>,
-      IVec = <<16#12,16#34,16#56,16#78,16#90,16#ab,16#cd,16#ef>>,
-      P = "Now is the time for all ",
-      C = crypto:des_cbc_encrypt(Key, IVec, P),
-         % Which is the same as 
-      P1 = "Now is t", P2 = "he time ", P3 = "for all ",
-      C1 = crypto:des_cbc_encrypt(Key, IVec, P1),
-      C2 = crypto:des_cbc_encrypt(Key, C1, P2),
-      C3 = crypto:des_cbc_encrypt(Key, C2, P3),
-
-      C = <>,
-      C = <<16#e5,16#c7,16#cd,16#de,16#87,16#2b,16#f2,16#7c,
-             16#43,16#e9,16#34,16#00,16#8c,16#38,16#9c,16#0f,
-             16#68,16#37,16#88,16#49,16#9a,16#7c,16#05,16#f6>>,
-      <<"Now is the time for all ">> == 
-                        crypto:des_cbc_decrypt(Key, IVec, C).
-    ]]>
-

The following is true for the DES CBC mode. For all - decompositions P1 ++ P2 = P of a plain text message - P (where the length of all quantities are multiples of 8 - bytes), the encryption C of P is equal to C1 ++ - C2, where C1 is obtained by encrypting P1 with - Key and the initializing vector IVec, and where - C2 is obtained by encrypting P2 with Key - and the initializing vector last8(C1), - where last(Binary) denotes the last 8 bytes of the - binary Binary. -

-

Similarly, for all decompositions C1 ++ C2 = C of a - cipher text message C (where the length of all quantities - are multiples of 8 bytes), the decryption P of C - is equal to P1 ++ P2, where P1 is obtained by - decrypting C1 with Key and the initializing vector - IVec, and where P2 is obtained by decrypting - C2 with Key and the initializing vector - last8(C1), where last8(Binary) is as above. -

-

For DES3 (which uses three 64 bit keys) the situation is the - same. -

-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 2b5ccb6ef4..f3fd119cdd 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -21,39 +21,23 @@ -module(crypto). --export([start/0, stop/0, info/0, info_lib/0, algorithms/0, version/0]). +-export([start/0, stop/0, info_lib/0, algorithms/0, version/0]). -export([hash/2, hash_init/1, hash_update/2, hash_final/1]). -export([sign/4, verify/5]). -export([generate_key/2, generate_key/3, compute_key/4]). -export([hmac/3, hmac/4, hmac_init/2, hmac_update/2, hmac_final/1, hmac_final_n/2]). --export([exor/2]). --export([strong_rand_bytes/1, mod_exp_prime/3]). +-export([exor/2, strong_rand_bytes/1, mod_exp_prime/3]). -export([rand_bytes/1, rand_bytes/3, rand_uniform/2]). - --export([des_cbc_encrypt/3, des_cbc_decrypt/3, des_cbc_ivec/1]). --export([des_ecb_encrypt/2, des_ecb_decrypt/2]). --export([des_cfb_encrypt/3, des_cfb_decrypt/3, des_cfb_ivec/2]). --export([des3_cbc_encrypt/5, des3_cbc_decrypt/5]). --export([des3_cfb_encrypt/5, des3_cfb_decrypt/5]). --export([blowfish_ecb_encrypt/2, blowfish_ecb_decrypt/2]). --export([blowfish_cbc_encrypt/3, blowfish_cbc_decrypt/3]). --export([blowfish_cfb64_encrypt/3, blowfish_cfb64_decrypt/3]). --export([blowfish_ofb64_encrypt/3]). --export([des_ede3_cbc_encrypt/5, des_ede3_cbc_decrypt/5]). --export([aes_cfb_128_encrypt/3, aes_cfb_128_decrypt/3]). --export([rc4_encrypt/2, rc4_set_key/1, rc4_encrypt_with_state/2]). --export([rc2_cbc_encrypt/3, rc2_cbc_decrypt/3, rc2_40_cbc_encrypt/3, rc2_40_cbc_decrypt/3]). --export([rsa_public_encrypt/3, rsa_private_decrypt/3]). --export([rsa_private_encrypt/3, rsa_public_decrypt/3]). --export([aes_cbc_128_encrypt/3, aes_cbc_128_decrypt/3]). --export([aes_cbc_256_encrypt/3, aes_cbc_256_decrypt/3]). --export([aes_cbc_ivec/1]). --export([aes_ctr_encrypt/3, aes_ctr_decrypt/3]). --export([aes_ctr_stream_init/2, aes_ctr_stream_encrypt/2, aes_ctr_stream_decrypt/2]). +-export([block_encrypt/3, block_decrypt/3, block_encrypt/4, block_decrypt/4]). +-export([next_iv/2, next_iv/3]). +-export([stream_init/2, stream_init/3, stream_encrypt/3, stream_decrypt/3]). +-export([public_encrypt/4, private_decrypt/4]). +-export([private_encrypt/4, public_decrypt/4]). -export([dh_generate_parameters/2, dh_check/1]). %% Testing see %% DEPRECATED +%% Replaced by hash_* -export([md4/1, md4_init/0, md4_update/2, md4_final/1]). -export([md5/1, md5_init/0, md5_update/2, md5_final/1]). -export([sha/1, sha_init/0, sha_update/2, sha_final/1]). @@ -70,6 +54,7 @@ -deprecated({md5_final, 1, next_major_release}). -deprecated({sha_final, 1, next_major_release}). +%% Replaced by hmac_* -export([md5_mac/2, md5_mac_96/2, sha_mac/2, sha_mac/3, sha_mac_96/2]). -deprecated({md5_mac, 2, next_major_release}). -deprecated({md5_mac_96, 2, next_major_release}). @@ -77,6 +62,7 @@ -deprecated({sha_mac, 3, next_major_release}). -deprecated({sha_mac_96, 2, next_major_release}). +%% Replaced by sign/verify -export([dss_verify/3, dss_verify/4, rsa_verify/3, rsa_verify/4]). -export([dss_sign/2, dss_sign/3, rsa_sign/2, rsa_sign/3]). -deprecated({dss_verify, 3, next_major_release}). @@ -88,53 +74,150 @@ -deprecated({rsa_sign, 2, next_major_release}). -deprecated({rsa_sign, 3, next_major_release}). +%% Replaced by generate_key -export([dh_generate_key/1, dh_generate_key/2, dh_compute_key/3]). -deprecated({dh_generate_key, 1, next_major_release}). -deprecated({dh_generate_key, 2, next_major_release}). -deprecated({dh_compute_key, 3, next_major_release}). +%% Replaced by mod_exp_prim and no longer needed -export([mod_exp/3, mpint/1, erlint/1, strong_rand_mpint/3]). -deprecated({mod_exp, 3, next_major_release}). -deprecated({mpint, 1, next_major_release}). -deprecated({erlint, 1, next_major_release}). -deprecated({strong_rand_mpint, 3, next_major_release}). --define(FUNC_LIST, [md4, md4_init, md4_update, md4_final, +%% Replaced by block_* +-export([des_cbc_encrypt/3, des_cbc_decrypt/3, des_cbc_ivec/1]). +-export([des3_cbc_encrypt/5, des3_cbc_decrypt/5]). +-export([des_ecb_encrypt/2, des_ecb_decrypt/2]). +-export([des_ede3_cbc_encrypt/5, des_ede3_cbc_decrypt/5]). +-export([des_cfb_encrypt/3, des_cfb_decrypt/3, des_cfb_ivec/2]). +-export([des3_cfb_encrypt/5, des3_cfb_decrypt/5]). +-deprecated({des_cbc_encrypt, 3, next_major_release}). +-deprecated({des_cbc_decrypt, 3, next_major_release}). +-deprecated({des_cbc_ivec, 1, next_major_release}). +-deprecated({des3_cbc_encrypt, 5, next_major_release}). +-deprecated({des3_cbc_decrypt, 5, next_major_release}). +-deprecated({des_ecb_encrypt, 2, next_major_release}). +-deprecated({des_ecb_decrypt, 2, next_major_release}). +-deprecated({des_ede3_cbc_encrypt, 5, next_major_release}). +-deprecated({des_ede3_cbc_decrypt, 5, next_major_release}). +-deprecated({des_cfb_encrypt, 3, next_major_release}). +-deprecated({des_cfb_decrypt, 3, next_major_release}). +-deprecated({des_cfb_ivec, 2, next_major_release}). +-deprecated({des3_cfb_encrypt, 5, next_major_release}). +-deprecated({des3_cfb_decrypt, 5, next_major_release}). +-export([blowfish_ecb_encrypt/2, blowfish_ecb_decrypt/2]). +-export([blowfish_cbc_encrypt/3, blowfish_cbc_decrypt/3]). +-export([blowfish_cfb64_encrypt/3, blowfish_cfb64_decrypt/3]). +-export([blowfish_ofb64_encrypt/3]). +-deprecated({blowfish_ecb_encrypt, 2, next_major_release}). +-deprecated({blowfish_ecb_decrypt, 2, next_major_release}). +-deprecated({blowfish_cbc_encrypt, 3, next_major_release}). +-deprecated({blowfish_cbc_decrypt, 3, next_major_release}). +-deprecated({blowfish_cfb64_encrypt, 3, next_major_release}). +-deprecated({blowfish_cfb64_decrypt, 3, next_major_release}). +-deprecated({blowfish_ofb64_encrypt, 3, next_major_release}). +-export([aes_cfb_128_encrypt/3, aes_cfb_128_decrypt/3]). +-export([aes_cbc_128_encrypt/3, aes_cbc_128_decrypt/3]). +-export([aes_cbc_256_encrypt/3, aes_cbc_256_decrypt/3]). +-export([aes_cbc_ivec/1]). +-deprecated({aes_cfb_128_encrypt, 3, next_major_release}). +-deprecated({aes_cfb_128_decrypt, 3, next_major_release}). +-deprecated({aes_cbc_128_encrypt, 3, next_major_release}). +-deprecated({aes_cbc_128_decrypt, 3, next_major_release}). +-deprecated({aes_cbc_256_encrypt, 3, next_major_release}). +-deprecated({aes_cbc_256_decrypt, 3, next_major_release}). +-deprecated({aes_cbc_ivec, 1, next_major_release}). +-export([rc2_cbc_encrypt/3, rc2_cbc_decrypt/3]). +-export([rc2_40_cbc_encrypt/3, rc2_40_cbc_decrypt/3]). +-deprecated({rc2_cbc_encrypt, 3, next_major_release}). +-deprecated({rc2_cbc_decrypt, 3, next_major_release}). +%% allready replaced by above! +-deprecated({rc2_40_cbc_encrypt, 3, next_major_release}). +-deprecated({rc2_40_cbc_decrypt, 3, next_major_release}). + +%% Replaced by stream_* +-export([aes_ctr_stream_init/2, aes_ctr_stream_encrypt/2, aes_ctr_stream_decrypt/2]). +-export([rc4_set_key/1, rc4_encrypt_with_state/2]). +-deprecated({aes_ctr_stream_init, 2, next_major_release}). +-deprecated({aes_ctr_stream_encrypt, 2, next_major_release}). +-deprecated({aes_ctr_stream_decrypt, 2, next_major_release}). +-deprecated({rc4_set_key, 1, next_major_release}). +-deprecated({rc4_encrypt_with_state, 2, next_major_release}). + +%% Not needed special case of stream_* +-export([aes_ctr_encrypt/3, aes_ctr_decrypt/3, rc4_encrypt/2]). +-deprecated({aes_ctr_encrypt, 3, next_major_release}). +-deprecated({aes_ctr_decrypt, 3, next_major_release}). +-deprecated({rc4_encrypt, 2, next_major_release}). + +%% Replace by public/private_encrypt/decrypt +-export([rsa_public_encrypt/3, rsa_private_decrypt/3]). +-export([rsa_private_encrypt/3, rsa_public_decrypt/3]). +-deprecated({rsa_public_encrypt, 3, next_major_release}). +-deprecated({rsa_private_decrypt, 3, next_major_release}). +-deprecated({rsa_public_decrypt, 3, next_major_release}). +-deprecated({rsa_private_encrypt, 3, next_major_release}). + +%% Replaced by crypto:module_info() +-export([info/0]). +-deprecated({info, 0, next_major_release}). + +-define(FUNC_LIST, [hash, hash_init, hash_update, hash_final, + hmac, hmac_init, hmac_update, hmac_final, hmac_final_n, + %% deprecated + md4, md4_init, md4_update, md4_final, md5, md5_init, md5_update, md5_final, sha, sha_init, sha_update, sha_final, md5_mac, md5_mac_96, sha_mac, sha_mac_96, + %% + block_encrypt, block_decrypt, + %% deprecated des_cbc_encrypt, des_cbc_decrypt, des_cfb_encrypt, des_cfb_decrypt, des_ecb_encrypt, des_ecb_decrypt, des3_cbc_encrypt, des3_cbc_decrypt, des3_cfb_encrypt, des3_cfb_decrypt, aes_cfb_128_encrypt, aes_cfb_128_decrypt, + rc2_cbc_encrypt, rc2_cbc_decrypt, + rc2_40_cbc_encrypt, rc2_40_cbc_decrypt, + aes_cbc_128_encrypt, aes_cbc_128_decrypt, + aes_cbc_256_encrypt, aes_cbc_256_decrypt, + blowfish_cbc_encrypt, blowfish_cbc_decrypt, + blowfish_cfb64_encrypt, blowfish_cfb64_decrypt, + blowfish_ecb_encrypt, blowfish_ecb_decrypt, blowfish_ofb64_encrypt, + %% rand_bytes, strong_rand_bytes, - strong_rand_mpint, rand_uniform, - mod_exp, mod_exp_prime, + mod_exp_prime, + exor, + %% deprecated + mod_exp,strong_rand_mpint,erlint, mpint, + %% + sign, verify, generate_key, compute_key, + %% deprecated dss_verify,dss_sign, rsa_verify,rsa_sign, rsa_public_encrypt,rsa_private_decrypt, rsa_private_encrypt,rsa_public_decrypt, dh_generate_key, dh_compute_key, - aes_cbc_128_encrypt, aes_cbc_128_decrypt, - exor, + %% + stream_init, stream_encrypt, stream_decrypt, + %% deprecated rc4_encrypt, rc4_set_key, rc4_encrypt_with_state, - rc2_40_cbc_encrypt, rc2_40_cbc_decrypt, - aes_cbc_256_encrypt, aes_cbc_256_decrypt, aes_ctr_encrypt, aes_ctr_decrypt, aes_ctr_stream_init, aes_ctr_stream_encrypt, aes_ctr_stream_decrypt, - aes_cbc_ivec, blowfish_cbc_encrypt, blowfish_cbc_decrypt, - blowfish_cfb64_encrypt, blowfish_cfb64_decrypt, - blowfish_ecb_encrypt, blowfish_ecb_decrypt, blowfish_ofb64_encrypt, - des_cbc_ivec, des_cfb_ivec, erlint, mpint, - hash, hash_init, hash_update, hash_final, - hmac, hmac_init, hmac_update, hmac_final, hmac_final_n, info, - rc2_cbc_encrypt, rc2_cbc_decrypt, - sign, verify, generate_key, compute_key, + %% + next_iv, + %% deprecated + aes_cbc_ivec, + des_cbc_ivec, des_cfb_ivec, + info, + %% info_lib, algorithms]). -type mpint() :: binary(). @@ -598,6 +681,106 @@ sha512_mac(Key, Data, MacSz) -> sha512_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub. + +%% Ecrypt/decrypt %%% + +-spec block_encrypt(des_cbc | des_cfb | des3_cbc | des3_cbf | des_ede3 | blowfish_cbc | + blowfish_cfb64 | aes_cbc128 | aes_cfb128 | rc2_cbc, + Key::iodata(), Ivec::binary(), Data::iodata()) -> binary(). + +block_encrypt(des_cbc, Key, Ivec, Data) -> + des_cbc_encrypt(Key, Ivec, Data); +block_encrypt(des_cfb, Key, Ivec, Data) -> + des_cfb_encrypt(Key, Ivec, Data); +block_encrypt(des3_cbc, [Key1, Key2, Key3], Ivec, Data) -> + des3_cbc_encrypt(Key1, Key2, Key3, Ivec, Data); +block_encrypt(des3_cbf, [Key1, Key2, Key3], Ivec, Data) -> + des3_cfb_encrypt(Key1, Key2, Key3, Ivec, Data); +block_encrypt(des_ede3, [Key1, Key2, Key3], Ivec, Data) -> + des_ede3_cbc_encrypt(Key1, Key2, Key3, Ivec, Data); +block_encrypt(blowfish_cbc, Key, Ivec, Data) -> + blowfish_cbc_encrypt(Key, Ivec, Data); +block_encrypt(blowfish_cfb64, Key, Ivec, Data) -> + blowfish_cfb64_encrypt(Key, Ivec, Data); +block_encrypt(blowfish_ofb64, Key, Ivec, Data) -> + blowfish_ofb64_encrypt(Key, Ivec, Data); +block_encrypt(aes_cbc128, Key, Ivec, Data) -> + aes_cbc_128_encrypt(Key, Ivec, Data); +block_encrypt(aes_cbc256, Key, Ivec, Data) -> + aes_cbc_256_encrypt(Key, Ivec, Data); +block_encrypt(aes_cfb128, Key, Ivec, Data) -> + aes_cfb_128_encrypt(Key, Ivec, Data); +block_encrypt(rc2_cbc, Key, Ivec, Data) -> + rc2_cbc_encrypt(Key, Ivec, Data). + +-spec block_decrypt(des_cbc | des_cfb | des3_cbc | des3_cbf | des_ede3 | blowfish_cbc | + blowfish_cfb64 | blowfish_ofb64 | aes_cbc128 | aes_cfb128 | rc2_cbc, + Key::iodata(), Ivec::binary(), Data::iodata()) -> binary(). + +block_decrypt(des_cbc, Key, Ivec, Data) -> + des_cbc_decrypt(Key, Ivec, Data); +block_decrypt(des_cfb, Key, Ivec, Data) -> + des_cfb_decrypt(Key, Ivec, Data); +block_decrypt(des3_cbc, [Key1, Key2, Key3], Ivec, Data) -> + des3_cbc_decrypt(Key1, Key2, Key3, Ivec, Data); +block_decrypt(des3_cbf, [Key1, Key2, Key3], Ivec, Data) -> + des3_cfb_decrypt(Key1, Key2, Key3, Ivec, Data); +block_decrypt(des_ede3, [Key1, Key2, Key3], Ivec, Data) -> + des_ede3_cbc_decrypt(Key1, Key2, Key3, Ivec, Data); +block_decrypt(blowfish_cbc, Key, Ivec, Data) -> + blowfish_cbc_decrypt(Key, Ivec, Data); +block_decrypt(blowfish_cfb64, Key, Ivec, Data) -> + blowfish_cfb64_decrypt(Key, Ivec, Data); +block_decrypt(blowfish_ofb, Key, Ivec, Data) -> + blowfish_ofb64_decrypt(Key, Ivec, Data); +block_decrypt(aes_cbc128, Key, Ivec, Data) -> + aes_cbc_128_decrypt(Key, Ivec, Data); +block_decrypt(aes_cbc256, Key, Ivec, Data) -> + aes_cbc_256_decrypt(Key, Ivec, Data); +block_decrypt(aes_cfb128, Key, Ivec, Data) -> + aes_cfb_128_decrypt(Key, Ivec, Data); +block_decrypt(rc2_cbc, Key, Ivec, Data) -> + rc2_cbc_decrypt(Key, Ivec, Data). + +-spec block_encrypt(des_ecb | blowfish_ecb, Key::iodata(), Data::iodata()) -> binary(). + +block_encrypt(des_ecb, Key, Data) -> + des_ecb_encrypt(Key, Data); +block_encrypt(blowfish_ecb, Key, Data) -> + blowfish_ecb_encrypt(Key, Data). + +-spec block_decrypt(des_ecb | blowfish_ecb, Key::iodata(), Data::iodata()) -> binary(). + +block_decrypt(des_ecb, Key, Data) -> + des_ecb_decrypt(Key, Data); +block_decrypt(blowfish_ecb, Key, Data) -> + blowfish_ecb_decrypt(Key, Data). + +-spec next_iv(des_cbc | aes_cbc, Data::iodata()) -> binary(). + +next_iv(des_cbc, Data) -> + des_cbc_ivec(Data); +next_iv(aes_cbc, Data) -> + aes_cbc_ivec(Data). + +-spec next_iv(des_cbf, Ivec::binary(), Data::iodata()) -> binary(). + +next_iv(des_cbf, Ivec, Data) -> + des_cfb_ivec(Ivec, Data). + +stream_init(aes_ctr, Key, Ivec) -> + aes_ctr_stream_init(Key, Ivec). +stream_init(rc4, Key) -> + rc4_set_key(Key). +stream_encrypt(aes_ctr, State, Data) -> + aes_ctr_stream_encrypt(State, Data); +stream_encrypt(rc4, State, Data) -> + rc4_encrypt_with_state(State, Data). +stream_decrypt(aes_ctr, State, Data) -> + aes_ctr_stream_decrypt(State, Data); +stream_decrypt(rc4, State, Data) -> + rc4_encrypt_with_state (State, Data). + %% %% CRYPTO FUNCTIONS %% @@ -746,8 +929,12 @@ blowfish_cfb64_decrypt(Key, IVec, Data) -> bf_cfb64_crypt(_Key, _IVec, _Data, _IsEncrypt) -> ?nif_stub. +blowfish_ofb64_decrypt(Key, Ivec, Data) -> + blowfish_ofb64_encrypt(Key, Ivec, Data). + blowfish_ofb64_encrypt(_Key, _IVec, _Data) -> ?nif_stub. + %% %% AES in cipher feedback mode (CFB) %% @@ -956,6 +1143,46 @@ ecdsa_sign_nif(_Type, _DataOrDigest, _Key) -> ?nif_stub. +-spec public_encrypt(rsa, binary(), [binary()], rsa_padding()) -> + binary(). +-spec public_decrypt(rsa, binary(), [integer() | binary()], rsa_padding()) -> + binary(). +-spec private_encrypt(rsa, binary(), [integer() | binary()], rsa_padding()) -> + binary(). +-spec private_decrypt(rsa, binary(), [integer() | binary()], rsa_padding()) -> + binary(). + +public_encrypt(rsa, BinMesg, Key, Padding) -> + case rsa_public_crypt(BinMesg, map_ensure_int_as_bin(Key), Padding, true) of + error -> + erlang:error(encrypt_failed, [BinMesg,Key, Padding]); + Sign -> Sign + end. + +%% Binary, Key = [E,N,D] +private_decrypt(rsa, BinMesg, Key, Padding) -> + case rsa_private_crypt(BinMesg, map_ensure_int_as_bin(Key), Padding, false) of + error -> + erlang:error(decrypt_failed, [BinMesg,Key, Padding]); + Sign -> Sign + end. + + +%% Binary, Key = [E,N,D] +private_encrypt(rsa, BinMesg, Key, Padding) -> + case rsa_private_crypt(BinMesg, map_ensure_int_as_bin(Key), Padding, true) of + error -> + erlang:error(encrypt_failed, [BinMesg,Key, Padding]); + Sign -> Sign + end. + +%% Binary, Key = [E,N] +public_decrypt(rsa, BinMesg, Key, Padding) -> + case rsa_public_crypt(BinMesg, map_ensure_int_as_bin(Key), Padding, false) of + error -> + erlang:error(decrypt_failed, [BinMesg,Key, Padding]); + Sign -> Sign + end. %% diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl index eff0f8a878..cff257bb8c 100644 --- a/lib/crypto/test/crypto_SUITE.erl +++ b/lib/crypto/test/crypto_SUITE.erl @@ -191,8 +191,8 @@ ldd_program() -> Ldd when is_list(Ldd) -> Ldd end. -%% -%% + + info(doc) -> ["Call the info function."]; info(suite) -> @@ -208,10 +208,10 @@ info(Config) when is_list(Config) -> ?line [] = Info -- Exports, ?line NotInInfo = Exports -- Info, io:format("NotInInfo = ~p\n", [NotInInfo]), - BlackList = lists:sort([des_ede3_cbc_decrypt, des_ede3_cbc_encrypt, - dh_check, dh_generate_parameters, - module_info, start, stop, version]), - ?line BlackList = NotInInfo, + %% BlackList = lists:sort([des_ede3_cbc_decrypt, des_ede3_cbc_encrypt, + %% dh_check, dh_generate_parameters, + %% module_info, start, stop, version]), + %% ?line BlackList = NotInInfo, ?line InfoLib = crypto:info_lib(), ?line [_|_] = InfoLib, @@ -222,10 +222,10 @@ info(Config) when is_list(Config) -> Me(T,Me); ([],_) -> ok - end, + end, ?line F(InfoLib,F), ?line crypto:stop() - end. + end. %% %% -- cgit v1.2.3 From cb1305212e71855890bbfb0a509a007543529d24 Mon Sep 17 00:00:00 2001 From: Ingela Anderton Andin Date: Fri, 3 May 2013 10:20:37 +0200 Subject: ssl & crypto: Generalize the remaining crypto API --- lib/crypto/c_src/crypto.c | 6 ++- lib/crypto/doc/src/crypto.xml | 106 ++++++++++++++++++++------------------ lib/crypto/doc/src/crypto_app.xml | 36 ++++--------- lib/crypto/src/crypto.erl | 42 ++++++++------- lib/crypto/test/crypto_SUITE.erl | 10 ++-- 5 files changed, 99 insertions(+), 101 deletions(-) (limited to 'lib/crypto') diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index c5d181ea25..0129526303 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -496,6 +496,7 @@ static ERL_NIF_TERM atom_sha256; static ERL_NIF_TERM atom_sha384; static ERL_NIF_TERM atom_sha512; static ERL_NIF_TERM atom_md5; +static ERL_NIF_TERM atom_md4; static ERL_NIF_TERM atom_ripemd160; static ERL_NIF_TERM atom_error; static ERL_NIF_TERM atom_rsa_pkcs1_padding; @@ -590,6 +591,7 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info) atom_sha256 = enif_make_atom(env,"sha256"); atom_sha384 = enif_make_atom(env,"sha384"); atom_sha512 = enif_make_atom(env,"sha512"); + atom_md4 = enif_make_atom(env,"md4"); atom_md5 = enif_make_atom(env,"md5"); atom_ripemd160 = enif_make_atom(env,"ripemd160"); atom_error = enif_make_atom(env,"error"); @@ -708,12 +710,12 @@ static void unload(ErlNifEnv* env, void* priv_data) } static int algos_cnt; -static ERL_NIF_TERM algos[8]; /* increase when extending the list */ +static ERL_NIF_TERM algos[9]; /* increase when extending the list */ static void init_algorithms_types(void) { algos_cnt = 0; - + algos[algos_cnt++] = atom_md4; algos[algos_cnt++] = atom_md5; algos[algos_cnt++] = atom_sha; algos[algos_cnt++] = atom_ripemd160; diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml index 0fb53346ca..df765ade87 100644 --- a/lib/crypto/doc/src/crypto.xml +++ b/lib/crypto/doc/src/crypto.xml @@ -30,23 +30,24 @@

-

Hash functions - The MD4 Message Digest Algorithm (RFC 1320), +

Hash functions - + Secure Hash Standard, The MD5 Message Digest Algorithm (RFC 1321) and - Secure Hash Standard + The MD4 Message Digest Algorithm (RFC 1320)

Hmac functions - Keyed-Hashing for Message Authentication (RFC 2104)

-

Block ciphers - DES and AES and - and Block Cipher Modes - ECB, CBC, CFB, OFB and CTR

+

Block ciphers - DES and AES in + Block Cipher Modes - ECB, CBC, CFB, OFB and CTR

RSA encryption RFC 1321

-

Digital signatures Digital Signature Standard (DSS) and Elliptic Curve Digital +

Digital signatures Digital Signature Standard (DSS) and Elliptic Curve Digital Signature Algorithm (ECDSA)

@@ -57,13 +58,7 @@
DATA TYPES - -

byte() = 0 ... 255

- -

ioelem() = byte() | binary() | iolist()

- -

iolist() = [ioelem()]

- +

key_value() = integer() | binary()

rsa_public() = [key_value()] = [E, N]

@@ -74,7 +69,7 @@ the private exponent.The longer key format contains redundant information that will make the calculation faster. P1,P2 are first and second prime factors. E1,E2 are first and second exponents. C - is the CRT coefficient. Terminology is taken from RFC 3447.

+ is the CRT coefficient. Terminology is taken from RFC 3447.

dss_public() = [key_value()] = [P, Q, G, Y]

Where P, Q and G are the dss parameters and Y is the public key.

@@ -137,25 +132,28 @@

block_key() = aes_key() | blowfish_key() | des_key()| des3_key()

-

aes_key() = binary() Key length is 128, 192 or 256 bits

+

aes_key() = iodata() Key length is 128, 192 or 256 bits

-

rc4_key() = binary() Variable key length from 8 bits up to 2048 bits (usually between 40 and 256)

+

rc4_key() = iodata() Variable key length from 8 bits up to 2048 bits (usually between 40 and 256)

-

blowfish_key() = binary() Variable key length from 32 bits up to 448 bits

+

blowfish_key() = iodata() Variable key length from 32 bits up to 448 bits

-

des_key() = binary() Key length is 64 bits (in CBC mod only 8 bits are used)

+

des_key() = iodata() Key length is 64 bits (in CBC mode only 8 bits are used)

-

des3_key() = [binary(), binary(), binary()] Each key part is 64 bits (in CBC mod only 8 bits are used)

+

des3_key() = [binary(), binary(), binary()] Each key part is 64 bits (in CBC mode only 8 bits are used)

+ +

message_digest_algorithms() = md5 | ripemd160 | sha | sha224 | sha256 | sha384 | sha512 md4 is aslo supported for hash_init/1 and hash/2. + Note that both md4 and md5 are recommended only for compatibility with existing applications. +

- algorithms() -> [atom()] + algorithms() -> [message_digest_algorithms() | md4 | ec] Provide a list of available crypto algorithms. -

Provides the available crypto algorithms in terms of a list - of atoms. This is interesting as older versions of the openssl - crypto library may not support all algorithms used in the crypto API.

+

Can be used to determine if the crypto library has support for elliptic curve (ec) and + which message digest algorithms that are supported.

@@ -164,7 +162,7 @@ Encrypt PlainTextaccording to Type block cipher Key = block_key() - PlainText = iodata() | binary() + PlainText = iodata() IVec = CipherText = binary() @@ -179,7 +177,7 @@ Decrypt CipherTextaccording to Type block cipher Key = block_key() - PlainText = iodata() | binary() + PlainText = iodata() IVec = CipherText = binary() @@ -201,6 +199,7 @@

Computes the shared secret from the private key and the other party's public key. + See also public_key:compute_key/2

@@ -209,7 +208,7 @@ exor(Data1, Data2) -> Result XOR data - Data1, Data2 = iolist() | binary() + Data1, Data2 = iodata() Result = binary() @@ -229,6 +228,7 @@

Generates public keys of type Type. + See also public_key:generate_key/1

@@ -237,7 +237,7 @@ hash(Type, Data) -> Digest - Type = md4 | md5 | ripemd160 | sha | sha224 | sha256 | sha384 | sha512 + Type = md4 | message_digest_algorithms() Data = iodata() Digest = binary() @@ -252,7 +252,7 @@ hash_init(Type) -> Context - Type = md4 | md5 | ripemd160 | sha | sha224 | sha256 | sha384 | sha512 + Type = md4 | message_digest_algorithms()

Initializes the context for streaming hash operations. Type determines @@ -296,7 +296,7 @@ hmac(Type, Key, Data, MacLength) -> Mac - Type = md5 | sha | sha224 | sha256 | sha384 | sha512 + Type = message_digest_algorithms() Key = iodata() Data = iodata() MacLength = integer() @@ -313,8 +313,8 @@ hmac_init(Type, Key) -> Context - Type = md5 | ripemd160 | sha | sha224 | sha256 | sha384 | sha512 - Key = iolist() | binary() + Type = message_digest_algorithms() + Key = iodata() Context = binary() @@ -329,13 +329,17 @@ Context = NewContext = binary() - Data = iolist() | binary() + Data = iodata()

Updates the HMAC represented by Context using the given Data. Context must have been generated using an HMAC init function (such as hmac_init). Data can be any length. NewContext - must be passed into the next call to hmac_update.

+ must be passed into the next call to hmac_update + or to one of the functions hmac_final and + hmac_final_n +

+
@@ -391,10 +395,10 @@ - mod_exp_prime(N, P, M) -> Result + mod_pow(N, P, M) -> Result Computes the function: N^P mod M - N, P, M = binary() + N, P, M = binary() | integer() Result = binary() | error @@ -433,6 +437,7 @@ message. The Padding is the padding mode that was used to encrypt the data, see public_encrypt/3. + See also public_key:decrypt_private/[2,3]

@@ -455,6 +460,7 @@ The size of the Msg must be less than byte_size(N)-11 if rsa_pkcs1_padding is used, and byte_size(N) if rsa_no_padding is used. + See also public_key:encrypt_private/[2,3]

@@ -475,6 +481,7 @@ message. The Padding is the padding mode that was used to encrypt the data, see private_encrypt/3. + See also public_key:decrypt_public/[2,3]

@@ -501,6 +508,7 @@ rsa_pkcs1_padding is used, byte_size(N)-41 if rsa_pkcs1_oaep_padding is used and byte_size(N) if rsa_no_padding is used. + See also public_key:encrypt_public/[2,3]

@@ -545,6 +553,7 @@

Creates a digital signature.

+ See also public_key:sign/3
@@ -613,36 +622,32 @@ - stream_encrypt(Type, State, PlainText) -> { NewState, CipherText} + stream_encrypt(State, PlainText) -> { NewState, CipherText} - Type = stream_cipher() - Text = iolist() | binary() + Text = iodata() CipherText = binary() -

Encrypts PlainText according to the stream cipher Type. - Text can be any number of bytes. State is initialized using - stream_init on - the next invocation of this function the returned State shall be - given as input and so on until the end of the stream is reached.

+

Encrypts PlainText according to the stream cipher Type specified in stream_init/3. + Text can be any number of bytes. The initial State is created using + stream_init. + NewState must be passed into the next call to stream_encrypt.

- stream_decrypt(Type, State, CipherText) -> { NewState, PlainText } + stream_decrypt(State, CipherText) -> { NewState, PlainText } - Type = stream_cipher() - CipherText = iodata() | binary() + CipherText = iodata() PlainText = binary() -

Decrypts CipherText according to the stream cipher Type. - PlainText can be any number of bytes. State is initialized using - stream_init on - the next invocation of this function the returned State shall be - given as input and so on until the end of the stream is reached.

+

Decrypts CipherText according to the stream cipher Type specified in stream_init/3. + PlainText can be any number of bytes. The initial State is created using + stream_init. + NewState must be passed into the next call to stream_encrypt.

@@ -660,6 +665,7 @@

Verifies a digital signature

+ See also public_key:verify/3
diff --git a/lib/crypto/doc/src/crypto_app.xml b/lib/crypto/doc/src/crypto_app.xml index 20f4ed5c45..6d26076c04 100644 --- a/lib/crypto/doc/src/crypto_app.xml +++ b/lib/crypto/doc/src/crypto_app.xml @@ -29,37 +29,23 @@ crypto The Crypto Application -

The purpose of the Crypto application is to provide erlang - acess to crypto graphic functions in openssl. +

The purpose of the Crypto application is to provide an Erlang API + to cryptographic functions, see crypto(3). + Note that the API is on a fairly low level and there are some + corresponding API functions available in public_key(3), + on a higher abstraction level, that uses the crypto application in its implementation.

- Configuration -

The following environment configuration parameters are defined - for the Crypto application. Refer to application(3) for more - information about configuration parameters. -

- - ]]> - -

Causes debug information to be written to standard - error or standard output. Default is false. -

-
-
-
+ DEPENDENCIES -
- OpenSSL libraries -

The current implementation of the Erlang Crypto application is - based on the OpenSSL package version 0.9.8 or higher. - There are source and binary releases on the web. -

+

The current crypto implementation uses nifs to interface OpenSSLs crypto library + and requires OpenSSL package version 0.9.8 or higher.

Source releases of OpenSSL can be downloaded from the OpenSSL project home page, - or mirror sites listed there. -

-
+ or mirror sites listed there. +

+
SEE ALSO diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index f3fd119cdd..f4e157198c 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -26,11 +26,11 @@ -export([sign/4, verify/5]). -export([generate_key/2, generate_key/3, compute_key/4]). -export([hmac/3, hmac/4, hmac_init/2, hmac_update/2, hmac_final/1, hmac_final_n/2]). --export([exor/2, strong_rand_bytes/1, mod_exp_prime/3]). +-export([exor/2, strong_rand_bytes/1, mod_pow/3]). -export([rand_bytes/1, rand_bytes/3, rand_uniform/2]). -export([block_encrypt/3, block_decrypt/3, block_encrypt/4, block_decrypt/4]). -export([next_iv/2, next_iv/3]). --export([stream_init/2, stream_init/3, stream_encrypt/3, stream_decrypt/3]). +-export([stream_init/2, stream_init/3, stream_encrypt/2, stream_decrypt/2]). -export([public_encrypt/4, private_decrypt/4]). -export([private_encrypt/4, public_decrypt/4]). @@ -193,7 +193,7 @@ rand_bytes, strong_rand_bytes, rand_uniform, - mod_exp_prime, + mod_pow, exor, %% deprecated mod_exp,strong_rand_mpint,erlint, mpint, @@ -685,7 +685,7 @@ sha512_mac_nif(_Key,_Data,_MacSz) -> ?nif_stub. %% Ecrypt/decrypt %%% -spec block_encrypt(des_cbc | des_cfb | des3_cbc | des3_cbf | des_ede3 | blowfish_cbc | - blowfish_cfb64 | aes_cbc128 | aes_cfb128 | rc2_cbc, + blowfish_cfb64 | aes_cbc128 | aes_cfb128 | aes_cbc256 | rc2_cbc, Key::iodata(), Ivec::binary(), Data::iodata()) -> binary(). block_encrypt(des_cbc, Key, Ivec, Data) -> @@ -714,7 +714,7 @@ block_encrypt(rc2_cbc, Key, Ivec, Data) -> rc2_cbc_encrypt(Key, Ivec, Data). -spec block_decrypt(des_cbc | des_cfb | des3_cbc | des3_cbf | des_ede3 | blowfish_cbc | - blowfish_cfb64 | blowfish_ofb64 | aes_cbc128 | aes_cfb128 | rc2_cbc, + blowfish_cfb64 | blowfish_ofb64 | aes_cbc128 | aes_cbc256 | aes_cfb128 | rc2_cbc, Key::iodata(), Ivec::binary(), Data::iodata()) -> binary(). block_decrypt(des_cbc, Key, Ivec, Data) -> @@ -769,17 +769,21 @@ next_iv(des_cbf, Ivec, Data) -> des_cfb_ivec(Ivec, Data). stream_init(aes_ctr, Key, Ivec) -> - aes_ctr_stream_init(Key, Ivec). + {aes_ctr, aes_ctr_stream_init(Key, Ivec)}. stream_init(rc4, Key) -> - rc4_set_key(Key). -stream_encrypt(aes_ctr, State, Data) -> - aes_ctr_stream_encrypt(State, Data); -stream_encrypt(rc4, State, Data) -> - rc4_encrypt_with_state(State, Data). -stream_decrypt(aes_ctr, State, Data) -> - aes_ctr_stream_decrypt(State, Data); -stream_decrypt(rc4, State, Data) -> - rc4_encrypt_with_state (State, Data). + {rc4, rc4_set_key(Key)}. +stream_encrypt({aes_ctr, State}, Data) -> + {State, Cipher} = aes_ctr_stream_encrypt(State, Data), + {{aes_ctr, State}, Cipher}; +stream_encrypt({rc4, State0}, Data) -> + {State, Cipher} = rc4_encrypt_with_state(State0, Data), + {{rc4, State}, Cipher}. +stream_decrypt({aes_ctr, State0}, Data) -> + {State, Text} = aes_ctr_stream_decrypt(State0, Data), + {{aes_ctr, State}, Text}; +stream_decrypt({rc4, State0}, Data) -> + {State, Text} = rc4_encrypt_with_state (State0, Data), + {{rc4, State}, Text}. %% %% CRYPTO FUNCTIONS @@ -1018,9 +1022,9 @@ mod_exp(Base, Exponent, Modulo) mod_exp(Base, Exponent, Modulo) -> mod_exp_nif(mpint_to_bin(Base),mpint_to_bin(Exponent),mpint_to_bin(Modulo), 4). --spec mod_exp_prime(binary(), binary(), binary()) -> binary() | error. -mod_exp_prime(Base, Exponent, Prime) -> - case mod_exp_nif(Base, Exponent, Prime, 0) of +-spec mod_pow(binary()|integer(), binary()|integer(), binary()|integer()) -> binary() | error. +mod_pow(Base, Exponent, Prime) -> + case mod_exp_nif(ensure_int_as_bin(Base), ensure_int_as_bin(Exponent), ensure_int_as_bin(Prime), 0) of <<0>> -> error; R -> R end. @@ -1500,7 +1504,7 @@ term_to_ec_key_nif(_Curve, _PrivKey, _PubKey) -> ?nif_stub. %% user_srp_gen_key(Private, Generator, Prime) -> - case mod_exp_prime(Generator, Private, Prime) of + case mod_pow(Generator, Private, Prime) of error -> error; Public -> diff --git a/lib/crypto/test/crypto_SUITE.erl b/lib/crypto/test/crypto_SUITE.erl index cff257bb8c..eddb6b83f9 100644 --- a/lib/crypto/test/crypto_SUITE.erl +++ b/lib/crypto/test/crypto_SUITE.erl @@ -1979,8 +1979,8 @@ srp3(Config) when is_list(Config) -> "9176A9192615DC0277AE7C12F1F6A7F6563FCA11675D809AF578BDE5" "2B51E05D440B63099A017A0B45044801"), UserPassHash = crypto:sha([Salt, crypto:sha([Username, <<$:>>, Password])]), - Verifier = crypto:mod_exp_prime(Generator, UserPassHash, Prime), - ClientPublic = crypto:mod_exp_prime(Generator, ClientPrivate, Prime), + Verifier = crypto:mod_pow(Generator, UserPassHash, Prime), + ClientPublic = crypto:mod_pow(Generator, ClientPrivate, Prime), {ClientPublic, ClientPrivate} = crypto:generate_key(srp, {user, [Generator, Prime, Version]}, ClientPrivate), {ServerPublic, ServerPrivate} = crypto:generate_key(srp, {host, [Verifier, Generator, Prime, Version]}, ServerPrivate), @@ -2030,8 +2030,8 @@ srp6(Config) when is_list(Config) -> "72E992AAD89095A84B6A5FADA152369AB1E350A03693BEF044DF3EDF" "0C34741F4696C30E9F675D09F58ACBEB"), UserPassHash = crypto:sha([Salt, crypto:sha([Username, <<$:>>, Password])]), - Verifier = crypto:mod_exp_prime(Generator, UserPassHash, Prime), - ClientPublic = crypto:mod_exp_prime(Generator, ClientPrivate, Prime), + Verifier = crypto:mod_pow(Generator, UserPassHash, Prime), + ClientPublic = crypto:mod_pow(Generator, ClientPrivate, Prime), {ClientPublic, ClientPrivate} = crypto:generate_key(srp, {user, [Generator, Prime, Version]}, ClientPrivate), {ServerPublic, ServerPrivate} = crypto:generate_key(srp, {host, [Verifier, Generator, Prime, Version]}, ServerPrivate), @@ -2081,7 +2081,7 @@ srp6a(Config) when is_list(Config) -> "3499B200210DCC1F10EB33943CD67FC88A2F39A4BE5BEC4EC0A3212D" "C346D7E474B29EDE8A469FFECA686E5A"), UserPassHash = crypto:sha([Salt, crypto:sha([Username, <<$:>>, Password])]), - Verifier = crypto:mod_exp_prime(Generator, UserPassHash, Prime), + Verifier = crypto:mod_pow(Generator, UserPassHash, Prime), {ClientPublic, ClientPrivate} = crypto:generate_key(srp, {user, [Generator, Prime, Version]}, ClientPrivate), {ServerPublic, ServerPrivate} = crypto:generate_key(srp, {host, [Verifier, Generator, Prime, Version]}, ServerPrivate), -- cgit v1.2.3 From cadab5a955d2db70d42d9e8e9c9658ad3a46d472 Mon Sep 17 00:00:00 2001 From: Sverker Eriksson Date: Fri, 3 May 2013 15:05:17 +0200 Subject: crypto: Remove debug printouts --- lib/crypto/c_src/crypto.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'lib/crypto') diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index 0129526303..9d43a1d907 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -3002,7 +3002,6 @@ static EC_KEY* ec_key_new(ErlNifEnv* env, ERL_NIF_TERM curve_arg) EC_KEY_set_group(key, group); } else { - printf("#3\n"); goto out_err; } @@ -3136,14 +3135,12 @@ static ERL_NIF_TERM term_to_ec_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T if (!(argv[1] == atom_undefined || get_bn_from_bin(env, argv[1], &priv_key)) || !(argv[2] == atom_undefined || enif_is_binary(env, argv[2]))) { - printf("#1\n"); goto out_err; } key = ec_key_new(env, argv[0]); if (!key) { - printf("#4\n"); goto out_err; } @@ -3152,7 +3149,6 @@ static ERL_NIF_TERM term_to_ec_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T if (term2point(env, argv[2], group, &pub_key)) { if (!EC_KEY_set_public_key(key, pub_key)) { - printf("#5\n"); goto out_err; } } -- cgit v1.2.3