crypto: Add functions for computing the Legendre symbol and EC y^2
These are needed to implement side-channel protection for SAE PWE derivation for ECC. Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
9e286d5ea2
commit
16841ab246
2 changed files with 90 additions and 2 deletions
|
@ -613,6 +613,15 @@ int crypto_bignum_is_zero(const struct crypto_bignum *a);
|
|||
*/
|
||||
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
|
||||
*
|
||||
|
@ -757,6 +766,16 @@ int crypto_ec_point_solve_y_coord(struct crypto_ec *e,
|
|||
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()
|
||||
|
|
|
@ -1107,6 +1107,42 @@ int crypto_bignum_is_one(const struct crypto_bignum *a)
|
|||
}
|
||||
|
||||
|
||||
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 {
|
||||
|
@ -1114,6 +1150,8 @@ struct crypto_ec {
|
|||
BN_CTX *bnctx;
|
||||
BIGNUM *prime;
|
||||
BIGNUM *order;
|
||||
BIGNUM *a;
|
||||
BIGNUM *b;
|
||||
};
|
||||
|
||||
struct crypto_ec * crypto_ec_init(int group)
|
||||
|
@ -1170,9 +1208,11 @@ 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;
|
||||
|
@ -1186,6 +1226,8 @@ void crypto_ec_deinit(struct crypto_ec *e)
|
|||
{
|
||||
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);
|
||||
|
@ -1333,6 +1375,33 @@ int crypto_ec_point_solve_y_coord(struct crypto_ec *e,
|
|||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue