aboutsummaryrefslogtreecommitdiffstats
path: root/lib/crypto/c_src/crypto.c
diff options
context:
space:
mode:
authorNiclas Eklund <[email protected]>2011-04-15 15:49:42 +0200
committerNiclas Eklund <[email protected]>2011-04-15 15:49:42 +0200
commitf505644be64cd4844742b361a8ff411d70f4aa88 (patch)
treef0b198ec6b9dbb0fdbc211f5ea06f9791ca04bc1 /lib/crypto/c_src/crypto.c
parentfb1eab890f6776419b3999285dff45802658e8f0 (diff)
downloadotp-f505644be64cd4844742b361a8ff411d70f4aa88.tar.gz
otp-f505644be64cd4844742b361a8ff411d70f4aa88.tar.bz2
otp-f505644be64cd4844742b361a8ff411d70f4aa88.zip
Adds NIFs for cryptographically strong random number generation.
Also adds documentation and unit tests. Thanks to Geoff Cant.
Diffstat (limited to 'lib/crypto/c_src/crypto.c')
-rw-r--r--lib/crypto/c_src/crypto.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index b8786f6f94..d4139f0dfa 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -134,7 +134,9 @@ static ERL_NIF_TERM des_ede3_cbc_crypt(ErlNifEnv* env, int argc, const ERL_NIF_T
static ERL_NIF_TERM aes_cfb_128_crypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM aes_ctr_encrypt(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rand_bytes_1(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM strong_rand_bytes_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
static ERL_NIF_TERM rand_bytes_3(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
+static ERL_NIF_TERM strong_rand_uniform_3(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[]);
@@ -204,7 +206,9 @@ static ErlNifFunc nif_funcs[] = {
{"aes_ctr_encrypt", 3, aes_ctr_encrypt},
{"aes_ctr_decrypt", 3, aes_ctr_encrypt},
{"rand_bytes", 1, rand_bytes_1},
+ {"strong_rand_bytes_nif", 1, strong_rand_bytes_nif},
{"rand_bytes", 3, rand_bytes_3},
+ {"strong_rand_uniform", 3, strong_rand_uniform_3},
{"rand_uniform_nif", 2, rand_uniform_nif},
{"mod_exp_nif", 3, mod_exp_nif},
{"dss_verify", 4, dss_verify},
@@ -704,6 +708,22 @@ static ERL_NIF_TERM rand_bytes_1(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
ERL_VALGRIND_MAKE_MEM_DEFINED(data, bytes);
return ret;
}
+static ERL_NIF_TERM strong_rand_bytes_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Bytes) */
+ unsigned bytes;
+ unsigned char* data;
+ ERL_NIF_TERM ret;
+ if (!enif_get_uint(env, argv[0], &bytes)) {
+ return enif_make_badarg(env);
+ }
+ data = enif_make_new_binary(env, bytes, &ret);
+ if ( RAND_bytes(data, bytes) != 1) {
+ return atom_false;
+ }
+ ERL_VALGRIND_MAKE_MEM_DEFINED(data, bytes);
+ return ret;
+}
+
static ERL_NIF_TERM rand_bytes_3(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Bytes, TopMask, BottomMask) */
unsigned bytes;
@@ -724,6 +744,46 @@ static ERL_NIF_TERM rand_bytes_3(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar
}
return ret;
}
+static ERL_NIF_TERM strong_rand_uniform_3(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
+{/* (Bytes, TopMask, BottomMask) */
+ unsigned bits;
+ BIGNUM *bn_rand;
+ int top, bottom;
+ unsigned char* data;
+ unsigned dlen;
+ ERL_NIF_TERM ret;
+ if (!enif_get_uint(env, argv[0], &bits)
+ || !enif_get_int(env, argv[1], &top)
+ || !enif_get_int(env, argv[2], &bottom)) {
+ return enif_make_badarg(env);
+ }
+ if (! (top == -1 || top == 0 || top == 1) ) {
+ return enif_make_badarg(env);
+ }
+ if (! (bottom == 0 || bottom == 1) ) {
+ return enif_make_badarg(env);
+ }
+
+ bn_rand = BN_new();
+ if (! bn_rand ) {
+ return enif_make_badarg(env);
+ }
+
+ /* Get a (bits) bit random number */
+ if (! BN_rand(bn_rand, bits, top, bottom) ) {
+ return enif_make_badarg(env);
+ }
+
+ /* Copy the bignum into an erlang mpint binary. */
+ dlen = BN_num_bytes(bn_rand);
+ data = enif_make_new_binary(env, dlen+4, &ret);
+ put_int32(data, dlen);
+ BN_bn2bin(bn_rand, data+4);
+ ERL_VALGRIND_MAKE_MEM_DEFINED(data+4, dlen);
+ BN_free(bn_rand);
+
+ return ret;
+}
static int get_bn_from_mpint(ErlNifEnv* env, ERL_NIF_TERM term, BIGNUM** bnp)
{