bool android_pubkey_encode(const RSA* key, uint8_t* key_buffer, size_t size) { RSAPublicKey* key_struct = (RSAPublicKey*)key_buffer; bool ret = false; BN_CTX* ctx = BN_CTX_new(); BIGNUM* r32 = BN_new(); BIGNUM* n0inv = BN_new(); BIGNUM* rr = BN_new(); if (sizeof(RSAPublicKey) > size || RSA_size(key) != ANDROID_PUBKEY_MODULUS_SIZE) { goto cleanup; } // Store the modulus size. key_struct->modulus_size_words = ANDROID_PUBKEY_MODULUS_SIZE_WORDS; // Compute and store n0inv = -1 / N[0] mod 2^32. if (!ctx || !r32 || !n0inv || !BN_set_bit(r32, 32) || !BN_mod(n0inv, key->n, r32, ctx) || !BN_mod_inverse(n0inv, n0inv, r32, ctx) || !BN_sub(n0inv, r32, n0inv)) { goto cleanup; } key_struct->n0inv = (uint32_t)BN_get_word(n0inv); // Store the modulus. if (!android_pubkey_encode_bignum(key->n, key_struct->modulus)) { goto cleanup; } // Compute and store rr = (2^(rsa_size)) ^ 2 mod N. if (!ctx || !rr || !BN_set_bit(rr, ANDROID_PUBKEY_MODULUS_SIZE * 8) || !BN_mod_sqr(rr, rr, key->n, ctx) || !android_pubkey_encode_bignum(rr, key_struct->rr)) { goto cleanup; } // Store the exponent. key_struct->exponent = (uint32_t)BN_get_word(key->e); ret = true; cleanup: BN_free(rr); BN_free(n0inv); BN_free(r32); BN_CTX_free(ctx); 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; 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) || !group->meth->field_mul(group, tmp1, tmp2, x_, ctx)) { goto err; } } else { if (!BN_mod_sqr(tmp2, x_, &group->field, ctx) || !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) || !BN_mod_add_quick(tmp2, tmp2, x, &group->field) || !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) || !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) || !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(); OPENSSL_PUT_ERROR(EC, ec_GFp_simple_set_compressed_coordinates, EC_R_INVALID_COMPRESSED_POINT); } else { OPENSSL_PUT_ERROR(EC, 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) { OPENSSL_PUT_ERROR(EC, ec_GFp_simple_set_compressed_coordinates, EC_R_INVALID_COMPRESSION_BIT); } else { /* BN_mod_sqrt() should have cought this error (not a square) */ OPENSSL_PUT_ERROR(EC, 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)) { OPENSSL_PUT_ERROR(EC, 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; }
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; }
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: */ if (!group->meth->field_mul(group, y, point->Y, Z_3, ctx)) goto err; } } ret = 1; err: BN_CTX_end(ctx); BN_CTX_free(new_ctx); return ret; }
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); BN_CTX_free(new_ctx); return ret; }
int ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a, BN_CTX *ctx) { return BN_mod_sqr(r, a, group->field, ctx); }
int test_sqrt(BIO *bp, BN_CTX *ctx) { BIGNUM *a,*p,*r; int i, j; int ret = 0; a = BN_new(); p = BN_new(); r = BN_new(); if (a == NULL || p == NULL || r == NULL) goto err; for (i = 0; i < 16; i++) { if (i < 8) { unsigned primes[8] = { 2, 3, 5, 7, 11, 13, 17, 19 }; if (!BN_set_word(p, primes[i])) goto err; } else { if (!BN_set_word(a, 32)) goto err; if (!BN_set_word(r, 2*i + 1)) goto err; if (!BN_generate_prime(p, 256, 0, a, r, genprime_cb, NULL)) goto err; putc('\n', stderr); } p->neg = rand_neg(); for (j = 0; j < num2; j++) { /* construct 'a' such that it is a square modulo p, * but in general not a proper square and not reduced modulo p */ if (!BN_bntest_rand(r, 256, 0, 3)) goto err; if (!BN_nnmod(r, r, p, ctx)) goto err; if (!BN_mod_sqr(r, r, p, ctx)) goto err; if (!BN_bntest_rand(a, 256, 0, 3)) goto err; if (!BN_nnmod(a, a, p, ctx)) goto err; if (!BN_mod_sqr(a, a, p, ctx)) goto err; if (!BN_mul(a, a, r, ctx)) goto err; if (rand_neg()) if (!BN_sub(a, a, p)) goto err; if (!BN_mod_sqrt(r, a, p, ctx)) goto err; if (!BN_mod_sqr(r, r, p, ctx)) goto err; if (!BN_nnmod(a, a, p, ctx)) goto err; if (BN_cmp(a, r) != 0) { fprintf(stderr, "BN_mod_sqrt failed: a = "); BN_print_fp(stderr, a); fprintf(stderr, ", r = "); BN_print_fp(stderr, r); fprintf(stderr, ", p = "); BN_print_fp(stderr, p); fprintf(stderr, "\n"); goto err; } putc('.', stderr); fflush(stderr); } putc('\n', stderr); fflush(stderr); } ret = 1; err: if (a != NULL) BN_free(a); if (p != NULL) BN_free(p); if (r != NULL) BN_free(r); 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_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_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; }
void do_mul_exp(BIGNUM *r, BIGNUM *a, BIGNUM *b, BIGNUM *c, BN_CTX *ctx) { int i,k; double tm; long num; num=BASENUM; for (i=NUM_START; i<NUM_SIZES; i++) { #ifdef C_PRIME # ifdef TEST_SQRT if (!BN_set_word(a, 64)) goto err; if (!BN_set_word(b, P_MOD_64)) goto err; # define ADD a # define REM b # else # define ADD NULL # define REM NULL # endif if (!BN_generate_prime(c,sizes[i],0,ADD,REM,genprime_cb,NULL)) goto err; putc('\n', stderr); fflush(stderr); #endif for (k=0; k<num; k++) { if (k%50 == 0) /* Average over num/50 different choices of random numbers. */ { if (!BN_pseudo_rand(a,sizes[i],1,0)) goto err; if (!BN_pseudo_rand(b,sizes[i],1,0)) goto err; #ifndef C_PRIME if (!BN_pseudo_rand(c,sizes[i],1,1)) goto err; #endif #ifdef TEST_SQRT if (!BN_mod_sqr(a,a,c,ctx)) goto err; if (!BN_mod_sqr(b,b,c,ctx)) goto err; #else if (!BN_nnmod(a,a,c,ctx)) goto err; if (!BN_nnmod(b,b,c,ctx)) goto err; #endif if (k == 0) Time_F(START); } #if defined(TEST_EXP) if (!BN_mod_exp(r,a,b,c,ctx)) goto err; #elif defined(TEST_MUL) { int i = 0; for (i = 0; i < 50; i++) if (!BN_mod_mul(r,a,b,c,ctx)) goto err; } #elif defined(TEST_SQR) { int i = 0; for (i = 0; i < 50; i++) { if (!BN_mod_sqr(r,a,c,ctx)) goto err; if (!BN_mod_sqr(r,b,c,ctx)) goto err; } } #elif defined(TEST_GCD) if (!BN_gcd(r,a,b,ctx)) goto err; if (!BN_gcd(r,b,c,ctx)) goto err; if (!BN_gcd(r,c,a,ctx)) goto err; #elif defined(TEST_KRON) if (-2 == BN_kronecker(a,b,ctx)) goto err; if (-2 == BN_kronecker(b,c,ctx)) goto err; if (-2 == BN_kronecker(c,a,ctx)) goto err; #elif defined(TEST_INV) if (!BN_mod_inverse(r,a,c,ctx)) goto err; if (!BN_mod_inverse(r,b,c,ctx)) goto err; #else /* TEST_SQRT */ if (!BN_mod_sqrt(r,a,c,ctx)) goto err; if (!BN_mod_sqrt(r,b,c,ctx)) goto err; #endif } tm=Time_F(STOP); printf( #if defined(TEST_EXP) "modexp %4d ^ %4d %% %4d" #elif defined(TEST_MUL) "50*modmul %4d %4d %4d" #elif defined(TEST_SQR) "100*modsqr %4d %4d %4d" #elif defined(TEST_GCD) "3*gcd %4d %4d %4d" #elif defined(TEST_KRON) "3*kronecker %4d %4d %4d" #elif defined(TEST_INV) "2*inv %4d %4d mod %4d" #else /* TEST_SQRT */ "2*sqrt [prime == %d (mod 64)] %4d %4d mod %4d" #endif " -> %8.3fms %5.1f (%ld)\n", #ifdef TEST_SQRT P_MOD_64, #endif sizes[i],sizes[i],sizes[i],tm*1000.0/num,tm*mul_c[i]/num, num); num/=7; if (num <= 0) num=1; } return; err: ERR_print_errors_fp(stderr); }
int ecdh_im_compute_key(PACE_CTX * ctx, const BUF_MEM * s, const BUF_MEM * in, BN_CTX *bn_ctx) { int ret = 0; BUF_MEM * x_mem = NULL; BIGNUM * a = NULL, *b = NULL, *p = NULL; BIGNUM * x = NULL, *y = NULL, *v = NULL, *u = NULL; BIGNUM * tmp = NULL, *tmp2 = NULL, *bn_inv = NULL; BIGNUM * two = NULL, *three = NULL, *four = NULL, *six = NULL; BIGNUM * twentyseven = NULL; EC_KEY *static_key = NULL, *ephemeral_key = NULL; EC_POINT *g = NULL; BN_CTX_start(bn_ctx); check((ctx && ctx->static_key && s && ctx->ka_ctx), "Invalid arguments"); static_key = EVP_PKEY_get1_EC_KEY(ctx->static_key); if (!static_key) goto err; /* Setup all the variables*/ a = BN_CTX_get(bn_ctx); b = BN_CTX_get(bn_ctx); p = BN_CTX_get(bn_ctx); x = BN_CTX_get(bn_ctx); y = BN_CTX_get(bn_ctx); v = BN_CTX_get(bn_ctx); two = BN_CTX_get(bn_ctx); three = BN_CTX_get(bn_ctx); four = BN_CTX_get(bn_ctx); six = BN_CTX_get(bn_ctx); twentyseven = BN_CTX_get(bn_ctx); tmp = BN_CTX_get(bn_ctx); tmp2 = BN_CTX_get(bn_ctx); bn_inv = BN_CTX_get(bn_ctx); if (!bn_inv) goto err; /* Encrypt the Nonce using the symmetric key in */ x_mem = cipher_no_pad(ctx->ka_ctx, NULL, in, s, 1); if (!x_mem) goto err; /* Fetch the curve parameters */ if (!EC_GROUP_get_curve_GFp(EC_KEY_get0_group(static_key), p, a, b, bn_ctx)) goto err; /* Assign constants */ if ( !BN_set_word(two,2)|| !BN_set_word(three,3)|| !BN_set_word(four,4)|| !BN_set_word(six,6)|| !BN_set_word(twentyseven,27) ) goto err; /* Check prerequisites for curve parameters */ check( /* p > 3;*/ (BN_cmp(p, three) == 1) && /* p mod 3 = 2; (p has the form p=q^n, q prime) */ BN_nnmod(tmp, p, three, bn_ctx) && (BN_cmp(tmp, two) == 0), "Unsuited curve"); /* Convert encrypted nonce to BIGNUM */ u = BN_bin2bn((unsigned char *) x_mem->data, x_mem->length, u); if (!u) goto err; if ( /* v = (3a - u^4) / 6u mod p */ !BN_mod_mul(tmp, three, a, p, bn_ctx) || !BN_mod_exp(tmp2, u, four, p, bn_ctx) || !BN_mod_sub(v, tmp, tmp2, p, bn_ctx) || !BN_mod_mul(tmp, u, six, p, bn_ctx) || /* For division within a galois field we need to compute * the multiplicative inverse of a number */ !BN_mod_inverse(bn_inv, tmp, p, bn_ctx) || !BN_mod_mul(v, v, bn_inv, p, bn_ctx) || /* x = (v^2 - b - ((u^6)/27)) */ !BN_mod_sqr(tmp, v, p, bn_ctx) || !BN_mod_sub(tmp2, tmp, b, p, bn_ctx) || !BN_mod_exp(tmp, u, six, p, bn_ctx) || !BN_mod_inverse(bn_inv, twentyseven, p, bn_ctx) || !BN_mod_mul(tmp, tmp, bn_inv, p, bn_ctx) || !BN_mod_sub(x, tmp2, tmp, p, bn_ctx) || /* x -> x^(1/3) = x^((2p^n -1)/3) */ !BN_mul(tmp, two, p, bn_ctx) || !BN_sub(tmp, tmp, BN_value_one()) || /* Division is defined, because p^n = 2 mod 3 */ !BN_div(tmp, y, tmp, three, bn_ctx) || !BN_mod_exp(tmp2, x, tmp, p, bn_ctx) || !BN_copy(x, tmp2) || /* x += (u^2)/3 */ !BN_mod_sqr(tmp, u, p, bn_ctx) || !BN_mod_inverse(bn_inv, three, p, bn_ctx) || !BN_mod_mul(tmp2, tmp, bn_inv, p, bn_ctx) || !BN_mod_add(tmp, x, tmp2, p, bn_ctx) || !BN_copy(x, tmp) || /* y = ux + v */ !BN_mod_mul(y, u, x, p, bn_ctx) || !BN_mod_add(tmp, y, v, p, bn_ctx) || !BN_copy(y, tmp) ) goto err; /* Initialize ephemeral parameters with parameters from the static key */ ephemeral_key = EC_KEY_dup(static_key); if (!ephemeral_key) goto err; EVP_PKEY_set1_EC_KEY(ctx->ka_ctx->key, ephemeral_key); /* configure the new EC_KEY */ g = EC_POINT_new(EC_KEY_get0_group(ephemeral_key)); if (!g) goto err; if (!EC_POINT_set_affine_coordinates_GFp(EC_KEY_get0_group(ephemeral_key), g, x, y, bn_ctx)) goto err; ret = 1; err: if (x_mem) BUF_MEM_free(x_mem); if (u) BN_free(u); BN_CTX_end(bn_ctx); if (g) EC_POINT_clear_free(g); /* Decrement reference count, keys are still available via PACE_CTX */ if (static_key) EC_KEY_free(static_key); if (ephemeral_key) EC_KEY_free(ephemeral_key); return ret; }