aboutsummaryrefslogtreecommitdiffstats
path: root/lib/crypto/c_src/crypto.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/crypto/c_src/crypto.c')
-rw-r--r--lib/crypto/c_src/crypto.c265
1 files changed, 140 insertions, 125 deletions
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index 98ebb21f29..c28ff8136c 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -142,6 +142,19 @@
(s)[3] = (char)((i) & 0xff);\
}
+/* This shall correspond to the similar macro in crypto.erl */
+/* Current value is: erlang:system_info(context_reductions) * 10 */
+#define MAX_BYTES_TO_NIF 20000
+
+#define CONSUME_REDS(NifEnv, Ibin) \
+do { \
+ int _cost = ((Ibin).size * 100) / MAX_BYTES_TO_NIF;\
+ if (_cost) { \
+ (void) enif_consume_timeslice((NifEnv), \
+ (_cost > 100) ? 100 : _cost); \
+ } \
+ } while (0)
+
/* NIF interface declarations */
static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info);
static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info);
@@ -208,7 +221,7 @@ static ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
static ERL_NIF_TERM dss_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM aes_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
-static ERL_NIF_TERM exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM do_exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_set_key(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
@@ -229,8 +242,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_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[]);
@@ -338,7 +349,7 @@ static ErlNifFunc nif_funcs[] = {
{"dss_verify_nif", 4, dss_verify_nif},
{"rsa_verify_nif", 4, rsa_verify_nif},
{"aes_cbc_crypt", 4, aes_cbc_crypt},
- {"exor", 2, exor},
+ {"do_exor", 2, do_exor},
{"rc4_encrypt", 2, rc4_encrypt},
{"rc4_set_key", 1, rc4_set_key},
{"rc4_encrypt_with_state", 2, rc4_encrypt_with_state},
@@ -359,12 +370,10 @@ static ErlNifFunc nif_funcs[] = {
{"bf_ecb_crypt", 3, bf_ecb_crypt},
{"blowfish_ofb64_encrypt", 3, blowfish_ofb64_encrypt},
- {"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_nif", 2, ecdh_compute_key_nif}
+ {"ecdsa_sign_nif", 4, ecdsa_sign_nif},
+ {"ecdsa_verify_nif", 5, ecdsa_verify_nif},
+ {"ecdh_compute_key_nif", 3, ecdh_compute_key_nif}
};
#if defined(HAVE_EC)
@@ -459,10 +468,7 @@ static struct nid_map ec_curves[] = {
#define EC_CURVES_CNT (sizeof(ec_curves)/sizeof(struct nid_map))
-struct nif_ec_key {
- EC_KEY *key;
-};
-#endif
+#endif /* HAVE_EC */
ERL_NIF_INIT(crypto,nif_funcs,load,NULL,upgrade,unload)
@@ -515,17 +521,13 @@ 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_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
/*
@@ -557,7 +559,6 @@ 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;
@@ -577,6 +578,7 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info)
PRINTF_ERR1("CRYPTO: Invalid load_info '%T'", load_info);
return 0;
}
+
if (library_refc > 0) {
/* Repeated loading of this library (module upgrade).
* Atoms and callbacks are already set, we are done.
@@ -618,13 +620,11 @@ static int init(ErlNifEnv* env, ERL_NIF_TERM load_info)
atom_ppbasis = enif_make_atom(env,"ppbasis");
atom_onbasis = enif_make_atom(env,"onbasis");
- for (i = 0; i < EC_CURVES_CNT; i++)
+ {
+ int i;
+ 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|ERL_NIF_RT_TAKEOVER,
- NULL);
+ }
#endif
init_digest_types(env);
@@ -778,6 +778,7 @@ static ERL_NIF_TERM md5(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
}
MD5((unsigned char *) ibin.data, ibin.size,
enif_make_new_binary(env,MD5_LEN, &ret));
+ CONSUME_REDS(env,ibin);
return ret;
}
static ERL_NIF_TERM md5_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -799,6 +800,7 @@ static ERL_NIF_TERM md5_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
new_ctx = (MD5_CTX*) enif_make_new_binary(env,MD5_CTX_LEN, &ret);
memcpy(new_ctx, ctx_bin.data, MD5_CTX_LEN);
MD5_Update(new_ctx, data_bin.data, data_bin.size);
+ CONSUME_REDS(env,data_bin);
return ret;
}
static ERL_NIF_TERM md5_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -820,10 +822,11 @@ static ERL_NIF_TERM ripemd160(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
ERL_NIF_TERM ret;
if (!enif_inspect_iolist_as_binary(env, argv[0], &ibin)) {
- return enif_make_badarg(env);
+ return enif_make_badarg(env);
}
RIPEMD160((unsigned char *) ibin.data, ibin.size,
- enif_make_new_binary(env,RIPEMD160_LEN, &ret));
+ enif_make_new_binary(env,RIPEMD160_LEN, &ret));
+ CONSUME_REDS(env,ibin);
return ret;
}
static ERL_NIF_TERM ripemd160_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -838,13 +841,14 @@ static ERL_NIF_TERM ripemd160_update(ErlNifEnv* env, int argc, const ERL_NIF_TER
ErlNifBinary ctx_bin, data_bin;
ERL_NIF_TERM ret;
if (!enif_inspect_binary(env, argv[0], &ctx_bin)
- || ctx_bin.size != RIPEMD160_CTX_LEN
- || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
- return enif_make_badarg(env);
+ || ctx_bin.size != RIPEMD160_CTX_LEN
+ || !enif_inspect_iolist_as_binary(env, argv[1], &data_bin)) {
+ return enif_make_badarg(env);
}
new_ctx = (RIPEMD160_CTX*) enif_make_new_binary(env,RIPEMD160_CTX_LEN, &ret);
memcpy(new_ctx, ctx_bin.data, RIPEMD160_CTX_LEN);
RIPEMD160_Update(new_ctx, data_bin.data, data_bin.size);
+ CONSUME_REDS(env, data_bin);
return ret;
}
static ERL_NIF_TERM ripemd160_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -853,7 +857,7 @@ static ERL_NIF_TERM ripemd160_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM
RIPEMD160_CTX ctx_clone;
ERL_NIF_TERM ret;
if (!enif_inspect_binary(env, argv[0], &ctx_bin) || ctx_bin.size != RIPEMD160_CTX_LEN) {
- return enif_make_badarg(env);
+ return enif_make_badarg(env);
}
memcpy(&ctx_clone, ctx_bin.data, RIPEMD160_CTX_LEN); /* writable */
RIPEMD160_Final(enif_make_new_binary(env, RIPEMD160_LEN, &ret), &ctx_clone);
@@ -871,6 +875,7 @@ static ERL_NIF_TERM sha(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
}
SHA1((unsigned char *) ibin.data, ibin.size,
enif_make_new_binary(env,SHA_LEN, &ret));
+ CONSUME_REDS(env,ibin);
return ret;
}
static ERL_NIF_TERM sha_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -891,6 +896,7 @@ static ERL_NIF_TERM sha_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
new_ctx = (SHA_CTX*) enif_make_new_binary(env,SHA_CTX_LEN, &ret);
memcpy(new_ctx, ctx_bin.data, SHA_CTX_LEN);
SHA1_Update(new_ctx, data_bin.data, data_bin.size);
+ CONSUME_REDS(env,data_bin);
return ret;
}
static ERL_NIF_TERM sha_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -917,6 +923,7 @@ static ERL_NIF_TERM sha224_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
}
SHA224((unsigned char *) ibin.data, ibin.size,
enif_make_new_binary(env,SHA224_LEN, &ret));
+ CONSUME_REDS(env,ibin);
return ret;
#else
return atom_notsup;
@@ -945,6 +952,7 @@ static ERL_NIF_TERM sha224_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE
new_ctx = (SHA256_CTX*) enif_make_new_binary(env,sizeof(SHA256_CTX), &ret);
memcpy(new_ctx, ctx_bin.data, sizeof(SHA256_CTX));
SHA224_Update(new_ctx, data_bin.data, data_bin.size);
+ CONSUME_REDS(env,data_bin);
return ret;
#else
return atom_notsup;
@@ -978,6 +986,7 @@ static ERL_NIF_TERM sha256_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
}
SHA256((unsigned char *) ibin.data, ibin.size,
enif_make_new_binary(env,SHA256_LEN, &ret));
+ CONSUME_REDS(env,ibin);
return ret;
#else
return atom_notsup;
@@ -1006,6 +1015,7 @@ static ERL_NIF_TERM sha256_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE
new_ctx = (SHA256_CTX*) enif_make_new_binary(env,sizeof(SHA256_CTX), &ret);
memcpy(new_ctx, ctx_bin.data, sizeof(SHA256_CTX));
SHA256_Update(new_ctx, data_bin.data, data_bin.size);
+ CONSUME_REDS(env,data_bin);
return ret;
#else
return atom_notsup;
@@ -1039,6 +1049,7 @@ static ERL_NIF_TERM sha384_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
}
SHA384((unsigned char *) ibin.data, ibin.size,
enif_make_new_binary(env,SHA384_LEN, &ret));
+ CONSUME_REDS(env,ibin);
return ret;
#else
return atom_notsup;
@@ -1067,6 +1078,7 @@ static ERL_NIF_TERM sha384_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE
new_ctx = (SHA512_CTX*) enif_make_new_binary(env,sizeof(SHA512_CTX), &ret);
memcpy(new_ctx, ctx_bin.data, sizeof(SHA512_CTX));
SHA384_Update(new_ctx, data_bin.data, data_bin.size);
+ CONSUME_REDS(env,data_bin);
return ret;
#else
return atom_notsup;
@@ -1100,6 +1112,7 @@ static ERL_NIF_TERM sha512_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
}
SHA512((unsigned char *) ibin.data, ibin.size,
enif_make_new_binary(env,SHA512_LEN, &ret));
+ CONSUME_REDS(env,ibin);
return ret;
#else
return atom_notsup;
@@ -1128,6 +1141,7 @@ static ERL_NIF_TERM sha512_update_nif(ErlNifEnv* env, int argc, const ERL_NIF_TE
new_ctx = (SHA512_CTX*) enif_make_new_binary(env,sizeof(SHA512_CTX), &ret);
memcpy(new_ctx, ctx_bin.data, sizeof(SHA512_CTX));
SHA512_Update(new_ctx, data_bin.data, data_bin.size);
+ CONSUME_REDS(env,data_bin);
return ret;
#else
return atom_notsup;
@@ -1161,6 +1175,7 @@ static ERL_NIF_TERM md4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
}
MD4((unsigned char *) ibin.data, ibin.size,
enif_make_new_binary(env,MD4_LEN, &ret));
+ CONSUME_REDS(env,ibin);
return ret;
}
static ERL_NIF_TERM md4_init(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -1181,6 +1196,7 @@ static ERL_NIF_TERM md4_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
new_ctx = (MD4_CTX*) enif_make_new_binary(env,MD4_CTX_LEN, &ret);
memcpy(new_ctx, ctx_bin.data, MD4_CTX_LEN);
MD4_Update(new_ctx, data_bin.data, data_bin.size);
+ CONSUME_REDS(env,data_bin);
return ret;
}
static ERL_NIF_TERM md4_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
@@ -1210,6 +1226,7 @@ static ERL_NIF_TERM md5_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
}
hmac_md5(key.data, key.size, data.data, data.size, hmacbuf);
memcpy(enif_make_new_binary(env, mac_sz, &ret), hmacbuf, mac_sz);
+ CONSUME_REDS(env,data);
return ret;
}
@@ -1228,6 +1245,7 @@ static ERL_NIF_TERM sha_mac_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
hmac_sha1(key.data, key.size, data.data, data.size, hmacbuf);
memcpy(enif_make_new_binary(env, mac_sz, &ret),
hmacbuf, mac_sz);
+ CONSUME_REDS(env,data);
return ret;
}
@@ -1247,6 +1265,7 @@ static ERL_NIF_TERM sha224_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
hmac_sha224(key.data, key.size, data.data, data.size, hmacbuf);
memcpy(enif_make_new_binary(env, mac_sz, &ret),
hmacbuf, mac_sz);
+ CONSUME_REDS(env,data);
return ret;
#else
return atom_notsup;
@@ -1269,6 +1288,7 @@ static ERL_NIF_TERM sha256_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
hmac_sha256(key.data, key.size, data.data, data.size, hmacbuf);
memcpy(enif_make_new_binary(env, mac_sz, &ret),
hmacbuf, mac_sz);
+ CONSUME_REDS(env,data);
return ret;
#else
return atom_notsup;
@@ -1291,6 +1311,7 @@ static ERL_NIF_TERM sha384_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
hmac_sha384(key.data, key.size, data.data, data.size, hmacbuf);
memcpy(enif_make_new_binary(env, mac_sz, &ret),
hmacbuf, mac_sz);
+ CONSUME_REDS(env,data);
return ret;
#else
return atom_notsup;
@@ -1314,6 +1335,7 @@ static ERL_NIF_TERM sha512_mac_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
hmac_sha512(key.data, key.size, data.data, data.size, hmacbuf);
memcpy(enif_make_new_binary(env, mac_sz, &ret),
hmacbuf, mac_sz);
+ CONSUME_REDS(env,data);
return ret;
#else
return atom_notsup;
@@ -1371,6 +1393,7 @@ static ERL_NIF_TERM hmac_update(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
ctx_buf = enif_make_new_binary(env, sizeof(HMAC_CTX), &ret);
memcpy(ctx_buf, context.data, context.size);
HMAC_Update((HMAC_CTX *)ctx_buf, data.data, data.size);
+ CONSUME_REDS(env,data);
return ret;
}
@@ -1401,7 +1424,7 @@ static ERL_NIF_TERM hmac_final(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv
HMAC_CTX_cleanup(&ctx);
if (argc == 2 && req_len < mac_len) {
- // Only truncate to req_len bytes if asked.
+ /* Only truncate to req_len bytes if asked. */
mac_len = req_len;
}
mac_bin = enif_make_new_binary(env, mac_len, &ret);
@@ -1427,6 +1450,7 @@ static ERL_NIF_TERM des_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
DES_set_key((const_DES_cblock*)key.data, &schedule);
DES_ncbc_encrypt(text.data, enif_make_new_binary(env, text.size, &ret),
text.size, &schedule, &ivec_clone, (argv[3] == atom_true));
+ CONSUME_REDS(env,text);
return ret;
}
@@ -1446,6 +1470,7 @@ static ERL_NIF_TERM des_cfb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
DES_set_key((const_DES_cblock*)key.data, &schedule);
DES_cfb_encrypt(text.data, enif_make_new_binary(env, text.size, &ret),
8, text.size, &schedule, &ivec_clone, (argv[3] == atom_true));
+ CONSUME_REDS(env,text);
return ret;
}
@@ -1462,6 +1487,7 @@ static ERL_NIF_TERM des_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
DES_ecb_encrypt((const_DES_cblock*)text.data,
(DES_cblock*)enif_make_new_binary(env, 8, &ret),
&schedule, (argv[2] == atom_true));
+ CONSUME_REDS(env,text);
return ret;
}
@@ -1488,6 +1514,7 @@ static ERL_NIF_TERM des_ede3_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_T
DES_ede3_cbc_encrypt(text.data, enif_make_new_binary(env,text.size,&ret),
text.size, &schedule1, &schedule2, &schedule3,
&ivec_clone, (argv[5] == atom_true));
+ CONSUME_REDS(env,text);
return ret;
}
@@ -1514,6 +1541,7 @@ static ERL_NIF_TERM des_ede3_cfb_crypt_nif(ErlNifEnv* env, int argc, const ERL_N
DES_ede3_cfb_encrypt(text.data, enif_make_new_binary(env,text.size,&ret),
8, text.size, &schedule1, &schedule2, &schedule3,
&ivec_clone, (argv[5] == atom_true));
+ CONSUME_REDS(env,text);
return ret;
#else
return atom_notsup;
@@ -1540,6 +1568,7 @@ static ERL_NIF_TERM aes_cfb_128_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TE
enif_make_new_binary(env, text.size, &ret),
text.size, &aes_key, ivec_clone, &new_ivlen,
(argv[3] == atom_true));
+ CONSUME_REDS(env,text);
return ret;
}
@@ -1565,6 +1594,7 @@ static ERL_NIF_TERM aes_ctr_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM
AES_ctr128_encrypt((unsigned char *) text.data,
enif_make_new_binary(env, text.size, &ret),
text.size, &aes_key, ivec_clone, ecount_buf, &num);
+ CONSUME_REDS(env,text);
/* To do an incremental {en|de}cryption, the state to to keep between calls
must include ivec_clone, ecount_buf and num. */
@@ -1608,6 +1638,7 @@ static ERL_NIF_TERM aes_ctr_stream_encrypt(ErlNifEnv* env, int argc, const ERL_N
num2_term = enif_make_uint(env, num);
new_state_term = enif_make_tuple4(env, state_term[0], ivec2_term, ecount2_term, num2_term);
ret = enif_make_tuple2(env, new_state_term, cipher_term);
+ CONSUME_REDS(env,text_bin);
return ret;
}
@@ -2055,10 +2086,11 @@ static ERL_NIF_TERM aes_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
ret_ptr = enif_make_new_binary(env, data_bin.size, &ret);
memcpy(ivec, ivec_bin.data, 16); /* writable copy */
AES_cbc_encrypt(data_bin.data, ret_ptr, data_bin.size, &aes_key, ivec, i);
+ CONSUME_REDS(env,data_bin);
return ret;
}
-static ERL_NIF_TERM exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+static ERL_NIF_TERM do_exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Data1, Data2) */
ErlNifBinary d1, d2;
unsigned char* ret_ptr;
@@ -2075,6 +2107,7 @@ static ERL_NIF_TERM exor(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
for (i=0; i<d1.size; i++) {
ret_ptr[i] = d1.data[i] ^ d2.data[i];
}
+ CONSUME_REDS(env,d1);
return ret;
}
@@ -2091,6 +2124,7 @@ static ERL_NIF_TERM rc4_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM arg
RC4_set_key(&rc4_key, key.size, key.data);
RC4(&rc4_key, data.size, data.data,
enif_make_new_binary(env, data.size, &ret));
+ CONSUME_REDS(env,data);
return ret;
}
@@ -2123,7 +2157,7 @@ static ERL_NIF_TERM rc4_encrypt_with_state(ErlNifEnv* env, int argc, const ERL_N
memcpy(rc4_key, state.data, sizeof(RC4_KEY));
RC4(rc4_key, data.size, data.data,
enif_make_new_binary(env, data.size, &new_data));
-
+ CONSUME_REDS(env,data);
return enif_make_tuple2(env,new_state,new_data);
}
@@ -2150,6 +2184,7 @@ static ERL_NIF_TERM rc2_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM a
data_bin.size, &rc2_key,
iv_copy,
(argv[3] == atom_true));
+ CONSUME_REDS(env,data_bin);
return ret;
}
@@ -2781,6 +2816,7 @@ static ERL_NIF_TERM bf_cfb64_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM
BF_cfb64_encrypt(data_bin.data, enif_make_new_binary(env,data_bin.size,&ret),
data_bin.size, &bf_key, bf_tkey, &bf_n,
(argv[3] == atom_true ? BF_ENCRYPT : BF_DECRYPT));
+ CONSUME_REDS(env,data_bin);
return ret;
}
@@ -2804,6 +2840,7 @@ static ERL_NIF_TERM bf_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
BF_cbc_encrypt(data_bin.data, enif_make_new_binary(env,data_bin.size,&ret),
data_bin.size, &bf_key, bf_tkey,
(argv[3] == atom_true ? BF_ENCRYPT : BF_DECRYPT));
+ CONSUME_REDS(env,data_bin);
return ret;
}
@@ -2821,6 +2858,7 @@ static ERL_NIF_TERM bf_ecb_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
BF_set_key(&bf_key, key_bin.size, key_bin.data);
BF_ecb_encrypt(data_bin.data, enif_make_new_binary(env,data_bin.size,&ret),
&bf_key, (argv[2] == atom_true ? BF_ENCRYPT : BF_DECRYPT));
+ CONSUME_REDS(env,data_bin);
return ret;
}
@@ -2843,6 +2881,7 @@ static ERL_NIF_TERM blowfish_ofb64_encrypt(ErlNifEnv* env, int argc, const ERL_N
memcpy(bf_tkey, ivec_bin.data, 8);
BF_ofb64_encrypt(data_bin.data, enif_make_new_binary(env,data_bin.size,&ret),
data_bin.size, &bf_key, bf_tkey, &bf_n);
+ CONSUME_REDS(env,data_bin);
return ret;
}
@@ -2884,7 +2923,7 @@ static EC_KEY* ec_key_new(ErlNifEnv* env, ERL_NIF_TERM curve_arg)
&& 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 */
+ /* {Field, Prime, Point, Order, CoFactor} = Curve */
int f_arity = -1;
const ERL_NIF_TERM* field;
@@ -3038,7 +3077,7 @@ static ERL_NIF_TERM bn2term(ErlNifEnv* env, const BIGNUM *bn)
dlen = BN_num_bytes(bn);
ptr = enif_make_new_binary(env, dlen, &ret);
BN_bn2bin(bn, ptr);
-
+ ERL_VALGRIND_MAKE_MEM_DEFINED(ptr, dlen);
return ret;
}
@@ -3061,39 +3100,10 @@ static ERL_NIF_TERM point2term(ErlNifEnv* env,
enif_release_binary(&bin);
return enif_make_badarg(env);
}
-
+ ERL_VALGRIND_MAKE_MEM_DEFINED(bin.data, bin.size);
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, pub_key, bn2term(env, priv_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)
{
@@ -3121,24 +3131,22 @@ static int term2point(ErlNifEnv* env, ERL_NIF_TERM term,
return ret;
}
-#endif
-static ERL_NIF_TERM term_to_ec_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+static int get_ec_key(ErlNifEnv* env,
+ ERL_NIF_TERM curve, ERL_NIF_TERM priv, ERL_NIF_TERM pub,
+ EC_KEY** res)
{
-#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]))) {
+ if (!(priv == atom_undefined || get_bn_from_bin(env, priv, &priv_key))
+ || !(pub == atom_undefined || enif_is_binary(env, pub))) {
goto out_err;
}
- key = ec_key_new(env, argv[0]);
+ key = ec_key_new(env, curve);
if (!key) {
goto out_err;
@@ -3147,12 +3155,12 @@ static ERL_NIF_TERM term_to_ec_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T
if (!group)
group = EC_GROUP_dup(EC_KEY_get0_group(key));
- if (term2point(env, argv[2], group, &pub_key)) {
+ if (term2point(env, pub, group, &pub_key)) {
if (!EC_KEY_set_public_key(key, pub_key)) {
goto out_err;
}
}
- if (argv[1] != atom_undefined
+ if (priv != atom_undefined
&& !BN_is_zero(priv_key)) {
if (!EC_KEY_set_private_key(key, priv_key))
goto out_err;
@@ -3171,19 +3179,11 @@ static ERL_NIF_TERM term_to_ec_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_T
}
}
- 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);
+ key = NULL;
out:
/* some OpenSSL structures are mem-dup'ed into the key,
@@ -3191,11 +3191,12 @@ out:
if (priv_key) BN_clear_free(priv_key);
if (pub_key) EC_POINT_free(pub_key);
if (group) EC_GROUP_free(group);
- return ret;
-#else
- return atom_notsup;
-#endif
+ if (!key)
+ return 0;
+ *res = key;
+ return 1;
}
+#endif /* HAVE_EC */
static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
@@ -3203,14 +3204,21 @@ static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM
EC_KEY *key = ec_key_new(env, argv[0]);
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;
+ const EC_GROUP *group;
+ const EC_POINT *public_key;
+ ERL_NIF_TERM priv_key;
+ ERL_NIF_TERM pub_key = atom_undefined;
+
+ group = EC_KEY_get0_group(key);
+ public_key = EC_KEY_get0_public_key(key);
+
+ if (group && public_key) {
+ pub_key = point2term(env, group, public_key,
+ EC_KEY_get_conv_form(key));
+ }
+ priv_key = bn2term(env, EC_KEY_get0_private_key(key));
+ EC_KEY_free(key);
+ return enif_make_tuple2(env, pub_key, priv_key);
}
else
return enif_make_badarg(env);
@@ -3219,21 +3227,13 @@ static ERL_NIF_TERM ec_key_generate(ErlNifEnv* env, int argc, const ERL_NIF_TERM
#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) */
+{/* (Type, Data|{digest,Digest}, Curve, 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;
+ EC_KEY* key = NULL;
int i;
const ERL_NIF_TERM* tpl_terms;
int tpl_arity;
@@ -3248,30 +3248,32 @@ static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
return atom_notsup;
}
- if (!enif_get_resource(env, argv[2], res_type_ec_key, (void **)&obj))
- return enif_make_badarg(env);
+ if (!get_ec_key(env, argv[2], argv[3], atom_undefined, &key))
+ goto badarg;
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);
+ goto badarg;
}
digest = data_bin.data;
}
else {
if (!enif_inspect_binary(env,argv[1],&data_bin)) {
- return enif_make_badarg(env);
+ goto badarg;
}
digest = hmacbuf;
digp->funcp(data_bin.data, data_bin.size, digest);
}
- enif_alloc_binary(ECDSA_size(obj->key), &ret_bin);
+ enif_alloc_binary(ECDSA_size(key), &ret_bin);
i = ECDSA_sign(digp->NID_type, digest, digp->len,
- ret_bin.data, &dsa_s_len, obj->key);
+ ret_bin.data, &dsa_s_len, key);
+
+ EC_KEY_free(key);
if (i) {
if (dsa_s_len != ret_bin.size) {
enif_realloc_binary(&ret_bin, dsa_s_len);
@@ -3282,18 +3284,23 @@ static ERL_NIF_TERM ecdsa_sign_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM
enif_release_binary(&ret_bin);
return atom_error;
}
+
+badarg:
+ if (key)
+ EC_KEY_free(key);
+ return enif_make_badarg(env);
#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) */
+{/* (Type, Data|{digest,Digest}, Signature, Curve, Key) */
#if defined(HAVE_EC)
ErlNifBinary data_bin, sign_bin;
unsigned char hmacbuf[SHA512_LEN];
int i;
- struct nif_ec_key *obj;
+ EC_KEY* key = NULL;
const ERL_NIF_TERM type = argv[0];
const ERL_NIF_TERM* tpl_terms;
int tpl_arity;
@@ -3309,15 +3316,15 @@ static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER
}
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);
+ || !get_ec_key(env, argv[3], atom_undefined, argv[4], &key))
+ goto badarg;
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);
+ goto badarg;
}
digest = data_bin.data;
}
@@ -3326,13 +3333,20 @@ static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER
digp->funcp(data_bin.data, data_bin.size, digest);
}
else {
- return enif_make_badarg(env);
+ goto badarg;
}
i = ECDSA_verify(digp->NID_type, digest, digp->len,
- sign_bin.data, sign_bin.size, obj->key);
+ sign_bin.data, sign_bin.size, key);
+
+ EC_KEY_free(key);
return (i==1 ? atom_true : atom_false);
+
+badarg:
+ if (key)
+ EC_KEY_free(key);
+ return enif_make_badarg(env);
#else
return atom_notsup;
#endif
@@ -3343,24 +3357,24 @@ static ERL_NIF_TERM ecdsa_verify_nif(ErlNifEnv* env, int argc, const ERL_NIF_TER
(_OthersPublicKey, _MyEC_Point)
*/
static ERL_NIF_TERM ecdh_compute_key_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+/* (OtherPublicKey, Curve, My) */
{
#if defined(HAVE_EC)
ERL_NIF_TERM ret;
unsigned char *p;
- struct nif_ec_key *other_key;
+ EC_KEY* key = NULL;
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[1], res_type_ec_key, (void **)&other_key))
+ if (!get_ec_key(env, argv[1], argv[2], atom_undefined, &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);
+ group = EC_GROUP_dup(EC_KEY_get0_group(key));
+ priv_key = EC_KEY_get0_private_key(key);
if (!term2point(env, argv[0], group, &my_ecpoint)) {
goto out_err;
@@ -3384,6 +3398,7 @@ out:
if (group) EC_GROUP_free(group);
if (my_ecpoint) EC_POINT_free(my_ecpoint);
if (other_ecdh) EC_KEY_free(other_ecdh);
+ if (key) EC_KEY_free(key);
return ret;