Skip to content

Commit 79eb8c4

Browse files
dani-garciaquexten
andauthored
[PM-18102] Use opaque autogenerated local key ids (#274)
## 🎟️ Tracking https://bitwarden.atlassian.net/browse/PM-18102 ## 📔 Objective Currently any function that adds/decrypts a key needs to provide the KeyId under which it can be stored. This is fairly cumbersome and error prone as it can lead to accidentally using the wrong key. This PR changes all the functions that store a key in a context to instead generate and return a unique ID, which simplifies the code and makes the code less error prone. ## ⏰ Reminders before review - Contributor guidelines followed - All formatters and local linters executed and passed - Written new unit and / or integration tests where applicable - Protected functional changes with optionality (feature flags) - Used internationalization (i18n) for all UI strings - CI builds passed - Communicated to DevOps any deployment requirements - Updated any necessary documentation (Confluence, contributing docs) or informed the documentation team ## 🦮 Reviewer guidelines <!-- Suggested interactions but feel free to use (or not) as you desire! --> - 👍 (`:+1:`) or similar for great changes - 📝 (`:memo:`) or ℹ️ (`:information_source:`) for notes or general info - ❓ (`:question:`) for questions - 🤔 (`:thinking:`) or 💭 (`:thought_balloon:`) for more open inquiry that's not quite a confirmed issue and could potentially benefit from discussion - 🎨 (`:art:`) for suggestions / improvements - ❌ (`:x:`) or ⚠️ (`:warning:`) for more significant problems or concerns needing attention - 🌱 (`:seedling:`) or ♻️ (`:recycle:`) for future improvements or indications of technical debt - ⛏ (`:pick:`) for minor or nitpick changes --------- Co-authored-by: Bernd Schoolmann <[email protected]>
1 parent d553d37 commit 79eb8c4

File tree

20 files changed

+196
-237
lines changed

20 files changed

+196
-237
lines changed

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -358,10 +358,9 @@ impl InternalClient {
358358
let decrypted_user_key = {
359359
// Note: This block ensures ctx is dropped. Otherwise it would cause a deadlock when
360360
// initializing the user crypto
361-
use crate::key_management::SymmetricKeyId;
362361
let ctx = &mut self.key_store.context_mut();
363362
let decrypted_user_key_id = pin_protected_user_key_envelope
364-
.unseal(SymmetricKeyId::Local("tmp_unlock_pin"), &pin, ctx)
363+
.unseal(&pin, ctx)
365364
.map_err(|_| EncryptionSettingsError::WrongPin)?;
366365

367366
// Allowing deprecated here, until a refactor to pass the Local key ids to

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

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -724,8 +724,6 @@ pub(crate) fn make_v2_keys_for_v1_user(
724724
let key_store = client.internal.get_key_store();
725725
let mut ctx = key_store.context();
726726

727-
let temporary_user_key_id = SymmetricKeyId::Local("temporary_user_key");
728-
let temporary_signing_key_id = SigningKeyId::Local("temporary_signing_key");
729727
// Re-use existing private key
730728
let private_key_id = AsymmetricKeyId::UserPrivateKey;
731729

@@ -751,13 +749,10 @@ pub(crate) fn make_v2_keys_for_v1_user(
751749

752750
// New user key
753751
let user_key = SymmetricCryptoKey::make_xchacha20_poly1305_key();
754-
#[allow(deprecated)]
755-
ctx.set_symmetric_key(temporary_user_key_id, user_key.clone())?;
756752

757753
// New signing key
758754
let signing_key = SigningKey::make(SignatureAlgorithm::Ed25519);
759-
#[allow(deprecated)]
760-
ctx.set_signing_key(temporary_signing_key_id, signing_key.clone())?;
755+
let temporary_signing_key_id = ctx.add_local_signing_key(signing_key.clone())?;
761756

762757
// Sign existing public key
763758
let signed_public_key = ctx.make_signed_public_key(private_key_id, temporary_signing_key_id)?;

crates/bitwarden-core/src/key_management/crypto_client.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,7 @@ impl CryptoClient {
131131
envelope: PasswordProtectedKeyEnvelope,
132132
) -> Result<Vec<u8>, CryptoClientError> {
133133
let mut ctx = self.client.internal.get_key_store().context_mut();
134-
let key_slot = SymmetricKeyId::Local("unseal_password_protected_key_envelope");
135-
envelope.unseal(key_slot, pin.as_str(), &mut ctx)?;
134+
let key_slot = envelope.unseal(pin.as_str(), &mut ctx)?;
136135
#[allow(deprecated)]
137136
let key = ctx.dangerous_get_symmetric_key(key_slot)?;
138137
Ok(key.to_encoded().to_vec())

crates/bitwarden-core/src/key_management/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,21 +47,21 @@ key_ids! {
4747
User,
4848
Organization(OrganizationId),
4949
#[local]
50-
Local(&'static str),
50+
Local(LocalId),
5151
}
5252

5353
#[asymmetric]
5454
pub enum AsymmetricKeyId {
5555
UserPrivateKey,
5656
#[local]
57-
Local(&'static str),
57+
Local(LocalId),
5858
}
5959

6060
#[signing]
6161
pub enum SigningKeyId {
6262
UserSigningKey,
6363
#[local]
64-
Local(&'static str),
64+
Local(LocalId),
6565
}
6666

6767
pub KeyIds => SymmetricKeyId, AsymmetricKeyId, SigningKeyId;

crates/bitwarden-core/src/key_management/security_state.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ mod tests {
151151
use bitwarden_crypto::{KeyStore, SignatureAlgorithm, SigningKey};
152152

153153
use super::*;
154-
use crate::key_management::{KeyIds, SigningKeyId};
154+
use crate::key_management::KeyIds;
155155

156156
#[test]
157157
fn test_security_state_signing() {
@@ -161,12 +161,8 @@ mod tests {
161161
let user_id = UserId::new_v4();
162162
let security_state = SecurityState::initialize_for_user(user_id);
163163
let signing_key = SigningKey::make(SignatureAlgorithm::Ed25519);
164-
#[allow(deprecated)]
165-
ctx.set_signing_key(SigningKeyId::Local(""), signing_key.clone())
166-
.unwrap();
167-
let signed_security_state = security_state
168-
.sign(SigningKeyId::Local(""), &mut ctx)
169-
.unwrap();
164+
let key = ctx.add_local_signing_key(signing_key.clone()).unwrap();
165+
let signed_security_state = security_state.sign(key, &mut ctx).unwrap();
170166

171167
let verifying_key = signing_key.to_verifying_key();
172168
let verified_security_state = signed_security_state

crates/bitwarden-crypto/examples/protect_key_with_password.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,7 @@ fn main() {
2020

2121
// Alice has a vault protected with a symmetric key. She wants the symmetric key protected with
2222
// a PIN.
23-
let vault_key = ctx
24-
.generate_symmetric_key(ExampleSymmetricKey::VaultKey)
25-
.expect("Generating vault key should work");
23+
let vault_key = ctx.generate_symmetric_key();
2624

2725
// Seal the key with the PIN
2826
// The KDF settings are chosen for you, and do not need to be separately tracked or synced
@@ -43,7 +41,7 @@ fn main() {
4341
)
4442
.expect("Deserializing envelope should work");
4543
deserialized
46-
.unseal(ExampleSymmetricKey::VaultKey, pin, &mut ctx)
44+
.unseal(pin, &mut ctx)
4745
.expect("Unsealing should work");
4846

4947
// Alice wants to change her password; also her KDF settings are below the minimums.
@@ -54,15 +52,14 @@ fn main() {
5452
disk.save("vault_key_envelope", (&envelope).into());
5553

5654
// Alice wants to change the protected key. This requires creating a new envelope
57-
ctx.generate_symmetric_key(ExampleSymmetricKey::VaultKey)
58-
.expect("Generating vault key should work");
59-
let envelope = PasswordProtectedKeyEnvelope::seal(ExampleSymmetricKey::VaultKey, "0000", &ctx)
60-
.expect("Sealing should work");
55+
let vault_key = ctx.generate_symmetric_key();
56+
let envelope =
57+
PasswordProtectedKeyEnvelope::seal(vault_key, "0000", &ctx).expect("Sealing should work");
6158
disk.save("vault_key_envelope", (&envelope).into());
6259

6360
// Alice tries the password but it is wrong
6461
assert!(matches!(
65-
envelope.unseal(ExampleSymmetricKey::VaultKey, "9999", &mut ctx),
62+
envelope.unseal("9999", &mut ctx),
6663
Err(PasswordProtectedKeyEnvelopeError::WrongPassword)
6764
));
6865
}
@@ -91,17 +88,21 @@ key_ids! {
9188
#[symmetric]
9289
pub enum ExampleSymmetricKey {
9390
#[local]
94-
VaultKey
91+
VaultKey(LocalId)
9592
}
9693

9794
#[asymmetric]
9895
pub enum ExampleAsymmetricKey {
9996
Key(u8),
97+
#[local]
98+
Local(LocalId)
10099
}
101100

102101
#[signing]
103102
pub enum ExampleSigningKey {
104103
Key(u8),
104+
#[local]
105+
Local(LocalId)
105106
}
106107

107108
pub ExampleIds => ExampleSymmetricKey, ExampleAsymmetricKey, ExampleSigningKey;

crates/bitwarden-crypto/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ pub use signing::*;
4242
mod traits;
4343
mod xchacha20;
4444
pub use traits::{
45-
CompositeEncryptable, Decryptable, IdentifyKey, KeyId, KeyIds, PrimitiveEncryptable,
45+
CompositeEncryptable, Decryptable, IdentifyKey, KeyId, KeyIds, LocalId, PrimitiveEncryptable,
4646
};
4747
pub use zeroizing_alloc::ZeroAlloc as ZeroizingAllocator;
4848

crates/bitwarden-crypto/src/safe/password_protected_key_envelope.rs

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -139,15 +139,11 @@ impl<Ids: KeyIds> PasswordProtectedKeyEnvelope<Ids> {
139139
/// context.
140140
pub fn unseal(
141141
&self,
142-
target_keyslot: Ids::Symmetric,
143142
password: &str,
144143
ctx: &mut KeyStoreContext<Ids>,
145144
) -> Result<Ids::Symmetric, PasswordProtectedKeyEnvelopeError> {
146145
let key = self.unseal_ref(password)?;
147-
#[allow(deprecated)]
148-
ctx.set_symmetric_key(target_keyslot, key)
149-
.map_err(|_| PasswordProtectedKeyEnvelopeError::KeyStore)?;
150-
Ok(target_keyslot)
146+
Ok(ctx.add_local_symmetric_key(key))
151147
}
152148

153149
fn unseal_ref(
@@ -501,12 +497,12 @@ mod tests {
501497
let envelope =
502498
PasswordProtectedKeyEnvelope::try_from(&TESTVECTOR_COSEKEY_ENVELOPE.to_vec())
503499
.expect("Key envelope should be valid");
504-
envelope
505-
.unseal(TestSymmKey::A(0), TESTVECTOR_PASSWORD, &mut ctx)
500+
let key = envelope
501+
.unseal(TESTVECTOR_PASSWORD, &mut ctx)
506502
.expect("Unsealing should succeed");
507503
#[allow(deprecated)]
508504
let unsealed_key = ctx
509-
.dangerous_get_symmetric_key(TestSymmKey::A(0))
505+
.dangerous_get_symmetric_key(key)
510506
.expect("Key should exist in the key store");
511507
assert_eq!(
512508
unsealed_key.to_encoded().to_vec(),
@@ -521,12 +517,12 @@ mod tests {
521517
let envelope =
522518
PasswordProtectedKeyEnvelope::try_from(&TESTVECTOR_LEGACYKEY_ENVELOPE.to_vec())
523519
.expect("Key envelope should be valid");
524-
envelope
525-
.unseal(TestSymmKey::A(0), TESTVECTOR_PASSWORD, &mut ctx)
520+
let key = envelope
521+
.unseal(TESTVECTOR_PASSWORD, &mut ctx)
526522
.expect("Unsealing should succeed");
527523
#[allow(deprecated)]
528524
let unsealed_key = ctx
529-
.dangerous_get_symmetric_key(TestSymmKey::A(0))
525+
.dangerous_get_symmetric_key(key)
530526
.expect("Key should exist in the key store");
531527
assert_eq!(
532528
unsealed_key.to_encoded().to_vec(),
@@ -549,14 +545,12 @@ mod tests {
549545
// Unseal the key from the envelope
550546
let deserialized: PasswordProtectedKeyEnvelope<TestIds> =
551547
PasswordProtectedKeyEnvelope::try_from(&serialized).unwrap();
552-
deserialized
553-
.unseal(TestSymmKey::A(1), password, &mut ctx)
554-
.unwrap();
548+
let key = deserialized.unseal(password, &mut ctx).unwrap();
555549

556550
// Verify that the unsealed key matches the original key
557551
#[allow(deprecated)]
558552
let unsealed_key = ctx
559-
.dangerous_get_symmetric_key(TestSymmKey::A(1))
553+
.dangerous_get_symmetric_key(key)
560554
.expect("Key should exist in the key store");
561555

562556
#[allow(deprecated)]
@@ -571,7 +565,7 @@ mod tests {
571565
fn test_make_envelope_legacy_key() {
572566
let key_store = KeyStore::<TestIds>::default();
573567
let mut ctx: KeyStoreContext<'_, TestIds> = key_store.context_mut();
574-
let test_key = ctx.generate_symmetric_key(TestSymmKey::A(0)).unwrap();
568+
let test_key = ctx.generate_symmetric_key();
575569

576570
let password = "test_password";
577571

@@ -582,14 +576,12 @@ mod tests {
582576
// Unseal the key from the envelope
583577
let deserialized: PasswordProtectedKeyEnvelope<TestIds> =
584578
PasswordProtectedKeyEnvelope::try_from(&serialized).unwrap();
585-
deserialized
586-
.unseal(TestSymmKey::A(1), password, &mut ctx)
587-
.unwrap();
579+
let key = deserialized.unseal(password, &mut ctx).unwrap();
588580

589581
// Verify that the unsealed key matches the original key
590582
#[allow(deprecated)]
591583
let unsealed_key = ctx
592-
.dangerous_get_symmetric_key(TestSymmKey::A(1))
584+
.dangerous_get_symmetric_key(key)
593585
.expect("Key should exist in the key store");
594586

595587
#[allow(deprecated)]
@@ -638,7 +630,7 @@ mod tests {
638630
let deserialized: PasswordProtectedKeyEnvelope<TestIds> =
639631
PasswordProtectedKeyEnvelope::try_from(&(&envelope).into()).unwrap();
640632
assert!(matches!(
641-
deserialized.unseal(TestSymmKey::A(1), wrong_password, &mut ctx),
633+
deserialized.unseal(wrong_password, &mut ctx),
642634
Err(PasswordProtectedKeyEnvelopeError::WrongPassword)
643635
));
644636
}

0 commit comments

Comments
 (0)