*/
int crypto_bignum_is_one(const struct crypto_bignum *a);
+/**
+ * crypto_bignum_legendre - Compute the Legendre symbol (a/p)
+ * @a: Bignum
+ * @p: Bignum
+ * Returns: Legendre symbol -1,0,1 on success; -2 on calculation failure
+ */
+int crypto_bignum_legendre(const struct crypto_bignum *a,
+ const struct crypto_bignum *p);
+
/**
* struct crypto_ec - Elliptic curve context
*
struct crypto_ec_point *p,
const struct crypto_bignum *x, int y_bit);
+/**
+ * crypto_ec_point_compute_y_sqr - Compute y^2 = x^3 + ax + b
+ * @e: EC context from crypto_ec_init()
+ * @x: x coordinate
+ * Returns: y^2 on success, %NULL failure
+ */
+struct crypto_bignum *
+crypto_ec_point_compute_y_sqr(struct crypto_ec *e,
+ const struct crypto_bignum *x);
+
/**
* crypto_ec_point_is_at_infinity - Check whether EC point is neutral element
* @e: EC context from crypto_ec_init()
}
+int crypto_bignum_legendre(const struct crypto_bignum *a,
+ const struct crypto_bignum *p)
+{
+ BN_CTX *bnctx;
+ BIGNUM *exp = NULL, *tmp = NULL;
+ int res = -2;
+
+ bnctx = BN_CTX_new();
+ if (bnctx == NULL)
+ return -2;
+
+ exp = BN_new();
+ tmp = BN_new();
+ if (!exp || !tmp ||
+ /* exp = (p-1) / 2 */
+ !BN_sub(exp, (const BIGNUM *) p, BN_value_one()) ||
+ !BN_rshift1(exp, exp) ||
+ !BN_mod_exp(tmp, (const BIGNUM *) a, exp, (const BIGNUM *) p,
+ bnctx))
+ goto fail;
+
+ if (BN_is_word(tmp, 1))
+ res = 1;
+ else if (BN_is_zero(tmp))
+ res = 0;
+ else
+ res = -1;
+
+fail:
+ BN_clear_free(tmp);
+ BN_clear_free(exp);
+ BN_CTX_free(bnctx);
+ return res;
+}
+
+
#ifdef CONFIG_ECC
struct crypto_ec {
BN_CTX *bnctx;
BIGNUM *prime;
BIGNUM *order;
+ BIGNUM *a;
+ BIGNUM *b;
};
struct crypto_ec * crypto_ec_init(int group)
e->group = EC_GROUP_new_by_curve_name(nid);
e->prime = BN_new();
e->order = BN_new();
+ e->a = BN_new();
+ e->b = BN_new();
if (e->group == NULL || e->bnctx == NULL || e->prime == NULL ||
- e->order == NULL ||
- !EC_GROUP_get_curve_GFp(e->group, e->prime, NULL, NULL, e->bnctx) ||
+ e->order == NULL || e->a == NULL || e->b == NULL ||
+ !EC_GROUP_get_curve_GFp(e->group, e->prime, e->a, e->b, e->bnctx) ||
!EC_GROUP_get_order(e->group, e->order, e->bnctx)) {
crypto_ec_deinit(e);
e = NULL;
{
if (e == NULL)
return;
+ BN_clear_free(e->b);
+ BN_clear_free(e->a);
BN_clear_free(e->order);
BN_clear_free(e->prime);
EC_GROUP_free(e->group);
}
+struct crypto_bignum *
+crypto_ec_point_compute_y_sqr(struct crypto_ec *e,
+ const struct crypto_bignum *x)
+{
+ BIGNUM *tmp, *tmp2, *y_sqr = NULL;
+
+ tmp = BN_new();
+ tmp2 = BN_new();
+
+ /* y^2 = x^3 + ax + b */
+ if (tmp && tmp2 &&
+ BN_mod_sqr(tmp, (const BIGNUM *) x, e->prime, e->bnctx) &&
+ BN_mod_mul(tmp, tmp, (const BIGNUM *) x, e->prime, e->bnctx) &&
+ BN_mod_mul(tmp2, e->a, (const BIGNUM *) x, e->prime, e->bnctx) &&
+ BN_mod_add_quick(tmp2, tmp2, tmp, e->prime) &&
+ BN_mod_add_quick(tmp2, tmp2, e->b, e->prime)) {
+ y_sqr = tmp2;
+ tmp2 = NULL;
+ }
+
+ BN_clear_free(tmp);
+ BN_clear_free(tmp2);
+
+ return (struct crypto_bignum *) y_sqr;
+}
+
+
int crypto_ec_point_is_at_infinity(struct crypto_ec *e,
const struct crypto_ec_point *p)
{