diff options
Diffstat (limited to 'lib/crypto/c_src/rand.c')
-rw-r--r-- | lib/crypto/c_src/rand.c | 136 |
1 files changed, 93 insertions, 43 deletions
diff --git a/lib/crypto/c_src/rand.c b/lib/crypto/c_src/rand.c index e71e202f36..3812ae0991 100644 --- a/lib/crypto/c_src/rand.c +++ b/lib/crypto/c_src/rand.c @@ -27,73 +27,123 @@ ERL_NIF_TERM strong_rand_bytes_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM 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; - } + ASSERT(argc == 1); + + if (!enif_get_uint(env, argv[0], &bytes)) + goto bad_arg; + if (bytes > INT_MAX) + goto bad_arg; + + if ((data = enif_make_new_binary(env, bytes, &ret)) == NULL) + goto err; + if (RAND_bytes(data, (int)bytes) != 1) + goto err; + ERL_VALGRIND_MAKE_MEM_DEFINED(data, bytes); return ret; + + bad_arg: + return enif_make_badarg(env); + + err: + return atom_false; } ERL_NIF_TERM strong_rand_range_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Range) */ - BIGNUM *bn_range, *bn_rand; + BIGNUM *bn_range = NULL, *bn_rand = NULL; ERL_NIF_TERM ret; - if(!get_bn_from_bin(env, argv[0], &bn_range)) { - return enif_make_badarg(env); - } - - bn_rand = BN_new(); - if (BN_rand_range(bn_rand, bn_range) != 1) { - ret = atom_false; - } - else { - ret = bin_from_bn(env, bn_rand); - } - BN_free(bn_rand); - BN_free(bn_range); + ASSERT(argc == 1); + + if (!get_bn_from_bin(env, argv[0], &bn_range)) + goto bad_arg; + + if ((bn_rand = BN_new()) == NULL) + goto err; + if (!BN_rand_range(bn_rand, bn_range)) + goto err; + + if ((ret = bin_from_bn(env, bn_rand)) == atom_error) + goto err; + goto done; + + bad_arg: + return enif_make_badarg(env); + + err: + ret = atom_false; + + done: + if (bn_rand) + BN_free(bn_rand); + if (bn_range) + BN_free(bn_range); return ret; } ERL_NIF_TERM rand_uniform_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {/* (Lo,Hi) */ - BIGNUM *bn_from = NULL, *bn_to, *bn_rand; + BIGNUM *bn_from = NULL, *bn_to = NULL, *bn_rand = NULL; unsigned char* data; - unsigned dlen; + int dlen; ERL_NIF_TERM ret; - if (!get_bn_from_mpint(env, argv[0], &bn_from) - || !get_bn_from_mpint(env, argv[1], &bn_rand)) { - if (bn_from) BN_free(bn_from); - return enif_make_badarg(env); - } - - bn_to = BN_new(); - BN_sub(bn_to, bn_rand, bn_from); - BN_pseudo_rand_range(bn_rand, bn_to); - BN_add(bn_rand, bn_rand, bn_from); - dlen = BN_num_bytes(bn_rand); - data = enif_make_new_binary(env, dlen+4, &ret); - put_int32(data, dlen); + ASSERT(argc == 2); + + if (!get_bn_from_mpint(env, argv[0], &bn_from)) + goto bad_arg; + if (!get_bn_from_mpint(env, argv[1], &bn_rand)) + goto bad_arg; + + if ((bn_to = BN_new()) == NULL) + goto err; + + if (!BN_sub(bn_to, bn_rand, bn_from)) + goto err; + if (!BN_pseudo_rand_range(bn_rand, bn_to)) + goto err; + if (!BN_add(bn_rand, bn_rand, bn_from)) + goto err; + + if ((dlen = BN_num_bytes(bn_rand)) < 0) + goto err; + if ((data = enif_make_new_binary(env, (size_t)dlen+4, &ret)) == NULL) + goto err; + + put_uint32(data, (unsigned int)dlen); BN_bn2bin(bn_rand, data+4); ERL_VALGRIND_MAKE_MEM_DEFINED(data+4, dlen); - BN_free(bn_rand); - BN_free(bn_from); - BN_free(bn_to); + goto done; + + bad_arg: + err: + ret = enif_make_badarg(env); + + done: + if (bn_rand) + BN_free(bn_rand); + if (bn_from) + BN_free(bn_from); + if (bn_to) + BN_free(bn_to); return ret; } ERL_NIF_TERM rand_seed_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) -{ +{/* (Seed) */ ErlNifBinary seed_bin; + ASSERT(argc == 1); + if (!enif_inspect_binary(env, argv[0], &seed_bin)) - return enif_make_badarg(env); - RAND_seed(seed_bin.data,seed_bin.size); + goto bad_arg; + if (seed_bin.size > INT_MAX) + goto bad_arg; + + RAND_seed(seed_bin.data, (int)seed_bin.size); return atom_ok; -} + bad_arg: + return enif_make_badarg(env); +} |