crypto: Encode our keys in the sled cryptostore as well

master
Damir Jelić 2021-01-26 14:22:03 +01:00
parent fc085a7391
commit 71a087c379
1 changed files with 74 additions and 25 deletions

View File

@ -46,6 +46,55 @@ use crate::{
/// panic once we try to pickle a Signing object. /// panic once we try to pickle a Signing object.
const DEFAULT_PICKLE: &str = "DEFAULT_PICKLE_PASSPHRASE_123456"; const DEFAULT_PICKLE: &str = "DEFAULT_PICKLE_PASSPHRASE_123456";
trait EncodeKey {
const SEPARATOR: u8 = 0xff;
fn encode(&self) -> Vec<u8>;
}
impl EncodeKey for &UserId {
fn encode(&self) -> Vec<u8> {
self.as_str().encode()
}
}
impl EncodeKey for &RoomId {
fn encode(&self) -> Vec<u8> {
self.as_str().encode()
}
}
impl EncodeKey for &str {
fn encode(&self) -> Vec<u8> {
[self.as_bytes(), &[Self::SEPARATOR]].concat()
}
}
impl EncodeKey for (&str, &str) {
fn encode(&self) -> Vec<u8> {
[
self.0.as_bytes(),
&[Self::SEPARATOR],
self.1.as_bytes(),
&[Self::SEPARATOR],
]
.concat()
}
}
impl EncodeKey for (&str, &str, &str) {
fn encode(&self) -> Vec<u8> {
[
self.0.as_bytes(),
&[Self::SEPARATOR],
self.1.as_bytes(),
&[Self::SEPARATOR],
self.2.as_bytes(),
&[Self::SEPARATOR],
]
.concat()
}
}
/// An in-memory only store that will forget all the E2EE key once it's dropped. /// An in-memory only store that will forget all the E2EE key once it's dropped.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct SledStore { pub struct SledStore {
@ -143,7 +192,7 @@ impl SledStore {
fn get_or_create_pickle_key(passphrase: &str, database: &Db) -> Result<PickleKey> { fn get_or_create_pickle_key(passphrase: &str, database: &Db) -> Result<PickleKey> {
let key = if let Some(key) = database let key = if let Some(key) = database
.get("pickle_key")? .get("pickle_key".encode())?
.map(|v| serde_json::from_slice(&v)) .map(|v| serde_json::from_slice(&v))
{ {
PickleKey::from_encrypted(passphrase, key?) PickleKey::from_encrypted(passphrase, key?)
@ -151,7 +200,7 @@ impl SledStore {
} else { } else {
let key = PickleKey::new(); let key = PickleKey::new();
let encrypted = key.encrypt(passphrase); let encrypted = key.encrypt(passphrase);
database.insert("pickle_key", serde_json::to_vec(&encrypted)?)?; database.insert("pickle_key".encode(), serde_json::to_vec(&encrypted)?)?;
key key
}; };
@ -195,7 +244,7 @@ impl SledStore {
let identity_keys = account.identity_keys; let identity_keys = account.identity_keys;
self.outbound_group_sessions self.outbound_group_sessions
.get(room_id.as_str())? .get(room_id.encode())?
.map(|p| serde_json::from_slice(&p).map_err(CryptoStoreError::Serialization)) .map(|p| serde_json::from_slice(&p).map_err(CryptoStoreError::Serialization))
.transpose()? .transpose()?
.map(|p| { .map(|p| {
@ -231,7 +280,7 @@ impl SledStore {
let session_id = session.session_id(); let session_id = session.session_id();
let pickle = session.pickle(self.get_pickle_mode()).await; let pickle = session.pickle(self.get_pickle_mode()).await;
let key = format!("{}{}", sender_key, session_id); let key = (sender_key, session_id).encode();
self.session_cache.add(session).await; self.session_cache.add(session).await;
session_changes.insert(key, pickle); session_changes.insert(key, pickle);
@ -243,7 +292,7 @@ impl SledStore {
let room_id = session.room_id(); let room_id = session.room_id();
let sender_key = session.sender_key(); let sender_key = session.sender_key();
let session_id = session.session_id(); let session_id = session.session_id();
let key = format!("{}{}{}", room_id, sender_key, session_id); let key = (room_id.as_str(), sender_key, session_id).encode();
let pickle = session.pickle(self.get_pickle_mode()).await; let pickle = session.pickle(self.get_pickle_mode()).await;
inbound_session_changes.insert(key, pickle); inbound_session_changes.insert(key, pickle);
@ -284,33 +333,33 @@ impl SledStore {
)| { )| {
if let Some(a) = &account_pickle { if let Some(a) = &account_pickle {
account.insert( account.insert(
"account", "account".encode(),
serde_json::to_vec(a).map_err(ConflictableTransactionError::Abort)?, serde_json::to_vec(a).map_err(ConflictableTransactionError::Abort)?,
)?; )?;
} }
if let Some(i) = &private_identity_pickle { if let Some(i) = &private_identity_pickle {
private_identity.insert( private_identity.insert(
"identity", "identity".encode(),
serde_json::to_vec(&i).map_err(ConflictableTransactionError::Abort)?, serde_json::to_vec(&i).map_err(ConflictableTransactionError::Abort)?,
)?; )?;
} }
for device in device_changes.new.iter().chain(&device_changes.changed) { for device in device_changes.new.iter().chain(&device_changes.changed) {
let key = format!("{}{}", device.user_id(), device.device_id()); let key = (device.user_id().as_str(), device.device_id().as_str()).encode();
let device = serde_json::to_vec(&device) let device = serde_json::to_vec(&device)
.map_err(ConflictableTransactionError::Abort)?; .map_err(ConflictableTransactionError::Abort)?;
devices.insert(key.as_str(), device)?; devices.insert(key, device)?;
} }
for device in &device_changes.deleted { for device in &device_changes.deleted {
let key = format!("{}{}", device.user_id(), device.device_id()); let key = (device.user_id().as_str(), device.device_id().as_str()).encode();
devices.remove(key.as_str())?; devices.remove(key)?;
} }
for identity in identity_changes.changed.iter().chain(&identity_changes.new) { for identity in identity_changes.changed.iter().chain(&identity_changes.new) {
identities.insert( identities.insert(
identity.user_id().as_str(), identity.user_id().encode(),
serde_json::to_vec(&identity) serde_json::to_vec(&identity)
.map_err(ConflictableTransactionError::Abort)?, .map_err(ConflictableTransactionError::Abort)?,
)?; )?;
@ -318,7 +367,7 @@ impl SledStore {
for (key, session) in &session_changes { for (key, session) in &session_changes {
sessions.insert( sessions.insert(
key.as_str(), key.as_slice(),
serde_json::to_vec(&session) serde_json::to_vec(&session)
.map_err(ConflictableTransactionError::Abort)?, .map_err(ConflictableTransactionError::Abort)?,
)?; )?;
@ -326,7 +375,7 @@ impl SledStore {
for (key, session) in &inbound_session_changes { for (key, session) in &inbound_session_changes {
inbound_sessions.insert( inbound_sessions.insert(
key.as_str(), key.as_slice(),
serde_json::to_vec(&session) serde_json::to_vec(&session)
.map_err(ConflictableTransactionError::Abort)?, .map_err(ConflictableTransactionError::Abort)?,
)?; )?;
@ -334,7 +383,7 @@ impl SledStore {
for (key, session) in &outbound_session_changes { for (key, session) in &outbound_session_changes {
outbound_sessions.insert( outbound_sessions.insert(
key.as_str(), key.encode(),
serde_json::to_vec(&session) serde_json::to_vec(&session)
.map_err(ConflictableTransactionError::Abort)?, .map_err(ConflictableTransactionError::Abort)?,
)?; )?;
@ -362,7 +411,7 @@ impl SledStore {
#[async_trait] #[async_trait]
impl CryptoStore for SledStore { impl CryptoStore for SledStore {
async fn load_account(&self) -> Result<Option<ReadOnlyAccount>> { async fn load_account(&self) -> Result<Option<ReadOnlyAccount>> {
if let Some(pickle) = self.account.get("account")? { if let Some(pickle) = self.account.get("account".encode())? {
let pickle = serde_json::from_slice(&pickle)?; let pickle = serde_json::from_slice(&pickle)?;
self.load_tracked_users().await?; self.load_tracked_users().await?;
@ -379,7 +428,7 @@ impl CryptoStore for SledStore {
async fn save_account(&self, account: ReadOnlyAccount) -> Result<()> { async fn save_account(&self, account: ReadOnlyAccount) -> Result<()> {
let pickle = account.pickle(self.get_pickle_mode()).await; let pickle = account.pickle(self.get_pickle_mode()).await;
self.account self.account
.insert("account", serde_json::to_vec(&pickle)?)?; .insert("account".encode(), serde_json::to_vec(&pickle)?)?;
Ok(()) Ok(())
} }
@ -397,7 +446,7 @@ impl CryptoStore for SledStore {
if self.session_cache.get(sender_key).is_none() { if self.session_cache.get(sender_key).is_none() {
let sessions: Result<Vec<Session>> = self let sessions: Result<Vec<Session>> = self
.sessions .sessions
.scan_prefix(sender_key) .scan_prefix(sender_key.encode())
.map(|s| serde_json::from_slice(&s?.1).map_err(CryptoStoreError::Serialization)) .map(|s| serde_json::from_slice(&s?.1).map_err(CryptoStoreError::Serialization))
.map(|p| { .map(|p| {
Session::from_pickle( Session::from_pickle(
@ -423,7 +472,7 @@ impl CryptoStore for SledStore {
sender_key: &str, sender_key: &str,
session_id: &str, session_id: &str,
) -> Result<Option<InboundGroupSession>> { ) -> Result<Option<InboundGroupSession>> {
let key = format!("{}{}{}", room_id, sender_key, session_id); let key = (room_id.as_str(), sender_key, session_id).encode();
let pickle = self let pickle = self
.inbound_group_sessions .inbound_group_sessions
.get(&key)? .get(&key)?
@ -487,7 +536,7 @@ impl CryptoStore for SledStore {
user_id: &UserId, user_id: &UserId,
device_id: &DeviceId, device_id: &DeviceId,
) -> Result<Option<ReadOnlyDevice>> { ) -> Result<Option<ReadOnlyDevice>> {
let key = format!("{}{}", user_id, device_id); let key = (user_id.as_str(), device_id.as_str()).encode();
if let Some(d) = self.devices.get(key)? { if let Some(d) = self.devices.get(key)? {
Ok(Some(serde_json::from_slice(&d)?)) Ok(Some(serde_json::from_slice(&d)?))
@ -501,7 +550,7 @@ impl CryptoStore for SledStore {
user_id: &UserId, user_id: &UserId,
) -> Result<HashMap<DeviceIdBox, ReadOnlyDevice>> { ) -> Result<HashMap<DeviceIdBox, ReadOnlyDevice>> {
self.devices self.devices
.scan_prefix(user_id.as_str()) .scan_prefix(user_id.encode())
.map(|d| serde_json::from_slice(&d?.1).map_err(CryptoStoreError::Serialization)) .map(|d| serde_json::from_slice(&d?.1).map_err(CryptoStoreError::Serialization))
.map(|d| { .map(|d| {
let d: ReadOnlyDevice = d?; let d: ReadOnlyDevice = d?;
@ -513,13 +562,13 @@ impl CryptoStore for SledStore {
async fn get_user_identity(&self, user_id: &UserId) -> Result<Option<UserIdentities>> { async fn get_user_identity(&self, user_id: &UserId) -> Result<Option<UserIdentities>> {
Ok(self Ok(self
.identities .identities
.get(user_id.as_str())? .get(user_id.encode())?
.map(|i| serde_json::from_slice(&i)) .map(|i| serde_json::from_slice(&i))
.transpose()?) .transpose()?)
} }
async fn save_value(&self, key: String, value: String) -> Result<()> { async fn save_value(&self, key: String, value: String) -> Result<()> {
self.values.insert(key.as_str(), value.as_str())?; self.values.insert(key.as_str().encode(), value.as_str())?;
Ok(()) Ok(())
} }
@ -531,12 +580,12 @@ impl CryptoStore for SledStore {
async fn get_value(&self, key: &str) -> Result<Option<String>> { async fn get_value(&self, key: &str) -> Result<Option<String>> {
Ok(self Ok(self
.values .values
.get(key)? .get(key.encode())?
.map(|v| String::from_utf8_lossy(&v).to_string())) .map(|v| String::from_utf8_lossy(&v).to_string()))
} }
async fn load_identity(&self) -> Result<Option<PrivateCrossSigningIdentity>> { async fn load_identity(&self) -> Result<Option<PrivateCrossSigningIdentity>> {
if let Some(i) = self.private_identity.get("identity")? { if let Some(i) = self.private_identity.get("identity".encode())? {
let pickle = serde_json::from_slice(&i)?; let pickle = serde_json::from_slice(&i)?;
Ok(Some( Ok(Some(
PrivateCrossSigningIdentity::from_pickle(pickle, self.get_pickle_key()) PrivateCrossSigningIdentity::from_pickle(pickle, self.get_pickle_key())