Skip to content

Commit 4c84068

Browse files
committed
Merge branch 'km/cose' into km/cose-content-format
2 parents 7358ee6 + e18b3df commit 4c84068

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+330
-308
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ rust-version = "1.75"
1313
homepage = "https://bitwarden.com"
1414
repository = "https://github.com/bitwarden/sdk-internal"
1515
license-file = "LICENSE"
16+
readme = "DISCLAIMER.md"
1617
keywords = ["bitwarden"]
1718

1819
# Define dependencies that are expected to be consistent across all crates

DISCLAIMER.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
This is an internal crate for the Bitwarden SDK. Do not depend on this directly and use the
2+
[`bitwarden`](https://crates.io/crates/bitwarden) crate instead.
3+
4+
This crate does not follow semantic versioning and the public interface may change at any time.

crates/bitwarden-cli/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ version.workspace = true
88
authors.workspace = true
99
edition.workspace = true
1010
rust-version.workspace = true
11+
readme.workspace = true
1112
homepage.workspace = true
1213
repository.workspace = true
1314
license-file.workspace = true

crates/bitwarden-cli/README.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
11
# Bitwarden Cli
22

3-
This is an internal crate for the Bitwarden SDK do not depend on this directly and use the
4-
[`bitwarden`](https://crates.io/crates/bitwarden) crate instead.
5-
6-
This crate does not follow semantic versioning and the public interface may change at any time.
3+
Common utilities for the Bitwarden Password Manager CLI and Secrets Manager CLI.

crates/bitwarden-cli/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#![doc = include_str!("../README.md")]
2+
13
mod color;
24

35
pub use color::{install_color_eyre, Color};

crates/bitwarden-core/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,16 @@ name = "bitwarden-core"
33
description = """
44
Internal crate for the bitwarden crate. Do not use.
55
"""
6-
keywords = ["bitwarden"]
76

87
version.workspace = true
98
authors.workspace = true
109
edition.workspace = true
1110
rust-version.workspace = true
11+
readme.workspace = true
1212
homepage.workspace = true
1313
repository.workspace = true
1414
license-file.workspace = true
15+
keywords.workspace = true
1516

1617
[features]
1718
internal = ["dep:zxcvbn"]

crates/bitwarden-core/README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Bitwarden Core
22

3-
This is an internal crate for the Bitwarden SDK do not depend on this directly and use the
4-
[`bitwarden`](https://crates.io/crates/bitwarden) crate instead.
3+
Contains core functionality used by the feature crates.
54

6-
This crate does not follow semantic versioning and the public interface may change at any time.
5+
<div class="warning">
6+
Generally you should <b>not</b> find yourself needing to edit this crate! When possible, please use the feature crates instead.
7+
</div>

crates/bitwarden-core/src/auth/auth_request.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,8 @@ pub(crate) fn auth_request_decrypt_user_key(
5454
user_key: AsymmetricEncString,
5555
) -> Result<SymmetricCryptoKey, EncryptionSettingsError> {
5656
let key = AsymmetricCryptoKey::from_der(&STANDARD.decode(private_key)?)?;
57-
let mut key: Vec<u8> = user_key.decapsulate_key_unsigned(&key)?;
58-
59-
Ok(SymmetricCryptoKey::try_from(key.as_mut_slice())?)
57+
let key: SymmetricCryptoKey = user_key.decapsulate_key_unsigned(&key)?;
58+
Ok(key)
6059
}
6160

6261
/// Decrypt the user key using the private key generated previously.
@@ -69,8 +68,8 @@ pub(crate) fn auth_request_decrypt_master_key(
6968
use bitwarden_crypto::MasterKey;
7069

7170
let key = AsymmetricCryptoKey::from_der(&STANDARD.decode(private_key)?)?;
72-
let mut master_key: Vec<u8> = master_key.decapsulate_key_unsigned(&key)?;
73-
let master_key = MasterKey::try_from(master_key.as_mut_slice())?;
71+
let master_key: SymmetricCryptoKey = master_key.decapsulate_key_unsigned(&key)?;
72+
let master_key = MasterKey::try_from(&master_key)?;
7473

7574
Ok(master_key.decrypt_user_key(user_key)?)
7675
}
@@ -102,7 +101,7 @@ pub(crate) fn approve_auth_request(
102101
let key = ctx.dangerous_get_symmetric_key(SymmetricKeyId::User)?;
103102

104103
Ok(AsymmetricEncString::encapsulate_key_unsigned(
105-
&key.to_encoded(),
104+
key,
106105
&public_key,
107106
)?)
108107
}
@@ -117,15 +116,20 @@ fn test_auth_request() {
117116
96, 31, 114, 127, 212, 187, 167, 110, 205, 116, 198, 243, 218, 72, 137, 53, 248, 43, 255,
118117
67, 35, 61, 245, 93,
119118
];
119+
let secret = secret.to_vec();
120120

121121
let private_key =
122122
AsymmetricCryptoKey::from_der(&STANDARD.decode(&request.private_key).unwrap()).unwrap();
123123

124-
let encrypted = AsymmetricEncString::encapsulate_key_unsigned(secret, &private_key).unwrap();
124+
let encrypted = AsymmetricEncString::encapsulate_key_unsigned(
125+
&SymmetricCryptoKey::try_from(secret.clone()).unwrap(),
126+
&private_key,
127+
)
128+
.unwrap();
125129

126130
let decrypted = auth_request_decrypt_user_key(request.private_key, encrypted).unwrap();
127131

128-
assert_eq!(&decrypted.to_encoded(), secret);
132+
assert_eq!(decrypted.to_encoded(), secret);
129133
}
130134

131135
#[cfg(test)]

crates/bitwarden-core/src/auth/tde.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ pub(super) fn make_register_tde_keys(
2020
let user_key = UserKey::new(SymmetricCryptoKey::generate());
2121
let key_pair = user_key.make_key_pair()?;
2222

23-
let admin_reset =
24-
AsymmetricEncString::encapsulate_key_unsigned(&user_key.0.to_encoded(), &public_key)?;
23+
let admin_reset = AsymmetricEncString::encapsulate_key_unsigned(&user_key.0, &public_key)?;
2524

2625
let device_key = if remember_device {
2726
Some(DeviceKey::trust_device(&user_key.0)?)

crates/bitwarden-core/src/client/encryption_settings.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ impl EncryptionSettings {
111111

112112
// Decrypt the org keys with the private key
113113
for (org_id, org_enc_key) in org_enc_keys {
114-
ctx.decrypt_symmetric_key_with_asymmetric_key(
114+
ctx.decapsulate_key_unsigned(
115115
AsymmetricKeyId::UserPrivateKey,
116116
SymmetricKeyId::Organization(org_id),
117117
&org_enc_key,

crates/bitwarden-core/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#![doc = include_str!("../README.md")]
2+
13
#[cfg(feature = "uniffi")]
24
uniffi::setup_scaffolding!();
35
#[cfg(feature = "uniffi")]

crates/bitwarden-core/src/mobile/crypto.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ pub(super) fn enroll_admin_password_reset(
375375
let key = ctx.dangerous_get_symmetric_key(SymmetricKeyId::User)?;
376376

377377
Ok(AsymmetricEncString::encapsulate_key_unsigned(
378-
&key.to_encoded(),
378+
key,
379379
&public_key,
380380
)?)
381381
}
@@ -737,7 +737,8 @@ mod tests {
737737
let private_key = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCzLtEUdxfcLxDj84yaGFsVF5hZ8Hjlb08NMQDy1RnBma06I3ZESshLYzVz4r/gegMn9OOltfV/Yxlyvida8oW6qdlfJ7AVz6Oa8pV7BiL40C7b76+oqraQpyYw2HChANB1AhXL9SqWngKmLZwjA7qiCrmcc0kZHeOb4KnKtp9iVvPVs+8veFvKgYO4ba2AAOHKFdR0W55/agXfAy+fWUAkC8mc9ikyJdQWaPV6OZvC2XFkOseBQm9Rynudh3BQpoWiL6w620efe7t5k+02/EyOFJL9f/XEEjM/+Yo0t3LAfkuhHGeKiRST59Xc9hTEmyJTeVXROtz+0fjqOp3xkaObAgMBAAECggEACs4xhnO0HaZhh1/iH7zORMIRXKeyxP2LQiTR8xwN5JJ9wRWmGAR9VasS7EZFTDidIGVME2u/h4s5EqXnhxfO+0gGksVvgNXJ/qw87E8K2216g6ZNo6vSGA7H1GH2voWwejJ4/k/cJug6dz2S402rRAKh2Wong1arYHSkVlQp3diiMa5FHAOSE+Cy09O2ZsaF9IXQYUtlW6AVXFrBEPYH2kvkaPXchh8VETMijo6tbvoKLnUHe+wTaDMls7hy8exjtVyI59r3DNzjy1lNGaGb5QSnFMXR+eHhPZc844Wv02MxC15zKABADrl58gpJyjTl6XpDdHCYGsmGpVGH3X9TQQKBgQDz/9beFjzq59ve6rGwn+EtnQfSsyYT+jr7GN8lNEXb3YOFXBgPhfFIcHRh2R00Vm9w2ApfAx2cd8xm2I6HuvQ1Os7g26LWazvuWY0Qzb+KaCLQTEGH1RnTq6CCG+BTRq/a3J8M4t38GV5TWlzv8wr9U4dl6FR4efjb65HXs1GQ4QKBgQC7/uHfrOTEHrLeIeqEuSl0vWNqEotFKdKLV6xpOvNuxDGbgW4/r/zaxDqt0YBOXmRbQYSEhmO3oy9J6XfE1SUln0gbavZeW0HESCAmUIC88bDnspUwS9RxauqT5aF8ODKN/bNCWCnBM1xyonPOs1oT1nyparJVdQoG//Y7vkB3+wKBgBqLqPq8fKAp3XfhHLfUjREDVoiLyQa/YI9U42IOz9LdxKNLo6p8rgVthpvmnRDGnpUuS+KOWjhdqDVANjF6G3t3DG7WNl8Rh5Gk2H4NhFswfSkgQrjebFLlBy9gjQVCWXt8KSmjvPbiY6q52Aaa8IUjA0YJAregvXxfopxO+/7BAoGARicvEtDp7WWnSc1OPoj6N14VIxgYcI7SyrzE0d/1x3ffKzB5e7qomNpxKzvqrVP8DzG7ydh8jaKPmv1MfF8tpYRy3AhmN3/GYwCnPqT75YYrhcrWcVdax5gmQVqHkFtIQkRSCIftzPLlpMGKha/YBV8c1fvC4LD0NPh/Ynv0gtECgYEAyOZg95/kte0jpgUEgwuMrzkhY/AaUJULFuR5MkyvReEbtSBQwV5tx60+T95PHNiFooWWVXiLMsAgyI2IbkxVR1Pzdri3gWK5CTfqb7kLuaj/B7SGvBa2Sxo478KS5K8tBBBWkITqo+wLC0mn3uZi1dyMWO1zopTA+KtEGF2dtGQ=";
738738
let private_key =
739739
AsymmetricCryptoKey::from_der(&STANDARD.decode(private_key).unwrap()).unwrap();
740-
let decrypted: Vec<u8> = encrypted.decapsulate_key_unsigned(&private_key).unwrap();
740+
let decrypted: SymmetricCryptoKey =
741+
encrypted.decapsulate_key_unsigned(&private_key).unwrap();
741742

742743
let key_store = client.internal.get_key_store();
743744
let ctx = key_store.context();
@@ -746,7 +747,7 @@ mod tests {
746747
.dangerous_get_symmetric_key(SymmetricKeyId::User)
747748
.unwrap();
748749

749-
assert_eq!(&decrypted, &expected.to_encoded())
750+
assert_eq!(decrypted, *expected);
750751
}
751752

752753
#[test]

crates/bitwarden-crypto/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ version.workspace = true
88
authors.workspace = true
99
edition.workspace = true
1010
rust-version.workspace = true
11+
readme.workspace = true
1112
homepage.workspace = true
1213
repository.workspace = true
1314
license-file.workspace = true
@@ -43,7 +44,6 @@ rayon = ">=1.8.1, <2.0"
4344
rsa = ">=0.9.2, <0.10"
4445
schemars = { workspace = true }
4546
serde = { workspace = true }
46-
serde_bytes = "0.11.15"
4747
sha1 = ">=0.10.5, <0.11"
4848
sha2 = ">=0.10.6, <0.11"
4949
subtle = ">=2.5.0, <3.0"

crates/bitwarden-crypto/README.md

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,60 @@
1-
# Bitwarden Crypto
1+
# Bitwarden Cryptographic primitives
22

3-
This is an internal crate for the Bitwarden SDK do not depend on this directly and use the
4-
[`bitwarden`](https://crates.io/crates/bitwarden) crate instead.
3+
This crate contains the cryptographic primitives used throughout the SDK. The general aspiration is
4+
for this crate to handle all the difficult cryptographic operations and expose higher level concepts
5+
to the rest of the SDK.
56

6-
This crate does not follow semantic versioning and the public interface may change at any time.
7+
<div class="warning">
8+
Generally you should <b>not</b> find yourself needing to edit this crate! Everything written
9+
here requires additional care and attention to ensure that the cryptographic primitives are
10+
secure.
11+
</div>
12+
13+
## Example:
14+
15+
```rust
16+
use bitwarden_crypto::{SymmetricCryptoKey, TypedKeyEncryptable, KeyDecryptable, CryptoError};
17+
18+
async fn example() -> Result<(), CryptoError> {
19+
let key = SymmetricCryptoKey::generate();
20+
21+
let data = "Hello, World!".to_owned();
22+
let encrypted = data.clone().encrypt_with_key(&key)?;
23+
let decrypted: String = encrypted.decrypt_with_key(&key)?;
24+
25+
assert_eq!(data, decrypted);
26+
Ok(())
27+
}
28+
```
29+
30+
## Development considerations
31+
32+
This crate is expected to provide long term support for cryptographic operations. To that end, the
33+
following considerations should be taken into account when making changes to this crate:
34+
35+
- Limit public interfaces to the bare minimum.
36+
- Breaking changes should be rare and well communicated.
37+
- Serializable representation of keys and encrypted data must be supported indefinitely as we have
38+
no way to update all data.
39+
40+
### Conventions:
41+
42+
- Pure Functions that deterministically "derive" keys from input are prefixed with `derive_`.
43+
- Functions that generate non deterministically keys are prefixed with `make_`.
44+
45+
### Differences from `clients`
46+
47+
There are some noteworthy differences compared to the other Bitwarden
48+
[clients](https://github.com/bitwarden/clients). These changes are made in an effort to introduce
49+
conventions in how we name things, improve best practices and abstracting away internal complexity.
50+
51+
- `CryptoService.makeSendKey` & `AccessService.createAccessToken` are replaced by the generic
52+
`derive_shareable_key`
53+
- MasterKey operations such as `makeMasterKey` and `hashMasterKey` are moved to the MasterKey
54+
struct.
55+
56+
## Crate features
57+
58+
- `no-memory-hardening` - Disables memory hardening which ensures that allocated memory is zeroed on
59+
drop. This feature primarily exists in case you do not want to use the standard allocator, and we
60+
advise to still define a `global_allocator` using the [`ZeroizingAllocator`].

crates/bitwarden-crypto/src/cose.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
/**
2-
* This file contains private-use constants for COSE encoded key types and algorithms.
3-
*/
4-
use coset::iana;
1+
//! This file contains private-use constants for COSE encoded key types and algorithms.
2+
//! Standardized values from <https://www.iana.org/assignments/cose/cose.xhtml> should always be preferred
3+
//! unless there is a specific reason to use a private-use value.
4+
55
use serde::{Deserialize, Serialize};
66
#[cfg(feature = "wasm")]
77
use tsify_next::Tsify;
88

9+
// XChaCha20 <https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha-03> is used over ChaCha20
10+
// to be able to randomly generate nonces, and to not have to worry about key wearout. Since
11+
// the draft was never published as an RFC, we use a private-use value for the algorithm.
912
pub(crate) const XCHACHA20_POLY1305: i64 = -70000;
1013

11-
pub(crate) const SYMMETRIC_KEY: i64 = iana::SymmetricKeyParameter::K as i64;
12-
1314
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1415
#[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
1516
pub enum ContentFormat {

0 commit comments

Comments
 (0)