mirror of https://github.com/openssl/openssl.git
ec/ecdsa_ossl.c: revert blinding in ECDSA signature.
Originally suggested solution for "Return Of the Hidden Number Problem" is arguably too expensive. While it has marginal impact on slower curves, none to ~6%, optimized implementations suffer real penalties. Most notably sign with P-256 went more than 2 times[!] slower. Instead, just implement constant-time BN_mod_add_quick. Reviewed-by: Rich Salz <rsalz@openssl.org> Reviewed-by: David Benjamin <davidben@google.com> (Merged from https://github.com/openssl/openssl/pull/6664)
This commit is contained in:
parent
83e034379f
commit
3fc7a9b96c
|
@ -35,16 +35,70 @@ int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* BN_mod_add variant that may be used if both a and b are non-negative and
|
* BN_mod_add variant that may be used if both a and b are non-negative and
|
||||||
* less than m
|
* less than m. The original algorithm was
|
||||||
|
*
|
||||||
|
* if (!BN_uadd(r, a, b))
|
||||||
|
* return 0;
|
||||||
|
* if (BN_ucmp(r, m) >= 0)
|
||||||
|
* return BN_usub(r, r, m);
|
||||||
|
*
|
||||||
|
* which is replaced with addition, subtracting modulus, and conditional
|
||||||
|
* move depending on whether or not subtraction borrowed.
|
||||||
*/
|
*/
|
||||||
|
int bn_mod_add_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
|
||||||
|
const BIGNUM *m)
|
||||||
|
{
|
||||||
|
size_t i, ai, bi, mtop = m->top;
|
||||||
|
BN_ULONG storage[1024 / BN_BITS2];
|
||||||
|
BN_ULONG carry, temp, mask, *rp, *tp = storage;
|
||||||
|
const BN_ULONG *ap, *bp;
|
||||||
|
|
||||||
|
if (bn_wexpand(r, mtop) == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (mtop > sizeof(storage) / sizeof(storage[0])
|
||||||
|
&& (tp = OPENSSL_malloc(mtop * sizeof(BN_ULONG))) == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ap = a->d != NULL ? a->d : tp;
|
||||||
|
bp = b->d != NULL ? b->d : tp;
|
||||||
|
|
||||||
|
for (i = 0, ai = 0, bi = 0, carry = 0; i < mtop;) {
|
||||||
|
mask = (BN_ULONG)0 - ((i - a->top) >> (8 * sizeof(i) - 1));
|
||||||
|
temp = ((ap[ai] & mask) + carry) & BN_MASK2;
|
||||||
|
carry = (temp < carry);
|
||||||
|
|
||||||
|
mask = (BN_ULONG)0 - ((i - b->top) >> (8 * sizeof(i) - 1));
|
||||||
|
tp[i] = ((bp[bi] & mask) + temp) & BN_MASK2;
|
||||||
|
carry += (tp[i] < temp);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
ai += (i - a->dmax) >> (8 * sizeof(i) - 1);
|
||||||
|
bi += (i - b->dmax) >> (8 * sizeof(i) - 1);
|
||||||
|
}
|
||||||
|
rp = r->d;
|
||||||
|
carry -= bn_sub_words(rp, tp, m->d, mtop);
|
||||||
|
for (i = 0; i < mtop; i++) {
|
||||||
|
rp[i] = (carry & tp[i]) | (~carry & rp[i]);
|
||||||
|
((volatile BN_ULONG *)tp)[i] = 0;
|
||||||
|
}
|
||||||
|
r->top = mtop;
|
||||||
|
|
||||||
|
if (tp != storage)
|
||||||
|
OPENSSL_free(tp);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
|
int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
|
||||||
const BIGNUM *m)
|
const BIGNUM *m)
|
||||||
{
|
{
|
||||||
if (!BN_uadd(r, a, b))
|
int ret = bn_mod_add_fixed_top(r, a, b, m);
|
||||||
return 0;
|
|
||||||
if (BN_ucmp(r, m) >= 0)
|
if (ret)
|
||||||
return BN_usub(r, r, m);
|
bn_correct_top(r);
|
||||||
return 1;
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
|
int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
|
||||||
|
|
|
@ -172,8 +172,7 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
|
||||||
EC_KEY *eckey)
|
EC_KEY *eckey)
|
||||||
{
|
{
|
||||||
int ok = 0, i;
|
int ok = 0, i;
|
||||||
BIGNUM *kinv = NULL, *s, *m = NULL, *tmp = NULL, *blind = NULL;
|
BIGNUM *kinv = NULL, *s, *m = NULL, *tmp = NULL;
|
||||||
BIGNUM *blindm = NULL;
|
|
||||||
const BIGNUM *order, *ckinv;
|
const BIGNUM *order, *ckinv;
|
||||||
BN_CTX *ctx = NULL;
|
BN_CTX *ctx = NULL;
|
||||||
const EC_GROUP *group;
|
const EC_GROUP *group;
|
||||||
|
@ -206,18 +205,8 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
|
||||||
}
|
}
|
||||||
s = ret->s;
|
s = ret->s;
|
||||||
|
|
||||||
ctx = BN_CTX_secure_new();
|
if ((ctx = BN_CTX_new()) == NULL ||
|
||||||
if (ctx == NULL) {
|
(tmp = BN_new()) == NULL || (m = BN_new()) == NULL) {
|
||||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
BN_CTX_start(ctx);
|
|
||||||
tmp = BN_CTX_get(ctx);
|
|
||||||
m = BN_CTX_get(ctx);
|
|
||||||
blind = BN_CTX_get(ctx);
|
|
||||||
blindm = BN_CTX_get(ctx);
|
|
||||||
if (blindm == NULL) {
|
|
||||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE);
|
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_MALLOC_FAILURE);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
@ -257,64 +246,18 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (!BN_mod_mul(tmp, priv_key, ret->r, order, ctx)) {
|
||||||
* The normal signature calculation is:
|
|
||||||
*
|
|
||||||
* s := k^-1 * (m + r * priv_key) mod order
|
|
||||||
*
|
|
||||||
* We will blind this to protect against side channel attacks
|
|
||||||
*
|
|
||||||
* s := blind^-1 * k^-1 * (blind * m + blind * r * priv_key) mod order
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Generate a blinding value */
|
|
||||||
do {
|
|
||||||
if (!BN_priv_rand(blind, BN_num_bits(order) - 1,
|
|
||||||
BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY))
|
|
||||||
goto err;
|
|
||||||
} while (BN_is_zero(blind));
|
|
||||||
BN_set_flags(blind, BN_FLG_CONSTTIME);
|
|
||||||
BN_set_flags(blindm, BN_FLG_CONSTTIME);
|
|
||||||
BN_set_flags(tmp, BN_FLG_CONSTTIME);
|
|
||||||
|
|
||||||
/* tmp := blind * priv_key * r mod order */
|
|
||||||
if (!BN_mod_mul(tmp, blind, priv_key, order, ctx)) {
|
|
||||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
|
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if (!BN_mod_mul(tmp, tmp, ret->r, order, ctx)) {
|
if (!BN_mod_add_quick(s, tmp, m, order)) {
|
||||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
|
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* blindm := blind * m mod order */
|
|
||||||
if (!BN_mod_mul(blindm, blind, m, order, ctx)) {
|
|
||||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* s : = (blind * priv_key * r) + (blind * m) mod order */
|
|
||||||
if (!BN_mod_add_quick(s, tmp, blindm, order)) {
|
|
||||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* s := s * k^-1 mod order */
|
|
||||||
if (!BN_mod_mul(s, s, ckinv, order, ctx)) {
|
if (!BN_mod_mul(s, s, ckinv, order, ctx)) {
|
||||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
|
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* s:= s * blind^-1 mod order */
|
|
||||||
if (BN_mod_inverse(blind, blind, order, ctx) == NULL) {
|
|
||||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (!BN_mod_mul(s, s, blind, order, ctx)) {
|
|
||||||
ECerr(EC_F_OSSL_ECDSA_SIGN_SIG, ERR_R_BN_LIB);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BN_is_zero(s)) {
|
if (BN_is_zero(s)) {
|
||||||
/*
|
/*
|
||||||
* if kinv and r have been supplied by the caller, don't
|
* if kinv and r have been supplied by the caller, don't
|
||||||
|
@ -336,9 +279,9 @@ ECDSA_SIG *ossl_ecdsa_sign_sig(const unsigned char *dgst, int dgst_len,
|
||||||
ECDSA_SIG_free(ret);
|
ECDSA_SIG_free(ret);
|
||||||
ret = NULL;
|
ret = NULL;
|
||||||
}
|
}
|
||||||
if (ctx != NULL)
|
|
||||||
BN_CTX_end(ctx);
|
|
||||||
BN_CTX_free(ctx);
|
BN_CTX_free(ctx);
|
||||||
|
BN_clear_free(m);
|
||||||
|
BN_clear_free(tmp);
|
||||||
BN_clear_free(kinv);
|
BN_clear_free(kinv);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,5 +71,7 @@ int bn_mul_mont_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
|
||||||
BN_MONT_CTX *mont, BN_CTX *ctx);
|
BN_MONT_CTX *mont, BN_CTX *ctx);
|
||||||
int bn_to_mont_fixed_top(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont,
|
int bn_to_mont_fixed_top(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont,
|
||||||
BN_CTX *ctx);
|
BN_CTX *ctx);
|
||||||
|
int bn_mod_add_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
|
||||||
|
const BIGNUM *m);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue