crypto: Correctly store the ed25519 key map for inbound group sessions.
parent
aff1e1d0a8
commit
3e9b0a8e7f
|
@ -49,9 +49,10 @@ pub struct InboundGroupSession {
|
||||||
inner: Arc<Mutex<OlmInboundGroupSession>>,
|
inner: Arc<Mutex<OlmInboundGroupSession>>,
|
||||||
session_id: Arc<String>,
|
session_id: Arc<String>,
|
||||||
pub(crate) sender_key: Arc<String>,
|
pub(crate) sender_key: Arc<String>,
|
||||||
pub(crate) signing_key: Arc<String>,
|
pub(crate) signing_key: Arc<BTreeMap<DeviceKeyAlgorithm, String>>,
|
||||||
pub(crate) room_id: Arc<RoomId>,
|
pub(crate) room_id: Arc<RoomId>,
|
||||||
forwarding_chains: Arc<Mutex<Option<Vec<String>>>>,
|
forwarding_chains: Arc<Mutex<Option<Vec<String>>>>,
|
||||||
|
imported: Arc<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InboundGroupSession {
|
impl InboundGroupSession {
|
||||||
|
@ -80,13 +81,17 @@ impl InboundGroupSession {
|
||||||
let session = OlmInboundGroupSession::new(&session_key.0)?;
|
let session = OlmInboundGroupSession::new(&session_key.0)?;
|
||||||
let session_id = session.session_id();
|
let session_id = session.session_id();
|
||||||
|
|
||||||
|
let mut keys: BTreeMap<DeviceKeyAlgorithm, String> = BTreeMap::new();
|
||||||
|
keys.insert(DeviceKeyAlgorithm::Ed25519, signing_key.to_owned());
|
||||||
|
|
||||||
Ok(InboundGroupSession {
|
Ok(InboundGroupSession {
|
||||||
inner: Arc::new(Mutex::new(session)),
|
inner: Arc::new(Mutex::new(session)),
|
||||||
session_id: Arc::new(session_id),
|
session_id: Arc::new(session_id),
|
||||||
sender_key: Arc::new(sender_key.to_owned()),
|
sender_key: Arc::new(sender_key.to_owned()),
|
||||||
signing_key: Arc::new(signing_key.to_owned()),
|
signing_key: Arc::new(keys),
|
||||||
room_id: Arc::new(room_id.clone()),
|
room_id: Arc::new(room_id.clone()),
|
||||||
forwarding_chains: Arc::new(Mutex::new(None)),
|
forwarding_chains: Arc::new(Mutex::new(None)),
|
||||||
|
imported: Arc::new(false),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,9 +107,10 @@ impl InboundGroupSession {
|
||||||
PickledInboundGroupSession {
|
PickledInboundGroupSession {
|
||||||
pickle: InboundGroupSessionPickle::from(pickle),
|
pickle: InboundGroupSessionPickle::from(pickle),
|
||||||
sender_key: self.sender_key.to_string(),
|
sender_key: self.sender_key.to_string(),
|
||||||
signing_key: self.signing_key.to_string(),
|
signing_key: (&*self.signing_key).clone(),
|
||||||
room_id: (&*self.room_id).clone(),
|
room_id: (&*self.room_id).clone(),
|
||||||
forwarding_chains: self.forwarding_chains.lock().await.clone(),
|
forwarding_chains: self.forwarding_chains.lock().await.clone(),
|
||||||
|
imported: *self.imported,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,10 +126,6 @@ impl InboundGroupSession {
|
||||||
let session_key =
|
let session_key =
|
||||||
ExportedGroupSessionKey(self.inner.lock().await.export(message_index).ok()?);
|
ExportedGroupSessionKey(self.inner.lock().await.export(message_index).ok()?);
|
||||||
|
|
||||||
let mut sender_claimed_keys: BTreeMap<DeviceKeyAlgorithm, String> = BTreeMap::new();
|
|
||||||
|
|
||||||
sender_claimed_keys.insert(DeviceKeyAlgorithm::Ed25519, (&*self.signing_key).to_owned());
|
|
||||||
|
|
||||||
Some(ExportedRoomKey {
|
Some(ExportedRoomKey {
|
||||||
algorithm: EventEncryptionAlgorithm::MegolmV1AesSha2,
|
algorithm: EventEncryptionAlgorithm::MegolmV1AesSha2,
|
||||||
room_id: (&*self.room_id).clone(),
|
room_id: (&*self.room_id).clone(),
|
||||||
|
@ -136,7 +138,7 @@ impl InboundGroupSession {
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.cloned()
|
.cloned()
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
sender_claimed_keys,
|
sender_claimed_keys: (&*self.signing_key).clone(),
|
||||||
session_key,
|
session_key,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -166,6 +168,7 @@ impl InboundGroupSession {
|
||||||
signing_key: Arc::new(pickle.signing_key),
|
signing_key: Arc::new(pickle.signing_key),
|
||||||
room_id: Arc::new(pickle.room_id),
|
room_id: Arc::new(pickle.room_id),
|
||||||
forwarding_chains: Arc::new(Mutex::new(pickle.forwarding_chains)),
|
forwarding_chains: Arc::new(Mutex::new(pickle.forwarding_chains)),
|
||||||
|
imported: Arc::new(pickle.imported),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,12 +268,15 @@ pub struct PickledInboundGroupSession {
|
||||||
/// The public curve25519 key of the account that sent us the session
|
/// The public curve25519 key of the account that sent us the session
|
||||||
pub sender_key: String,
|
pub sender_key: String,
|
||||||
/// The public ed25519 key of the account that sent us the session.
|
/// The public ed25519 key of the account that sent us the session.
|
||||||
pub signing_key: String,
|
pub signing_key: BTreeMap<DeviceKeyAlgorithm, String>,
|
||||||
/// The id of the room that the session is used in.
|
/// The id of the room that the session is used in.
|
||||||
pub room_id: RoomId,
|
pub room_id: RoomId,
|
||||||
/// The list of claimed ed25519 that forwarded us this key. Will be None if
|
/// The list of claimed ed25519 that forwarded us this key. Will be None if
|
||||||
/// we dirrectly received this session.
|
/// we dirrectly received this session.
|
||||||
pub forwarding_chains: Option<Vec<String>>,
|
pub forwarding_chains: Option<Vec<String>>,
|
||||||
|
/// Flag remembering if the session was dirrectly sent to us by the sender
|
||||||
|
/// or if it was imported.
|
||||||
|
pub imported: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The typed representation of a base64 encoded string of the GroupSession pickle.
|
/// The typed representation of a base64 encoded string of the GroupSession pickle.
|
||||||
|
|
|
@ -231,14 +231,16 @@ impl SqliteStore {
|
||||||
.execute(
|
.execute(
|
||||||
r#"
|
r#"
|
||||||
CREATE TABLE IF NOT EXISTS inbound_group_sessions (
|
CREATE TABLE IF NOT EXISTS inbound_group_sessions (
|
||||||
"session_id" TEXT NOT NULL PRIMARY KEY,
|
"id" INTEGER NOT NULL PRIMARY KEY,
|
||||||
|
"session_id" TEXT NOT NULL,
|
||||||
"account_id" INTEGER NOT NULL,
|
"account_id" INTEGER NOT NULL,
|
||||||
"sender_key" TEXT NOT NULL,
|
"sender_key" TEXT NOT NULL,
|
||||||
"signing_key" TEXT NOT NULL,
|
|
||||||
"room_id" TEXT NOT NULL,
|
"room_id" TEXT NOT NULL,
|
||||||
"pickle" BLOB NOT NULL,
|
"pickle" BLOB NOT NULL,
|
||||||
|
"imported" INTEGER NOT NULL,
|
||||||
FOREIGN KEY ("account_id") REFERENCES "accounts" ("id")
|
FOREIGN KEY ("account_id") REFERENCES "accounts" ("id")
|
||||||
ON DELETE CASCADE
|
ON DELETE CASCADE
|
||||||
|
UNIQUE(account_id,session_id,sender_key)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE INDEX IF NOT EXISTS "olm_groups_sessions_account_id" ON "inbound_group_sessions" ("account_id");
|
CREATE INDEX IF NOT EXISTS "olm_groups_sessions_account_id" ON "inbound_group_sessions" ("account_id");
|
||||||
|
@ -246,6 +248,24 @@ impl SqliteStore {
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
connection
|
||||||
|
.execute(
|
||||||
|
r#"
|
||||||
|
CREATE TABLE IF NOT EXISTS group_session_claimed_keys (
|
||||||
|
"id" INTEGER NOT NULL PRIMARY KEY,
|
||||||
|
"session_id" INTEGER NOT NULL,
|
||||||
|
"algorithm" TEXT NOT NULL,
|
||||||
|
"key" TEXT NOT NULL,
|
||||||
|
FOREIGN KEY ("session_id") REFERENCES "inbound_group_sessions" ("id")
|
||||||
|
ON DELETE CASCADE
|
||||||
|
UNIQUE(session_id, algorithm)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS "group_session_claimed_keys_session_id" ON "inbound_group_sessions" ("session_id");
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
connection
|
connection
|
||||||
.execute(
|
.execute(
|
||||||
r#"
|
r#"
|
||||||
|
@ -475,45 +495,55 @@ impl SqliteStore {
|
||||||
let account_id = self.account_id().ok_or(CryptoStoreError::AccountUnset)?;
|
let account_id = self.account_id().ok_or(CryptoStoreError::AccountUnset)?;
|
||||||
let mut connection = self.connection.lock().await;
|
let mut connection = self.connection.lock().await;
|
||||||
|
|
||||||
let mut rows: Vec<(String, String, String, String)> = query_as(
|
let mut rows: Vec<(i64, String, String, String, bool)> = query_as(
|
||||||
"SELECT pickle, sender_key, signing_key, room_id
|
"SELECT id, pickle, sender_key, room_id, imported
|
||||||
FROM inbound_group_sessions WHERE account_id = ?",
|
FROM inbound_group_sessions WHERE account_id = ?",
|
||||||
)
|
)
|
||||||
.bind(account_id)
|
.bind(account_id)
|
||||||
.fetch_all(&mut *connection)
|
.fetch_all(&mut *connection)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let mut group_sessions = rows
|
for row in rows.drain(..) {
|
||||||
.drain(..)
|
let session_row_id = row.0;
|
||||||
.map(|row| {
|
let pickle = row.1;
|
||||||
let pickle = row.0;
|
let sender_key = row.2;
|
||||||
let sender_key = row.1;
|
let room_id = row.3;
|
||||||
let signing_key = row.2;
|
let imported = row.4;
|
||||||
let room_id = row.3;
|
|
||||||
|
|
||||||
let pickle = PickledInboundGroupSession {
|
let key_rows: Vec<(String, String)> = query_as(
|
||||||
pickle: InboundGroupSessionPickle::from(pickle),
|
"SELECT algorithm, key FROM group_session_claimed_keys WHERE session_id = ?",
|
||||||
sender_key,
|
)
|
||||||
signing_key,
|
.bind(session_row_id)
|
||||||
room_id: RoomId::try_from(room_id)?,
|
.fetch_all(&mut *connection)
|
||||||
// Fixme we need to store/restore these once we get support
|
.await?;
|
||||||
// for key requesting/forwarding.
|
|
||||||
forwarding_chains: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(InboundGroupSession::from_pickle(
|
let claimed_keys: BTreeMap<DeviceKeyAlgorithm, String> = key_rows
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|row| {
|
||||||
|
let algorithm = row.0.parse::<DeviceKeyAlgorithm>().ok()?;
|
||||||
|
let key = row.1;
|
||||||
|
|
||||||
|
Some((algorithm, key))
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let pickle = PickledInboundGroupSession {
|
||||||
|
pickle: InboundGroupSessionPickle::from(pickle),
|
||||||
|
sender_key,
|
||||||
|
signing_key: claimed_keys,
|
||||||
|
room_id: RoomId::try_from(room_id)?,
|
||||||
|
// Fixme we need to store/restore these once we get support
|
||||||
|
// for key requesting/forwarding.
|
||||||
|
forwarding_chains: None,
|
||||||
|
imported,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.inbound_group_sessions
|
||||||
|
.add(InboundGroupSession::from_pickle(
|
||||||
pickle,
|
pickle,
|
||||||
self.get_pickle_mode(),
|
self.get_pickle_mode(),
|
||||||
)?)
|
)?);
|
||||||
})
|
}
|
||||||
.collect::<Result<Vec<InboundGroupSession>>>()?;
|
|
||||||
|
|
||||||
group_sessions
|
|
||||||
.drain(..)
|
|
||||||
.map(|s| {
|
|
||||||
self.inbound_group_sessions.add(s);
|
|
||||||
})
|
|
||||||
.for_each(drop);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1146,23 +1176,47 @@ impl CryptoStore for SqliteStore {
|
||||||
// the key import feature.
|
// the key import feature.
|
||||||
|
|
||||||
query(
|
query(
|
||||||
"INSERT INTO inbound_group_sessions (
|
"REPLACE INTO inbound_group_sessions (
|
||||||
session_id, account_id, sender_key, signing_key,
|
session_id, account_id, sender_key,
|
||||||
room_id, pickle
|
room_id, pickle, imported
|
||||||
) VALUES (?1, ?2, ?3, ?4, ?5, ?6)
|
) VALUES (?1, ?2, ?3, ?4, ?5, ?6)
|
||||||
ON CONFLICT(session_id) DO UPDATE SET
|
|
||||||
pickle = excluded.pickle
|
|
||||||
",
|
",
|
||||||
)
|
)
|
||||||
.bind(session_id)
|
.bind(session_id)
|
||||||
.bind(account_id)
|
.bind(account_id)
|
||||||
.bind(pickle.sender_key)
|
.bind(&pickle.sender_key)
|
||||||
.bind(pickle.signing_key)
|
|
||||||
.bind(pickle.room_id.as_str())
|
.bind(pickle.room_id.as_str())
|
||||||
.bind(pickle.pickle.as_str())
|
.bind(pickle.pickle.as_str())
|
||||||
|
.bind(pickle.imported)
|
||||||
.execute(&mut *connection)
|
.execute(&mut *connection)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
let row: (i64,) = query_as(
|
||||||
|
"SELECT id FROM inbound_group_sessions
|
||||||
|
WHERE account_id = ? and session_id = ? and sender_key = ?",
|
||||||
|
)
|
||||||
|
.bind(account_id)
|
||||||
|
.bind(session_id)
|
||||||
|
.bind(pickle.sender_key)
|
||||||
|
.fetch_one(&mut *connection)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let session_row_id = row.0;
|
||||||
|
|
||||||
|
for (key_id, key) in pickle.signing_key {
|
||||||
|
query(
|
||||||
|
"INSERT OR IGNORE INTO group_session_claimed_keys (
|
||||||
|
session_id, algorithm, key
|
||||||
|
) VALUES (?1, ?2, ?3)
|
||||||
|
",
|
||||||
|
)
|
||||||
|
.bind(session_row_id)
|
||||||
|
.bind(serde_json::to_string(&key_id)?)
|
||||||
|
.bind(key)
|
||||||
|
.execute(&mut *connection)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(self.inbound_group_sessions.add(session))
|
Ok(self.inbound_group_sessions.add(session))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue