diff options
author | Doug Hogan <[email protected]> | 2019-01-03 23:35:17 -0800 |
---|---|---|
committer | Doug Hogan <[email protected]> | 2019-01-08 01:11:58 -0800 |
commit | 7040f760cb41639024b114f15e4f6d28a154864c (patch) | |
tree | 2d11eb548cd01aa908f5ac4f16e7116a4254da9d /lib/crypto/c_src | |
parent | 0eab42611349dace5a596fcbd495bd5e1ddf1d19 (diff) | |
download | otp-7040f760cb41639024b114f15e4f6d28a154864c.tar.gz otp-7040f760cb41639024b114f15e4f6d28a154864c.tar.bz2 otp-7040f760cb41639024b114f15e4f6d28a154864c.zip |
Revamp srp_host_secret_nif()
* Add error checking on all OpenSSL calls.
* Change dlen to int.
* Consolidate all of the freeing of resources into a common path.
Diffstat (limited to 'lib/crypto/c_src')
-rw-r--r-- | lib/crypto/c_src/srp.c | 116 |
1 files changed, 69 insertions, 47 deletions
diff --git a/lib/crypto/c_src/srp.c b/lib/crypto/c_src/srp.c index e5ef72af08..5a49a1c1b4 100644 --- a/lib/crypto/c_src/srp.c +++ b/lib/crypto/c_src/srp.c @@ -224,63 +224,85 @@ ERL_NIF_TERM srp_host_secret_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM ar <premaster secret> = (A * v^u) ^ b % N */ BIGNUM *bn_b = NULL, *bn_verifier = NULL; - BIGNUM *bn_prime = NULL, *bn_A = NULL, *bn_u = NULL, *bn_base, *bn_result; - BN_CTX *bn_ctx; - unsigned char* ptr; - unsigned dlen; + BIGNUM *bn_prime = NULL, *bn_A = NULL, *bn_u = NULL, *bn_base = NULL, *bn_result = NULL; + BN_CTX *bn_ctx = NULL; + unsigned char *ptr; + int dlen; ERL_NIF_TERM ret; CHECK_NO_FIPS_MODE(); - if (!get_bn_from_bin(env, argv[0], &bn_verifier) - || !get_bn_from_bin(env, argv[1], &bn_b) - || !get_bn_from_bin(env, argv[2], &bn_u) - || !get_bn_from_bin(env, argv[3], &bn_A) - || !get_bn_from_bin(env, argv[4], &bn_prime)) - { - if (bn_verifier) BN_free(bn_verifier); - if (bn_b) BN_free(bn_b); - if (bn_u) BN_free(bn_u); - if (bn_A) BN_free(bn_A); - if (bn_prime) BN_free(bn_prime); - return enif_make_badarg(env); - } - - bn_ctx = BN_CTX_new(); - bn_result = BN_new(); + if (argc != 5) + goto bad_arg; + if (!get_bn_from_bin(env, argv[0], &bn_verifier)) + goto bad_arg; + if (!get_bn_from_bin(env, argv[1], &bn_b)) + goto bad_arg; + if (!get_bn_from_bin(env, argv[2], &bn_u)) + goto bad_arg; + if (!get_bn_from_bin(env, argv[3], &bn_A)) + goto bad_arg; + if (!get_bn_from_bin(env, argv[4], &bn_prime)) + goto bad_arg; - /* check that A % N != 0 */ - BN_nnmod(bn_result, bn_A, bn_prime, bn_ctx); - if (BN_is_zero(bn_result)) { - BN_free(bn_b); - BN_free(bn_verifier); - BN_free(bn_prime); - BN_free(bn_A); - BN_CTX_free(bn_ctx); + if ((bn_ctx = BN_CTX_new()) == NULL) + goto err; + if ((bn_result = BN_new()) == NULL) + goto err; - return atom_error; - } + /* check that A % N != 0 */ + if (!BN_nnmod(bn_result, bn_A, bn_prime, bn_ctx)) + goto err; + if (BN_is_zero(bn_result)) + goto err; /* (A * v^u) */ - bn_base = BN_new(); - BN_mod_exp(bn_base, bn_verifier, bn_u, bn_prime, bn_ctx); - BN_mod_mul(bn_base, bn_A, bn_base, bn_prime, bn_ctx); + if ((bn_base = BN_new()) == NULL) + goto err; + if (!BN_mod_exp(bn_base, bn_verifier, bn_u, bn_prime, bn_ctx)) + goto err; + if (!BN_mod_mul(bn_base, bn_A, bn_base, bn_prime, bn_ctx)) + goto err; /* (A * v^u) ^ b % N */ - BN_mod_exp(bn_result, bn_base, bn_b, bn_prime, bn_ctx); - - dlen = BN_num_bytes(bn_result); - ptr = enif_make_new_binary(env, dlen, &ret); - BN_bn2bin(bn_result, ptr); - BN_free(bn_result); - BN_CTX_free(bn_ctx); - - BN_free(bn_u); - BN_free(bn_base); - BN_free(bn_verifier); - BN_free(bn_prime); - BN_free(bn_A); - BN_free(bn_b); + if (!BN_mod_exp(bn_result, bn_base, bn_b, bn_prime, bn_ctx)) + goto err; + + if ((dlen = BN_num_bytes(bn_result)) < 0) + goto err; + if ((ptr = enif_make_new_binary(env, (size_t)dlen, &ret)) == NULL) + goto err; + + if (BN_bn2bin(bn_result, ptr) < 0) + goto err; + + goto done; + + bad_arg: + ret = enif_make_badarg(env); + goto done; + + err: + ret = atom_error; + + done: + if (bn_verifier) + BN_free(bn_verifier); + if (bn_b) + BN_free(bn_b); + if (bn_u) + BN_free(bn_u); + if (bn_A) + BN_free(bn_A); + if (bn_prime) + BN_free(bn_prime); + if (bn_ctx) + BN_CTX_free(bn_ctx); + if (bn_result) + BN_free(bn_result); + if (bn_base) + BN_free(bn_base); + return ret; } |