Skip to content

Commit 0a211df

Browse files
davidbenAdam Langley
authored andcommitted
Remove BN_FLG_CONSTTIME.
BN_FLG_CONSTTIME is a ridiculous API and easy to mess up (CVE-2016-2178). Instead, code that needs a particular algorithm which preserves secrecy of some arguemnt should call into that algorithm directly. This is never set outside the library and is finally unused within the library! Credit for all this goes almost entirely to Brian Smith. I just took care of the last bits. Note there was one BN_FLG_CONSTTIME check that was still reachable, the BN_mod_inverse in RSA key generation. However, it used the same code in both cases for even moduli and φ(n) is even if n is not a power of two. Traditionally, RSA keys are not powers of two, even though it would make the modular reductions a lot easier. When reviewing, check that I didn't remove a BN_FLG_CONSTTIME that led to a BN_mod_exp(_mont) or BN_mod_inverse call (with the exception of the RSA one mentioned above). They should all go to functions for the algorithms themselves like BN_mod_exp_mont_consttime. This CL shows the checks are a no-op for all our tests: https://boringssl-review.googlesource.com/c/12927/ BUG=125 Change-Id: I19cbb375cc75aac202bd76b51ca098841d84f337 Reviewed-on: https://boringssl-review.googlesource.com/12926 Reviewed-by: Adam Langley <[email protected]>
1 parent d261004 commit 0a211df

File tree

10 files changed

+26
-105
lines changed

10 files changed

+26
-105
lines changed

crypto/bn/bn.c

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -172,12 +172,6 @@ const BIGNUM *BN_value_one(void) {
172172
return &kOne;
173173
}
174174

175-
void BN_with_flags(BIGNUM *out, const BIGNUM *in, int flags) {
176-
OPENSSL_memcpy(out, in, sizeof(BIGNUM));
177-
out->flags &= ~BN_FLG_MALLOCED;
178-
out->flags |= BN_FLG_STATIC_DATA | flags;
179-
}
180-
181175
/* BN_num_bits_word returns the minimum number of bits needed to represent the
182176
* value in |l|. */
183177
unsigned BN_num_bits_word(BN_ULONG l) {
@@ -369,11 +363,3 @@ void bn_correct_top(BIGNUM *bn) {
369363
bn->neg = 0;
370364
}
371365
}
372-
373-
int BN_get_flags(const BIGNUM *bn, int flags) {
374-
return bn->flags & flags;
375-
}
376-
377-
void BN_set_flags(BIGNUM *bn, int flags) {
378-
bn->flags |= flags;
379-
}

crypto/bn/bn_test.cc

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -632,15 +632,6 @@ static bool TestModInv(FileTest *t, BN_CTX *ctx) {
632632
return false;
633633
}
634634

635-
BN_set_flags(a.get(), BN_FLG_CONSTTIME);
636-
637-
if (!ret ||
638-
!BN_mod_inverse(ret.get(), a.get(), m.get(), ctx) ||
639-
!ExpectBIGNUMsEqual(t, "inv(A) (mod M) (constant-time)", mod_inv.get(),
640-
ret.get())) {
641-
return false;
642-
}
643-
644635
return true;
645636
}
646637

crypto/bn/exponentiation.c

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -140,12 +140,6 @@ int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) {
140140
int i, bits, ret = 0;
141141
BIGNUM *v, *rr;
142142

143-
if ((p->flags & BN_FLG_CONSTTIME) != 0) {
144-
/* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */
145-
OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
146-
return 0;
147-
}
148-
149143
BN_CTX_start(ctx);
150144
if (r == a || r == p) {
151145
rr = BN_CTX_get(ctx);
@@ -437,12 +431,6 @@ static int mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
437431
BIGNUM *val[TABLE_SIZE];
438432
BN_RECP_CTX recp;
439433

440-
if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0) {
441-
/* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */
442-
OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
443-
return 0;
444-
}
445-
446434
bits = BN_num_bits(p);
447435

448436
if (bits == 0) {
@@ -593,10 +581,6 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
593581
BIGNUM *val[TABLE_SIZE];
594582
BN_MONT_CTX *new_mont = NULL;
595583

596-
if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0) {
597-
return BN_mod_exp_mont_consttime(rr, a, p, m, ctx, mont);
598-
}
599-
600584
if (!BN_is_odd(m)) {
601585
OPENSSL_PUT_ERROR(BN, BN_R_CALLED_WITH_EVEN_MODULUS);
602586
return 0;

crypto/bn/gcd.c

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -399,10 +399,6 @@ int BN_mod_inverse_odd(BIGNUM *out, int *out_no_inverse, const BIGNUM *a,
399399

400400
BIGNUM *BN_mod_inverse(BIGNUM *out, const BIGNUM *a, const BIGNUM *n,
401401
BN_CTX *ctx) {
402-
int no_inverse;
403-
404-
BIGNUM *a_reduced = NULL;
405-
406402
BIGNUM *new_out = NULL;
407403
if (out == NULL) {
408404
new_out = BN_new();
@@ -414,10 +410,7 @@ BIGNUM *BN_mod_inverse(BIGNUM *out, const BIGNUM *a, const BIGNUM *n,
414410
}
415411

416412
int ok = 0;
417-
418-
int no_branch =
419-
(a->flags & BN_FLG_CONSTTIME) != 0 || (n->flags & BN_FLG_CONSTTIME) != 0;
420-
413+
BIGNUM *a_reduced = NULL;
421414
if (a->neg || BN_ucmp(a, n) >= 0) {
422415
a_reduced = BN_dup(a);
423416
if (a_reduced == NULL) {
@@ -429,7 +422,8 @@ BIGNUM *BN_mod_inverse(BIGNUM *out, const BIGNUM *a, const BIGNUM *n,
429422
a = a_reduced;
430423
}
431424

432-
if (no_branch || !BN_is_odd(n)) {
425+
int no_inverse;
426+
if (!BN_is_odd(n)) {
433427
if (!bn_mod_inverse_general(out, &no_inverse, a, n, ctx)) {
434428
goto err;
435429
}

crypto/bn/montgomery.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,6 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) {
187187
OPENSSL_PUT_ERROR(BN, ERR_R_INTERNAL_ERROR);
188188
return 0;
189189
}
190-
if (BN_get_flags(mod, BN_FLG_CONSTTIME)) {
191-
BN_set_flags(&mont->N, BN_FLG_CONSTTIME);
192-
}
193190

194191
/* Find n0 such that n0 * N == -1 (mod r).
195192
*

crypto/dh/dh.c

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,6 @@ int DH_generate_key(DH *dh) {
258258
int generate_new_key = 0;
259259
BN_CTX *ctx = NULL;
260260
BIGNUM *pub_key = NULL, *priv_key = NULL;
261-
BIGNUM local_priv;
262261

263262
if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
264263
OPENSSL_PUT_ERROR(DH, DH_R_MODULUS_TOO_LARGE);
@@ -317,8 +316,7 @@ int DH_generate_key(DH *dh) {
317316
}
318317
}
319318

320-
BN_with_flags(&local_priv, priv_key, BN_FLG_CONSTTIME);
321-
if (!BN_mod_exp_mont_consttime(pub_key, dh->g, &local_priv, dh->p, ctx,
319+
if (!BN_mod_exp_mont_consttime(pub_key, dh->g, priv_key, dh->p, ctx,
322320
dh->method_mont_p)) {
323321
goto err;
324322
}
@@ -347,7 +345,6 @@ int DH_compute_key(unsigned char *out, const BIGNUM *peers_key, DH *dh) {
347345
BIGNUM *shared_key;
348346
int ret = -1;
349347
int check_result;
350-
BIGNUM local_priv;
351348

352349
if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
353350
OPENSSL_PUT_ERROR(DH, DH_R_MODULUS_TOO_LARGE);
@@ -379,9 +376,8 @@ int DH_compute_key(unsigned char *out, const BIGNUM *peers_key, DH *dh) {
379376
goto err;
380377
}
381378

382-
BN_with_flags(&local_priv, dh->priv_key, BN_FLG_CONSTTIME);
383-
if (!BN_mod_exp_mont_consttime(shared_key, peers_key, &local_priv, dh->p, ctx,
384-
dh->method_mont_p)) {
379+
if (!BN_mod_exp_mont_consttime(shared_key, peers_key, dh->priv_key, dh->p,
380+
ctx, dh->method_mont_p)) {
385381
OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB);
386382
goto err;
387383
}

crypto/dsa/dsa.c

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,6 @@ int DSA_generate_key(DSA *dsa) {
434434
int ok = 0;
435435
BN_CTX *ctx = NULL;
436436
BIGNUM *pub_key = NULL, *priv_key = NULL;
437-
BIGNUM prk;
438437

439438
ctx = BN_CTX_new();
440439
if (ctx == NULL) {
@@ -461,12 +460,9 @@ int DSA_generate_key(DSA *dsa) {
461460
}
462461
}
463462

464-
BN_init(&prk);
465-
BN_with_flags(&prk, priv_key, BN_FLG_CONSTTIME);
466-
467463
if (!BN_MONT_CTX_set_locked(&dsa->method_mont_p, &dsa->method_mont_lock,
468464
dsa->p, ctx) ||
469-
!BN_mod_exp_mont_consttime(pub_key, dsa->g, &prk, dsa->p, ctx,
465+
!BN_mod_exp_mont_consttime(pub_key, dsa->g, priv_key, dsa->p, ctx,
470466
dsa->method_mont_p)) {
471467
goto err;
472468
}
@@ -844,8 +840,6 @@ int DSA_sign_setup(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **out_kinv,
844840
goto err;
845841
}
846842

847-
BN_set_flags(&k, BN_FLG_CONSTTIME);
848-
849843
if (!BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p,
850844
(CRYPTO_MUTEX *)&dsa->method_mont_lock, dsa->p,
851845
ctx) ||
@@ -873,7 +867,6 @@ int DSA_sign_setup(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **out_kinv,
873867
goto err;
874868
}
875869

876-
BN_set_flags(&kq, BN_FLG_CONSTTIME);
877870
if (!BN_mod_exp_mont_consttime(r, dsa->g, &kq, dsa->p, ctx,
878871
dsa->method_mont_p)) {
879872
goto err;

crypto/rsa/rsa_impl.c

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -769,8 +769,6 @@ static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) {
769769
int rsa_default_multi_prime_keygen(RSA *rsa, int bits, int num_primes,
770770
BIGNUM *e_value, BN_GENCB *cb) {
771771
BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *r3 = NULL, *tmp;
772-
BIGNUM local_r0, local_p;
773-
BIGNUM *pr0, *p;
774772
int prime_bits, ok = -1, n = 0, i, j;
775773
BN_CTX *ctx = NULL;
776774
STACK_OF(RSA_additional_prime) *additional_primes = NULL;
@@ -999,9 +997,7 @@ int rsa_default_multi_prime_keygen(RSA *rsa, int bits, int num_primes,
999997
goto err;
1000998
}
1001999
}
1002-
pr0 = &local_r0;
1003-
BN_with_flags(pr0, r0, BN_FLG_CONSTTIME);
1004-
if (!BN_mod_inverse(rsa->d, rsa->e, pr0, ctx)) {
1000+
if (!BN_mod_inverse(rsa->d, rsa->e, r0, ctx)) {
10051001
goto err; /* d */
10061002
}
10071003

@@ -1019,10 +1015,9 @@ int rsa_default_multi_prime_keygen(RSA *rsa, int bits, int num_primes,
10191015
* from constant-time, |bn_mod_inverse_secret_prime| uses the same modular
10201016
* exponentation logic as in RSA private key operations and, if the RSAZ-1024
10211017
* code is enabled, will be optimized for common RSA prime sizes. */
1022-
p = &local_p;
1023-
BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME);
10241018
if (!BN_MONT_CTX_set_locked(&rsa->mont_p, &rsa->lock, rsa->p, ctx) ||
1025-
!bn_mod_inverse_secret_prime(rsa->iqmp, rsa->q, p, ctx, rsa->mont_p)) {
1019+
!bn_mod_inverse_secret_prime(rsa->iqmp, rsa->q, rsa->p, ctx,
1020+
rsa->mont_p)) {
10261021
goto err;
10271022
}
10281023

include/openssl/bn.h

Lines changed: 15 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -194,13 +194,6 @@ OPENSSL_EXPORT void BN_clear(BIGNUM *bn);
194194
/* BN_value_one returns a static BIGNUM with value 1. */
195195
OPENSSL_EXPORT const BIGNUM *BN_value_one(void);
196196

197-
/* BN_with_flags initialises a stack allocated |BIGNUM| with pointers to the
198-
* contents of |in| but with |flags| ORed into the flags field.
199-
*
200-
* Note: the two BIGNUMs share state and so |out| should /not/ be passed to
201-
* |BN_free|. */
202-
OPENSSL_EXPORT void BN_with_flags(BIGNUM *out, const BIGNUM *in, int flags);
203-
204197

205198
/* Basic functions. */
206199

@@ -233,12 +226,6 @@ OPENSSL_EXPORT void BN_set_negative(BIGNUM *bn, int sign);
233226
/* BN_is_negative returns one if |bn| is negative and zero otherwise. */
234227
OPENSSL_EXPORT int BN_is_negative(const BIGNUM *bn);
235228

236-
/* BN_get_flags returns |bn->flags| & |flags|. */
237-
OPENSSL_EXPORT int BN_get_flags(const BIGNUM *bn, int flags);
238-
239-
/* BN_set_flags sets |flags| on |bn|. */
240-
OPENSSL_EXPORT void BN_set_flags(BIGNUM *bn, int flags);
241-
242229

243230
/* Conversion functions. */
244231

@@ -762,11 +749,10 @@ OPENSSL_EXPORT int BN_gcd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
762749
/* BN_mod_inverse sets |out| equal to |a|^-1, mod |n|. If |out| is NULL, a
763750
* fresh BIGNUM is allocated. It returns the result or NULL on error.
764751
*
765-
* If either of |a| or |n| have |BN_FLG_CONSTTIME| set then the operation is
766-
* performed using an algorithm that avoids some branches but which isn't
767-
* constant-time. This function shouldn't be used for secret values, even
768-
* with |BN_FLG_CONSTTIME|; use |BN_mod_inverse_blinded| instead. Or, if
769-
* |n| is guaranteed to be prime, use
752+
* If |n| is even then the operation is performed using an algorithm that avoids
753+
* some branches but which isn't constant-time. This function shouldn't be used
754+
* for secret values; use |BN_mod_inverse_blinded| instead. Or, if |n| is
755+
* guaranteed to be prime, use
770756
* |BN_mod_exp_mont_consttime(out, a, m_minus_2, m, ctx, m_mont)|, taking
771757
* advantage of Fermat's Little Theorem. */
772758
OPENSSL_EXPORT BIGNUM *BN_mod_inverse(BIGNUM *out, const BIGNUM *a,
@@ -775,11 +761,9 @@ OPENSSL_EXPORT BIGNUM *BN_mod_inverse(BIGNUM *out, const BIGNUM *a,
775761
/* BN_mod_inverse_blinded sets |out| equal to |a|^-1, mod |n|, where |n| is the
776762
* Montgomery modulus for |mont|. |a| must be non-negative and must be less
777763
* than |n|. |n| must be greater than 1. |a| is blinded (masked by a random
778-
* value) to protect it against side-channel attacks. |BN_mod_inverse_blinded|
779-
* may or may not ignore the |BN_FLG_CONSTTIME| flag on any/all of its inputs.
780-
* It returns one on success or zero on failure. On failure, if the failure was
781-
* caused by |a| having no inverse mod |n| then |*out_no_inverse| will be set
782-
* to one; otherwise it will be set to zero. */
764+
* value) to protect it against side-channel attacks. On failure, if the failure
765+
* was caused by |a| having no inverse mod |n| then |*out_no_inverse| will be
766+
* set to one; otherwise it will be set to zero. */
783767
int BN_mod_inverse_blinded(BIGNUM *out, int *out_no_inverse, const BIGNUM *a,
784768
const BN_MONT_CTX *mont, BN_CTX *ctx);
785769

@@ -860,9 +844,9 @@ OPENSSL_EXPORT int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
860844
BN_CTX *ctx);
861845

862846
/* BN_mod_exp sets |r| equal to |a|^{|p|} mod |m|. It does so with the best
863-
* algorithm for the values provided and can run in constant time if
864-
* |BN_FLG_CONSTTIME| is set for |p|. It returns one on success or zero
865-
* otherwise. */
847+
* algorithm for the values provided. It returns one on success or zero
848+
* otherwise. The |BN_mod_exp_mont_consttime| variant must be used if the
849+
* exponent is secret. */
866850
OPENSSL_EXPORT int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
867851
const BIGNUM *m, BN_CTX *ctx);
868852

@@ -930,10 +914,11 @@ OPENSSL_EXPORT unsigned BN_num_bits_word(BN_ULONG l);
930914

931915
#define BN_FLG_MALLOCED 0x01
932916
#define BN_FLG_STATIC_DATA 0x02
933-
/* Avoid leaking exponent information through timing. |BN_mod_exp_mont| will
934-
* call |BN_mod_exp_mont_consttime| and |BN_mod_inverse| will call
935-
* |BN_mod_inverse_no_branch|. */
936-
#define BN_FLG_CONSTTIME 0x04
917+
/* |BN_FLG_CONSTTIME| has been removed and intentionally omitted so code relying
918+
* on it will not compile. Consumers outside BoringSSL should use the
919+
* higher-level cryptographic algorithms exposed by other modules. Consumers
920+
* within the library should call the appropriate timing-sensitive algorithm
921+
* directly. */
937922

938923

939924
#if defined(__cplusplus)

util/doc.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ func extractComment(lines []string, lineNo int) (comment []string, rest []string
139139
}
140140

141141
func extractDecl(lines []string, lineNo int) (decl string, rest []string, restLineNo int, err error) {
142-
if len(lines) == 0 {
142+
if len(lines) == 0 || len(lines[0]) == 0 {
143143
return "", lines, lineNo, nil
144144
}
145145

0 commit comments

Comments
 (0)