Skip to content

Commit 5cfa5df

Browse files
authored
Bump crypto-bigint dependency to v0.7.0-rc.12 (#615)
This release migrates from `subtle` to the new `ctutils` library, which should improve constant-time properties. It also brings a new `rand_core` release and the first new `getrandom` series prerelease: v0.4.0-rc.0, which makes it possible to remove the direct dependency on `rand`. I've pulled `getrandom` in through an optional dependency on `crypto-common`, as I'd like to impl the `Generate` trait in a followup. Finally, as noted earlier `crypto-common` has migrated to `ctutils`, so this also removes the direct dependency on `subtle`, replacing it with the same-named types from `ctutils` which act as a mostly drop-in replacement.
1 parent 5d9d004 commit 5cfa5df

File tree

11 files changed

+105
-76
lines changed

11 files changed

+105
-76
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ jobs:
5151
with:
5252
toolchain: ${{ matrix.rust }}
5353
- uses: RustCrypto/actions/cargo-hack-install@master
54-
- run: cargo hack test --release --feature-powerset --exclude-features os_rng,serde
55-
- run: cargo test --release --features os_rng
54+
- run: cargo hack test --release --feature-powerset --exclude-features getrandom,serde
55+
- run: cargo test --release --features getrandom
5656
- run: cargo test --release --features serde
5757

5858
minimal-versions:
@@ -66,7 +66,7 @@ jobs:
6666
- uses: dtolnay/rust-toolchain@nightly
6767
- run: cargo update -Z minimal-versions
6868
- uses: dtolnay/rust-toolchain@stable
69-
- run: cargo test --release --features os_rng,serde,pkcs5
69+
- run: cargo test --release --features getrandom,serde,pkcs5
7070

7171
nightly:
7272
runs-on: ubuntu-latest

Cargo.lock

Lines changed: 57 additions & 28 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,31 +15,30 @@ exclude = ["marvin_toolkit/", "thirdparty/"]
1515

1616
[dependencies]
1717
const-oid = { version = "0.10", default-features = false }
18-
crypto-bigint = { version = "0.7.0-rc.10", default-features = false, features = ["zeroize", "alloc"] }
19-
crypto-primes = { version = "0.7.0-pre.4", default-features = false }
18+
crypto-bigint = { version = "0.7.0-rc.12", default-features = false, features = ["zeroize", "alloc"] }
19+
crypto-primes = { version = "0.7.0-dev", default-features = false }
2020
digest = { version = "0.11.0-rc.4", default-features = false, features = ["alloc", "oid"] }
2121
rand_core = { version = "0.10.0-rc-2", default-features = false }
2222
signature = { version = "3.0.0-rc.5", default-features = false, features = ["alloc", "digest", "rand_core"] }
23-
subtle = { version = "2.6.1", default-features = false }
2423
zeroize = { version = "1.8", features = ["alloc"] }
2524

2625
# optional dependencies
26+
crypto-common = { version = "0.2.0-rc.8", optional = true, features = ["getrandom"] }
2727
pkcs1 = { version = "0.8.0-rc.3", optional = true, default-features = false, features = ["alloc", "pem"] }
2828
pkcs8 = { version = "0.11.0-rc.8", optional = true, default-features = false, features = ["alloc", "pem"] }
2929
serdect = { version = "0.4", optional = true }
3030
sha1 = { version = "0.11.0-rc.3", optional = true, default-features = false, features = ["oid"] }
3131
sha2 = { version = "0.11.0-rc.3", optional = true, default-features = false, features = ["oid"] }
3232
spki = { version = "0.8.0-rc.4", optional = true, default-features = false, features = ["alloc"] }
3333
serde = { version = "1.0.184", optional = true, default-features = false, features = ["derive"] }
34-
rand = { version = "0.10.0-rc.1", optional = true, default-features = false }
3534

3635
[dev-dependencies]
3736
base64ct = { version = "1", features = ["alloc"] }
3837
hex-literal = "1"
3938
proptest = "1"
4039
serde_test = "1.0.89"
41-
rand = { version = "0.10.0-rc.1", features = ["chacha"] }
42-
rand_core = { version = "0.10.0-rc-2", default-features = false }
40+
rand = { version = "0.10.0-rc.5", features = ["chacha"] }
41+
rand_core = { version = "0.10.0-rc-3", default-features = false }
4342
sha1 = { version = "0.11.0-rc.3", default-features = false, features = ["oid"] }
4443
sha2 = { version = "0.11.0-rc.3", default-features = false, features = ["oid"] }
4544
sha3 = { version = "0.11.0-rc.3", default-features = false, features = ["oid"] }
@@ -55,10 +54,10 @@ name = "key"
5554
default = ["std", "encoding"]
5655
encoding = ["dep:pkcs1", "dep:pkcs8", "dep:spki"]
5756
hazmat = []
58-
os_rng = ["crypto-bigint/rand_core", "rand/os_rng"]
57+
getrandom = ["crypto-bigint/getrandom", "crypto-common"]
5958
serde = ["encoding", "dep:serde", "dep:serdect", "crypto-bigint/serde"]
6059
pkcs5 = ["pkcs8/encryption"]
61-
std = ["pkcs1?/std", "pkcs8?/std", "crypto-bigint/rand"]
60+
std = ["pkcs1?/std", "pkcs8?/std"]
6261

6362
[package.metadata.docs.rs]
6463
features = ["std", "serde", "hazmat", "sha2"]
@@ -69,3 +68,7 @@ opt-level = 2
6968

7069
[profile.bench]
7170
debug = true
71+
72+
[patch.crates-io]
73+
crypto-primes = { git = "https://github.com/tarcieri/crypto-primes", branch = "crypto-bigint/v0.7.0-rc.12" }
74+
rand = { git = "https://github.com/rust-random/rand" }

src/algorithms/oaep.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
use alloc::boxed::Box;
44
use alloc::vec::Vec;
55

6+
use crypto_bigint::{Choice, CtEq, CtOption, CtSelect};
67
use digest::{Digest, FixedOutputReset};
78
use rand_core::TryCryptoRng;
8-
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
99
use zeroize::Zeroizing;
1010

1111
use super::mgf::{mgf1_xor, mgf1_xor_digest};
@@ -242,14 +242,14 @@ fn decrypt_inner<MGF: FnMut(&mut [u8], &mut [u8])>(
242242
// looking_for_index: 1 if we are still looking for the 0x01
243243
// index: the offset of the first 0x01 byte
244244
// zero_before_one: 1 if we saw a non-zero byte before the 1
245-
let mut looking_for_index = Choice::from(1u8);
245+
let mut looking_for_index = Choice::TRUE;
246246
let mut index = 0u32;
247-
let mut nonzero_before_one = Choice::from(0u8);
247+
let mut nonzero_before_one = Choice::FALSE;
248248

249249
for (i, el) in db.iter().skip(h_size).enumerate() {
250250
let equals0 = el.ct_eq(&0u8);
251251
let equals1 = el.ct_eq(&1u8);
252-
index.conditional_assign(&(i as u32), looking_for_index & equals1);
252+
index.ct_assign(&(i as u32), looking_for_index & equals1);
253253
looking_for_index &= !equals1;
254254
nonzero_before_one |= looking_for_index & !equals0;
255255
}

src/algorithms/pkcs1v15.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
99
use alloc::vec::Vec;
1010
use const_oid::AssociatedOid;
11+
use crypto_bigint::{Choice, CtEq, CtSelect};
1112
use digest::Digest;
1213
use rand_core::TryCryptoRng;
13-
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq};
1414
use zeroize::Zeroizing;
1515

1616
use crate::errors::{Error, Result};
@@ -99,8 +99,8 @@ fn decrypt_inner(em: Vec<u8>, k: usize) -> Result<(u8, Vec<u8>, u32)> {
9999

100100
for (i, el) in em.iter().enumerate().skip(2) {
101101
let equals0 = el.ct_eq(&0u8);
102-
index.conditional_assign(&(i as u32), Choice::from(looking_for_index) & equals0);
103-
looking_for_index.conditional_assign(&0u8, equals0);
102+
index.ct_assign(&(i as u32), Choice::new(looking_for_index) & equals0);
103+
looking_for_index.ct_assign(&0u8, equals0);
104104
}
105105

106106
// The PS padding must be at least 8 bytes long, and it starts two
@@ -109,12 +109,12 @@ fn decrypt_inner(em: Vec<u8>, k: usize) -> Result<(u8, Vec<u8>, u32)> {
109109
// Ref: https://github.com/dalek-cryptography/subtle/issues/20
110110
// This is currently copy & paste from the constant time impl in
111111
// go, but very likely not sufficient.
112-
let valid_ps = Choice::from((((2i32 + 8i32 - index as i32 - 1i32) >> 31) & 1) as u8);
112+
let valid_ps = Choice::new((((2i32 + 8i32 - index as i32 - 1i32) >> 31) & 1) as u8);
113113
let valid =
114-
first_byte_is_zero & second_byte_is_two & Choice::from(!looking_for_index & 1) & valid_ps;
115-
index = u32::conditional_select(&0, &(index + 1), valid);
114+
first_byte_is_zero & second_byte_is_two & Choice::new(!looking_for_index & 1) & valid_ps;
115+
index = u32::ct_select(&0, &(index + 1), valid);
116116

117-
Ok((valid.unwrap_u8(), em, index))
117+
Ok((valid.to_u8(), em, index))
118118
}
119119

120120
#[inline]
@@ -155,7 +155,8 @@ pub(crate) fn pkcs1v15_sign_unpad(prefix: &[u8], hashed: &[u8], em: &[u8], k: us
155155
ok &= el.ct_eq(&0xff)
156156
}
157157

158-
if ok.unwrap_u8() != 1 {
158+
// TODO(tarcieri): avoid branching here by e.g. using a pseudorandom rejection symbol
159+
if !ok.to_bool() {
159160
return Err(Error::Verification);
160161
}
161162

0 commit comments

Comments
 (0)