Skip to content
This repository was archived by the owner on Mar 14, 2025. It is now read-only.

Commit 11ba23a

Browse files
committed
Prevent side channel leak in Scala::check_overflow
1 parent 91d4b49 commit 11ba23a

File tree

3 files changed

+23
-17
lines changed

3 files changed

+23
-17
lines changed

Cargo.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "libsecp256k1"
33
description = "Pure Rust secp256k1 implementation."
44
license = "Apache-2.0"
5-
version = "0.3.0"
5+
version = "0.4.0"
66
authors = ["Wei Tang <[email protected]>"]
77
repository = "https://github.com/sorpaas/libsecp256k1-rs"
88
keywords = [ "crypto", "ECDSA", "secp256k1", "bitcoin", "no_std" ]
@@ -18,12 +18,17 @@ sha2 = "0.8"
1818
digest = "0.8"
1919
typenum = "1.11"
2020
arrayref = "0.3"
21+
subtle = { version = "2.2", default-features = false }
2122

2223
[dev-dependencies]
2324
secp256k1-test = "0.7"
2425
clear_on_drop = "0.2"
2526
rand-test = { package = "rand", version = "0.4" }
2627

28+
[features]
29+
default = ["std"]
30+
std = ["subtle/std", "rand/std"]
31+
2732
[workspace]
2833
members = [
2934
"./gen/ecmult",

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
unused_variables, non_shorthand_field_patterns,
88
unreachable_code, unused_parens)]
99

10-
#![no_std]
10+
#![cfg_attr(not(feature = "std"), no_std)]
1111

1212
#[macro_use]
1313
mod field;

src/scalar.rs

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use core::ops::{Add, AddAssign, Mul, MulAssign};
2+
use subtle::Choice;
23

34
const SECP256K1_N_0: u32 = 0xD0364141;
45
const SECP256K1_N_1: u32 = 0xBFD25E8C;
@@ -69,21 +70,21 @@ impl Scalar {
6970

7071
#[must_use]
7172
fn check_overflow(&self) -> bool {
72-
let mut yes: bool = false;
73-
let mut no: bool = false;
74-
no = no || (self.0[7] < SECP256K1_N_7); /* No need for a > check. */
75-
no = no || (self.0[6] < SECP256K1_N_6); /* No need for a > check. */
76-
no = no || (self.0[5] < SECP256K1_N_5); /* No need for a > check. */
77-
no = no || (self.0[4] < SECP256K1_N_4);
78-
yes = yes || ((self.0[4] > SECP256K1_N_4) && !no);
79-
no = no || ((self.0[3] < SECP256K1_N_3) && !yes);
80-
yes = yes || ((self.0[3] > SECP256K1_N_3) && !no);
81-
no = no || ((self.0[2] < SECP256K1_N_2) && !yes);
82-
yes = yes || ((self.0[2] > SECP256K1_N_2) && !no);
83-
no = no || ((self.0[1] < SECP256K1_N_1) && !yes);
84-
yes = yes || ((self.0[1] > SECP256K1_N_1) && !no);
85-
yes = yes || ((self.0[0] >= SECP256K1_N_0) && !no);
86-
return yes;
73+
let mut yes: Choice = 0.into();
74+
let mut no: Choice = 0.into();
75+
no |= Choice::from((self.0[7] < SECP256K1_N_7) as u8); /* No need for a > check. */
76+
no |= Choice::from((self.0[6] < SECP256K1_N_6) as u8); /* No need for a > check. */
77+
no |= Choice::from((self.0[5] < SECP256K1_N_5) as u8); /* No need for a > check. */
78+
no |= Choice::from((self.0[4] < SECP256K1_N_4) as u8);
79+
yes |= Choice::from((self.0[4] > SECP256K1_N_4) as u8) & !no;
80+
no |= Choice::from((self.0[3] < SECP256K1_N_3) as u8) & !yes;
81+
yes |= Choice::from((self.0[3] > SECP256K1_N_3) as u8) & !no;
82+
no |= Choice::from((self.0[2] < SECP256K1_N_2) as u8) & !yes;
83+
yes |= Choice::from((self.0[2] > SECP256K1_N_2) as u8) & !no;
84+
no |= Choice::from((self.0[1] < SECP256K1_N_1) as u8) & !yes;
85+
yes |= Choice::from((self.0[1] > SECP256K1_N_1) as u8) & !no;
86+
yes |= Choice::from((self.0[0] >= SECP256K1_N_0) as u8) & !no;
87+
return yes.into();
8788
}
8889

8990
#[must_use]

0 commit comments

Comments
 (0)