/* solves ax == 1 (mod n) */ BIGNUM *BN_mod_inverse(BIGNUM *in, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx) { BIGNUM *A,*B,*X,*Y,*M,*D,*T,*R=NULL; BIGNUM *ret=NULL; int sign; bn_check_top(a); bn_check_top(n); BN_CTX_start(ctx); A = BN_CTX_get(ctx); B = BN_CTX_get(ctx); X = BN_CTX_get(ctx); D = BN_CTX_get(ctx); M = BN_CTX_get(ctx); Y = BN_CTX_get(ctx); T = BN_CTX_get(ctx); if (T == NULL) goto err; if (in == NULL) R=BN_new(); else R=in; if (R == NULL) goto err; BN_one(X); BN_zero(Y); if (BN_copy(B,a) == NULL) goto err; if (BN_copy(A,n) == NULL) goto err; A->neg = 0; if (B->neg || (BN_ucmp(B, A) >= 0)) { if (!BN_nnmod(B, B, A, ctx)) goto err; } sign = -1; /* From B = a mod |n|, A = |n| it follows that * * 0 <= B < A, * -sign*X*a == B (mod |n|), * sign*Y*a == A (mod |n|). */ if (BN_is_odd(n) && (BN_num_bits(n) <= (BN_BITS <= 32 ? 450 : 2048))) { /* Binary inversion algorithm; requires odd modulus. * This is faster than the general algorithm if the modulus * is sufficiently small (about 400 .. 500 bits on 32-bit * sytems, but much more on 64-bit systems) */ int shift; while (!BN_is_zero(B)) { /* * 0 < B < |n|, * 0 < A <= |n|, * (1) -sign*X*a == B (mod |n|), * (2) sign*Y*a == A (mod |n|) */ /* Now divide B by the maximum possible power of two in the integers, * and divide X by the same value mod |n|. * When we're done, (1) still holds. */ shift = 0; while (!BN_is_bit_set(B, shift)) /* note that 0 < B */ { shift++; if (BN_is_odd(X)) { if (!BN_uadd(X, X, n)) goto err; } /* now X is even, so we can easily divide it by two */ if (!BN_rshift1(X, X)) goto err; } if (shift > 0) { if (!BN_rshift(B, B, shift)) goto err; } /* Same for A and Y. Afterwards, (2) still holds. */ shift = 0; while (!BN_is_bit_set(A, shift)) /* note that 0 < A */ { shift++; if (BN_is_odd(Y)) { if (!BN_uadd(Y, Y, n)) goto err; } /* now Y is even */ if (!BN_rshift1(Y, Y)) goto err; } if (shift > 0) { if (!BN_rshift(A, A, shift)) goto err; } /* We still have (1) and (2). * Both A and B are odd. * The following computations ensure that * * 0 <= B < |n|, * 0 < A < |n|, * (1) -sign*X*a == B (mod |n|), * (2) sign*Y*a == A (mod |n|), * * and that either A or B is even in the next iteration. */ if (BN_ucmp(B, A) >= 0) { /* -sign*(X + Y)*a == B - A (mod |n|) */ if (!BN_uadd(X, X, Y)) goto err; /* NB: we could use BN_mod_add_quick(X, X, Y, n), but that * actually makes the algorithm slower */ if (!BN_usub(B, B, A)) goto err; } else { /* sign*(X + Y)*a == A - B (mod |n|) */ if (!BN_uadd(Y, Y, X)) goto err; /* as above, BN_mod_add_quick(Y, Y, X, n) would slow things down */ if (!BN_usub(A, A, B)) goto err; } } } else { /* general inversion algorithm */ while (!BN_is_zero(B)) { BIGNUM *tmp; /* * 0 < B < A, * (*) -sign*X*a == B (mod |n|), * sign*Y*a == A (mod |n|) */ /* (D, M) := (A/B, A%B) ... */ if (BN_num_bits(A) == BN_num_bits(B)) { if (!BN_one(D)) goto err; if (!BN_sub(M,A,B)) goto err; } else if (BN_num_bits(A) == BN_num_bits(B) + 1) { /* A/B is 1, 2, or 3 */ if (!BN_lshift1(T,B)) goto err; if (BN_ucmp(A,T) < 0) { /* A < 2*B, so D=1 */ if (!BN_one(D)) goto err; if (!BN_sub(M,A,B)) goto err; } else { /* A >= 2*B, so D=2 or D=3 */ if (!BN_sub(M,A,T)) goto err; if (!BN_add(D,T,B)) goto err; /* use D (:= 3*B) as temp */ if (BN_ucmp(A,D) < 0) { /* A < 3*B, so D=2 */ if (!BN_set_word(D,2)) goto err; /* M (= A - 2*B) already has the correct value */ } else { /* only D=3 remains */ if (!BN_set_word(D,3)) goto err; /* currently M = A - 2*B, but we need M = A - 3*B */ if (!BN_sub(M,M,B)) goto err; } } } else { if (!BN_div(D,M,A,B,ctx)) goto err; } /* Now * A = D*B + M; * thus we have * (**) sign*Y*a == D*B + M (mod |n|). */ tmp=A; /* keep the BIGNUM object, the value does not matter */ /* (A, B) := (B, A mod B) ... */ A=B; B=M; /* ... so we have 0 <= B < A again */ /* Since the former M is now B and the former B is now A, * (**) translates into * sign*Y*a == D*A + B (mod |n|), * i.e. * sign*Y*a - D*A == B (mod |n|). * Similarly, (*) translates into * -sign*X*a == A (mod |n|). * * Thus, * sign*Y*a + D*sign*X*a == B (mod |n|), * i.e. * sign*(Y + D*X)*a == B (mod |n|). * * So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at * -sign*X*a == B (mod |n|), * sign*Y*a == A (mod |n|). * Note that X and Y stay non-negative all the time. */ /* most of the time D is very small, so we can optimize tmp := D*X+Y */ if (BN_is_one(D)) { if (!BN_add(tmp,X,Y)) goto err; } else { if (BN_is_word(D,2)) { if (!BN_lshift1(tmp,X)) goto err; } else if (BN_is_word(D,4)) { if (!BN_lshift(tmp,X,2)) goto err; } else if (D->top == 1) { if (!BN_copy(tmp,X)) goto err; if (!BN_mul_word(tmp,D->d[0])) goto err; } else { if (!BN_mul(tmp,D,X,ctx)) goto err; } if (!BN_add(tmp,tmp,Y)) goto err; } M=Y; /* keep the BIGNUM object, the value does not matter */ Y=X; X=tmp; sign = -sign; } } /* * The while loop (Euclid's algorithm) ends when * A == gcd(a,n); * we have * sign*Y*a == A (mod |n|), * where Y is non-negative. */ if (sign < 0) { if (!BN_sub(Y,n,Y)) goto err; } /* Now Y*a == A (mod |n|). */ if (BN_is_one(A)) { /* Y*a == 1 (mod |n|) */ if (!Y->neg && BN_ucmp(Y,n) < 0) { if (!BN_copy(R,Y)) goto err; } else { if (!BN_nnmod(R,Y,n,ctx)) goto err; } } else { BNerr(BN_F_BN_MOD_INVERSE,BN_R_NO_INVERSE); goto err; } ret=R; err: if ((ret == NULL) && (in == NULL)) BN_free(R); BN_CTX_end(ctx); return(ret); }
int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, 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 *rh, *tmp, *Z4, *Z6; int ret = -1; if (EC_POINT_is_at_infinity(group, point)) return 1; 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 -1; } BN_CTX_start(ctx); rh = BN_CTX_get(ctx); tmp = BN_CTX_get(ctx); Z4 = BN_CTX_get(ctx); Z6 = BN_CTX_get(ctx); if (Z6 == NULL) goto err; /* We have a curve defined by a Weierstrass equation * y^2 = x^3 + a*x + b. * The point to consider is given in Jacobian projective coordinates * where (X, Y, Z) represents (x, y) = (X/Z^2, Y/Z^3). * Substituting this and multiplying by Z^6 transforms the above equation into * Y^2 = X^3 + a*X*Z^4 + b*Z^6. * To test this, we add up the right-hand side in 'rh'. */ /* rh := X^2 */ if (!field_sqr(group, rh, &point->X, ctx)) goto err; if (!point->Z_is_one) { if (!field_sqr(group, tmp, &point->Z, ctx)) goto err; if (!field_sqr(group, Z4, tmp, ctx)) goto err; if (!field_mul(group, Z6, Z4, tmp, ctx)) goto err; /* rh := (rh + a*Z^4)*X */ if (group->a_is_minus3) { if (!BN_mod_lshift1_quick(tmp, Z4, p)) goto err; if (!BN_mod_add_quick(tmp, tmp, Z4, p)) goto err; if (!BN_mod_sub_quick(rh, rh, tmp, p)) goto err; if (!field_mul(group, rh, rh, &point->X, ctx)) goto err; } else { if (!field_mul(group, tmp, Z4, &group->a, ctx)) goto err; if (!BN_mod_add_quick(rh, rh, tmp, p)) goto err; if (!field_mul(group, rh, rh, &point->X, ctx)) goto err; } /* rh := rh + b*Z^6 */ if (!field_mul(group, tmp, &group->b, Z6, ctx)) goto err; if (!BN_mod_add_quick(rh, rh, tmp, p)) goto err; } else { /* point->Z_is_one */ /* rh := (rh + a)*X */ if (!BN_mod_add_quick(rh, rh, &group->a, p)) goto err; if (!field_mul(group, rh, rh, &point->X, ctx)) goto err; /* rh := rh + b */ if (!BN_mod_add_quick(rh, rh, &group->b, p)) goto err; } /* 'lh' := Y^2 */ if (!field_sqr(group, tmp, &point->Y, ctx)) goto err; ret = (0 == BN_ucmp(tmp, rh)); err: BN_CTX_end(ctx); if (new_ctx != NULL) BN_CTX_free(new_ctx); return ret; }
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)) goto err; /* Replace points[i]->Z by its inverse. */ if (!BN_copy(&points[i]->Z, tmp_Z)) goto err; } } if (!BN_is_zero(&points[0]->Z)) { /* Replace points[0]->Z by its inverse. */ if (!BN_copy(&points[0]->Z, tmp)) goto err; } /* Finally, fix up the X and Y coordinates for all points. */ for (i = 0; i < num; i++) { EC_POINT *p = points[i]; if (!BN_is_zero(&p->Z)) { /* turn (X, Y, 1/Z) into (X/Z^2, Y/Z^3, 1) */ if (!group->meth->field_sqr(group, tmp, &p->Z, ctx)) goto err; if (!group->meth->field_mul(group, &p->X, &p->X, tmp, ctx)) goto err; if (!group->meth->field_mul(group, tmp, tmp, &p->Z, ctx)) goto err; if (!group->meth->field_mul(group, &p->Y, &p->Y, tmp, ctx)) goto err; if (group->meth->field_set_to_one != 0) { if (!group->meth->field_set_to_one(group, &p->Z, ctx)) goto err; } else { if (!BN_one(&p->Z)) goto err; } p->Z_is_one = 1; } } ret = 1; err: BN_CTX_end(ctx); if (new_ctx != NULL) BN_CTX_free(new_ctx); if (prod_Z != NULL) { for (i = 0; i < num; i++) { if (prod_Z[i] == NULL) break; BN_clear_free(prod_Z[i]); } OPENSSL_free(prod_Z); } return ret; }
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, 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, 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; } ret = 1; err: BN_CTX_end(ctx); if (new_ctx != NULL) BN_CTX_free(new_ctx); return ret; }
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 */ BN_CTX_end(ctx); ret = EC_POINT_dbl(group, r, a, ctx); ctx = NULL; goto end; } else { /* a is the inverse of b */ BN_zero(&r->Z); r->Z_is_one = 0; ret = 1; goto end; } } /* 'n7', 'n8' */ if (!BN_mod_add_quick(n1, n1, n3, p)) goto end; if (!BN_mod_add_quick(n2, n2, n4, p)) goto end; /* 'n7' = n1 + n3 */ /* 'n8' = n2 + n4 */ /* Z_r */ if (a->Z_is_one && b->Z_is_one) { if (!BN_copy(&r->Z, n5)) goto end; } else { if (a->Z_is_one) { if (!BN_copy(n0, &b->Z)) goto end; } else if (b->Z_is_one) { if (!BN_copy(n0, &a->Z)) goto end; } else { if (!field_mul(group, n0, &a->Z, &b->Z, ctx)) goto end; } if (!field_mul(group, &r->Z, n0, n5, ctx)) goto end; } r->Z_is_one = 0; /* Z_r = Z_a * Z_b * n5 */ /* X_r */ if (!field_sqr(group, n0, n6, ctx)) goto end; if (!field_sqr(group, n4, n5, ctx)) goto end; if (!field_mul(group, n3, n1, n4, ctx)) goto end; if (!BN_mod_sub_quick(&r->X, n0, n3, p)) goto end; /* X_r = n6^2 - n5^2 * 'n7' */ /* 'n9' */ if (!BN_mod_lshift1_quick(n0, &r->X, p)) goto end; if (!BN_mod_sub_quick(n0, n3, n0, p)) goto end; /* n9 = n5^2 * 'n7' - 2 * X_r */ /* Y_r */ if (!field_mul(group, n0, n0, n6, ctx)) goto end; if (!field_mul(group, n5, n4, n5, ctx)) goto end; /* now n5 is n5^3 */ if (!field_mul(group, n1, n2, n5, ctx)) goto end; if (!BN_mod_sub_quick(n0, n0, n1, p)) goto end; if (BN_is_odd(n0)) if (!BN_add(n0, n0, p)) goto end; /* now 0 <= n0 < 2*p, and n0 is even */ if (!BN_rshift1(&r->Y, n0)) goto end; /* Y_r = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */ ret = 1; end: if (ctx) /* otherwise we already called BN_CTX_end */ BN_CTX_end(ctx); if (new_ctx != NULL) BN_CTX_free(new_ctx); return ret; }
int DH_check(const DH *dh, int *ret) { int ok=0; BN_CTX *ctx=NULL; BN_ULONG l; BIGNUM *t1=NULL, *t2 = NULL; *ret=0; ctx=BN_CTX_new(); if (ctx == NULL) goto err; BN_CTX_start(ctx); t1=BN_CTX_get(ctx); if (t1 == NULL) goto err; t2=BN_CTX_get(ctx); if (t2 == NULL) goto err; if (dh->q) { if (BN_cmp(dh->g, BN_value_one()) <= 0) *ret|=DH_NOT_SUITABLE_GENERATOR; else if (BN_cmp(dh->g, dh->p) >= 0) *ret|=DH_NOT_SUITABLE_GENERATOR; else { /* Check g^q == 1 mod p */ if (!BN_mod_exp(t1, dh->g, dh->q, dh->p, ctx)) goto err; if (!BN_is_one(t1)) *ret|=DH_NOT_SUITABLE_GENERATOR; } if (!BN_is_prime_ex(dh->q,BN_prime_checks,ctx,NULL)) *ret|=DH_CHECK_Q_NOT_PRIME; /* Check p == 1 mod q i.e. q divides p - 1 */ if (!BN_div(t1, t2, dh->p, dh->q, ctx)) goto err; if (!BN_is_one(t2)) *ret|=DH_CHECK_INVALID_Q_VALUE; if (dh->j && BN_cmp(dh->j, t1)) *ret|=DH_CHECK_INVALID_J_VALUE; } else if (BN_is_word(dh->g,DH_GENERATOR_2)) { l=BN_mod_word(dh->p,24); if (l != 11) *ret|=DH_NOT_SUITABLE_GENERATOR; } #if 0 else if (BN_is_word(dh->g,DH_GENERATOR_3)) { l=BN_mod_word(dh->p,12); if (l != 5) *ret|=DH_NOT_SUITABLE_GENERATOR; } #endif else if (BN_is_word(dh->g,DH_GENERATOR_5)) { l=BN_mod_word(dh->p,10); if ((l != 3) && (l != 7)) *ret|=DH_NOT_SUITABLE_GENERATOR; } else *ret|=DH_UNABLE_TO_CHECK_GENERATOR; if (!BN_is_prime_ex(dh->p,BN_prime_checks,ctx,NULL)) *ret|=DH_CHECK_P_NOT_PRIME; else if (!dh->q) { if (!BN_rshift1(t1,dh->p)) goto err; if (!BN_is_prime_ex(t1,BN_prime_checks,ctx,NULL)) *ret|=DH_CHECK_P_NOT_SAFE_PRIME; } ok=1; err: if (ctx != NULL) { BN_CTX_end(ctx); BN_CTX_free(ctx); } return(ok); }
int BN_X931_derive_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2, const BIGNUM *Xp, const BIGNUM *Xp1, const BIGNUM *Xp2, const BIGNUM *e, BN_CTX *ctx, BN_GENCB *cb) { int ret = 0; BIGNUM *t, *p1p2, *pm1; /* Only even e supported */ if (!BN_is_odd(e)) return 0; BN_CTX_start(ctx); if (!p1) p1 = BN_CTX_get(ctx); if (!p2) p2 = BN_CTX_get(ctx); t = BN_CTX_get(ctx); p1p2 = BN_CTX_get(ctx); pm1 = BN_CTX_get(ctx); if (!bn_x931_derive_pi(p1, Xp1, ctx, cb)) goto err; if (!bn_x931_derive_pi(p2, Xp2, ctx, cb)) goto err; if (!BN_mul(p1p2, p1, p2, ctx)) goto err; /* First set p to value of Rp */ if (!BN_mod_inverse(p, p2, p1, ctx)) goto err; if (!BN_mul(p, p, p2, ctx)) goto err; if (!BN_mod_inverse(t, p1, p2, ctx)) goto err; if (!BN_mul(t, t, p1, ctx)) goto err; if (!BN_sub(p, p, t)) goto err; if (p->neg && !BN_add(p, p, p1p2)) goto err; /* p now equals Rp */ if (!BN_mod_sub(p, p, Xp, p1p2, ctx)) goto err; if (!BN_add(p, p, Xp)) goto err; /* p now equals Yp0 */ for (;;) { int i = 1; BN_GENCB_call(cb, 0, i++); if (!BN_copy(pm1, p)) goto err; if (!BN_sub_word(pm1, 1)) goto err; if (!BN_gcd(t, pm1, e, ctx)) goto err; if (BN_is_one(t) /* X9.31 specifies 8 MR and 1 Lucas test or any prime test * offering similar or better guarantees 50 MR is considerably * better. */ && BN_is_prime_fasttest_ex(p, 50, ctx, 1, cb)) break; if (!BN_add(p, p, p1p2)) goto err; } BN_GENCB_call(cb, 3, 0); ret = 1; err: BN_CTX_end(ctx); return ret; }
int RSA_recover_crt_params(RSA *rsa) { BN_CTX *ctx; BIGNUM *totient, *rem, *multiple, *p_plus_q, *p_minus_q; int ok = 0; if (rsa->n == NULL || rsa->e == NULL || rsa->d == NULL) { OPENSSL_PUT_ERROR(RSA, RSA_R_EMPTY_PUBLIC_KEY); return 0; } if (rsa->p || rsa->q || rsa->dmp1 || rsa->dmq1 || rsa->iqmp) { OPENSSL_PUT_ERROR(RSA, RSA_R_CRT_PARAMS_ALREADY_GIVEN); return 0; } if (rsa->additional_primes != NULL) { OPENSSL_PUT_ERROR(RSA, RSA_R_CANNOT_RECOVER_MULTI_PRIME_KEY); return 0; } /* This uses the algorithm from section 9B of the RSA paper: * http://people.csail.mit.edu/rivest/Rsapaper.pdf */ ctx = BN_CTX_new(); if (ctx == NULL) { OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); return 0; } BN_CTX_start(ctx); totient = BN_CTX_get(ctx); rem = BN_CTX_get(ctx); multiple = BN_CTX_get(ctx); p_plus_q = BN_CTX_get(ctx); p_minus_q = BN_CTX_get(ctx); if (totient == NULL || rem == NULL || multiple == NULL || p_plus_q == NULL || p_minus_q == NULL) { OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); goto err; } /* ed-1 is a small multiple of φ(n). */ if (!BN_mul(totient, rsa->e, rsa->d, ctx) || !BN_sub_word(totient, 1) || /* φ(n) = * pq - p - q + 1 = * n - (p + q) + 1 * * Thus n is a reasonable estimate for φ(n). So, (ed-1)/n will be very * close. But, when we calculate the quotient, we'll be truncating it * because we discard the remainder. Thus (ed-1)/multiple will be >= n, * which the totient cannot be. So we add one to the estimate. * * Consider ed-1 as: * * multiple * (n - (p+q) + 1) = * multiple*n - multiple*(p+q) + multiple * * When we divide by n, the first term becomes multiple and, since * multiple and p+q is tiny compared to n, the second and third terms can * be ignored. Thus I claim that subtracting one from the estimate is * sufficient. */ !BN_div(multiple, NULL, totient, rsa->n, ctx) || !BN_add_word(multiple, 1) || !BN_div(totient, rem, totient, multiple, ctx)) { OPENSSL_PUT_ERROR(RSA, ERR_R_BN_LIB); goto err; } if (!BN_is_zero(rem)) { OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_RSA_PARAMETERS); goto err; } rsa->p = BN_new(); rsa->q = BN_new(); rsa->dmp1 = BN_new(); rsa->dmq1 = BN_new(); rsa->iqmp = BN_new(); if (rsa->p == NULL || rsa->q == NULL || rsa->dmp1 == NULL || rsa->dmq1 == NULL || rsa->iqmp == NULL) { OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE); goto err; } /* φ(n) = n - (p + q) + 1 => * n - totient + 1 = p + q */ if (!BN_sub(p_plus_q, rsa->n, totient) || !BN_add_word(p_plus_q, 1) || /* p - q = sqrt((p+q)^2 - 4n) */ !BN_sqr(rem, p_plus_q, ctx) || !BN_lshift(multiple, rsa->n, 2) || !BN_sub(rem, rem, multiple) || !BN_sqrt(p_minus_q, rem, ctx) || /* q is 1/2 (p+q)-(p-q) */ !BN_sub(rsa->q, p_plus_q, p_minus_q) || !BN_rshift1(rsa->q, rsa->q) || !BN_div(rsa->p, NULL, rsa->n, rsa->q, ctx) || !BN_mul(multiple, rsa->p, rsa->q, ctx)) { OPENSSL_PUT_ERROR(RSA, ERR_R_BN_LIB); goto err; } if (BN_cmp(multiple, rsa->n) != 0) { OPENSSL_PUT_ERROR(RSA, RSA_R_INTERNAL_ERROR); goto err; } if (!BN_sub(rem, rsa->p, BN_value_one()) || !BN_mod(rsa->dmp1, rsa->d, rem, ctx) || !BN_sub(rem, rsa->q, BN_value_one()) || !BN_mod(rsa->dmq1, rsa->d, rem, ctx) || !BN_mod_inverse(rsa->iqmp, rsa->q, rsa->p, ctx)) { OPENSSL_PUT_ERROR(RSA, ERR_R_BN_LIB); goto err; } ok = 1; err: BN_CTX_end(ctx); BN_CTX_free(ctx); if (!ok) { bn_free_and_null(&rsa->p); bn_free_and_null(&rsa->q); bn_free_and_null(&rsa->dmp1); bn_free_and_null(&rsa->dmq1); bn_free_and_null(&rsa->iqmp); } return ok; }
/* Compute the x, y affine coordinates from the point (x1, z1) (x2, z2) * using Montgomery point multiplication algorithm Mxy() in appendix of * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over * GF(2^m) without precomputation" (CHES '99, LNCS 1717). * Returns: * 0 on error * 1 if return value should be the point at infinity * 2 otherwise */ static int gf2m_Mxy(const EC_GROUP *group, const BIGNUM *x, const BIGNUM *y, BIGNUM *x1, BIGNUM *z1, BIGNUM *x2, BIGNUM *z2, BN_CTX *ctx) { BIGNUM *t3, *t4, *t5; int ret = 0; if (BN_is_zero(z1)) { BN_zero(x2); BN_zero(z2); return 1; } if (BN_is_zero(z2)) { if (!BN_copy(x2, x)) return 0; if (!BN_GF2m_add(z2, x, y)) return 0; return 2; } /* Since Mxy is static we can guarantee that ctx != NULL. */ BN_CTX_start(ctx); if ((t3 = BN_CTX_get(ctx)) == NULL) goto err; if ((t4 = BN_CTX_get(ctx)) == NULL) goto err; if ((t5 = BN_CTX_get(ctx)) == NULL) goto err; if (!BN_one(t5)) goto err; if (!group->meth->field_mul(group, t3, z1, z2, ctx)) goto err; if (!group->meth->field_mul(group, z1, z1, x, ctx)) goto err; if (!BN_GF2m_add(z1, z1, x1)) goto err; if (!group->meth->field_mul(group, z2, z2, x, ctx)) goto err; if (!group->meth->field_mul(group, x1, z2, x1, ctx)) goto err; if (!BN_GF2m_add(z2, z2, x2)) goto err; if (!group->meth->field_mul(group, z2, z2, z1, ctx)) goto err; if (!group->meth->field_sqr(group, t4, x, ctx)) goto err; if (!BN_GF2m_add(t4, t4, y)) goto err; if (!group->meth->field_mul(group, t4, t4, t3, ctx)) goto err; if (!BN_GF2m_add(t4, t4, z2)) goto err; if (!group->meth->field_mul(group, t3, t3, x, ctx)) goto err; if (!group->meth->field_div(group, t3, t5, t3, ctx)) goto err; if (!group->meth->field_mul(group, t4, t3, t4, ctx)) goto err; if (!group->meth->field_mul(group, x2, x1, t3, ctx)) goto err; if (!BN_GF2m_add(z2, x2, x)) goto err; if (!group->meth->field_mul(group, z2, z2, t4, ctx)) goto err; if (!BN_GF2m_add(z2, z2, y)) goto err; ret = 2; err: BN_CTX_end(ctx); return ret; }
static size_t ec_GFp_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form, uint8_t *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; if ((form != POINT_CONVERSION_COMPRESSED) && (form != POINT_CONVERSION_UNCOMPRESSED)) { OPENSSL_PUT_ERROR(EC, EC_R_INVALID_FORM); goto err; } if (EC_POINT_is_at_infinity(group, point)) { OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY); goto err; } /* 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) { OPENSSL_PUT_ERROR(EC, EC_R_BUFFER_TOO_SMALL); goto err; } if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) { goto err; } } 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) && BN_is_odd(y)) { buf[0] = form + 1; } else { buf[0] = form; } i = 1; if (!BN_bn2bin_padded(buf + i, field_len, x)) { OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); goto err; } i += field_len; if (form == POINT_CONVERSION_UNCOMPRESSED) { if (!BN_bn2bin_padded(buf + i, field_len, y)) { OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); goto err; } i += field_len; } if (i != ret) { OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); goto err; } } if (used_ctx) { BN_CTX_end(ctx); } BN_CTX_free(new_ctx); return ret; err: if (used_ctx) { BN_CTX_end(ctx); } BN_CTX_free(new_ctx); return 0; }
int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) { int ret = 0; BIGNUM *Ri,*R; BN_CTX_start(ctx); if((Ri = BN_CTX_get(ctx)) == NULL) goto err; R= &(mont->RR); /* grab RR as a temp */ if (!BN_copy(&(mont->N),mod)) goto err; /* Set N */ mont->N.neg = 0; #ifdef MONT_WORD { BIGNUM tmod; BN_ULONG buf[2]; BN_init(&tmod); tmod.d=buf; tmod.dmax=2; tmod.neg=0; mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2; #if defined(OPENSSL_BN_ASM_MONT) && (BN_BITS2<=32) /* Only certain BN_BITS2<=32 platforms actually make use of * n0[1], and we could use the #else case (with a shorter R * value) for the others. However, currently only the assembler * files do know which is which. */ BN_zero(R); if (!(BN_set_bit(R,2*BN_BITS2))) goto err; tmod.top=0; if ((buf[0] = mod->d[0])) tmod.top=1; if ((buf[1] = mod->top>1 ? mod->d[1] : 0)) tmod.top=2; if ((BN_mod_inverse(Ri,R,&tmod,ctx)) == NULL) goto err; if (!BN_lshift(Ri,Ri,2*BN_BITS2)) goto err; /* R*Ri */ if (!BN_is_zero(Ri)) { if (!BN_sub_word(Ri,1)) goto err; } else /* if N mod word size == 1 */ { if (bn_expand(Ri,(int)sizeof(BN_ULONG)*2) == NULL) goto err; /* Ri-- (mod double word size) */ Ri->neg=0; Ri->d[0]=BN_MASK2; Ri->d[1]=BN_MASK2; Ri->top=2; } if (!BN_div(Ri,NULL,Ri,&tmod,ctx)) goto err; /* Ni = (R*Ri-1)/N, * keep only couple of least significant words: */ mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0; mont->n0[1] = (Ri->top > 1) ? Ri->d[1] : 0; #else BN_zero(R); if (!(BN_set_bit(R,BN_BITS2))) goto err; /* R */ buf[0]=mod->d[0]; /* tmod = N mod word size */ buf[1]=0; tmod.top = buf[0] != 0 ? 1 : 0; /* Ri = R^-1 mod N*/ if ((BN_mod_inverse(Ri,R,&tmod,ctx)) == NULL) goto err; if (!BN_lshift(Ri,Ri,BN_BITS2)) goto err; /* R*Ri */ if (!BN_is_zero(Ri)) { if (!BN_sub_word(Ri,1)) goto err; } else /* if N mod word size == 1 */ { if (!BN_set_word(Ri,BN_MASK2)) goto err; /* Ri-- (mod word size) */ } if (!BN_div(Ri,NULL,Ri,&tmod,ctx)) goto err; /* Ni = (R*Ri-1)/N, * keep only least significant word: */ mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0; mont->n0[1] = 0; #endif } #else /* !MONT_WORD */ { /* bignum version */ mont->ri=BN_num_bits(&mont->N); BN_zero(R); if (!BN_set_bit(R,mont->ri)) goto err; /* R = 2^ri */ /* Ri = R^-1 mod N*/ if ((BN_mod_inverse(Ri,R,&mont->N,ctx)) == NULL) goto err; if (!BN_lshift(Ri,Ri,mont->ri)) goto err; /* R*Ri */ if (!BN_sub_word(Ri,1)) goto err; /* Ni = (R*Ri-1) / N */ if (!BN_div(&(mont->Ni),NULL,Ri,&mont->N,ctx)) goto err; } #endif /* setup RR for conversions */ BN_zero(&(mont->RR)); if (!BN_set_bit(&(mont->RR),mont->ri*2)) goto err; if (!BN_mod(&(mont->RR),&(mont->RR),&(mont->N),ctx)) goto err; ret = 1; err: BN_CTX_end(ctx); return ret; }
static int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point, const uint8_t *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) { OPENSSL_PUT_ERROR(EC, EC_R_BUFFER_TOO_SMALL); return 0; } form = buf[0]; y_bit = form & 1; form = form & ~1U; if ((form != POINT_CONVERSION_COMPRESSED && form != POINT_CONVERSION_UNCOMPRESSED) || (form == POINT_CONVERSION_UNCOMPRESSED && y_bit)) { OPENSSL_PUT_ERROR(EC, EC_R_INVALID_ENCODING); return 0; } field_len = BN_num_bytes(&group->field); enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len; if (len != enc_len) { OPENSSL_PUT_ERROR(EC, 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 (x == NULL || y == NULL) { goto err; } if (!BN_bin2bn(buf + 1, field_len, x)) { goto err; } if (BN_ucmp(x, &group->field) >= 0) { OPENSSL_PUT_ERROR(EC, 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, field_len, y)) { goto err; } if (BN_ucmp(y, &group->field) >= 0) { OPENSSL_PUT_ERROR(EC, EC_R_INVALID_ENCODING); goto err; } if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) { goto err; } } ret = 1; err: BN_CTX_end(ctx); BN_CTX_free(new_ctx); return ret; }
int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx) { int r = 0; BIGNUM *a1, *a2, *a3, *b1, *b2, *b3; BN_CTX *ctx_new = NULL; /* compare the field types*/ if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) != EC_METHOD_get_field_type(EC_GROUP_method_of(b))) return 1; /* compare the curve name (if present) */ if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) && EC_GROUP_get_curve_name(a) == EC_GROUP_get_curve_name(b)) return 0; if (!ctx) ctx_new = ctx = BN_CTX_new(); if (!ctx) return -1; BN_CTX_start(ctx); a1 = BN_CTX_get(ctx); a2 = BN_CTX_get(ctx); a3 = BN_CTX_get(ctx); b1 = BN_CTX_get(ctx); b2 = BN_CTX_get(ctx); b3 = BN_CTX_get(ctx); if (!b3) { BN_CTX_end(ctx); if (ctx_new) BN_CTX_free(ctx); return -1; } /* XXX This approach assumes that the external representation * of curves over the same field type is the same. */ if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) || !b->meth->group_get_curve(b, b1, b2, b3, ctx)) r = 1; if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3)) r = 1; /* XXX EC_POINT_cmp() assumes that the methods are equal */ if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a), EC_GROUP_get0_generator(b), ctx)) r = 1; if (!r) { /* compare the order and cofactor */ if (!EC_GROUP_get_order(a, a1, ctx) || !EC_GROUP_get_order(b, b1, ctx) || !EC_GROUP_get_cofactor(a, a2, ctx) || !EC_GROUP_get_cofactor(b, b2, ctx)) { BN_CTX_end(ctx); if (ctx_new) BN_CTX_free(ctx); return -1; } if (BN_cmp(a1, b1) || BN_cmp(a2, b2)) r = 1; } BN_CTX_end(ctx); if (ctx_new) BN_CTX_free(ctx); return r; }
static int ssl_ec_point_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret, size_t *out_secret_len, uint8_t *out_alert, const uint8_t *peer_key, size_t peer_key_len) { BIGNUM *private_key = (BIGNUM *)ctx->data; assert(private_key != NULL); *out_alert = SSL_AD_INTERNAL_ERROR; /* Set up a shared |BN_CTX| for all operations. */ BN_CTX *bn_ctx = BN_CTX_new(); if (bn_ctx == NULL) { return 0; } BN_CTX_start(bn_ctx); int ret = 0; EC_GROUP *group = EC_GROUP_new_by_curve_name(ctx->method->nid); EC_POINT *peer_point = NULL, *result = NULL; uint8_t *secret = NULL; if (group == NULL) { goto err; } /* Compute the x-coordinate of |peer_key| * |private_key|. */ peer_point = EC_POINT_new(group); result = EC_POINT_new(group); if (peer_point == NULL || result == NULL) { goto err; } BIGNUM *x = BN_CTX_get(bn_ctx); if (x == NULL) { goto err; } if (!EC_POINT_oct2point(group, peer_point, peer_key, peer_key_len, bn_ctx)) { *out_alert = SSL_AD_DECODE_ERROR; goto err; } if (!EC_POINT_mul(group, result, NULL, peer_point, private_key, bn_ctx) || !EC_POINT_get_affine_coordinates_GFp(group, result, x, NULL, bn_ctx)) { goto err; } /* Encode the x-coordinate left-padded with zeros. */ size_t secret_len = (EC_GROUP_get_degree(group) + 7) / 8; secret = OPENSSL_malloc(secret_len); if (secret == NULL || !BN_bn2bin_padded(secret, secret_len, x)) { goto err; } *out_secret = secret; *out_secret_len = secret_len; secret = NULL; ret = 1; err: EC_GROUP_free(group); EC_POINT_free(peer_point); EC_POINT_free(result); BN_CTX_end(bn_ctx); BN_CTX_free(bn_ctx); OPENSSL_free(secret); return ret; }
BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) { // Compute a square root of |a| mod |p| using the Tonelli/Shanks algorithm // (cf. Henri Cohen, "A Course in Algebraic Computational Number Theory", // algorithm 1.5.1). |p| is assumed to be a prime. BIGNUM *ret = in; int err = 1; int r; BIGNUM *A, *b, *q, *t, *x, *y; int e, i, j; if (!BN_is_odd(p) || BN_abs_is_word(p, 1)) { if (BN_abs_is_word(p, 2)) { if (ret == NULL) { ret = BN_new(); } if (ret == NULL) { goto end; } if (!BN_set_word(ret, BN_is_bit_set(a, 0))) { if (ret != in) { BN_free(ret); } return NULL; } return ret; } OPENSSL_PUT_ERROR(BN, BN_R_P_IS_NOT_PRIME); return (NULL); } if (BN_is_zero(a) || BN_is_one(a)) { if (ret == NULL) { ret = BN_new(); } if (ret == NULL) { goto end; } if (!BN_set_word(ret, BN_is_one(a))) { if (ret != in) { BN_free(ret); } return NULL; } return ret; } BN_CTX_start(ctx); A = BN_CTX_get(ctx); b = BN_CTX_get(ctx); q = BN_CTX_get(ctx); t = BN_CTX_get(ctx); x = BN_CTX_get(ctx); y = BN_CTX_get(ctx); if (y == NULL) { goto end; } if (ret == NULL) { ret = BN_new(); } if (ret == NULL) { goto end; } // A = a mod p if (!BN_nnmod(A, a, p, ctx)) { goto end; } // now write |p| - 1 as 2^e*q where q is odd e = 1; while (!BN_is_bit_set(p, e)) { e++; } // we'll set q later (if needed) if (e == 1) { // The easy case: (|p|-1)/2 is odd, so 2 has an inverse // modulo (|p|-1)/2, and square roots can be computed // directly by modular exponentiation. // We have // 2 * (|p|+1)/4 == 1 (mod (|p|-1)/2), // so we can use exponent (|p|+1)/4, i.e. (|p|-3)/4 + 1. if (!BN_rshift(q, p, 2)) { goto end; } q->neg = 0; if (!BN_add_word(q, 1) || !BN_mod_exp_mont(ret, A, q, p, ctx, NULL)) { goto end; } err = 0; goto vrfy; } if (e == 2) { // |p| == 5 (mod 8) // // In this case 2 is always a non-square since // Legendre(2,p) = (-1)^((p^2-1)/8) for any odd prime. // So if a really is a square, then 2*a is a non-square. // Thus for // b := (2*a)^((|p|-5)/8), // i := (2*a)*b^2 // we have // i^2 = (2*a)^((1 + (|p|-5)/4)*2) // = (2*a)^((p-1)/2) // = -1; // so if we set // x := a*b*(i-1), // then // x^2 = a^2 * b^2 * (i^2 - 2*i + 1) // = a^2 * b^2 * (-2*i) // = a*(-i)*(2*a*b^2) // = a*(-i)*i // = a. // // (This is due to A.O.L. Atkin, // <URL: //http://listserv.nodak.edu/scripts/wa.exe?A2=ind9211&L=nmbrthry&O=T&P=562>, // November 1992.) // t := 2*a if (!bn_mod_lshift1_consttime(t, A, p, ctx)) { goto end; } // b := (2*a)^((|p|-5)/8) if (!BN_rshift(q, p, 3)) { goto end; } q->neg = 0; if (!BN_mod_exp_mont(b, t, q, p, ctx, NULL)) { goto end; } // y := b^2 if (!BN_mod_sqr(y, b, p, ctx)) { goto end; } // t := (2*a)*b^2 - 1 if (!BN_mod_mul(t, t, y, p, ctx) || !BN_sub_word(t, 1)) { goto end; } // x = a*b*t if (!BN_mod_mul(x, A, b, p, ctx) || !BN_mod_mul(x, x, t, p, ctx)) { goto end; } if (!BN_copy(ret, x)) { goto end; } err = 0; goto vrfy; } // e > 2, so we really have to use the Tonelli/Shanks algorithm. // First, find some y that is not a square. if (!BN_copy(q, p)) { goto end; // use 'q' as temp } q->neg = 0; i = 2; do { // For efficiency, try small numbers first; // if this fails, try random numbers. if (i < 22) { if (!BN_set_word(y, i)) { goto end; } } else { if (!BN_pseudo_rand(y, BN_num_bits(p), 0, 0)) { goto end; } if (BN_ucmp(y, p) >= 0) { if (!(p->neg ? BN_add : BN_sub)(y, y, p)) { goto end; } } // now 0 <= y < |p| if (BN_is_zero(y)) { if (!BN_set_word(y, i)) { goto end; } } } r = bn_jacobi(y, q, ctx); // here 'q' is |p| if (r < -1) { goto end; } if (r == 0) { // m divides p OPENSSL_PUT_ERROR(BN, BN_R_P_IS_NOT_PRIME); goto end; } } while (r == 1 && ++i < 82); if (r != -1) { // Many rounds and still no non-square -- this is more likely // a bug than just bad luck. // Even if p is not prime, we should have found some y // such that r == -1. OPENSSL_PUT_ERROR(BN, BN_R_TOO_MANY_ITERATIONS); goto end; } // Here's our actual 'q': if (!BN_rshift(q, q, e)) { goto end; } // Now that we have some non-square, we can find an element // of order 2^e by computing its q'th power. if (!BN_mod_exp_mont(y, y, q, p, ctx, NULL)) { goto end; } if (BN_is_one(y)) { OPENSSL_PUT_ERROR(BN, BN_R_P_IS_NOT_PRIME); goto end; } // Now we know that (if p is indeed prime) there is an integer // k, 0 <= k < 2^e, such that // // a^q * y^k == 1 (mod p). // // As a^q is a square and y is not, k must be even. // q+1 is even, too, so there is an element // // X := a^((q+1)/2) * y^(k/2), // // and it satisfies // // X^2 = a^q * a * y^k // = a, // // so it is the square root that we are looking for. // t := (q-1)/2 (note that q is odd) if (!BN_rshift1(t, q)) { goto end; } // x := a^((q-1)/2) if (BN_is_zero(t)) // special case: p = 2^e + 1 { if (!BN_nnmod(t, A, p, ctx)) { goto end; } if (BN_is_zero(t)) { // special case: a == 0 (mod p) BN_zero(ret); err = 0; goto end; } else if (!BN_one(x)) { goto end; } } else { if (!BN_mod_exp_mont(x, A, t, p, ctx, NULL)) { goto end; } if (BN_is_zero(x)) { // special case: a == 0 (mod p) BN_zero(ret); err = 0; goto end; } } // b := a*x^2 (= a^q) if (!BN_mod_sqr(b, x, p, ctx) || !BN_mod_mul(b, b, A, p, ctx)) { goto end; } // x := a*x (= a^((q+1)/2)) if (!BN_mod_mul(x, x, A, p, ctx)) { goto end; } while (1) { // Now b is a^q * y^k for some even k (0 <= k < 2^E // where E refers to the original value of e, which we // don't keep in a variable), and x is a^((q+1)/2) * y^(k/2). // // We have a*b = x^2, // y^2^(e-1) = -1, // b^2^(e-1) = 1. if (BN_is_one(b)) { if (!BN_copy(ret, x)) { goto end; } err = 0; goto vrfy; } // find smallest i such that b^(2^i) = 1 i = 1; if (!BN_mod_sqr(t, b, p, ctx)) { goto end; } while (!BN_is_one(t)) { i++; if (i == e) { OPENSSL_PUT_ERROR(BN, BN_R_NOT_A_SQUARE); goto end; } if (!BN_mod_mul(t, t, t, p, ctx)) { goto end; } } // t := y^2^(e - i - 1) if (!BN_copy(t, y)) { goto end; } for (j = e - i - 1; j > 0; j--) { if (!BN_mod_sqr(t, t, p, ctx)) { goto end; } } if (!BN_mod_mul(y, t, t, p, ctx) || !BN_mod_mul(x, x, t, p, ctx) || !BN_mod_mul(b, b, y, p, ctx)) { goto end; } e = i; } vrfy: if (!err) { // verify the result -- the input might have been not a square // (test added in 0.9.8) if (!BN_mod_sqr(x, ret, p, ctx)) { err = 1; } if (!err && 0 != BN_cmp(x, A)) { OPENSSL_PUT_ERROR(BN, BN_R_NOT_A_SQUARE); err = 1; } } end: if (err) { if (ret != in) { BN_clear_free(ret); } ret = NULL; } BN_CTX_end(ctx); return ret; }
/* Computes scalar*point and stores the result in r. * point can not equal r. * Uses a modified algorithm 2P of * Lopez, J. and Dahab, R. "Fast multiplication on elliptic curves over * GF(2^m) without precomputation" (CHES '99, LNCS 1717). * * To protect against side-channel attack the function uses constant time swap, * avoiding conditional branches. */ 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) > 0) { 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); if ((x1 = BN_CTX_get(ctx)) == NULL) goto err; if ((z1 = BN_CTX_get(ctx)) == NULL) goto err; x2 = &r->X; z2 = &r->Y; if (!bn_wexpand(x1, group->field.top)) goto err; if (!bn_wexpand(z1, group->field.top)) goto err; if (!bn_wexpand(x2, group->field.top)) goto err; if (!bn_wexpand(z2, group->field.top)) goto err; 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) { BN_consttime_swap(word & mask, x1, x2, group->field.top); BN_consttime_swap(word & mask, z1, z2, group->field.top); if (!gf2m_Madd(group, &point->X, x2, z2, x1, z1, ctx)) goto err; if (!gf2m_Mdouble(group, x1, z1, ctx)) goto err; BN_consttime_swap(word & mask, x1, x2, group->field.top); BN_consttime_swap(word & mask, z1, z2, group->field.top); 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; }
BIGNUM * BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) /* Returns 'ret' such that * ret^2 == a (mod p), * using the Tonelli/Shanks algorithm (cf. Henri Cohen, "A Course * in Algebraic Computational Number Theory", algorithm 1.5.1). * 'p' must be prime! */ { BIGNUM *ret = in; int err = 1; int r; BIGNUM *A, *b, *q, *t, *x, *y; int e, i, j; if (!BN_is_odd(p) || BN_abs_is_word(p, 1)) { if (BN_abs_is_word(p, 2)) { if (ret == NULL) ret = BN_new(); if (ret == NULL) goto end; if (!BN_set_word(ret, BN_is_bit_set(a, 0))) { if (ret != in) BN_free(ret); return NULL; } bn_check_top(ret); return ret; } BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME); return (NULL); } if (BN_is_zero(a) || BN_is_one(a)) { if (ret == NULL) ret = BN_new(); if (ret == NULL) goto end; if (!BN_set_word(ret, BN_is_one(a))) { if (ret != in) BN_free(ret); return NULL; } bn_check_top(ret); return ret; } BN_CTX_start(ctx); A = BN_CTX_get(ctx); b = BN_CTX_get(ctx); q = BN_CTX_get(ctx); t = BN_CTX_get(ctx); x = BN_CTX_get(ctx); y = BN_CTX_get(ctx); if (y == NULL) goto end; if (ret == NULL) ret = BN_new(); if (ret == NULL) goto end; /* A = a mod p */ if (!BN_nnmod(A, a, p, ctx)) goto end; /* now write |p| - 1 as 2^e*q where q is odd */ e = 1; while (!BN_is_bit_set(p, e)) e++; /* we'll set q later (if needed) */ if (e == 1) { /* The easy case: (|p|-1)/2 is odd, so 2 has an inverse * modulo (|p|-1)/2, and square roots can be computed * directly by modular exponentiation. * We have * 2 * (|p|+1)/4 == 1 (mod (|p|-1)/2), * so we can use exponent (|p|+1)/4, i.e. (|p|-3)/4 + 1. */ if (!BN_rshift(q, p, 2)) goto end; q->neg = 0; if (!BN_add_word(q, 1)) goto end; if (!BN_mod_exp(ret, A, q, p, ctx)) goto end; err = 0; goto vrfy; } if (e == 2) { /* |p| == 5 (mod 8) * * In this case 2 is always a non-square since * Legendre(2,p) = (-1)^((p^2-1)/8) for any odd prime. * So if a really is a square, then 2*a is a non-square. * Thus for * b := (2*a)^((|p|-5)/8), * i := (2*a)*b^2 * we have * i^2 = (2*a)^((1 + (|p|-5)/4)*2) * = (2*a)^((p-1)/2) * = -1; * so if we set * x := a*b*(i-1), * then * x^2 = a^2 * b^2 * (i^2 - 2*i + 1) * = a^2 * b^2 * (-2*i) * = a*(-i)*(2*a*b^2) * = a*(-i)*i * = a. * * (This is due to A.O.L. Atkin, * <URL: http://listserv.nodak.edu/scripts/wa.exe?A2=ind9211&L=nmbrthry&O=T&P=562>, * November 1992.) */ /* t := 2*a */ if (!BN_mod_lshift1_quick(t, A, p)) goto end; /* b := (2*a)^((|p|-5)/8) */ if (!BN_rshift(q, p, 3)) goto end; q->neg = 0; if (!BN_mod_exp(b, t, q, p, ctx)) goto end; /* y := b^2 */ if (!BN_mod_sqr(y, b, p, ctx)) goto end; /* t := (2*a)*b^2 - 1*/ if (!BN_mod_mul(t, t, y, p, ctx)) goto end; if (!BN_sub_word(t, 1)) goto end; /* x = a*b*t */ if (!BN_mod_mul(x, A, b, p, ctx)) goto end; if (!BN_mod_mul(x, x, t, p, ctx)) goto end; if (!BN_copy(ret, x)) goto end; err = 0; goto vrfy; } /* e > 2, so we really have to use the Tonelli/Shanks algorithm. * First, find some y that is not a square. */ if (!BN_copy(q, p)) goto end; /* use 'q' as temp */ q->neg = 0; i = 2; do { /* For efficiency, try small numbers first; * if this fails, try random numbers. */ if (i < 22) { if (!BN_set_word(y, i)) goto end; } else { if (!BN_pseudo_rand(y, BN_num_bits(p), 0, 0)) goto end; if (BN_ucmp(y, p) >= 0) { if (!(p->neg ? BN_add : BN_sub)(y, y, p)) goto end; } /* now 0 <= y < |p| */ if (BN_is_zero(y)) if (!BN_set_word(y, i)) goto end; } r = BN_kronecker(y, q, ctx); /* here 'q' is |p| */ if (r < -1) goto end; if (r == 0) { /* m divides p */ BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME); goto end; } } while (r == 1 && ++i < 82); if (r != -1) { /* Many rounds and still no non-square -- this is more likely * a bug than just bad luck. * Even if p is not prime, we should have found some y * such that r == -1. */ BNerr(BN_F_BN_MOD_SQRT, BN_R_TOO_MANY_ITERATIONS); goto end; } /* Here's our actual 'q': */ if (!BN_rshift(q, q, e)) goto end; /* Now that we have some non-square, we can find an element * of order 2^e by computing its q'th power. */ if (!BN_mod_exp(y, y, q, p, ctx)) goto end; if (BN_is_one(y)) { BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME); goto end; } /* Now we know that (if p is indeed prime) there is an integer * k, 0 <= k < 2^e, such that * * a^q * y^k == 1 (mod p). * * As a^q is a square and y is not, k must be even. * q+1 is even, too, so there is an element * * X := a^((q+1)/2) * y^(k/2), * * and it satisfies * * X^2 = a^q * a * y^k * = a, * * so it is the square root that we are looking for. */ /* t := (q-1)/2 (note that q is odd) */ if (!BN_rshift1(t, q)) goto end; /* x := a^((q-1)/2) */ if (BN_is_zero(t)) /* special case: p = 2^e + 1 */ { if (!BN_nnmod(t, A, p, ctx)) goto end; if (BN_is_zero(t)) { /* special case: a == 0 (mod p) */ BN_zero(ret); err = 0; goto end; } else if (!BN_one(x)) goto end; } else { if (!BN_mod_exp(x, A, t, p, ctx)) goto end; if (BN_is_zero(x)) { /* special case: a == 0 (mod p) */ BN_zero(ret); err = 0; goto end; } } /* b := a*x^2 (= a^q) */ if (!BN_mod_sqr(b, x, p, ctx)) goto end; if (!BN_mod_mul(b, b, A, p, ctx)) goto end; /* x := a*x (= a^((q+1)/2)) */ if (!BN_mod_mul(x, x, A, p, ctx)) goto end; while (1) { /* Now b is a^q * y^k for some even k (0 <= k < 2^E * where E refers to the original value of e, which we * don't keep in a variable), and x is a^((q+1)/2) * y^(k/2). * * We have a*b = x^2, * y^2^(e-1) = -1, * b^2^(e-1) = 1. */ if (BN_is_one(b)) { if (!BN_copy(ret, x)) goto end; err = 0; goto vrfy; } /* find smallest i such that b^(2^i) = 1 */ i = 1; if (!BN_mod_sqr(t, b, p, ctx)) goto end; while (!BN_is_one(t)) { i++; if (i == e) { BNerr(BN_F_BN_MOD_SQRT, BN_R_NOT_A_SQUARE); goto end; } if (!BN_mod_mul(t, t, t, p, ctx)) goto end; } /* t := y^2^(e - i - 1) */ if (!BN_copy(t, y)) goto end; for (j = e - i - 1; j > 0; j--) { if (!BN_mod_sqr(t, t, p, ctx)) goto end; } if (!BN_mod_mul(y, t, t, p, ctx)) goto end; if (!BN_mod_mul(x, x, t, p, ctx)) goto end; if (!BN_mod_mul(b, b, y, p, ctx)) goto end; e = i; } vrfy: if (!err) { /* verify the result -- the input might have been not a square * (test added in 0.9.8) */ if (!BN_mod_sqr(x, ret, p, ctx)) err = 1; if (!err && 0 != BN_cmp(x, A)) { BNerr(BN_F_BN_MOD_SQRT, BN_R_NOT_A_SQUARE); err = 1; } } end: if (err) { if (ret != NULL && ret != in) { BN_clear_free(ret); } ret = NULL; } BN_CTX_end(ctx); bn_check_top(ret); return ret; }
// 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; }
int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, const EC_KEY *priv_key, void *(*kdf)(const void *in, size_t inlen, void *out, size_t *outlen)) { if (priv_key->priv_key == NULL) { OPENSSL_PUT_ERROR(ECDH, ECDH_R_NO_PRIVATE_VALUE); return -1; } const EC_SCALAR *const priv = &priv_key->priv_key->scalar; BN_CTX *ctx = BN_CTX_new(); if (ctx == NULL) { return -1; } BN_CTX_start(ctx); int ret = -1; size_t buflen = 0; uint8_t *buf = NULL; const EC_GROUP *const group = EC_KEY_get0_group(priv_key); EC_POINT *tmp = EC_POINT_new(group); if (tmp == NULL) { OPENSSL_PUT_ERROR(ECDH, ERR_R_MALLOC_FAILURE); goto err; } if (!ec_point_mul_scalar(group, tmp, NULL, pub_key, priv, ctx)) { OPENSSL_PUT_ERROR(ECDH, ECDH_R_POINT_ARITHMETIC_FAILURE); goto err; } BIGNUM *x = BN_CTX_get(ctx); if (!x) { OPENSSL_PUT_ERROR(ECDH, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_POINT_get_affine_coordinates_GFp(group, tmp, x, NULL, ctx)) { OPENSSL_PUT_ERROR(ECDH, ECDH_R_POINT_ARITHMETIC_FAILURE); goto err; } buflen = (EC_GROUP_get_degree(group) + 7) / 8; buf = OPENSSL_malloc(buflen); if (buf == NULL) { OPENSSL_PUT_ERROR(ECDH, ERR_R_MALLOC_FAILURE); goto err; } if (!BN_bn2bin_padded(buf, buflen, x)) { OPENSSL_PUT_ERROR(ECDH, ERR_R_INTERNAL_ERROR); goto err; } if (kdf != NULL) { if (kdf(buf, buflen, out, &outlen) == NULL) { OPENSSL_PUT_ERROR(ECDH, ECDH_R_KDF_FAILED); goto err; } } else { // no KDF, just copy as much as we can if (buflen < outlen) { outlen = buflen; } OPENSSL_memcpy(out, buf, outlen); } if (outlen > INT_MAX) { OPENSSL_PUT_ERROR(ECDH, ERR_R_OVERFLOW); goto err; } ret = (int)outlen; err: OPENSSL_free(buf); EC_POINT_free(tmp); BN_CTX_end(ctx); BN_CTX_free(ctx); return ret; }
/*- * This implementation is based on the following primitives in the IEEE 1363 standard: * - ECKAS-DH1 * - ECSVDP-DH * Finally an optional KDF is applied. */ int ossl_ecdh_compute_key(void *out, size_t outlen, const EC_POINT *pub_key, const EC_KEY *ecdh, void *(*KDF) (const void *in, size_t inlen, void *out, size_t *outlen)) { BN_CTX *ctx; EC_POINT *tmp = NULL; BIGNUM *x = NULL, *y = NULL; const BIGNUM *priv_key; const EC_GROUP *group; int ret = -1; size_t buflen, len; unsigned char *buf = NULL; if (outlen > INT_MAX) { ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); /* sort of, * anyway */ return -1; } if (ecdh->group->meth->ecdh_compute_key != 0) return ecdh->group->meth->ecdh_compute_key(out, outlen, pub_key, ecdh, KDF); if ((ctx = BN_CTX_new()) == NULL) goto err; BN_CTX_start(ctx); x = BN_CTX_get(ctx); y = BN_CTX_get(ctx); priv_key = EC_KEY_get0_private_key(ecdh); if (priv_key == NULL) { ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, EC_R_NO_PRIVATE_VALUE); goto err; } group = EC_KEY_get0_group(ecdh); if (EC_KEY_get_flags(ecdh) & EC_FLAG_COFACTOR_ECDH) { if (!EC_GROUP_get_cofactor(group, x, NULL) || !BN_mul(x, x, priv_key, ctx)) { ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); goto err; } priv_key = x; } if ((tmp = EC_POINT_new(group)) == NULL) { ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_POINT_mul(group, tmp, NULL, pub_key, priv_key, ctx)) { ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, EC_R_POINT_ARITHMETIC_FAILURE); goto err; } if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(group, tmp, x, y, ctx)) { ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, EC_R_POINT_ARITHMETIC_FAILURE); goto err; } } #ifndef OPENSSL_NO_EC2M else { if (!EC_POINT_get_affine_coordinates_GF2m(group, tmp, x, y, ctx)) { ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, EC_R_POINT_ARITHMETIC_FAILURE); goto err; } } #endif buflen = (EC_GROUP_get_degree(group) + 7) / 8; len = BN_num_bytes(x); if (len > buflen) { ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, ERR_R_INTERNAL_ERROR); goto err; } if ((buf = OPENSSL_malloc(buflen)) == NULL) { ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, ERR_R_MALLOC_FAILURE); goto err; } memset(buf, 0, buflen - len); if (len != (size_t)BN_bn2bin(x, buf + buflen - len)) { ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, ERR_R_BN_LIB); goto err; } if (KDF != 0) { if (KDF(buf, buflen, out, &outlen) == NULL) { ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, EC_R_KDF_FAILED); goto err; } ret = outlen; } else { /* no KDF, just copy as much as we can */ if (outlen > buflen) outlen = buflen; memcpy(out, buf, outlen); ret = outlen; } err: EC_POINT_free(tmp); if (ctx) BN_CTX_end(ctx); BN_CTX_free(ctx); OPENSSL_free(buf); return (ret); }
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--; } skip = BN_bn2bin(y, buf + i); i += skip; } if (i != ret) { ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR); goto err; } } if (used_ctx) BN_CTX_end(ctx); if (new_ctx != NULL) BN_CTX_free(new_ctx); return ret; err: if (used_ctx) BN_CTX_end(ctx); if (new_ctx != NULL) BN_CTX_free(new_ctx); return 0; }
static int ecdsa_do_verify(const unsigned char *dgst, int dgst_len, const ECDSA_SIG *sig, EC_KEY *eckey) { int ret = -1, i; BN_CTX *ctx; BIGNUM *order, *u1, *u2, *m, *X; EC_POINT *point = NULL; const EC_GROUP *group; const EC_POINT *pub_key; /* check input values */ if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL || (pub_key = EC_KEY_get0_public_key(eckey)) == NULL || sig == NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_MISSING_PARAMETERS); return -1; } ctx = BN_CTX_new(); if (!ctx) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE); return -1; } BN_CTX_start(ctx); order = BN_CTX_get(ctx); u1 = BN_CTX_get(ctx); u2 = BN_CTX_get(ctx); m = BN_CTX_get(ctx); X = BN_CTX_get(ctx); if (!X) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } if (!EC_GROUP_get_order(group, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } if (BN_is_zero(sig->r) || BN_is_negative(sig->r) || BN_ucmp(sig->r, order) >= 0 || BN_is_zero(sig->s) || BN_is_negative(sig->s) || BN_ucmp(sig->s, order) >= 0) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_BAD_SIGNATURE); ret = 0; /* signature is invalid */ goto err; } /* calculate tmp1 = inv(S) mod order */ if (!BN_mod_inverse(u2, sig->s, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* digest -> m */ i = BN_num_bits(order); /* * Need to truncate digest if it is too long: first truncate whole bytes. */ if (8 * dgst_len > i) dgst_len = (i + 7) / 8; if (!BN_bin2bn(dgst, dgst_len, m)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* If still too long truncate remaining bits with a shift */ if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7))) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* u1 = m * tmp mod order */ if (!BN_mod_mul(u1, m, u2, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* u2 = r * w mod q */ if (!BN_mod_mul(u2, sig->r, u2, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } if ((point = EC_POINT_new(group)) == NULL) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_MALLOC_FAILURE); goto err; } if (!EC_POINT_mul(group, point, u1, pub_key, u2, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) == NID_X9_62_prime_field) { if (!EC_POINT_get_affine_coordinates_GFp(group, point, X, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } } #ifndef OPENSSL_NO_EC2M else { /* NID_X9_62_characteristic_two_field */ if (!EC_POINT_get_affine_coordinates_GF2m(group, point, X, NULL, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_EC_LIB); goto err; } } #endif if (!BN_nnmod(u1, X, order, ctx)) { ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ERR_R_BN_LIB); goto err; } /* if the signature is correct u1 is equal to sig->r */ ret = (BN_ucmp(u1, sig->r) == 0); err: BN_CTX_end(ctx); BN_CTX_free(ctx); EC_POINT_free(point); return ret; }
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); if (kron == -2) goto err; if (kron == 1) ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSION_BIT); else /* BN_mod_sqrt() should have cought this error (not a square) */ ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT); goto err; } if (!BN_usub(y, &group->field, y)) goto err; } if (y_bit != BN_is_odd(y)) { ECerr(EC_F_EC_GFP_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_INTERNAL_ERROR); goto err; } if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err; ret = 1; err: BN_CTX_end(ctx); if (new_ctx != NULL) BN_CTX_free(new_ctx); return ret; }
RSA *RSA_generate_key(int bits, unsigned long e_value, void (*callback)(int,int,void *), void *cb_arg) { RSA *rsa=NULL; BIGNUM *r0=NULL,*r1=NULL,*r2=NULL,*r3=NULL,*tmp; int bitsp,bitsq,ok= -1,n=0; unsigned i; BN_CTX *ctx=NULL,*ctx2=NULL; ctx=BN_CTX_new(); if (ctx == NULL) goto err; ctx2=BN_CTX_new(); if (ctx2 == NULL) goto err; BN_CTX_start(ctx); r0 = BN_CTX_get(ctx); r1 = BN_CTX_get(ctx); r2 = BN_CTX_get(ctx); r3 = BN_CTX_get(ctx); if (r3 == NULL) goto err; bitsp=(bits+1)/2; bitsq=bits-bitsp; rsa=RSA_new(); if (rsa == NULL) goto err; /* set e */ rsa->e=BN_new(); if (rsa->e == NULL) goto err; #if 1 /* The problem is when building with 8, 16, or 32 BN_ULONG, * unsigned long can be larger */ for (i=0; i<sizeof(unsigned long)*8; i++) { if (e_value & (((unsigned long)1)<<i)) BN_set_bit(rsa->e,i); } #else if (!BN_set_word(rsa->e,e_value)) goto err; #endif /* generate p and q */ for (;;) { rsa->p=BN_generate_prime(NULL,bitsp,0,NULL,NULL,callback,cb_arg); if (rsa->p == NULL) goto err; if (!BN_sub(r2,rsa->p,BN_value_one())) goto err; if (!BN_gcd(r1,r2,rsa->e,ctx)) goto err; if (BN_is_one(r1)) break; if (callback != NULL) callback(2,n++,cb_arg); BN_free(rsa->p); } if (callback != NULL) callback(3,0,cb_arg); for (;;) { rsa->q=BN_generate_prime(NULL,bitsq,0,NULL,NULL,callback,cb_arg); if (rsa->q == NULL) goto err; if (!BN_sub(r2,rsa->q,BN_value_one())) goto err; if (!BN_gcd(r1,r2,rsa->e,ctx)) goto err; if (BN_is_one(r1) && (BN_cmp(rsa->p,rsa->q) != 0)) break; if (callback != NULL) callback(2,n++,cb_arg); BN_free(rsa->q); } if (callback != NULL) callback(3,1,cb_arg); if (BN_cmp(rsa->p,rsa->q) < 0) { tmp=rsa->p; rsa->p=rsa->q; rsa->q=tmp; } /* calculate n */ rsa->n=BN_new(); if (rsa->n == NULL) goto err; if (!BN_mul(rsa->n,rsa->p,rsa->q,ctx)) goto err; /* calculate d */ if (!BN_sub(r1,rsa->p,BN_value_one())) goto err; /* p-1 */ if (!BN_sub(r2,rsa->q,BN_value_one())) goto err; /* q-1 */ if (!BN_mul(r0,r1,r2,ctx)) goto err; /* (p-1)(q-1) */ /* should not be needed, since gcd(p-1,e) == 1 and gcd(q-1,e) == 1 */ /* for (;;) { if (!BN_gcd(r3,r0,rsa->e,ctx)) goto err; if (BN_is_one(r3)) break; if (1) { if (!BN_add_word(rsa->e,2L)) goto err; continue; } RSAerr(RSA_F_RSA_GENERATE_KEY,RSA_R_BAD_E_VALUE); goto err; } */ rsa->d=BN_mod_inverse(NULL,rsa->e,r0,ctx2); /* d */ if (rsa->d == NULL) goto err; /* calculate d mod (p-1) */ rsa->dmp1=BN_new(); if (rsa->dmp1 == NULL) goto err; if (!BN_mod(rsa->dmp1,rsa->d,r1,ctx)) goto err; /* calculate d mod (q-1) */ rsa->dmq1=BN_new(); if (rsa->dmq1 == NULL) goto err; if (!BN_mod(rsa->dmq1,rsa->d,r2,ctx)) goto err; /* calculate inverse of q mod p */ rsa->iqmp=BN_mod_inverse(NULL,rsa->q,rsa->p,ctx2); if (rsa->iqmp == NULL) goto err; ok=1; err: if (ok == -1) { RSAerr(RSA_F_RSA_GENERATE_KEY,ERR_LIB_BN); ok=0; } BN_CTX_end(ctx); BN_CTX_free(ctx); BN_CTX_free(ctx2); if (!ok) { if (rsa != NULL) RSA_free(rsa); return(NULL); } else return(rsa); }
int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, 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; int ret = 0; if (EC_POINT_is_at_infinity(group, a)) { BN_zero(&r->Z); r->Z_is_one = 0; return 1; } 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); if (n3 == NULL) goto err; /* Note that in this function we must not read components of 'a' * once we have written the corresponding components of 'r'. * ('r' might the same as 'a'.) */ /* n1 */ if (a->Z_is_one) { if (!field_sqr(group, n0, &a->X, ctx)) goto err; if (!BN_mod_lshift1_quick(n1, n0, p)) goto err; if (!BN_mod_add_quick(n0, n0, n1, p)) goto err; if (!BN_mod_add_quick(n1, n0, &group->a, p)) goto err; /* n1 = 3 * X_a^2 + a_curve */ } else if (group->a_is_minus3) { if (!field_sqr(group, n1, &a->Z, ctx)) goto err; if (!BN_mod_add_quick(n0, &a->X, n1, p)) goto err; if (!BN_mod_sub_quick(n2, &a->X, n1, p)) goto err; if (!field_mul(group, n1, n0, n2, ctx)) goto err; if (!BN_mod_lshift1_quick(n0, n1, p)) goto err; if (!BN_mod_add_quick(n1, n0, n1, p)) goto err; /* n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2) * = 3 * X_a^2 - 3 * Z_a^4 */ } else { if (!field_sqr(group, n0, &a->X, ctx)) goto err; if (!BN_mod_lshift1_quick(n1, n0, p)) goto err; if (!BN_mod_add_quick(n0, n0, n1, p)) goto err; if (!field_sqr(group, n1, &a->Z, ctx)) goto err; if (!field_sqr(group, n1, n1, ctx)) goto err; if (!field_mul(group, n1, n1, &group->a, ctx)) goto err; if (!BN_mod_add_quick(n1, n1, n0, p)) goto err; /* n1 = 3 * X_a^2 + a_curve * Z_a^4 */ } /* Z_r */ if (a->Z_is_one) { if (!BN_copy(n0, &a->Y)) goto err; } else { if (!field_mul(group, n0, &a->Y, &a->Z, ctx)) goto err; } if (!BN_mod_lshift1_quick(&r->Z, n0, p)) goto err; r->Z_is_one = 0; /* Z_r = 2 * Y_a * Z_a */ /* n2 */ if (!field_sqr(group, n3, &a->Y, ctx)) goto err; if (!field_mul(group, n2, &a->X, n3, ctx)) goto err; if (!BN_mod_lshift_quick(n2, n2, 2, p)) goto err; /* n2 = 4 * X_a * Y_a^2 */ /* X_r */ if (!BN_mod_lshift1_quick(n0, n2, p)) goto err; if (!field_sqr(group, &r->X, n1, ctx)) goto err; if (!BN_mod_sub_quick(&r->X, &r->X, n0, p)) goto err; /* X_r = n1^2 - 2 * n2 */ /* n3 */ if (!field_sqr(group, n0, n3, ctx)) goto err; if (!BN_mod_lshift_quick(n3, n0, 3, p)) goto err; /* n3 = 8 * Y_a^4 */ /* Y_r */ if (!BN_mod_sub_quick(n0, n2, &r->X, p)) goto err; if (!field_mul(group, n0, n1, n0, ctx)) goto err; if (!BN_mod_sub_quick(&r->Y, n0, n3, p)) goto err; /* Y_r = n1 * (n2 - X_r) - n3 */ ret = 1; err: BN_CTX_end(ctx); if (new_ctx != NULL) BN_CTX_free(new_ctx); return ret; }
/* BN_div computes dv := num / divisor, rounding towards zero, and sets up * rm such that dv*divisor + rm = num holds. * Thus: * dv->neg == num->neg ^ divisor->neg (unless the result is zero) * rm->neg == num->neg (unless the remainder is zero) * If 'dv' or 'rm' is NULL, the respective value is not returned. */ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor, BN_CTX *ctx) { int norm_shift,i,loop; BIGNUM *tmp,wnum,*snum,*sdiv,*res; BN_ULONG *resp,*wnump; BN_ULONG d0,d1; int num_n,div_n; bn_check_top(dv); bn_check_top(rm); bn_check_top(num); bn_check_top(divisor); if (BN_is_zero(divisor)) { /*Begin: comment out , 17Aug2006, Chris */ #if 0 BNerr(BN_F_BN_DIV,BN_R_DIV_BY_ZERO); #endif /*End: comment out , 17Aug2006, Chris */ return(0); } if (BN_ucmp(num,divisor) < 0) { if (rm != NULL) { if (BN_copy(rm,num) == NULL) return(0); } if (dv != NULL) BN_zero(dv); return(1); } BN_CTX_start(ctx); tmp=BN_CTX_get(ctx); snum=BN_CTX_get(ctx); sdiv=BN_CTX_get(ctx); if (dv == NULL) res=BN_CTX_get(ctx); else res=dv; if (sdiv == NULL || res == NULL) goto err; /* First we normalise the numbers */ norm_shift=BN_BITS2-((BN_num_bits(divisor))%BN_BITS2); if (!(BN_lshift(sdiv,divisor,norm_shift))) goto err; sdiv->neg=0; norm_shift+=BN_BITS2; if (!(BN_lshift(snum,num,norm_shift))) goto err; snum->neg=0; div_n=sdiv->top; num_n=snum->top; loop=num_n-div_n; /* Lets setup a 'window' into snum * This is the part that corresponds to the current * 'area' being divided */ wnum.neg = 0; wnum.d = &(snum->d[loop]); wnum.top = div_n; /* only needed when BN_ucmp messes up the values between top and max */ wnum.dmax = snum->dmax - loop; /* so we don't step out of bounds */ /* Get the top 2 words of sdiv */ /* div_n=sdiv->top; */ d0=sdiv->d[div_n-1]; d1=(div_n == 1)?0:sdiv->d[div_n-2]; /* pointer to the 'top' of snum */ wnump= &(snum->d[num_n-1]); /* Setup to 'res' */ res->neg= (num->neg^divisor->neg); if (!bn_wexpand(res,(loop+1))) goto err; res->top=loop; resp= &(res->d[loop-1]); /* space for temp */ if (!bn_wexpand(tmp,(div_n+1))) goto err; if (BN_ucmp(&wnum,sdiv) >= 0) { /* If BN_DEBUG_RAND is defined BN_ucmp changes (via * bn_pollute) the const bignum arguments => * clean the values between top and max again */ bn_clear_top2max(&wnum); bn_sub_words(wnum.d, wnum.d, sdiv->d, div_n); *resp=1; } else res->top--; /* if res->top == 0 then clear the neg value otherwise decrease * the resp pointer */ if (res->top == 0) res->neg = 0; else resp--; for (i=0; i<loop-1; i++, wnump--, resp--) { BN_ULONG q,l0; /* the first part of the loop uses the top two words of * snum and sdiv to calculate a BN_ULONG q such that * | wnum - sdiv * q | < sdiv */ #if defined(BN_DIV3W) && !defined(OPENSSL_NO_ASM) BN_ULONG bn_div_3_words(BN_ULONG*,BN_ULONG,BN_ULONG); q=bn_div_3_words(wnump,d1,d0); #else BN_ULONG n0,n1,rem=0; n0=wnump[0]; n1=wnump[-1]; if (n0 == d0) q=BN_MASK2; else /* n0 < d0 */ { #ifdef BN_LLONG BN_ULLONG t2; #if defined(BN_LLONG) && defined(BN_DIV2W) && !defined(bn_div_words) q=(BN_ULONG)(((((BN_ULLONG)n0)<<BN_BITS2)|n1)/d0); #else q=bn_div_words(n0,n1,d0); #ifdef BN_DEBUG_LEVITTE fprintf(stderr,"DEBUG: bn_div_words(0x%08X,0x%08X,0x%08\ X) -> 0x%08X\n", n0, n1, d0, q); #endif #endif #ifndef REMAINDER_IS_ALREADY_CALCULATED /* * rem doesn't have to be BN_ULLONG. The least we * know it's less that d0, isn't it? */ rem=(n1-q*d0)&BN_MASK2; #endif t2=(BN_ULLONG)d1*q; for (;;) { if (t2 <= ((((BN_ULLONG)rem)<<BN_BITS2)|wnump[-2])) break; q--; rem += d0; if (rem < d0) break; /* don't let rem overflow */ t2 -= d1; } #else /* !BN_LLONG */ BN_ULONG t2l,t2h,ql,qh; q=bn_div_words(n0,n1,d0); #ifdef BN_DEBUG_LEVITTE fprintf(stderr,"DEBUG: bn_div_words(0x%08X,0x%08X,0x%08\ X) -> 0x%08X\n", n0, n1, d0, q); #endif #ifndef REMAINDER_IS_ALREADY_CALCULATED rem=(n1-q*d0)&BN_MASK2; #endif #if defined(BN_UMULT_LOHI) BN_UMULT_LOHI(t2l,t2h,d1,q); #elif defined(BN_UMULT_HIGH) t2l = d1 * q; t2h = BN_UMULT_HIGH(d1,q); #else t2l=LBITS(d1); t2h=HBITS(d1); ql =LBITS(q); qh =HBITS(q); mul64(t2l,t2h,ql,qh); /* t2=(BN_ULLONG)d1*q; */ #endif for (;;) { if ((t2h < rem) || ((t2h == rem) && (t2l <= wnump[-2]))) break; q--; rem += d0; if (rem < d0) break; /* don't let rem overflow */ if (t2l < d1) t2h--; t2l -= d1; } #endif /* !BN_LLONG */ } #endif /* !BN_DIV3W */ l0=bn_mul_words(tmp->d,sdiv->d,div_n,q); tmp->d[div_n]=l0; wnum.d--; /* ingore top values of the bignums just sub the two * BN_ULONG arrays with bn_sub_words */ if (bn_sub_words(wnum.d, wnum.d, tmp->d, div_n+1)) { /* Note: As we have considered only the leading * two BN_ULONGs in the calculation of q, sdiv * q * might be greater than wnum (but then (q-1) * sdiv * is less or equal than wnum) */ q--; if (bn_add_words(wnum.d, wnum.d, sdiv->d, div_n)) /* we can't have an overflow here (assuming * that q != 0, but if q == 0 then tmp is * zero anyway) */ (*wnump)++; } /* store part of the result */ *resp = q; } bn_correct_top(snum); if (rm != NULL) { /* Keep a copy of the neg flag in num because if rm==num * BN_rshift() will overwrite it. */ int neg = num->neg; BN_rshift(rm,snum,norm_shift); if (!BN_is_zero(rm)) rm->neg = neg; bn_check_top(rm); } BN_CTX_end(ctx); return(1); err: bn_check_top(rm); BN_CTX_end(ctx); return(0); }
int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) { /* return values: * -1 error * 0 equal (in affine coordinates) * 1 not equal */ int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *); int (*field_sqr)(const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *); BN_CTX *new_ctx = NULL; BIGNUM *tmp1, *tmp2, *Za23, *Zb23; const BIGNUM *tmp1_, *tmp2_; int ret = -1; if (EC_POINT_is_at_infinity(group, a)) { return EC_POINT_is_at_infinity(group, b) ? 0 : 1; } if (EC_POINT_is_at_infinity(group, b)) return 1; if (a->Z_is_one && b->Z_is_one) { return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1; } field_mul = group->meth->field_mul; field_sqr = group->meth->field_sqr; if (ctx == NULL) { ctx = new_ctx = BN_CTX_new(); if (ctx == NULL) return -1; } BN_CTX_start(ctx); tmp1 = BN_CTX_get(ctx); tmp2 = BN_CTX_get(ctx); Za23 = BN_CTX_get(ctx); Zb23 = BN_CTX_get(ctx); if (Zb23 == NULL) goto end; /* We have to decide whether * (X_a/Z_a^2, Y_a/Z_a^3) = (X_b/Z_b^2, Y_b/Z_b^3), * or equivalently, whether * (X_a*Z_b^2, Y_a*Z_b^3) = (X_b*Z_a^2, Y_b*Z_a^3). */ if (!b->Z_is_one) { if (!field_sqr(group, Zb23, &b->Z, ctx)) goto end; if (!field_mul(group, tmp1, &a->X, Zb23, ctx)) goto end; tmp1_ = tmp1; } else tmp1_ = &a->X; if (!a->Z_is_one) { if (!field_sqr(group, Za23, &a->Z, ctx)) goto end; if (!field_mul(group, tmp2, &b->X, Za23, ctx)) goto end; tmp2_ = tmp2; } else tmp2_ = &b->X; /* compare X_a*Z_b^2 with X_b*Z_a^2 */ if (BN_cmp(tmp1_, tmp2_) != 0) { ret = 1; /* points differ */ goto end; } if (!b->Z_is_one) { if (!field_mul(group, Zb23, Zb23, &b->Z, ctx)) goto end; if (!field_mul(group, tmp1, &a->Y, Zb23, ctx)) goto end; /* tmp1_ = tmp1 */ } else tmp1_ = &a->Y; if (!a->Z_is_one) { if (!field_mul(group, Za23, Za23, &a->Z, ctx)) goto end; if (!field_mul(group, tmp2, &b->Y, Za23, ctx)) goto end; /* tmp2_ = tmp2 */ } else tmp2_ = &b->Y; /* compare Y_a*Z_b^3 with Y_b*Z_a^3 */ if (BN_cmp(tmp1_, tmp2_) != 0) { ret = 1; /* points differ */ goto end; } /* points are equal */ ret = 0; end: BN_CTX_end(ctx); if (new_ctx != NULL) BN_CTX_free(new_ctx); return ret; }
int BN_sqrt(BIGNUM *out_sqrt, const BIGNUM *in, BN_CTX *ctx) { BIGNUM *estimate, *tmp, *delta, *last_delta, *tmp2; int ok = 0, last_delta_valid = 0; if (in->neg) { OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER); return 0; } if (BN_is_zero(in)) { BN_zero(out_sqrt); return 1; } BN_CTX_start(ctx); if (out_sqrt == in) { estimate = BN_CTX_get(ctx); } else { estimate = out_sqrt; } tmp = BN_CTX_get(ctx); last_delta = BN_CTX_get(ctx); delta = BN_CTX_get(ctx); if (estimate == NULL || tmp == NULL || last_delta == NULL || delta == NULL) { OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE); goto err; } // We estimate that the square root of an n-bit number is 2^{n/2}. if (!BN_lshift(estimate, BN_value_one(), BN_num_bits(in)/2)) { goto err; } // This is Newton's method for finding a root of the equation |estimate|^2 - // |in| = 0. for (;;) { // |estimate| = 1/2 * (|estimate| + |in|/|estimate|) if (!BN_div(tmp, NULL, in, estimate, ctx) || !BN_add(tmp, tmp, estimate) || !BN_rshift1(estimate, tmp) || // |tmp| = |estimate|^2 !BN_sqr(tmp, estimate, ctx) || // |delta| = |in| - |tmp| !BN_sub(delta, in, tmp)) { OPENSSL_PUT_ERROR(BN, ERR_R_BN_LIB); goto err; } delta->neg = 0; // The difference between |in| and |estimate| squared is required to always // decrease. This ensures that the loop always terminates, but I don't have // a proof that it always finds the square root for a given square. if (last_delta_valid && BN_cmp(delta, last_delta) >= 0) { break; } last_delta_valid = 1; tmp2 = last_delta; last_delta = delta; delta = tmp2; } if (BN_cmp(tmp, in) != 0) { OPENSSL_PUT_ERROR(BN, BN_R_NOT_A_SQUARE); goto err; } ok = 1; err: if (ok && out_sqrt == in && !BN_copy(out_sqrt, estimate)) { ok = 0; } BN_CTX_end(ctx); return ok; }
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; }
BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *in_ctx) { BIGNUM local_n; BIGNUM *e,*n; BN_CTX *ctx; BN_BLINDING *ret = NULL; if (in_ctx == NULL) { if ((ctx = BN_CTX_new()) == NULL) return 0; } else ctx = in_ctx; BN_CTX_start(ctx); e = BN_CTX_get(ctx); if (e == NULL) { //RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_MALLOC_FAILURE); goto err; } if (rsa->e == NULL) { e = rsa_get_public_exp(rsa->d, rsa->p, rsa->q, ctx); if (e == NULL) { //RSAerr(RSA_F_RSA_SETUP_BLINDING, RSA_R_NO_PUBLIC_EXPONENT); goto err; } } else e = rsa->e; if ((RAND_status() == 0) && rsa->d != NULL && rsa->d->d != NULL) { /* if PRNG is not properly seeded, resort to secret * exponent as unpredictable seed */ RAND_add(rsa->d->d, rsa->d->dmax * sizeof rsa->d->d[0], 0.0); } if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) { /* Set BN_FLG_CONSTTIME flag */ n = &local_n; BN_with_flags(n, rsa->n, BN_FLG_CONSTTIME); } else n = rsa->n; //ret = BN_BLINDING_create_param(NULL, e, n, ctx, // rsa->meth->bn_mod_exp, rsa->_method_mod_n); //if (ret == NULL) // { // //RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_BN_LIB); // goto err; // } //CRYPTO_THREADID_current(BN_BLINDING_thread_id(ret)); err: BN_CTX_end(ctx); if (in_ctx == NULL) BN_CTX_free(ctx); if(rsa->e == NULL) BN_free(e); return ret; }