本文整理汇总了C++中BN_CTX_start函数的典型用法代码示例。如果您正苦于以下问题:C++ BN_CTX_start函数的具体用法?C++ BN_CTX_start怎么用?C++ BN_CTX_start使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了BN_CTX_start函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: EC_KEY_set_public_key_affine_coordinates
int EC_KEY_set_public_key_affine_coordinates(EC_KEY *key, BIGNUM *x,
BIGNUM *y)
{
BN_CTX *ctx = NULL;
BIGNUM *tx, *ty;
EC_POINT *point = NULL;
int ok = 0;
#ifndef OPENSSL_NO_EC2M
int tmp_nid, is_char_two = 0;
#endif
if (key == NULL || key->group == NULL || x == NULL || y == NULL) {
ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES,
ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
ctx = BN_CTX_new();
if (ctx == NULL)
return 0;
BN_CTX_start(ctx);
point = EC_POINT_new(key->group);
if (point == NULL)
goto err;
tx = BN_CTX_get(ctx);
ty = BN_CTX_get(ctx);
if (ty == NULL)
goto err;
#ifndef OPENSSL_NO_EC2M
tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(key->group));
if (tmp_nid == NID_X9_62_characteristic_two_field)
is_char_two = 1;
if (is_char_two) {
if (!EC_POINT_set_affine_coordinates_GF2m(key->group, point,
x, y, ctx))
goto err;
if (!EC_POINT_get_affine_coordinates_GF2m(key->group, point,
tx, ty, ctx))
goto err;
} else
#endif
{
if (!EC_POINT_set_affine_coordinates_GFp(key->group, point,
x, y, ctx))
goto err;
if (!EC_POINT_get_affine_coordinates_GFp(key->group, point,
tx, ty, ctx))
goto err;
}
/*
* Check if retrieved coordinates match originals and are less than field
* order: if not values are out of range.
*/
if (BN_cmp(x, tx) || BN_cmp(y, ty)
|| (BN_cmp(x, key->group->field) >= 0)
|| (BN_cmp(y, key->group->field) >= 0)) {
ECerr(EC_F_EC_KEY_SET_PUBLIC_KEY_AFFINE_COORDINATES,
EC_R_COORDINATES_OUT_OF_RANGE);
goto err;
}
if (!EC_KEY_set_public_key(key, point))
goto err;
if (EC_KEY_check_key(key) == 0)
goto err;
ok = 1;
err:
BN_CTX_end(ctx);
BN_CTX_free(ctx);
EC_POINT_free(point);
return ok;
}
示例2: ec_GF2m_montgomery_point_multiply
/* Computes scalar*point and stores the result in r.
* point can not equal r.
* Uses algorithm 2P of
* Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over
* GF(2^m) without precomputation" (CHES '99, LNCS 1717).
*/
static int ec_GF2m_montgomery_point_multiply(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
const EC_POINT *point, BN_CTX *ctx)
{
BIGNUM *x1, *x2, *z1, *z2;
int ret = 0, i;
BN_ULONG mask,word;
if (r == point)
{
ECerr(EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY, EC_R_INVALID_ARGUMENT);
return 0;
}
/* if result should be point at infinity */
if ((scalar == NULL) || BN_is_zero(scalar) || (point == NULL) ||
EC_POINT_is_at_infinity(group, point))
{
return EC_POINT_set_to_infinity(group, r);
}
/* only support affine coordinates */
if (!point->Z_is_one) return 0;
/* Since point_multiply is static we can guarantee that ctx != NULL. */
BN_CTX_start(ctx);
x1 = BN_CTX_get(ctx);
z1 = BN_CTX_get(ctx);
if (z1 == NULL) goto err;
x2 = &r->X;
z2 = &r->Y;
if (!BN_GF2m_mod_arr(x1, &point->X, group->poly)) goto err; /* x1 = x */
if (!BN_one(z1)) goto err; /* z1 = 1 */
if (!group->meth->field_sqr(group, z2, x1, ctx)) goto err; /* z2 = x1^2 = x^2 */
if (!group->meth->field_sqr(group, x2, z2, ctx)) goto err;
if (!BN_GF2m_add(x2, x2, &group->b)) goto err; /* x2 = x^4 + b */
/* find top most bit and go one past it */
i = scalar->top - 1;
mask = BN_TBIT;
word = scalar->d[i];
while (!(word & mask)) mask >>= 1;
mask >>= 1;
/* if top most bit was at word break, go to next word */
if (!mask)
{
i--;
mask = BN_TBIT;
}
for (; i >= 0; i--)
{
word = scalar->d[i];
while (mask)
{
if (word & mask)
{
if (!gf2m_Madd(group, &point->X, x1, z1, x2, z2, ctx)) goto err;
if (!gf2m_Mdouble(group, x2, z2, ctx)) goto err;
}
else
{
if (!gf2m_Madd(group, &point->X, x2, z2, x1, z1, ctx)) goto err;
if (!gf2m_Mdouble(group, x1, z1, ctx)) goto err;
}
mask >>= 1;
}
mask = BN_TBIT;
}
/* convert out of "projective" coordinates */
i = gf2m_Mxy(group, &point->X, &point->Y, x1, z1, x2, z2, ctx);
if (i == 0) goto err;
else if (i == 1)
{
if (!EC_POINT_set_to_infinity(group, r)) goto err;
}
else
{
if (!BN_one(&r->Z)) goto err;
r->Z_is_one = 1;
}
/* GF(2^m) field elements should always have BIGNUM::neg = 0 */
BN_set_negative(&r->X, 0);
BN_set_negative(&r->Y, 0);
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
示例3: ec_GFp_simple_add
int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
const EC_POINT *b, BN_CTX *ctx)
{
int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *,
const BIGNUM *, BN_CTX *);
int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
const BIGNUM *p;
BN_CTX *new_ctx = NULL;
BIGNUM *n0, *n1, *n2, *n3, *n4, *n5, *n6;
int ret = 0;
if (a == b)
return EC_POINT_dbl(group, r, a, ctx);
if (EC_POINT_is_at_infinity(group, a))
return EC_POINT_copy(r, b);
if (EC_POINT_is_at_infinity(group, b))
return EC_POINT_copy(r, a);
field_mul = group->meth->field_mul;
field_sqr = group->meth->field_sqr;
p = &group->field;
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return 0;
}
BN_CTX_start(ctx);
n0 = BN_CTX_get(ctx);
n1 = BN_CTX_get(ctx);
n2 = BN_CTX_get(ctx);
n3 = BN_CTX_get(ctx);
n4 = BN_CTX_get(ctx);
n5 = BN_CTX_get(ctx);
n6 = BN_CTX_get(ctx);
if (n6 == NULL)
goto end;
/*
* Note that in this function we must not read components of 'a' or 'b'
* once we have written the corresponding components of 'r'. ('r' might
* be one of 'a' or 'b'.)
*/
/* n1, n2 */
if (b->Z_is_one) {
if (!BN_copy(n1, &a->X))
goto end;
if (!BN_copy(n2, &a->Y))
goto end;
/* n1 = X_a */
/* n2 = Y_a */
} else {
if (!field_sqr(group, n0, &b->Z, ctx))
goto end;
if (!field_mul(group, n1, &a->X, n0, ctx))
goto end;
/* n1 = X_a * Z_b^2 */
if (!field_mul(group, n0, n0, &b->Z, ctx))
goto end;
if (!field_mul(group, n2, &a->Y, n0, ctx))
goto end;
/* n2 = Y_a * Z_b^3 */
}
/* n3, n4 */
if (a->Z_is_one) {
if (!BN_copy(n3, &b->X))
goto end;
if (!BN_copy(n4, &b->Y))
goto end;
/* n3 = X_b */
/* n4 = Y_b */
} else {
if (!field_sqr(group, n0, &a->Z, ctx))
goto end;
if (!field_mul(group, n3, &b->X, n0, ctx))
goto end;
/* n3 = X_b * Z_a^2 */
if (!field_mul(group, n0, n0, &a->Z, ctx))
goto end;
if (!field_mul(group, n4, &b->Y, n0, ctx))
goto end;
/* n4 = Y_b * Z_a^3 */
}
/* n5, n6 */
if (!BN_mod_sub_quick(n5, n1, n3, p))
goto end;
if (!BN_mod_sub_quick(n6, n2, n4, p))
goto end;
/* n5 = n1 - n3 */
/* n6 = n2 - n4 */
if (BN_is_zero(n5)) {
if (BN_is_zero(n6)) {
/* a is the same point as b */
//.........这里部分代码省略.........
示例4: ECDSA_SIG_recover_key_GFp
// Perform ECDSA key recovery (see SEC1 4.1.6) for curves over (mod p)-fields
// recid selects which key is recovered
// if check is non-zero, additional checks are performed
int ECDSA_SIG_recover_key_GFp(EC_KEY *eckey, ECDSA_SIG *ecsig, const unsigned char *msg, int msglen, int recid, int check)
{
if (!eckey) return 0;
int ret = 0;
BN_CTX *ctx = NULL;
BIGNUM *x = NULL;
BIGNUM *e = NULL;
BIGNUM *order = NULL;
BIGNUM *sor = NULL;
BIGNUM *eor = NULL;
BIGNUM *field = NULL;
EC_POINT *R = NULL;
EC_POINT *O = NULL;
EC_POINT *Q = NULL;
BIGNUM *rr = NULL;
BIGNUM *zero = NULL;
int n = 0;
int i = recid / 2;
const EC_GROUP *group = EC_KEY_get0_group(eckey);
if ((ctx = BN_CTX_new()) == NULL) { ret = -1; goto err; }
BN_CTX_start(ctx);
order = BN_CTX_get(ctx);
if (!EC_GROUP_get_order(group, order, ctx)) { ret = -2; goto err; }
x = BN_CTX_get(ctx);
if (!BN_copy(x, order)) { ret=-1; goto err; }
if (!BN_mul_word(x, i)) { ret=-1; goto err; }
if (!BN_add(x, x, ecsig->r)) { ret=-1; goto err; }
field = BN_CTX_get(ctx);
if (!EC_GROUP_get_curve_GFp(group, field, NULL, NULL, ctx)) { ret=-2; goto err; }
if (BN_cmp(x, field) >= 0) { ret=0; goto err; }
if ((R = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
if (!EC_POINT_set_compressed_coordinates_GFp(group, R, x, recid % 2, ctx)) { ret=0; goto err; }
if (check)
{
if ((O = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
if (!EC_POINT_mul(group, O, NULL, R, order, ctx)) { ret=-2; goto err; }
if (!EC_POINT_is_at_infinity(group, O)) { ret = 0; goto err; }
}
if ((Q = EC_POINT_new(group)) == NULL) { ret = -2; goto err; }
n = EC_GROUP_get_degree(group);
e = BN_CTX_get(ctx);
if (!BN_bin2bn(msg, msglen, e)) { ret=-1; goto err; }
if (8*msglen > n) BN_rshift(e, e, 8-(n & 7));
zero = BN_CTX_get(ctx);
if (!BN_zero(zero)) { ret=-1; goto err; }
if (!BN_mod_sub(e, zero, e, order, ctx)) { ret=-1; goto err; }
rr = BN_CTX_get(ctx);
if (!BN_mod_inverse(rr, ecsig->r, order, ctx)) { ret=-1; goto err; }
sor = BN_CTX_get(ctx);
if (!BN_mod_mul(sor, ecsig->s, rr, order, ctx)) { ret=-1; goto err; }
eor = BN_CTX_get(ctx);
if (!BN_mod_mul(eor, e, rr, order, ctx)) { ret=-1; goto err; }
if (!EC_POINT_mul(group, Q, eor, R, sor, ctx)) { ret=-2; goto err; }
if (!EC_KEY_set_public_key(eckey, Q)) { ret=-2; goto err; }
ret = 1;
err:
if (ctx) {
BN_CTX_end(ctx);
BN_CTX_free(ctx);
}
if (R != NULL) EC_POINT_free(R);
if (O != NULL) EC_POINT_free(O);
if (Q != NULL) EC_POINT_free(Q);
return ret;
}
示例5: ec_GFp_simple_point_get_affine_coordinates
int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group,
const EC_POINT *point,
BIGNUM *x, BIGNUM *y,
BN_CTX *ctx)
{
BN_CTX *new_ctx = NULL;
BIGNUM *Z, *Z_1, *Z_2, *Z_3;
const BIGNUM *Z_;
int ret = 0;
if (EC_POINT_is_at_infinity(group, point)) {
ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES,
EC_R_POINT_AT_INFINITY);
return 0;
}
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return 0;
}
BN_CTX_start(ctx);
Z = BN_CTX_get(ctx);
Z_1 = BN_CTX_get(ctx);
Z_2 = BN_CTX_get(ctx);
Z_3 = BN_CTX_get(ctx);
if (Z_3 == NULL)
goto err;
/* transform (X, Y, Z) into (x, y) := (X/Z^2, Y/Z^3) */
if (group->meth->field_decode) {
if (!group->meth->field_decode(group, Z, &point->Z, ctx))
goto err;
Z_ = Z;
} else {
Z_ = &point->Z;
}
if (BN_is_one(Z_)) {
if (group->meth->field_decode) {
if (x != NULL) {
if (!group->meth->field_decode(group, x, &point->X, ctx))
goto err;
}
if (y != NULL) {
if (!group->meth->field_decode(group, y, &point->Y, ctx))
goto err;
}
} else {
if (x != NULL) {
if (!BN_copy(x, &point->X))
goto err;
}
if (y != NULL) {
if (!BN_copy(y, &point->Y))
goto err;
}
}
} else {
if (!BN_mod_inverse(Z_1, Z_, &group->field, ctx)) {
ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES,
ERR_R_BN_LIB);
goto err;
}
if (group->meth->field_encode == 0) {
/* field_sqr works on standard representation */
if (!group->meth->field_sqr(group, Z_2, Z_1, ctx))
goto err;
} else {
if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx))
goto err;
}
if (x != NULL) {
/*
* in the Montgomery case, field_mul will cancel out Montgomery
* factor in X:
*/
if (!group->meth->field_mul(group, x, &point->X, Z_2, ctx))
goto err;
}
if (y != NULL) {
if (group->meth->field_encode == 0) {
/*
* field_mul works on standard representation
*/
if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx))
goto err;
} else {
if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx))
goto err;
}
/*
* in the Montgomery case, field_mul will cancel out Montgomery
* factor in Y:
//.........这里部分代码省略.........
示例6: ec_GF2m_simple_add
/* Computes a + b and stores the result in r. r could be a or b, a could be b.
* Uses algorithm A.10.2 of IEEE P1363.
*/
int
ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
const EC_POINT *b, BN_CTX *ctx)
{
BN_CTX *new_ctx = NULL;
BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t;
int ret = 0;
if (EC_POINT_is_at_infinity(group, a) > 0) {
if (!EC_POINT_copy(r, b))
return 0;
return 1;
}
if (EC_POINT_is_at_infinity(group, b) > 0) {
if (!EC_POINT_copy(r, a))
return 0;
return 1;
}
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return 0;
}
BN_CTX_start(ctx);
if ((x0 = BN_CTX_get(ctx)) == NULL)
goto err;
if ((y0 = BN_CTX_get(ctx)) == NULL)
goto err;
if ((x1 = BN_CTX_get(ctx)) == NULL)
goto err;
if ((y1 = BN_CTX_get(ctx)) == NULL)
goto err;
if ((x2 = BN_CTX_get(ctx)) == NULL)
goto err;
if ((y2 = BN_CTX_get(ctx)) == NULL)
goto err;
if ((s = BN_CTX_get(ctx)) == NULL)
goto err;
if ((t = BN_CTX_get(ctx)) == NULL)
goto err;
if (a->Z_is_one) {
if (!BN_copy(x0, &a->X))
goto err;
if (!BN_copy(y0, &a->Y))
goto err;
} else {
if (!EC_POINT_get_affine_coordinates_GF2m(group, a, x0, y0, ctx))
goto err;
}
if (b->Z_is_one) {
if (!BN_copy(x1, &b->X))
goto err;
if (!BN_copy(y1, &b->Y))
goto err;
} else {
if (!EC_POINT_get_affine_coordinates_GF2m(group, b, x1, y1, ctx))
goto err;
}
if (BN_GF2m_cmp(x0, x1)) {
if (!BN_GF2m_add(t, x0, x1))
goto err;
if (!BN_GF2m_add(s, y0, y1))
goto err;
if (!group->meth->field_div(group, s, s, t, ctx))
goto err;
if (!group->meth->field_sqr(group, x2, s, ctx))
goto err;
if (!BN_GF2m_add(x2, x2, &group->a))
goto err;
if (!BN_GF2m_add(x2, x2, s))
goto err;
if (!BN_GF2m_add(x2, x2, t))
goto err;
} else {
if (BN_GF2m_cmp(y0, y1) || BN_is_zero(x1)) {
if (!EC_POINT_set_to_infinity(group, r))
goto err;
ret = 1;
goto err;
}
if (!group->meth->field_div(group, s, y1, x1, ctx))
goto err;
if (!BN_GF2m_add(s, s, x1))
goto err;
if (!group->meth->field_sqr(group, x2, s, ctx))
goto err;
if (!BN_GF2m_add(x2, x2, s))
goto err;
if (!BN_GF2m_add(x2, x2, &group->a))
goto err;
}
if (!BN_GF2m_add(y2, x1, x2))
//.........这里部分代码省略.........
示例7: ec_GFp_simple_point2oct
size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
unsigned char *buf, size_t len, BN_CTX *ctx)
{
size_t ret;
BN_CTX *new_ctx = NULL;
int used_ctx = 0;
BIGNUM *x, *y;
size_t field_len, i, skip;
if ((form != POINT_CONVERSION_COMPRESSED)
&& (form != POINT_CONVERSION_UNCOMPRESSED)
&& (form != POINT_CONVERSION_HYBRID))
{
ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
goto err;
}
if (EC_POINT_is_at_infinity(group, point))
{
/* encodes to a single 0 octet */
if (buf != NULL)
{
if (len < 1)
{
ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
return 0;
}
buf[0] = 0;
}
return 1;
}
/* ret := required output buffer length */
field_len = BN_num_bytes(&group->field);
ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
/* if 'buf' is NULL, just return required length */
if (buf != NULL)
{
if (len < ret)
{
ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
goto err;
}
if (ctx == NULL)
{
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return 0;
}
BN_CTX_start(ctx);
used_ctx = 1;
x = BN_CTX_get(ctx);
y = BN_CTX_get(ctx);
if (y == NULL) goto err;
if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
if ((form == POINT_CONVERSION_COMPRESSED || form == POINT_CONVERSION_HYBRID) && BN_is_odd(y))
buf[0] = form + 1;
else
buf[0] = form;
i = 1;
skip = field_len - BN_num_bytes(x);
if (skip > field_len)
{
ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
goto err;
}
while (skip > 0)
{
buf[i++] = 0;
skip--;
}
skip = BN_bn2bin(x, buf + i);
i += skip;
if (i != 1 + field_len)
{
ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
goto err;
}
if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID)
{
skip = field_len - BN_num_bytes(y);
if (skip > field_len)
{
ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
goto err;
}
while (skip > 0)
{
buf[i++] = 0;
skip--;
}
//.........这里部分代码省略.........
示例8: ec_GFp_simple_oct2point
int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
const unsigned char *buf, size_t len, BN_CTX *ctx)
{
point_conversion_form_t form;
int y_bit;
BN_CTX *new_ctx = NULL;
BIGNUM *x, *y;
size_t field_len, enc_len;
int ret = 0;
if (len == 0)
{
ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
return 0;
}
form = buf[0];
y_bit = form & 1;
form = form & ~1U;
if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED)
&& (form != POINT_CONVERSION_UNCOMPRESSED)
&& (form != POINT_CONVERSION_HYBRID))
{
ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
return 0;
}
if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit)
{
ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
return 0;
}
if (form == 0)
{
if (len != 1)
{
ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
return 0;
}
return EC_POINT_set_to_infinity(group, point);
}
field_len = BN_num_bytes(&group->field);
enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
if (len != enc_len)
{
ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
return 0;
}
if (ctx == NULL)
{
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return 0;
}
BN_CTX_start(ctx);
x = BN_CTX_get(ctx);
y = BN_CTX_get(ctx);
if (y == NULL) goto err;
if (!BN_bin2bn(buf + 1, (int)field_len, x)) goto err;
if (BN_ucmp(x, &group->field) >= 0)
{
ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
goto err;
}
if (form == POINT_CONVERSION_COMPRESSED)
{
if (!EC_POINT_set_compressed_coordinates_GFp(group, point, x, y_bit, ctx)) goto err;
}
else
{
if (!BN_bin2bn(buf + 1 + field_len, (int)field_len, y)) goto err;
if (BN_ucmp(y, &group->field) >= 0)
{
ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
goto err;
}
if (form == POINT_CONVERSION_HYBRID)
{
if (y_bit != BN_is_odd(y))
{
ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
goto err;
}
}
if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err;
}
if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
{
ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
goto err;
}
//.........这里部分代码省略.........
示例9: ec_GFp_simple_points_make_affine
int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx)
{
BN_CTX *new_ctx = NULL;
BIGNUM *tmp0, *tmp1;
size_t pow2 = 0;
BIGNUM **heap = NULL;
size_t i;
int ret = 0;
if (num == 0)
return 1;
if (ctx == NULL)
{
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return 0;
}
BN_CTX_start(ctx);
tmp0 = BN_CTX_get(ctx);
tmp1 = BN_CTX_get(ctx);
if (tmp0 == NULL || tmp1 == NULL) goto err;
/* Before converting the individual points, compute inverses of all Z values.
* Modular inversion is rather slow, but luckily we can do with a single
* explicit inversion, plus about 3 multiplications per input value.
*/
pow2 = 1;
while (num > pow2)
pow2 <<= 1;
/* Now pow2 is the smallest power of 2 satifsying pow2 >= num.
* We need twice that. */
pow2 <<= 1;
heap = OPENSSL_malloc(pow2 * sizeof heap[0]);
if (heap == NULL) goto err;
/* The array is used as a binary tree, exactly as in heapsort:
*
* heap[1]
* heap[2] heap[3]
* heap[4] heap[5] heap[6] heap[7]
* heap[8]heap[9] heap[10]heap[11] heap[12]heap[13] heap[14] heap[15]
*
* We put the Z's in the last line;
* then we set each other node to the product of its two child-nodes (where
* empty or 0 entries are treated as ones);
* then we invert heap[1];
* then we invert each other node by replacing it by the product of its
* parent (after inversion) and its sibling (before inversion).
*/
heap[0] = NULL;
for (i = pow2/2 - 1; i > 0; i--)
heap[i] = NULL;
for (i = 0; i < num; i++)
heap[pow2/2 + i] = &points[i]->Z;
for (i = pow2/2 + num; i < pow2; i++)
heap[i] = NULL;
/* set each node to the product of its children */
for (i = pow2/2 - 1; i > 0; i--)
{
heap[i] = BN_new();
if (heap[i] == NULL) goto err;
if (heap[2*i] != NULL)
{
if ((heap[2*i + 1] == NULL) || BN_is_zero(heap[2*i + 1]))
{
if (!BN_copy(heap[i], heap[2*i])) goto err;
}
else
{
if (BN_is_zero(heap[2*i]))
{
if (!BN_copy(heap[i], heap[2*i + 1])) goto err;
}
else
{
if (!group->meth->field_mul(group, heap[i],
heap[2*i], heap[2*i + 1], ctx)) goto err;
}
}
}
}
/* invert heap[1] */
if (!BN_is_zero(heap[1]))
{
if (!BN_mod_inverse(heap[1], heap[1], &group->field, ctx))
{
ECerr(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE, ERR_R_BN_LIB);
goto err;
}
}
if (group->meth->field_encode != 0)
{
/* in the Montgomery case, we just turned R*H (representing H)
//.........这里部分代码省略.........
示例10: ec_GFp_simple_set_compressed_coordinates
int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
const BIGNUM *x_, int y_bit, BN_CTX *ctx)
{
BN_CTX *new_ctx = NULL;
BIGNUM *tmp1, *tmp2, *x, *y;
int ret = 0;
/* clear error queue*/
ERR_clear_error();
if (ctx == NULL)
{
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return 0;
}
y_bit = (y_bit != 0);
BN_CTX_start(ctx);
tmp1 = BN_CTX_get(ctx);
tmp2 = BN_CTX_get(ctx);
x = BN_CTX_get(ctx);
y = BN_CTX_get(ctx);
if (y == NULL) goto err;
/* Recover y. We have a Weierstrass equation
* y^2 = x^3 + a*x + b,
* so y is one of the square roots of x^3 + a*x + b.
*/
/* tmp1 := x^3 */
if (!BN_nnmod(x, x_, &group->field,ctx)) goto err;
if (group->meth->field_decode == 0)
{
/* field_{sqr,mul} work on standard representation */
if (!group->meth->field_sqr(group, tmp2, x_, ctx)) goto err;
if (!group->meth->field_mul(group, tmp1, tmp2, x_, ctx)) goto err;
}
else
{
if (!BN_mod_sqr(tmp2, x_, &group->field, ctx)) goto err;
if (!BN_mod_mul(tmp1, tmp2, x_, &group->field, ctx)) goto err;
}
/* tmp1 := tmp1 + a*x */
if (group->a_is_minus3)
{
if (!BN_mod_lshift1_quick(tmp2, x, &group->field)) goto err;
if (!BN_mod_add_quick(tmp2, tmp2, x, &group->field)) goto err;
if (!BN_mod_sub_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
}
else
{
if (group->meth->field_decode)
{
if (!group->meth->field_decode(group, tmp2, &group->a, ctx)) goto err;
if (!BN_mod_mul(tmp2, tmp2, x, &group->field, ctx)) goto err;
}
else
{
/* field_mul works on standard representation */
if (!group->meth->field_mul(group, tmp2, &group->a, x, ctx)) goto err;
}
if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
}
/* tmp1 := tmp1 + b */
if (group->meth->field_decode)
{
if (!group->meth->field_decode(group, tmp2, &group->b, ctx)) goto err;
if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) goto err;
}
else
{
if (!BN_mod_add_quick(tmp1, tmp1, &group->b, &group->field)) goto err;
}
if (!BN_mod_sqrt(y, tmp1, &group->field, ctx))
{
unsigned long err = ERR_peek_last_error();
if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE)
{
ERR_clear_error();
ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
}
else
ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB);
goto err;
}
if (y_bit != BN_is_odd(y))
{
if (BN_is_zero(y))
{
int kron;
kron = BN_kronecker(x, &group->field, ctx);
//.........这里部分代码省略.........
示例11: fill_GOST2001_params
/*
* Fills EC_KEY structure hidden in the app_data field of DSA structure
* with parameter information, extracted from parameter array in
* params.c file.
*
* Also fils DSA->q field with copy of EC_GROUP order field to make
* DSA_size function work
*/
int fill_GOST2001_params(EC_KEY *eckey, int nid)
{
R3410_2001_params *params = R3410_2001_paramset;
EC_GROUP *grp = NULL;
BIGNUM *p = NULL, *q = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL;
EC_POINT *P = NULL;
BN_CTX *ctx = BN_CTX_new();
int ok = 0;
if (!ctx) {
GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE);
goto err;
}
BN_CTX_start(ctx);
p = BN_CTX_get(ctx);
a = BN_CTX_get(ctx);
b = BN_CTX_get(ctx);
x = BN_CTX_get(ctx);
y = BN_CTX_get(ctx);
q = BN_CTX_get(ctx);
if (!p || !a || !b || !x || !y || !q) {
GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE);
goto err;
}
while (params->nid != NID_undef && params->nid != nid)
params++;
if (params->nid == NID_undef) {
GOSTerr(GOST_F_FILL_GOST2001_PARAMS,
GOST_R_UNSUPPORTED_PARAMETER_SET);
goto err;
}
if (!BN_hex2bn(&p, params->p)
|| !BN_hex2bn(&a, params->a)
|| !BN_hex2bn(&b, params->b)) {
GOSTerr(GOST_F_FILL_GOST2001_PARAMS,
ERR_R_INTERNAL_ERROR);
goto err;
}
grp = EC_GROUP_new_curve_GFp(p, a, b, ctx);
if (!grp) {
GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE);
goto err;
}
P = EC_POINT_new(grp);
if (!P) {
GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!BN_hex2bn(&x, params->x)
|| !BN_hex2bn(&y, params->y)
|| !EC_POINT_set_affine_coordinates_GFp(grp, P, x, y, ctx)
|| !BN_hex2bn(&q, params->q)) {
GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_INTERNAL_ERROR);
goto err;
}
#ifdef DEBUG_KEYS
fprintf(stderr, "Set params index %d oid %s\nq=",
(params - R3410_2001_paramset), OBJ_nid2sn(params->nid));
BN_print_fp(stderr, q);
fprintf(stderr, "\n");
#endif
if (!EC_GROUP_set_generator(grp, P, q, NULL)) {
GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_INTERNAL_ERROR);
goto err;
}
EC_GROUP_set_curve_name(grp, params->nid);
if (!EC_KEY_set_group(eckey, grp)) {
GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_INTERNAL_ERROR);
goto err;
}
ok = 1;
err:
EC_POINT_free(P);
EC_GROUP_free(grp);
if (ctx)
BN_CTX_end(ctx);
BN_CTX_free(ctx);
return ok;
}
示例12: gost2001_do_verify
/*
* Verifies gost 2001 signature
*
*/
int gost2001_do_verify(const unsigned char *dgst, int dgst_len,
DSA_SIG *sig, EC_KEY *ec)
{
BN_CTX *ctx = BN_CTX_new();
const EC_GROUP *group = EC_KEY_get0_group(ec);
BIGNUM *order;
BIGNUM *md = NULL, *e = NULL, *R = NULL, *v = NULL, *z1 = NULL, *z2 =
NULL;
BIGNUM *X = NULL, *tmp = NULL;
EC_POINT *C = NULL;
const EC_POINT *pub_key = NULL;
int ok = 0;
if (!ctx || !group) {
GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR);
goto err;
}
BN_CTX_start(ctx);
order = BN_CTX_get(ctx);
e = BN_CTX_get(ctx);
z1 = BN_CTX_get(ctx);
z2 = BN_CTX_get(ctx);
tmp = BN_CTX_get(ctx);
X = BN_CTX_get(ctx);
R = BN_CTX_get(ctx);
v = BN_CTX_get(ctx);
if (!order || !e || !z1 || !z2 || !tmp || !X || !R || !v) {
GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_MALLOC_FAILURE);
goto err;
}
pub_key = EC_KEY_get0_public_key(ec);
if (!pub_key || !EC_GROUP_get_order(group, order, ctx)) {
GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR);
goto err;
}
if (BN_is_zero(sig->s) || BN_is_zero(sig->r) ||
(BN_cmp(sig->s, order) >= 1) || (BN_cmp(sig->r, order) >= 1)) {
GOSTerr(GOST_F_GOST2001_DO_VERIFY,
GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q);
goto err;
}
md = hashsum2bn(dgst);
if (!md || !BN_mod(e, md, order, ctx)) {
GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR);
goto err;
}
#ifdef DEBUG_SIGN
fprintf(stderr, "digest as bignum: ");
BN_print_fp(stderr, md);
fprintf(stderr, "\ndigest mod q: ");
BN_print_fp(stderr, e);
#endif
if (BN_is_zero(e) && !BN_one(e)) {
GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR);
goto err;
}
v = BN_mod_inverse(v, e, order, ctx);
if (!v
|| !BN_mod_mul(z1, sig->s, v, order, ctx)
|| !BN_sub(tmp, order, sig->r)
|| !BN_mod_mul(z2, tmp, v, order, ctx)) {
GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR);
goto err;
}
#ifdef DEBUG_SIGN
fprintf(stderr, "\nInverted digest value: ");
BN_print_fp(stderr, v);
fprintf(stderr, "\nz1: ");
BN_print_fp(stderr, z1);
fprintf(stderr, "\nz2: ");
BN_print_fp(stderr, z2);
#endif
C = EC_POINT_new(group);
if (!C) {
GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!EC_POINT_mul(group, C, z1, pub_key, z2, ctx)) {
GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB);
goto err;
}
if (!EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx)) {
GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB);
goto err;
}
if (!BN_mod(R, X, order, ctx)) {
GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR);
goto err;
}
#ifdef DEBUG_SIGN
fprintf(stderr, "\nX=");
//.........这里部分代码省略.........
示例13: hashsum2bn
/*
* Computes gost2001 signature as DSA_SIG structure
*
*
*/
DSA_SIG *gost2001_do_sign(const unsigned char *dgst, int dlen, EC_KEY *eckey)
{
DSA_SIG *newsig = NULL, *ret = NULL;
BIGNUM *md = hashsum2bn(dgst);
BIGNUM *order = NULL;
const EC_GROUP *group;
const BIGNUM *priv_key;
BIGNUM *r = NULL, *s = NULL, *X = NULL, *tmp = NULL, *tmp2 = NULL, *k =
NULL, *e = NULL;
EC_POINT *C = NULL;
BN_CTX *ctx = BN_CTX_new();
if (!ctx || !md) {
GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE);
goto err;
}
BN_CTX_start(ctx);
OPENSSL_assert(dlen == 32);
newsig = DSA_SIG_new();
if (!newsig) {
GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE);
goto err;
}
group = EC_KEY_get0_group(eckey);
if (!group) {
GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR);
goto err;
}
order = BN_CTX_get(ctx);
if (!order || !EC_GROUP_get_order(group, order, ctx)) {
GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR);
goto err;
}
priv_key = EC_KEY_get0_private_key(eckey);
if (!priv_key) {
GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR);
goto err;
}
e = BN_CTX_get(ctx);
if (!e || !BN_mod(e, md, order, ctx)) {
GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR);
goto err;
}
#ifdef DEBUG_SIGN
fprintf(stderr, "digest as bignum=");
BN_print_fp(stderr, md);
fprintf(stderr, "\ndigest mod q=");
BN_print_fp(stderr, e);
fprintf(stderr, "\n");
#endif
if (BN_is_zero(e)) {
BN_one(e);
}
k = BN_CTX_get(ctx);
C = EC_POINT_new(group);
if (!k || !C) {
GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE);
goto err;
}
do {
do {
if (!BN_rand_range(k, order)) {
GOSTerr(GOST_F_GOST2001_DO_SIGN,
GOST_R_RANDOM_NUMBER_GENERATOR_FAILED);
goto err;
}
if (!EC_POINT_mul(group, C, k, NULL, NULL, ctx)) {
GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB);
goto err;
}
if (!X)
X = BN_CTX_get(ctx);
if (!r)
r = BN_CTX_get(ctx);
if (!X || !r) {
GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx)) {
GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB);
goto err;
}
if (!BN_nnmod(r, X, order, ctx)) {
GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR);
goto err;
}
}
while (BN_is_zero(r));
/* s = (r*priv_key+k*e) mod order */
if (!tmp)
tmp = BN_CTX_get(ctx);
if (!tmp2)
tmp2 = BN_CTX_get(ctx);
if (!s)
s = BN_CTX_get(ctx);
//.........这里部分代码省略.........
示例14: ec_GFp_simple_points_make_affine
int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num,
EC_POINT *points[], BN_CTX *ctx)
{
BN_CTX *new_ctx = NULL;
BIGNUM *tmp, *tmp_Z;
BIGNUM **prod_Z = NULL;
size_t i;
int ret = 0;
if (num == 0)
return 1;
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return 0;
}
BN_CTX_start(ctx);
tmp = BN_CTX_get(ctx);
tmp_Z = BN_CTX_get(ctx);
if (tmp == NULL || tmp_Z == NULL)
goto err;
prod_Z = OPENSSL_malloc(num * sizeof(prod_Z[0]));
if (prod_Z == NULL)
goto err;
for (i = 0; i < num; i++) {
prod_Z[i] = BN_new();
if (prod_Z[i] == NULL)
goto err;
}
/*
* Set each prod_Z[i] to the product of points[0]->Z .. points[i]->Z,
* skipping any zero-valued inputs (pretend that they're 1).
*/
if (!BN_is_zero(&points[0]->Z)) {
if (!BN_copy(prod_Z[0], &points[0]->Z))
goto err;
} else {
if (group->meth->field_set_to_one != 0) {
if (!group->meth->field_set_to_one(group, prod_Z[0], ctx))
goto err;
} else {
if (!BN_one(prod_Z[0]))
goto err;
}
}
for (i = 1; i < num; i++) {
if (!BN_is_zero(&points[i]->Z)) {
if (!group->meth->field_mul(group, prod_Z[i], prod_Z[i - 1],
&points[i]->Z, ctx))
goto err;
} else {
if (!BN_copy(prod_Z[i], prod_Z[i - 1]))
goto err;
}
}
/*
* Now use a single explicit inversion to replace every non-zero
* points[i]->Z by its inverse.
*/
if (!BN_mod_inverse(tmp, prod_Z[num - 1], &group->field, ctx)) {
ECerr(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE, ERR_R_BN_LIB);
goto err;
}
if (group->meth->field_encode != 0) {
/*
* In the Montgomery case, we just turned R*H (representing H) into
* 1/(R*H), but we need R*(1/H) (representing 1/H); i.e. we need to
* multiply by the Montgomery factor twice.
*/
if (!group->meth->field_encode(group, tmp, tmp, ctx))
goto err;
if (!group->meth->field_encode(group, tmp, tmp, ctx))
goto err;
}
for (i = num - 1; i > 0; --i) {
/*
* Loop invariant: tmp is the product of the inverses of points[0]->Z
* .. points[i]->Z (zero-valued inputs skipped).
*/
if (!BN_is_zero(&points[i]->Z)) {
/*
* Set tmp_Z to the inverse of points[i]->Z (as product of Z
* inverses 0 .. i, Z values 0 .. i - 1).
*/
if (!group->
meth->field_mul(group, tmp_Z, prod_Z[i - 1], tmp, ctx))
goto err;
/*
* Update tmp to satisfy the loop invariant for i - 1.
*/
if (!group->meth->field_mul(group, tmp, tmp, &points[i]->Z, ctx))
//.........这里部分代码省略.........
示例15: ec_GFp_simple_group_check_discriminant
int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
{
int ret = 0;
BIGNUM *a, *b, *order, *tmp_1, *tmp_2;
const BIGNUM *p = &group->field;
BN_CTX *new_ctx = NULL;
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL) {
ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT,
ERR_R_MALLOC_FAILURE);
goto err;
}
}
BN_CTX_start(ctx);
a = BN_CTX_get(ctx);
b = BN_CTX_get(ctx);
tmp_1 = BN_CTX_get(ctx);
tmp_2 = BN_CTX_get(ctx);
order = BN_CTX_get(ctx);
if (order == NULL)
goto err;
if (group->meth->field_decode) {
if (!group->meth->field_decode(group, a, &group->a, ctx))
goto err;
if (!group->meth->field_decode(group, b, &group->b, ctx))
goto err;
} else {
if (!BN_copy(a, &group->a))
goto err;
if (!BN_copy(b, &group->b))
goto err;
}
/*-
* check the discriminant:
* y^2 = x^3 + a*x + b is an elliptic curve <=> 4*a^3 + 27*b^2 != 0 (mod p)
* 0 =< a, b < p
*/
if (BN_is_zero(a)) {
if (BN_is_zero(b))
goto err;
} else if (!BN_is_zero(b)) {
if (!BN_mod_sqr(tmp_1, a, p, ctx))
goto err;
if (!BN_mod_mul(tmp_2, tmp_1, a, p, ctx))
goto err;
if (!BN_lshift(tmp_1, tmp_2, 2))
goto err;
/* tmp_1 = 4*a^3 */
if (!BN_mod_sqr(tmp_2, b, p, ctx))
goto err;
if (!BN_mul_word(tmp_2, 27))
goto err;
/* tmp_2 = 27*b^2 */
if (!BN_mod_add(a, tmp_1, tmp_2, p, ctx))
goto err;
if (BN_is_zero(a))
goto err;
}
ret = 1;
err:
if (ctx != NULL)
BN_CTX_end(ctx);
if (new_ctx != NULL)
BN_CTX_free(new_ctx);
return ret;
}