aboutsummaryrefslogtreecommitdiffstats
path: root/lib/crypto/c_src/bn.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/crypto/c_src/bn.c')
-rw-r--r--lib/crypto/c_src/bn.c153
1 files changed, 109 insertions, 44 deletions
diff --git a/lib/crypto/c_src/bn.c b/lib/crypto/c_src/bn.c
index b576c46e1e..34ed4f7ebc 100644
--- a/lib/crypto/c_src/bn.c
+++ b/lib/crypto/c_src/bn.c
@@ -23,29 +23,53 @@
int get_bn_from_mpint(ErlNifEnv* env, ERL_NIF_TERM term, BIGNUM** bnp)
{
+ BIGNUM *ret;
ErlNifBinary bin;
int sz;
- if (!enif_inspect_binary(env,term,&bin)) {
- return 0;
- }
+
+ if (!enif_inspect_binary(env, term, &bin))
+ goto err;
+ if (bin.size > INT_MAX - 4)
+ goto err;
+
ERL_VALGRIND_ASSERT_MEM_DEFINED(bin.data, bin.size);
- sz = bin.size - 4;
- if (sz < 0 || get_int32(bin.data) != sz) {
- return 0;
- }
- *bnp = BN_bin2bn(bin.data+4, sz, NULL);
+
+ if (bin.size < 4)
+ goto err;
+ sz = (int)bin.size - 4;
+ if (get_int32(bin.data) != sz)
+ goto err;
+
+ if ((ret = BN_bin2bn(bin.data+4, sz, NULL)) == NULL)
+ goto err;
+
+ *bnp = ret;
return 1;
+
+ err:
+ return 0;
}
int get_bn_from_bin(ErlNifEnv* env, ERL_NIF_TERM term, BIGNUM** bnp)
{
+ BIGNUM *ret;
ErlNifBinary bin;
- if (!enif_inspect_binary(env,term,&bin)) {
- return 0;
- }
+
+ if (!enif_inspect_binary(env, term, &bin))
+ goto err;
+ if (bin.size > INT_MAX)
+ goto err;
+
ERL_VALGRIND_ASSERT_MEM_DEFINED(bin.data, bin.size);
- *bnp = BN_bin2bn(bin.data, bin.size, NULL);
+
+ if ((ret = BN_bin2bn(bin.data, (int)bin.size, NULL)) == NULL)
+ goto err;
+
+ *bnp = ret;
return 1;
+
+ err:
+ return 0;
}
ERL_NIF_TERM bin_from_bn(ErlNifEnv* env, const BIGNUM *bn)
@@ -55,67 +79,108 @@ ERL_NIF_TERM bin_from_bn(ErlNifEnv* env, const BIGNUM *bn)
ERL_NIF_TERM term;
/* Copy the bignum into an erlang binary. */
- bn_len = BN_num_bytes(bn);
- bin_ptr = enif_make_new_binary(env, bn_len, &term);
- BN_bn2bin(bn, bin_ptr);
+ if ((bn_len = BN_num_bytes(bn)) < 0)
+ goto err;
+ if ((bin_ptr = enif_make_new_binary(env, (size_t)bn_len, &term)) == NULL)
+ goto err;
+
+ if (BN_bn2bin(bn, bin_ptr) < 0)
+ goto err;
return term;
+
+ err:
+ return atom_error;
}
ERL_NIF_TERM mod_exp_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{/* (Base,Exponent,Modulo,bin_hdr) */
- BIGNUM *bn_base=NULL, *bn_exponent=NULL, *bn_modulo=NULL, *bn_result;
- BN_CTX *bn_ctx;
+ BIGNUM *bn_base = NULL, *bn_exponent = NULL, *bn_modulo = NULL, *bn_result = NULL;
+ BN_CTX *bn_ctx = NULL;
unsigned char* ptr;
- unsigned dlen;
+ int dlen;
unsigned bin_hdr; /* return type: 0=plain binary, 4: mpint */
unsigned extra_byte;
ERL_NIF_TERM ret;
- if (!get_bn_from_bin(env, argv[0], &bn_base)
- || !get_bn_from_bin(env, argv[1], &bn_exponent)
- || !get_bn_from_bin(env, argv[2], &bn_modulo)
- || !enif_get_uint(env,argv[3],&bin_hdr) || (bin_hdr & ~4)) {
+ ASSERT(argc == 4);
+
+ if (!get_bn_from_bin(env, argv[0], &bn_base))
+ goto bad_arg;
+ if (!get_bn_from_bin(env, argv[1], &bn_exponent))
+ goto bad_arg;
+ if (!get_bn_from_bin(env, argv[2], &bn_modulo))
+ goto bad_arg;
+ if (!enif_get_uint(env, argv[3], &bin_hdr))
+ goto bad_arg;
+ if (bin_hdr != 0 && bin_hdr != 4)
+ goto bad_arg;
+
+ if ((bn_result = BN_new()) == NULL)
+ goto err;
+ if ((bn_ctx = BN_CTX_new()) == NULL)
+ goto err;
+
+ if (!BN_mod_exp(bn_result, bn_base, bn_exponent, bn_modulo, bn_ctx))
+ goto err;
- if (bn_base) BN_free(bn_base);
- if (bn_exponent) BN_free(bn_exponent);
- if (bn_modulo) BN_free(bn_modulo);
- return enif_make_badarg(env);
- }
- bn_result = BN_new();
- bn_ctx = BN_CTX_new();
- BN_mod_exp(bn_result, bn_base, bn_exponent, bn_modulo, bn_ctx);
dlen = BN_num_bytes(bn_result);
- extra_byte = bin_hdr && BN_is_bit_set(bn_result, dlen*8-1);
- ptr = enif_make_new_binary(env, bin_hdr+extra_byte+dlen, &ret);
+ if (dlen < 0 || dlen > INT_MAX / 8)
+ goto bad_arg;
+ extra_byte = bin_hdr && BN_is_bit_set(bn_result, dlen * 8 - 1);
+
+ if ((ptr = enif_make_new_binary(env, bin_hdr + extra_byte + (unsigned int)dlen, &ret)) == NULL)
+ goto err;
+
if (bin_hdr) {
- put_int32(ptr, extra_byte+dlen);
- ptr[4] = 0; /* extra zeroed byte to ensure a positive mpint */
- ptr += bin_hdr + extra_byte;
+ put_uint32(ptr, extra_byte + (unsigned int)dlen);
+ ptr[4] = 0; /* extra zeroed byte to ensure a positive mpint */
+ ptr += bin_hdr + extra_byte;
}
+
BN_bn2bin(bn_result, ptr);
- BN_free(bn_result);
- BN_CTX_free(bn_ctx);
- BN_free(bn_modulo);
- BN_free(bn_exponent);
- BN_free(bn_base);
+ goto done;
+
+ bad_arg:
+ err:
+ ret = enif_make_badarg(env);
+
+ done:
+ if (bn_base)
+ BN_free(bn_base);
+ if (bn_exponent)
+ BN_free(bn_exponent);
+ if (bn_modulo)
+ BN_free(bn_modulo);
+ if (bn_result)
+ BN_free(bn_result);
+ if (bn_ctx)
+ BN_CTX_free(bn_ctx);
return ret;
}
#ifdef HAVE_EC
ERL_NIF_TERM bn2term(ErlNifEnv* env, const BIGNUM *bn)
{
- unsigned dlen;
+ int dlen;
unsigned char* ptr;
ERL_NIF_TERM ret;
- if (!bn)
- return atom_undefined;
+ if (bn == NULL)
+ return atom_undefined;
dlen = BN_num_bytes(bn);
- ptr = enif_make_new_binary(env, dlen, &ret);
+ if (dlen < 0)
+ goto err;
+ if ((ptr = enif_make_new_binary(env, (size_t)dlen, &ret)) == NULL)
+ goto err;
+
BN_bn2bin(bn, ptr);
+
ERL_VALGRIND_MAKE_MEM_DEFINED(ptr, dlen);
return ret;
+
+ err:
+ return enif_make_badarg(env);
}
#endif