Skip to content

Commit 392dcb3

Browse files
committed
Fix timing side-channel in ECDSA signature computation
There is a timing signal of around 300 nanoseconds when the top word of the inverted ECDSA nonce value is zero. This can happen with significant probability only for some of the supported elliptic curves. In particular the NIST P-521 curve is affected. To be able to measure this leak, the attacker process must either be located in the same physical computer or must have a very fast network connection with low latency. Attacks on ECDSA nonce are also known as Minerva attack. Fixes CVE-2024-13176 Reviewed-by: Tim Hudson <tjh@openssl.org> Reviewed-by: Neil Horman <nhorman@openssl.org> Reviewed-by: Paul Dale <ppzgs1@gmail.com> (Merged from #26429) (cherry picked from commit 63c40a6)
1 parent 71e8158 commit 392dcb3

File tree

3 files changed

+22
-9
lines changed

3 files changed

+22
-9
lines changed

crypto/bn/bn_exp.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,7 @@ static int MOD_EXP_CTIME_COPY_FROM_PREBUF(BIGNUM *b, int top,
606606
* out by Colin Percival,
607607
* http://www.daemonology.net/hyperthreading-considered-harmful/)
608608
*/
609-
int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
609+
int bn_mod_exp_mont_fixed_top(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
610610
const BIGNUM *m, BN_CTX *ctx,
611611
BN_MONT_CTX *in_mont)
612612
{
@@ -623,10 +623,6 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
623623
unsigned int t4 = 0;
624624
#endif
625625

626-
bn_check_top(a);
627-
bn_check_top(p);
628-
bn_check_top(m);
629-
630626
if (!BN_is_odd(m)) {
631627
ERR_raise(ERR_LIB_BN, BN_R_CALLED_WITH_EVEN_MODULUS);
632628
return 0;
@@ -1146,7 +1142,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
11461142
goto err;
11471143
} else
11481144
#endif
1149-
if (!BN_from_montgomery(rr, &tmp, mont, ctx))
1145+
if (!bn_from_mont_fixed_top(rr, &tmp, mont, ctx))
11501146
goto err;
11511147
ret = 1;
11521148
err:
@@ -1160,6 +1156,19 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
11601156
return ret;
11611157
}
11621158

1159+
int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
1160+
const BIGNUM *m, BN_CTX *ctx,
1161+
BN_MONT_CTX *in_mont)
1162+
{
1163+
bn_check_top(a);
1164+
bn_check_top(p);
1165+
bn_check_top(m);
1166+
if (!bn_mod_exp_mont_fixed_top(rr, a, p, m, ctx, in_mont))
1167+
return 0;
1168+
bn_correct_top(rr);
1169+
return 1;
1170+
}
1171+
11631172
int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p,
11641173
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont)
11651174
{

crypto/ec/ec_lib.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <openssl/opensslv.h>
2222
#include <openssl/param_build.h>
2323
#include "crypto/ec.h"
24+
#include "crypto/bn.h"
2425
#include "internal/nelem.h"
2526
#include "ec_local.h"
2627

@@ -1261,10 +1262,10 @@ static int ec_field_inverse_mod_ord(const EC_GROUP *group, BIGNUM *r,
12611262
if (!BN_sub(e, group->order, e))
12621263
goto err;
12631264
/*-
1264-
* Exponent e is public.
1265-
* No need for scatter-gather or BN_FLG_CONSTTIME.
1265+
* Although the exponent is public we want the result to be
1266+
* fixed top.
12661267
*/
1267-
if (!BN_mod_exp_mont(r, x, e, group->order, ctx, group->mont_data))
1268+
if (!bn_mod_exp_mont_fixed_top(r, x, e, group->order, ctx, group->mont_data))
12681269
goto err;
12691270

12701271
ret = 1;

include/crypto/bn.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ int bn_set_words(BIGNUM *a, const BN_ULONG *words, int num_words);
7373
*/
7474
int bn_mul_mont_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
7575
BN_MONT_CTX *mont, BN_CTX *ctx);
76+
int bn_mod_exp_mont_fixed_top(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
77+
const BIGNUM *m, BN_CTX *ctx,
78+
BN_MONT_CTX *in_mont);
7679
int bn_to_mont_fixed_top(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont,
7780
BN_CTX *ctx);
7881
int bn_from_mont_fixed_top(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont,

0 commit comments

Comments
 (0)