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);
|
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 - Elliptic curve context
|
||||||
*
|
*
|
||||||
|
@ -757,6 +766,16 @@ int crypto_ec_point_solve_y_coord(struct crypto_ec *e,
|
||||||
struct crypto_ec_point *p,
|
struct crypto_ec_point *p,
|
||||||
const struct crypto_bignum *x, int y_bit);
|
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
|
* crypto_ec_point_is_at_infinity - Check whether EC point is neutral element
|
||||||
* @e: EC context from crypto_ec_init()
|
* @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
|
#ifdef CONFIG_ECC
|
||||||
|
|
||||||
struct crypto_ec {
|
struct crypto_ec {
|
||||||
|
@ -1114,6 +1150,8 @@ struct crypto_ec {
|
||||||
BN_CTX *bnctx;
|
BN_CTX *bnctx;
|
||||||
BIGNUM *prime;
|
BIGNUM *prime;
|
||||||
BIGNUM *order;
|
BIGNUM *order;
|
||||||
|
BIGNUM *a;
|
||||||
|
BIGNUM *b;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct crypto_ec * crypto_ec_init(int group)
|
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->group = EC_GROUP_new_by_curve_name(nid);
|
||||||
e->prime = BN_new();
|
e->prime = BN_new();
|
||||||
e->order = BN_new();
|
e->order = BN_new();
|
||||||
|
e->a = BN_new();
|
||||||
|
e->b = BN_new();
|
||||||
if (e->group == NULL || e->bnctx == NULL || e->prime == NULL ||
|
if (e->group == NULL || e->bnctx == NULL || e->prime == NULL ||
|
||||||
e->order == NULL ||
|
e->order == NULL || e->a == NULL || e->b == NULL ||
|
||||||
!EC_GROUP_get_curve_GFp(e->group, e->prime, NULL, NULL, e->bnctx) ||
|
!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)) {
|
!EC_GROUP_get_order(e->group, e->order, e->bnctx)) {
|
||||||
crypto_ec_deinit(e);
|
crypto_ec_deinit(e);
|
||||||
e = NULL;
|
e = NULL;
|
||||||
|
@ -1186,6 +1226,8 @@ void crypto_ec_deinit(struct crypto_ec *e)
|
||||||
{
|
{
|
||||||
if (e == NULL)
|
if (e == NULL)
|
||||||
return;
|
return;
|
||||||
|
BN_clear_free(e->b);
|
||||||
|
BN_clear_free(e->a);
|
||||||
BN_clear_free(e->order);
|
BN_clear_free(e->order);
|
||||||
BN_clear_free(e->prime);
|
BN_clear_free(e->prime);
|
||||||
EC_GROUP_free(e->group);
|
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,
|
int crypto_ec_point_is_at_infinity(struct crypto_ec *e,
|
||||||
const struct crypto_ec_point *p)
|
const struct crypto_ec_point *p)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue