From fba65fa791a44b5d0226bd150e8d9accab1e442a Mon Sep 17 00:00:00 2001 From: Doug Hogan Date: Mon, 7 Jan 2019 00:39:03 -0800 Subject: Revamp ec_key_new() --- lib/crypto/c_src/ec.c | 290 +++++++++++++++++++++++++++----------------------- 1 file changed, 158 insertions(+), 132 deletions(-) (limited to 'lib/crypto') diff --git a/lib/crypto/c_src/ec.c b/lib/crypto/c_src/ec.c index 6d831ec9d2..98d3007f13 100644 --- a/lib/crypto/c_src/ec.c +++ b/lib/crypto/c_src/ec.c @@ -50,157 +50,183 @@ static EC_KEY* ec_key_new(ErlNifEnv* env, ERL_NIF_TERM curve_arg) BIGNUM *cofactor = NULL; EC_GROUP *group = NULL; EC_POINT *point = NULL; + int f_arity = -1; + const ERL_NIF_TERM *field; + int p_arity = -1; + const ERL_NIF_TERM *prime; + long field_bits; /* {Field, Prime, Point, Order, CoFactor} = Curve */ - if (enif_get_tuple(env,curve_arg,&c_arity,&curve) - && c_arity == 5 - && get_bn_from_bin(env, curve[3], &bn_order) - && (curve[4] != atom_none && get_bn_from_bin(env, curve[4], &cofactor))) { - - int f_arity = -1; - const ERL_NIF_TERM* field; - int p_arity = -1; - const ERL_NIF_TERM* prime; - - long field_bits; - - /* {A, B, Seed} = Prime */ - if (!enif_get_tuple(env,curve[1],&p_arity,&prime) - || !get_bn_from_bin(env, prime[0], &a) - || !get_bn_from_bin(env, prime[1], &b)) - goto out_err; - - if (!enif_get_tuple(env,curve[0],&f_arity,&field)) - goto out_err; - - if (f_arity == 2 && field[0] == atom_prime_field) { - /* {prime_field, Prime} */ - - if (!get_bn_from_bin(env, field[1], &p)) - goto out_err; - - if (BN_is_negative(p) || BN_is_zero(p)) - goto out_err; - - field_bits = BN_num_bits(p); - if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) - goto out_err; - - /* create the EC_GROUP structure */ - group = EC_GROUP_new_curve_GFp(p, a, b, NULL); + if (!enif_get_tuple(env, curve_arg, &c_arity, &curve)) + goto err; + if (c_arity != 5) + goto err; + if (!get_bn_from_bin(env, curve[3], &bn_order)) + goto err; + if (curve[4] != atom_none) { + if (!get_bn_from_bin(env, curve[4], &cofactor)) + goto err; + } - } else if (f_arity == 3 && field[0] == atom_characteristic_two_field) { + /* {A, B, Seed} = Prime */ + if (!enif_get_tuple(env, curve[1], &p_arity, &prime)) + goto err; + if (!get_bn_from_bin(env, prime[0], &a)) + goto err; + if (!get_bn_from_bin(env, prime[1], &b)) + goto err; + + if (!enif_get_tuple(env, curve[0], &f_arity, &field)) + goto err; + + if (f_arity == 2 && field[0] == atom_prime_field) { + /* {prime_field, Prime} */ + if (!get_bn_from_bin(env, field[1], &p)) + goto err; + if (BN_is_negative(p)) + goto err; + if (BN_is_zero(p)) + goto err; + + field_bits = BN_num_bits(p); + if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) + goto err; + + /* create the EC_GROUP structure */ + if ((group = EC_GROUP_new_curve_GFp(p, a, b, NULL)) == NULL) + goto err; + + } else if (f_arity == 3 && field[0] == atom_characteristic_two_field) { #if defined(OPENSSL_NO_EC2M) - enif_raise_exception(env, atom_notsup); - goto out_err; + enif_raise_exception(env, atom_notsup); + goto out_err; #else - /* {characteristic_two_field, M, Basis} */ - - int b_arity = -1; - const ERL_NIF_TERM* basis; - unsigned int k1, k2, k3; - - if ((p = BN_new()) == NULL) - goto out_err; - - if (!enif_get_long(env, field[1], &field_bits) - || field_bits > OPENSSL_ECC_MAX_FIELD_BITS) - goto out_err; - - if (enif_get_tuple(env,field[2],&b_arity,&basis)) { - if (b_arity == 2 - && basis[0] == atom_tpbasis - && enif_get_uint(env, basis[1], &k1)) { - /* {tpbasis, k} = Basis */ - - if (!(field_bits > k1 && k1 > 0)) - goto out_err; - - /* create the polynomial */ - if (!BN_set_bit(p, (int)field_bits) - || !BN_set_bit(p, (int)k1) - || !BN_set_bit(p, 0)) - goto out_err; - - } else if (b_arity == 4 - && basis[0] == atom_ppbasis - && enif_get_uint(env, basis[1], &k1) - && enif_get_uint(env, basis[2], &k2) - && enif_get_uint(env, basis[3], &k3)) { - /* {ppbasis, k1, k2, k3} = Basis */ - - if (!(field_bits > k3 && k3 > k2 && k2 > k1 && k1 > 0)) - goto out_err; - - /* create the polynomial */ - if (!BN_set_bit(p, (int)field_bits) - || !BN_set_bit(p, (int)k1) - || !BN_set_bit(p, (int)k2) - || !BN_set_bit(p, (int)k3) - || !BN_set_bit(p, 0)) - goto out_err; - - } else - goto out_err; - } else if (field[2] == atom_onbasis) { - /* onbasis = Basis */ - /* no parameters */ - goto out_err; - - } else - goto out_err; - - group = EC_GROUP_new_curve_GF2m(p, a, b, NULL); + /* {characteristic_two_field, M, Basis} */ + int b_arity = -1; + const ERL_NIF_TERM* basis; + + if ((p = BN_new()) == NULL) + goto err; + if (!enif_get_long(env, field[1], &field_bits)) + goto err; + if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS || field_bits > INT_MAX) + goto err; + + if (enif_get_tuple(env, field[2], &b_arity, &basis)) { + if (b_arity == 2) { + unsigned int k1; + + if (basis[0] != atom_tpbasis) + goto err; + if (!enif_get_uint(env, basis[1], &k1)) + goto err; + + /* {tpbasis, k} = Basis */ + if (field_bits <= k1 || k1 == 0 || k1 > INT_MAX) + goto err; + + /* create the polynomial */ + if (!BN_set_bit(p, (int)field_bits)) + goto err; + if (!BN_set_bit(p, (int)k1)) + goto err; + if (!BN_set_bit(p, 0)) + goto err; + + } else if (b_arity == 4) { + unsigned int k1, k2, k3; + + if (basis[0] != atom_ppbasis) + goto err; + if (!enif_get_uint(env, basis[1], &k1)) + goto err; + if (!enif_get_uint(env, basis[2], &k2)) + goto err; + if (!enif_get_uint(env, basis[3], &k3)) + goto err; + + /* {ppbasis, k1, k2, k3} = Basis */ + if (field_bits <= k3 || k3 <= k2 || k2 <= k1 || k1 == 0 || k3 > INT_MAX || k2 > INT_MAX || k1 > INT_MAX) + goto err; + + /* create the polynomial */ + if (!BN_set_bit(p, (int)field_bits)) + goto err; + if (!BN_set_bit(p, (int)k1)) + goto err; + if (!BN_set_bit(p, (int)k2)) + goto err; + if (!BN_set_bit(p, (int)k3)) + goto err; + if (!BN_set_bit(p, 0)) + goto err; + + } else + goto err; + } else if (field[2] == atom_onbasis) { + /* onbasis = Basis */ + /* no parameters */ + goto err; + + } else + goto err; + + if ((group = EC_GROUP_new_curve_GF2m(p, a, b, NULL)) == NULL) + goto err; #endif - } else - goto out_err; - - if (!group) - goto out_err; + } else + goto err; - if (enif_inspect_binary(env, prime[2], &seed)) { - EC_GROUP_set_seed(group, seed.data, seed.size); - } + if (enif_inspect_binary(env, prime[2], &seed)) { + if (!EC_GROUP_set_seed(group, seed.data, seed.size)) + goto err; + } - if (!term2point(env, curve[2], group, &point)) - goto out_err; + if (!term2point(env, curve[2], group, &point)) + goto err; - if (BN_is_negative(bn_order) - || BN_is_zero(bn_order) - || BN_num_bits(bn_order) > (int)field_bits + 1) - goto out_err; + if (BN_is_negative(bn_order)) + goto err; + if (BN_is_zero(bn_order)) + goto err; + if (BN_num_bits(bn_order) > (int)field_bits + 1) + goto err; - if (!EC_GROUP_set_generator(group, point, bn_order, cofactor)) - goto out_err; + if (!EC_GROUP_set_generator(group, point, bn_order, cofactor)) + goto err; - EC_GROUP_set_asn1_flag(group, 0x0); + EC_GROUP_set_asn1_flag(group, 0x0); - key = EC_KEY_new(); - if (!key) - goto out_err; - EC_KEY_set_group(key, group); - } - else { - goto out_err; - } + if ((key = EC_KEY_new()) == NULL) + goto err; + if (!EC_KEY_set_group(key, group)) + goto err; - goto out; + goto done; -out_err: - if (key) EC_KEY_free(key); + err: + if (key) + EC_KEY_free(key); key = NULL; -out: + done: /* some OpenSSL structures are mem-dup'ed into the key, so we have to free our copies here */ - if (p) BN_free(p); - if (a) BN_free(a); - if (b) BN_free(b); - if (bn_order) BN_free(bn_order); - if (cofactor) BN_free(cofactor); - if (group) EC_GROUP_free(group); - if (point) EC_POINT_free(point); + if (bn_order) + BN_free(bn_order); + if (cofactor) + BN_free(cofactor); + if (a) + BN_free(a); + if (b) + BN_free(b); + if (p) + BN_free(p); + if (group) + EC_GROUP_free(group); + if (point) + EC_POINT_free(point); return key; } -- cgit v1.2.3