Skip to main content

bitwarden_unlock/
session_key.rs

1use bitwarden_crypto::{
2    KeySlotIds, KeyStoreContext, SymmetricCryptoKey,
3    safe::{SymmetricKeyEnvelope, SymmetricKeyEnvelopeError, SymmetricKeyEnvelopeNamespace},
4};
5
6/// A symmetric key that wraps the user key in the persisted state, allowing a
7/// rehydrated client to unlock without re-deriving the user key from a master
8/// password or other primary unlock factor.
9///
10/// Callers are responsible for storing this key in a secure location outside
11/// the SDK (e.g. the OS keychain) and providing it back to
12/// [`UnlockClient::unlock`](crate::UnlockClient::unlock) when reconstructing
13/// the client.
14#[derive(PartialEq)] // This is ok because SymmetricCryptoKey implements PartialEq with constant-time equality checks.
15pub struct SessionKey(pub(crate) SymmetricCryptoKey);
16
17impl SessionKey {
18    /// Mint a new random session key.
19    pub fn make() -> Self {
20        Self(SymmetricCryptoKey::make_xchacha20_poly1305_key())
21    }
22
23    /// Mint a new session key, seal `key_to_seal` (already present in `ctx`)
24    /// with it, and return both the envelope and the new session key.
25    pub fn from_context<Ids: KeySlotIds>(
26        key_to_seal: Ids::Symmetric,
27        ctx: &mut KeyStoreContext<Ids>,
28    ) -> Result<(SymmetricKeyEnvelope, SessionKey), SymmetricKeyEnvelopeError> {
29        let session_key = SessionKey::make();
30        let session_key_id = ctx.add_local_symmetric_key(session_key.0.clone());
31        let envelope = SymmetricKeyEnvelope::seal(
32            key_to_seal,
33            session_key_id,
34            SymmetricKeyEnvelopeNamespace::SessionKey,
35            ctx,
36        )?;
37        Ok((envelope, session_key))
38    }
39
40    /// Unseal `envelope` using this session key and place the resulting key in
41    /// `ctx`, returning the local id under which it is registered.
42    pub fn unwrap_to_context<Ids: KeySlotIds>(
43        &self,
44        envelope: &SymmetricKeyEnvelope,
45        ctx: &mut KeyStoreContext<Ids>,
46    ) -> Result<Ids::Symmetric, SymmetricKeyEnvelopeError> {
47        let session_key_id = ctx.add_local_symmetric_key(self.0.clone());
48        envelope.unseal(
49            session_key_id,
50            SymmetricKeyEnvelopeNamespace::SessionKey,
51            ctx,
52        )
53    }
54}