Skip to content

Commit e4a871c

Browse files
committed
fix(ci): Use locked version of llvm-cov
A transitive dependency of llvm-cov was published 2025-10-23 that is incompatible with our current Rust version, 1.87. This adds the `--locked` flag so that the tool can successfully install.
1 parent 0364659 commit e4a871c

File tree

2 files changed

+58
-1
lines changed

2 files changed

+58
-1
lines changed

.github/workflows/rust-test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ jobs:
9797
uses: Swatinem/rust-cache@f0deed1e0edfc6a9be95417288c0e1099b1eeec3 # v2.7.7
9898

9999
- name: Install cargo-llvm-cov
100-
run: cargo install cargo-llvm-cov --version 0.5.38
100+
run: cargo install cargo-llvm-cov --version 0.5.38 --locked
101101

102102
- name: Generate coverage
103103
run: cargo llvm-cov --all-features --lcov --output-path lcov.info --ignore-filename-regex "crates/bitwarden-api-"
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
use crate::{CryptoError, SymmetricCryptoKey, utils::stretch_key};
2+
3+
/// Takes the output of a PRF and derives a symmetric key.
4+
///
5+
/// The PRF output must be at least 32 bytes long. If longer, only the first 32
6+
/// bytes will be used, and the remainder is discarded.
7+
pub fn derive_symmetric_key_from_prf(prf: &[u8]) -> Result<SymmetricCryptoKey, CryptoError> {
8+
let (secret, _) = prf.split_at_checked(32).ok_or(CryptoError::InvalidKeyLen)?;
9+
let secret: [u8; 32] = secret.try_into().expect("length to be 32 bytes");
10+
// Don't allow uninitialized PRFs
11+
if secret.iter().all(|b| *b == b'\0') {
12+
return Err(CryptoError::ZeroNumber);
13+
}
14+
Ok(SymmetricCryptoKey::Aes256CbcHmacKey(stretch_key(
15+
&secret.into(),
16+
)?))
17+
}
18+
19+
#[cfg(test)]
20+
mod tests {
21+
use super::*;
22+
23+
#[test]
24+
fn test_prf_succeeds() {
25+
let prf = pseudorandom_bytes(32);
26+
let key = derive_symmetric_key_from_prf(&prf).unwrap();
27+
assert!(matches!(key, SymmetricCryptoKey::Aes256CbcHmacKey(_)));
28+
}
29+
30+
#[test]
31+
fn test_zero_key_fails() {
32+
let prf: Vec<u8> = (0..32).map(|_| 0).collect();
33+
let err = derive_symmetric_key_from_prf(&prf).unwrap_err();
34+
assert!(matches!(err, CryptoError::ZeroNumber));
35+
}
36+
37+
#[test]
38+
fn test_short_prf_fails() {
39+
let prf = pseudorandom_bytes(9);
40+
let err = derive_symmetric_key_from_prf(&prf).unwrap_err();
41+
assert!(matches!(err, CryptoError::InvalidKeyLen));
42+
}
43+
44+
#[test]
45+
fn test_long_prf_truncated_to_proper_length() {
46+
let long_prf = pseudorandom_bytes(33);
47+
let prf = pseudorandom_bytes(32);
48+
let key1 = derive_symmetric_key_from_prf(&long_prf).unwrap();
49+
let key2 = derive_symmetric_key_from_prf(&prf).unwrap();
50+
assert_eq!(key1, key2);
51+
}
52+
53+
/// This returns the same bytes deterministically for a given length.
54+
fn pseudorandom_bytes(len: usize) -> Vec<u8> {
55+
(0..len).map(|x| (x % 255) as u8).collect()
56+
}
57+
}

0 commit comments

Comments
 (0)