Skip to content

Commit 330bde5

Browse files
committed
Merge branch 'km/cose-key-rotation' into km/account-security-version
2 parents 94a3983 + dd79e68 commit 330bde5

Some content is hidden

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

58 files changed

+1495
-541
lines changed

bitwarden_license/bitwarden-sm/src/projects/create.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use bitwarden_api_api::models::ProjectCreateRequestModel;
22
use bitwarden_core::{key_management::SymmetricKeyId, Client};
3-
use bitwarden_crypto::Encryptable;
3+
use bitwarden_crypto::PrimitiveEncryptable;
44
use schemars::JsonSchema;
55
use serde::{Deserialize, Serialize};
66
use uuid::Uuid;

bitwarden_license/bitwarden-sm/src/projects/update.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use bitwarden_api_api::models::ProjectUpdateRequestModel;
22
use bitwarden_core::{key_management::SymmetricKeyId, Client};
3-
use bitwarden_crypto::Encryptable;
3+
use bitwarden_crypto::PrimitiveEncryptable;
44
use schemars::JsonSchema;
55
use serde::{Deserialize, Serialize};
66
use uuid::Uuid;

bitwarden_license/bitwarden-sm/src/secrets/create.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use bitwarden_api_api::models::SecretCreateRequestModel;
22
use bitwarden_core::{key_management::SymmetricKeyId, Client};
3-
use bitwarden_crypto::Encryptable;
3+
use bitwarden_crypto::PrimitiveEncryptable;
44
use schemars::JsonSchema;
55
use serde::{Deserialize, Serialize};
66
use uuid::Uuid;

bitwarden_license/bitwarden-sm/src/secrets/update.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use bitwarden_api_api::models::SecretUpdateRequestModel;
22
use bitwarden_core::{key_management::SymmetricKeyId, Client};
3-
use bitwarden_crypto::Encryptable;
3+
use bitwarden_crypto::PrimitiveEncryptable;
44
use schemars::JsonSchema;
55
use serde::{Deserialize, Serialize};
66
use uuid::Uuid;

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use crate::{
2626
RegisterRequest,
2727
},
2828
client::encryption_settings::EncryptionSettingsError,
29+
Base64String,
2930
};
3031
use crate::{
3132
auth::{login::LoginError, renew::renew_token},
@@ -89,7 +90,7 @@ impl AuthClient {
8990
pub fn make_register_tde_keys(
9091
&self,
9192
email: String,
92-
org_public_key: String,
93+
org_public_key: Base64String,
9394
remember_device: bool,
9495
) -> Result<RegisterTdeKeyResponse, EncryptionSettingsError> {
9596
make_register_tde_keys(&self.client, email, org_public_key, remember_device)
@@ -172,7 +173,7 @@ impl AuthClient {
172173
#[allow(missing_docs)]
173174
pub fn approve_auth_request(
174175
&self,
175-
public_key: String,
176+
public_key: Base64String,
176177
) -> Result<UnsignedSharedKey, ApproveAuthRequestError> {
177178
approve_auth_request(&self.client, public_key)
178179
}

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

Lines changed: 54 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use bitwarden_crypto::{EncString, SymmetricCryptoKey};
88
use thiserror::Error;
99

1010
#[cfg(feature = "internal")]
11-
use crate::client::encryption_settings::EncryptionSettingsError;
11+
use crate::{client::encryption_settings::EncryptionSettingsError, Base64String};
1212
use crate::{key_management::SymmetricKeyId, Client, VaultLockedError};
1313

1414
/// Response for `new_auth_request`.
@@ -49,25 +49,25 @@ pub(crate) fn new_auth_request(email: &str) -> Result<AuthRequestResponse, Crypt
4949
/// Decrypt the user key using the private key generated previously.
5050
#[cfg(feature = "internal")]
5151
pub(crate) fn auth_request_decrypt_user_key(
52-
private_key: String,
52+
private_key: Base64String,
5353
user_key: UnsignedSharedKey,
5454
) -> Result<SymmetricCryptoKey, EncryptionSettingsError> {
55-
let key = AsymmetricCryptoKey::from_der(&STANDARD.decode(private_key)?)?;
56-
let key: SymmetricCryptoKey = user_key.decapsulate_key_unsigned(&key)?;
55+
let private_key = AsymmetricCryptoKey::from_der(&private_key.try_into()?)?;
56+
let key: SymmetricCryptoKey = user_key.decapsulate_key_unsigned(&private_key)?;
5757
Ok(key)
5858
}
5959

6060
/// Decrypt the user key using the private key generated previously.
6161
#[cfg(feature = "internal")]
6262
pub(crate) fn auth_request_decrypt_master_key(
63-
private_key: String,
63+
private_key: Base64String,
6464
master_key: UnsignedSharedKey,
6565
user_key: EncString,
6666
) -> Result<SymmetricCryptoKey, EncryptionSettingsError> {
6767
use bitwarden_crypto::MasterKey;
6868

69-
let key = AsymmetricCryptoKey::from_der(&STANDARD.decode(private_key)?)?;
70-
let master_key: SymmetricCryptoKey = master_key.decapsulate_key_unsigned(&key)?;
69+
let private_key = AsymmetricCryptoKey::from_der(&private_key.try_into()?)?;
70+
let master_key: SymmetricCryptoKey = master_key.decapsulate_key_unsigned(&private_key)?;
7171
let master_key = MasterKey::try_from(&master_key)?;
7272

7373
Ok(master_key.decrypt_user_key(user_key)?)
@@ -89,9 +89,9 @@ pub enum ApproveAuthRequestError {
8989
/// Encrypts the user key with a public key.
9090
pub(crate) fn approve_auth_request(
9191
client: &Client,
92-
public_key: String,
92+
public_key: Base64String,
9393
) -> Result<UnsignedSharedKey, ApproveAuthRequestError> {
94-
let public_key = AsymmetricPublicCryptoKey::from_der(&STANDARD.decode(public_key)?)?;
94+
let public_key = AsymmetricPublicCryptoKey::from_der(&public_key.try_into()?)?;
9595

9696
let key_store = client.internal.get_key_store();
9797
let ctx = key_store.context();
@@ -106,43 +106,46 @@ pub(crate) fn approve_auth_request(
106106
)?)
107107
}
108108

109-
#[test]
110-
fn test_auth_request() {
111-
let request = new_auth_request("[email protected]").unwrap();
112-
113-
let secret = vec![
114-
111, 32, 97, 169, 4, 241, 174, 74, 239, 206, 113, 86, 174, 68, 216, 238, 52, 85, 156, 27,
115-
134, 149, 54, 55, 91, 147, 45, 130, 131, 237, 51, 31, 191, 106, 155, 14, 160, 82, 47, 40,
116-
96, 31, 114, 127, 212, 187, 167, 110, 205, 116, 198, 243, 218, 72, 137, 53, 248, 43, 255,
117-
67, 35, 61, 245, 93,
118-
];
119-
120-
let private_key =
121-
AsymmetricCryptoKey::from_der(&STANDARD.decode(&request.private_key).unwrap()).unwrap();
122-
123-
let encrypted = UnsignedSharedKey::encapsulate_key_unsigned(
124-
&SymmetricCryptoKey::try_from(secret.clone()).unwrap(),
125-
&private_key.to_public_key(),
126-
)
127-
.unwrap();
128-
129-
let decrypted = auth_request_decrypt_user_key(request.private_key, encrypted).unwrap();
130-
131-
assert_eq!(decrypted.to_encoded(), secret);
132-
}
133-
134109
#[cfg(test)]
135110
mod tests {
136111
use std::num::NonZeroU32;
137112

138-
use bitwarden_crypto::{Kdf, MasterKey};
113+
use bitwarden_crypto::{BitwardenLegacyKeyBytes, Kdf, MasterKey, SpkiPublicKeyBytes};
139114

140115
use super::*;
141116
use crate::key_management::{
142117
crypto::{AuthRequestMethod, InitUserCryptoMethod, InitUserCryptoRequest},
143118
SymmetricKeyId,
144119
};
145120

121+
#[test]
122+
fn test_auth_request() {
123+
let request = new_auth_request("[email protected]").unwrap();
124+
125+
let secret = vec![
126+
111, 32, 97, 169, 4, 241, 174, 74, 239, 206, 113, 86, 174, 68, 216, 238, 52, 85, 156,
127+
27, 134, 149, 54, 55, 91, 147, 45, 130, 131, 237, 51, 31, 191, 106, 155, 14, 160, 82,
128+
47, 40, 96, 31, 114, 127, 212, 187, 167, 110, 205, 116, 198, 243, 218, 72, 137, 53,
129+
248, 43, 255, 67, 35, 61, 245, 93,
130+
];
131+
132+
let private_key =
133+
AsymmetricCryptoKey::from_der(&STANDARD.decode(&request.private_key).unwrap().into())
134+
.unwrap();
135+
136+
let secret = BitwardenLegacyKeyBytes::from(secret);
137+
let encrypted = UnsignedSharedKey::encapsulate_key_unsigned(
138+
&SymmetricCryptoKey::try_from(&secret).unwrap(),
139+
&private_key.to_public_key(),
140+
)
141+
.unwrap();
142+
143+
let decrypted =
144+
auth_request_decrypt_user_key(request.private_key.into(), encrypted).unwrap();
145+
146+
assert_eq!(decrypted.to_encoded().to_vec(), secret.to_vec());
147+
}
148+
146149
#[test]
147150
fn test_approve() {
148151
let client = Client::new(None);
@@ -166,22 +169,24 @@ mod tests {
166169
let public_key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvyLRDUwXB4BfQ507D4meFPmwn5zwy3IqTPJO4plrrhnclWahXa240BzyFW9gHgYu+Jrgms5xBfRTBMcEsqqNm7+JpB6C1B6yvnik0DpJgWQw1rwvy4SUYidpR/AWbQi47n/hvnmzI/sQxGddVfvWu1iTKOlf5blbKYAXnUE5DZBGnrWfacNXwRRdtP06tFB0LwDgw+91CeLSJ9py6dm1qX5JIxoO8StJOQl65goLCdrTWlox+0Jh4xFUfCkb+s3px+OhSCzJbvG/hlrSRcUz5GnwlCEyF3v5lfUtV96MJD+78d8pmH6CfFAp2wxKRAbGdk+JccJYO6y6oIXd3Fm7twIDAQAB";
167170

168171
// Verify fingerprint
169-
let pbkey = STANDARD.decode(public_key).unwrap();
170-
let fingerprint = fingerprint("[email protected]", &pbkey).unwrap();
172+
let pubkey = STANDARD.decode(public_key).unwrap();
173+
let pubkey = SpkiPublicKeyBytes::from(pubkey.clone());
174+
let fingerprint = fingerprint("[email protected]", &pubkey).unwrap();
171175
assert_eq!(fingerprint, "childless-unfair-prowler-dropbox-designate");
172176

173-
approve_auth_request(&client, public_key.to_owned()).unwrap();
177+
approve_auth_request(&client, public_key.to_owned().into()).unwrap();
174178
}
175179

176180
#[tokio::test]
177181
async fn test_decrypt_user_key() {
178182
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=";
179183

180184
let enc_user_key = "4.dxbd5OMwi/Avy7DQxvLV+Z7kDJgHBtg/jAbgYNO7QU0Zii4rLFNco2lS5aS9z42LTZHc2p5HYwn2ZwkZNfHsQ6//d5q40MDgGYJMKBXOZP62ZHhct1XsvYBmtcUtIOm5j2HSjt2pjEuGAc1LbyGIWRJJQ3Lp1ULbL2m71I+P23GF36JyOM8SUWvpvxE/3+qqVhRFPG2VqMCYa2kLLxwVfUmpV+KKjX1TXsrq6pfJIwHNwHw4h7MSfD8xTy2bx4MiBt638Z9Vt1pGsSQkh9RgPvCbnhuCpZQloUgJ8ByLVEcrlKx3yaaxiQXvte+ZhuOI7rGdjmoVoOzisooje4JgYw==".parse().unwrap();
181-
let dec = auth_request_decrypt_user_key(private_key.to_owned(), enc_user_key).unwrap();
185+
let dec =
186+
auth_request_decrypt_user_key(private_key.to_owned().into(), enc_user_key).unwrap();
182187

183188
assert_eq!(
184-
&dec.to_encoded(),
189+
&dec.to_encoded().to_vec(),
185190
&[
186191
201, 37, 234, 213, 21, 75, 40, 70, 149, 213, 234, 16, 19, 251, 162, 245, 161, 74,
187192
34, 245, 211, 151, 211, 192, 95, 10, 117, 50, 88, 223, 23, 157
@@ -195,12 +200,15 @@ mod tests {
195200

196201
let enc_master_key = "4.dxbd5OMwi/Avy7DQxvLV+Z7kDJgHBtg/jAbgYNO7QU0Zii4rLFNco2lS5aS9z42LTZHc2p5HYwn2ZwkZNfHsQ6//d5q40MDgGYJMKBXOZP62ZHhct1XsvYBmtcUtIOm5j2HSjt2pjEuGAc1LbyGIWRJJQ3Lp1ULbL2m71I+P23GF36JyOM8SUWvpvxE/3+qqVhRFPG2VqMCYa2kLLxwVfUmpV+KKjX1TXsrq6pfJIwHNwHw4h7MSfD8xTy2bx4MiBt638Z9Vt1pGsSQkh9RgPvCbnhuCpZQloUgJ8ByLVEcrlKx3yaaxiQXvte+ZhuOI7rGdjmoVoOzisooje4JgYw==".parse().unwrap();
197202
let enc_user_key = "2.Q/2PhzcC7GdeiMHhWguYAQ==|GpqzVdr0go0ug5cZh1n+uixeBC3oC90CIe0hd/HWA/pTRDZ8ane4fmsEIcuc8eMKUt55Y2q/fbNzsYu41YTZzzsJUSeqVjT8/iTQtgnNdpo=|dwI+uyvZ1h/iZ03VQ+/wrGEFYVewBUUl/syYgjsNMbE=".parse().unwrap();
198-
let dec =
199-
auth_request_decrypt_master_key(private_key.to_owned(), enc_master_key, enc_user_key)
200-
.unwrap();
203+
let dec = auth_request_decrypt_master_key(
204+
private_key.to_owned().into(),
205+
enc_master_key,
206+
enc_user_key,
207+
)
208+
.unwrap();
201209

202210
assert_eq!(
203-
&dec.to_encoded(),
211+
&dec.to_encoded().to_vec(),
204212
&[
205213
109, 128, 172, 147, 206, 123, 134, 95, 16, 36, 155, 113, 201, 18, 186, 230, 216,
206214
212, 173, 188, 74, 11, 134, 131, 137, 242, 105, 178, 105, 126, 52, 139, 248, 91,
@@ -241,7 +249,8 @@ mod tests {
241249

242250
// Initialize an auth request, and approve it on the existing device
243251
let auth_req = new_auth_request(email).unwrap();
244-
let approved_req = approve_auth_request(&existing_device, auth_req.public_key).unwrap();
252+
let approved_req =
253+
approve_auth_request(&existing_device, auth_req.public_key.into()).unwrap();
245254

246255
// Unlock the vault using the approved request
247256
new_device

crates/bitwarden-core/src/auth/login/access_token.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::path::{Path, PathBuf};
22

33
use base64::{engine::general_purpose::STANDARD, Engine};
4-
use bitwarden_crypto::{EncString, KeyDecryptable, SymmetricCryptoKey};
4+
use bitwarden_crypto::{BitwardenLegacyKeyBytes, EncString, KeyDecryptable, SymmetricCryptoKey};
55
use chrono::Utc;
66
use schemars::JsonSchema;
77
use serde::{Deserialize, Serialize};
@@ -67,7 +67,8 @@ pub(crate) async fn login_access_token(
6767

6868
let payload: Payload = serde_json::from_slice(&decrypted_payload)?;
6969
let encryption_key = STANDARD.decode(&payload.encryption_key)?;
70-
let encryption_key = SymmetricCryptoKey::try_from(encryption_key)?;
70+
let encryption_key = BitwardenLegacyKeyBytes::from(encryption_key);
71+
let encryption_key = SymmetricCryptoKey::try_from(&encryption_key)?;
7172

7273
let access_token_obj: JwtToken = r.access_token.parse()?;
7374

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,20 @@
1-
use base64::{engine::general_purpose::STANDARD, Engine};
21
use bitwarden_crypto::{
32
AsymmetricPublicCryptoKey, DeviceKey, EncString, Kdf, SymmetricCryptoKey, TrustDeviceResponse,
43
UnsignedSharedKey, UserKey,
54
};
65

7-
use crate::{client::encryption_settings::EncryptionSettingsError, Client};
6+
use crate::{client::encryption_settings::EncryptionSettingsError, Base64String, Client};
87

98
/// This function generates a new user key and key pair, initializes the client's crypto with the
109
/// generated user key, and encrypts the user key with the organization public key for admin
1110
/// password reset. If remember_device is true, it also generates a device key.
1211
pub(super) fn make_register_tde_keys(
1312
client: &Client,
1413
email: String,
15-
org_public_key: String,
14+
org_public_key: Base64String,
1615
remember_device: bool,
1716
) -> Result<RegisterTdeKeyResponse, EncryptionSettingsError> {
18-
let public_key = AsymmetricPublicCryptoKey::from_der(&STANDARD.decode(org_public_key)?)?;
17+
let public_key = AsymmetricPublicCryptoKey::from_der(&org_public_key.try_into()?)?;
1918

2019
let user_key = UserKey::new(SymmetricCryptoKey::make_aes256_cbc_hmac_key());
2120
let key_pair = user_key.make_key_pair()?;

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
use bitwarden_crypto::{security_state::SignedSecurityState, CryptoError};
1+
use bitwarden_crypto::{
2+
security_state::SignedSecurityState, CoseKeyBytes, CryptoError, Pkcs8PrivateKeyBytes,
3+
};
24
#[cfg(feature = "internal")]
35
use bitwarden_crypto::{EncString, UnsignedSharedKey};
46
#[cfg(any(feature = "internal", feature = "secrets"))]

0 commit comments

Comments
 (0)