diff options
author | Doug Hogan <[email protected]> | 2018-12-20 02:00:57 -0800 |
---|---|---|
committer | Doug Hogan <[email protected]> | 2018-12-20 02:30:26 -0800 |
commit | 21cd1994c280c705e99d48ae09f2d94e348875a3 (patch) | |
tree | 0a24a297c36b612a86ea23dd77bce6a0b3723f25 /lib/crypto/c_src/bn.c | |
parent | fe281a6554a32d654fca40bd65cdafe77140aa9f (diff) | |
download | otp-21cd1994c280c705e99d48ae09f2d94e348875a3.tar.gz otp-21cd1994c280c705e99d48ae09f2d94e348875a3.tar.bz2 otp-21cd1994c280c705e99d48ae09f2d94e348875a3.zip |
Move BN and RSA utility functions to new files
Diffstat (limited to 'lib/crypto/c_src/bn.c')
-rw-r--r-- | lib/crypto/c_src/bn.c | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/lib/crypto/c_src/bn.c b/lib/crypto/c_src/bn.c new file mode 100644 index 0000000000..4079870abe --- /dev/null +++ b/lib/crypto/c_src/bn.c @@ -0,0 +1,101 @@ +#include "bn.h" + + +int get_bn_from_mpint(ErlNifEnv* env, ERL_NIF_TERM term, BIGNUM** bnp) +{ + ErlNifBinary bin; + int sz; + if (!enif_inspect_binary(env,term,&bin)) { + return 0; + } + 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); + return 1; +} + +int get_bn_from_bin(ErlNifEnv* env, ERL_NIF_TERM term, BIGNUM** bnp) +{ + ErlNifBinary bin; + if (!enif_inspect_binary(env,term,&bin)) { + return 0; + } + ERL_VALGRIND_ASSERT_MEM_DEFINED(bin.data, bin.size); + *bnp = BN_bin2bn(bin.data, bin.size, NULL); + return 1; +} + +ERL_NIF_TERM bin_from_bn(ErlNifEnv* env, const BIGNUM *bn) +{ + int bn_len; + unsigned char *bin_ptr; + 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); + + return term; +} + +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; + unsigned char* ptr; + unsigned 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)) { + + 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 (bin_hdr) { + put_int32(ptr, extra_byte+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); + return ret; +} + +#ifdef HAVE_EC +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); + ERL_VALGRIND_MAKE_MEM_DEFINED(ptr, dlen); + return ret; +} +#endif |