crypto: Forward some more errors from the rust side to the kotlin side

This commit is contained in:
Damir Jelić 2021-04-12 15:03:28 +02:00
parent 0d708bc35a
commit 543a638e87
4 changed files with 90 additions and 56 deletions

View File

@ -22,6 +22,7 @@ import java.io.File
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import kotlinx.coroutines.runBlocking
import org.matrix.android.sdk.api.listeners.ProgressListener import org.matrix.android.sdk.api.listeners.ProgressListener
import org.matrix.android.sdk.api.session.crypto.MXCryptoError import org.matrix.android.sdk.api.session.crypto.MXCryptoError
import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.events.model.Content
@ -179,6 +180,7 @@ internal class OlmMachine(user_id: String, device_id: String, path: File, device
* *
* @param responseBody The body of the response that was received. * @param responseBody The body of the response that was received.
*/ */
@Throws(CryptoStoreErrorException::class)
suspend fun markRequestAsSent( suspend fun markRequestAsSent(
requestId: String, requestId: String,
requestType: RequestType, requestType: RequestType,
@ -206,11 +208,12 @@ internal class OlmMachine(user_id: String, device_id: String, path: File, device
* *
* @param keyCounts The map of uploaded one-time key types and counts. * @param keyCounts The map of uploaded one-time key types and counts.
*/ */
@Throws(CryptoStoreErrorException::class)
suspend fun receiveSyncChanges( suspend fun receiveSyncChanges(
toDevice: ToDeviceSyncResponse?, toDevice: ToDeviceSyncResponse?,
deviceChanges: DeviceListResponse?, deviceChanges: DeviceListResponse?,
keyCounts: DeviceOneTimeKeysCountSyncResponse? keyCounts: DeviceOneTimeKeysCountSyncResponse?
) = withContext(Dispatchers.IO) { ): ToDeviceSyncResponse = withContext(Dispatchers.IO) {
var counts: MutableMap<String, Int> = mutableMapOf() var counts: MutableMap<String, Int> = mutableMapOf()
if (keyCounts?.signedCurve25519 != null) { if (keyCounts?.signedCurve25519 != null) {
@ -221,7 +224,7 @@ internal class OlmMachine(user_id: String, device_id: String, path: File, device
val adapter = MoshiProvider.providesMoshi().adapter<ToDeviceSyncResponse>(ToDeviceSyncResponse::class.java) val adapter = MoshiProvider.providesMoshi().adapter<ToDeviceSyncResponse>(ToDeviceSyncResponse::class.java)
val events = adapter.toJson(toDevice ?: ToDeviceSyncResponse())!! val events = adapter.toJson(toDevice ?: ToDeviceSyncResponse())!!
inner.receiveSyncChanges(events, devices, counts) adapter.fromJson(inner.receiveSyncChanges(events, devices, counts))!!
} }
/** /**
@ -254,6 +257,7 @@ internal class OlmMachine(user_id: String, device_id: String, path: File, device
* *
* @return A keys claim request that needs to be sent out to the server. * @return A keys claim request that needs to be sent out to the server.
*/ */
@Throws(CryptoStoreErrorException::class)
suspend fun getMissingSessions(users: List<String>): Request? = withContext(Dispatchers.IO) { suspend fun getMissingSessions(users: List<String>): Request? = withContext(Dispatchers.IO) {
inner.getMissingSessions(users) inner.getMissingSessions(users)
} }
@ -277,6 +281,7 @@ internal class OlmMachine(user_id: String, device_id: String, path: File, device
* *
* @return The list of requests that need to be sent out. * @return The list of requests that need to be sent out.
*/ */
@Throws(CryptoStoreErrorException::class)
suspend fun shareGroupSession(roomId: String, users: List<String>): List<Request> = withContext(Dispatchers.IO) { suspend fun shareGroupSession(roomId: String, users: List<String>): List<Request> = withContext(Dispatchers.IO) {
inner.shareGroupSession(roomId, users) inner.shareGroupSession(roomId, users)
} }
@ -315,6 +320,7 @@ internal class OlmMachine(user_id: String, device_id: String, path: File, device
* *
* @return The encrypted version of the content * @return The encrypted version of the content
*/ */
@Throws(CryptoStoreErrorException::class)
suspend fun encrypt(roomId: String, eventType: String, content: Content): Content = withContext(Dispatchers.IO) { suspend fun encrypt(roomId: String, eventType: String, content: Content): Content = withContext(Dispatchers.IO) {
val adapter = MoshiProvider.providesMoshi().adapter<Content>(Map::class.java) val adapter = MoshiProvider.providesMoshi().adapter<Content>(Map::class.java)
val contentString = adapter.toJson(content) val contentString = adapter.toJson(content)
@ -400,6 +406,7 @@ internal class OlmMachine(user_id: String, device_id: String, path: File, device
* *
* @return The Device if it found one. * @return The Device if it found one.
*/ */
@Throws(CryptoStoreErrorException::class)
suspend fun getDevice(userId: String, deviceId: String): CryptoDeviceInfo? = withContext(Dispatchers.IO) { suspend fun getDevice(userId: String, deviceId: String): CryptoDeviceInfo? = withContext(Dispatchers.IO) {
when (val device: Device? = inner.getDevice(userId, deviceId)) { when (val device: Device? = inner.getDevice(userId, deviceId)) {
null -> null null -> null
@ -414,6 +421,7 @@ internal class OlmMachine(user_id: String, device_id: String, path: File, device
* *
* @return The list of Devices or an empty list if there aren't any. * @return The list of Devices or an empty list if there aren't any.
*/ */
@Throws(CryptoStoreErrorException::class)
suspend fun getUserDevices(userId: String): List<CryptoDeviceInfo> { suspend fun getUserDevices(userId: String): List<CryptoDeviceInfo> {
return inner.getUserDevices(userId).map { toCryptoDeviceInfo(it) } return inner.getUserDevices(userId).map { toCryptoDeviceInfo(it) }
} }
@ -481,7 +489,10 @@ internal class OlmMachine(user_id: String, device_id: String, path: File, device
/** /**
* Discard the currently active room key for the given room if there is one. * Discard the currently active room key for the given room if there is one.
*/ */
@Throws(CryptoStoreErrorException::class)
fun discardRoomKey(roomId: String) { fun discardRoomKey(roomId: String) {
this.inner.discardRoomKey(roomId) runBlocking {
inner.discardRoomKey(roomId)
}
} }
} }

View File

@ -27,6 +27,8 @@ pub enum CryptoStoreError {
OlmError(#[from] OlmError), OlmError(#[from] OlmError),
#[error(transparent)] #[error(transparent)]
Serialization(#[from] serde_json::Error), Serialization(#[from] serde_json::Error),
#[error(transparent)]
Identifier(#[from] RumaIdentifierError),
} }
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]

View File

@ -87,13 +87,17 @@ impl OlmMachine {
/// * `user_id` - The id of the device owner. /// * `user_id` - The id of the device owner.
/// ///
/// * `device_id` - The id of the device itself. /// * `device_id` - The id of the device itself.
pub fn get_device(&self, user_id: &str, device_id: &str) -> Option<Device> { pub fn get_device(
let user_id = UserId::try_from(user_id).unwrap(); &self,
user_id: &str,
device_id: &str,
) -> Result<Option<Device>, CryptoStoreError> {
let user_id = UserId::try_from(user_id)?;
self.runtime Ok(self
.block_on(self.inner.get_device(&user_id, device_id.into())) .runtime
.unwrap() .block_on(self.inner.get_device(&user_id, device_id.into()))?
.map(|d| d.into()) .map(|d| d.into()))
} }
/// Get all devices of an user. /// Get all devices of an user.
@ -101,14 +105,15 @@ impl OlmMachine {
/// # Arguments /// # Arguments
/// ///
/// * `user_id` - The id of the device owner. /// * `user_id` - The id of the device owner.
pub fn get_user_devices(&self, user_id: &str) -> Vec<Device> { pub fn get_user_devices(&self, user_id: &str) -> Result<Vec<Device>, CryptoStoreError> {
let user_id = UserId::try_from(user_id).unwrap(); let user_id = UserId::try_from(user_id)?;
self.runtime
.block_on(self.inner.get_user_devices(&user_id)) Ok(self
.unwrap() .runtime
.block_on(self.inner.get_user_devices(&user_id))?
.devices() .devices()
.map(|d| d.into()) .map(|d| d.into())
.collect() .collect())
} }
/// Get our own identity keys. /// Get our own identity keys.
@ -190,8 +195,8 @@ impl OlmMachine {
events: &str, events: &str,
device_changes: DeviceLists, device_changes: DeviceLists,
key_counts: HashMap<String, i32>, key_counts: HashMap<String, i32>,
) { ) -> Result<String, CryptoStoreError> {
let events: ToDevice = serde_json::from_str(events).unwrap(); let events: ToDevice = serde_json::from_str(events)?;
let device_changes: RumaDeviceLists = device_changes.into(); let device_changes: RumaDeviceLists = device_changes.into();
let key_counts: BTreeMap<DeviceKeyAlgorithm, UInt> = key_counts let key_counts: BTreeMap<DeviceKeyAlgorithm, UInt> = key_counts
.into_iter() .into_iter()
@ -205,12 +210,15 @@ impl OlmMachine {
}) })
.collect(); .collect();
self.runtime let events = self
.runtime
.block_on( .block_on(
self.inner self.inner
.receive_sync_changes(&events, &device_changes, &key_counts), .receive_sync_changes(&events, &device_changes, &key_counts),
) )
.unwrap(); .unwrap();
Ok(serde_json::to_string(&events)?)
} }
/// Add the given list of users to be tracked, triggering a key query request /// Add the given list of users to be tracked, triggering a key query request
@ -293,23 +301,24 @@ impl OlmMachine {
/// ///
/// * `users` - The list of users which are considered to be members of the /// * `users` - The list of users which are considered to be members of the
/// room and should receive the room key. /// room and should receive the room key.
pub fn share_group_session(&self, room_id: &str, users: Vec<String>) -> Vec<Request> { pub fn share_group_session(
&self,
room_id: &str,
users: Vec<String>,
) -> Result<Vec<Request>, CryptoStoreError> {
let users: Vec<UserId> = users let users: Vec<UserId> = users
.into_iter() .into_iter()
.filter_map(|u| UserId::try_from(u).ok()) .filter_map(|u| UserId::try_from(u).ok())
.collect(); .collect();
let room_id = RoomId::try_from(room_id).unwrap(); let room_id = RoomId::try_from(room_id)?;
let requests = self let requests = self.runtime.block_on(self.inner.share_group_session(
.runtime
.block_on(self.inner.share_group_session(
&room_id, &room_id,
users.iter(), users.iter(),
EncryptionSettings::default(), EncryptionSettings::default(),
)) ))?;
.unwrap();
requests.into_iter().map(|r| (&*r).into()).collect() Ok(requests.into_iter().map(|r| (&*r).into()).collect())
} }
/// Encrypt the given event with the given type and content for the given /// Encrypt the given event with the given type and content for the given
@ -345,17 +354,22 @@ impl OlmMachine {
/// * `even_type` - The type of the event. /// * `even_type` - The type of the event.
/// ///
/// * `content` - The serialized content of the event. /// * `content` - The serialized content of the event.
pub fn encrypt(&self, room_id: &str, event_type: &str, content: &str) -> String { pub fn encrypt(
let room_id = RoomId::try_from(room_id).unwrap(); &self,
let content: Box<RawValue> = serde_json::from_str(content).unwrap(); room_id: &str,
event_type: &str,
content: &str,
) -> Result<String, CryptoStoreError> {
let room_id = RoomId::try_from(room_id)?;
let content: Box<RawValue> = serde_json::from_str(content)?;
let content = AnyMessageEventContent::from_parts(event_type, content).unwrap(); let content = AnyMessageEventContent::from_parts(event_type, content)?;
let encrypted_content = self let encrypted_content = self
.runtime .runtime
.block_on(self.inner.encrypt(&room_id, content)) .block_on(self.inner.encrypt(&room_id, content))
.unwrap(); .unwrap();
serde_json::to_string(&encrypted_content).unwrap() Ok(serde_json::to_string(&encrypted_content)?)
} }
/// Decrypt the given event that was sent in the given room. /// Decrypt the given event that was sent in the given room.
@ -452,14 +466,17 @@ impl OlmMachine {
/// Discard the currently active room key for the given room if there is /// Discard the currently active room key for the given room if there is
/// one. /// one.
pub fn discard_room_key(&self, room_id: &str) { pub fn discard_room_key(&self, room_id: &str) -> Result<(), CryptoStoreError> {
let room_id = RoomId::try_from(room_id).unwrap(); let room_id = RoomId::try_from(room_id)?;
self.inner.invalidate_group_session(&room_id); self.runtime
.block_on(self.inner.invalidate_group_session(&room_id))?;
Ok(())
} }
pub fn start_verification(&self, device: &Device) -> Result<Sas, CryptoStoreError> { pub fn start_verification(&self, device: &Device) -> Result<Sas, CryptoStoreError> {
let user_id = UserId::try_from(device.user_id.clone()).unwrap(); let user_id = UserId::try_from(device.user_id.clone())?;
let device_id = device.device_id.as_str().into(); let device_id = device.device_id.as_str().into();
let device = self let device = self
.runtime .runtime

View File

@ -27,6 +27,7 @@ enum CryptoStoreError {
"CryptoStore", "CryptoStore",
"OlmError", "OlmError",
"Serialization", "Serialization",
"Identifier",
}; };
[Error] [Error]
@ -89,29 +90,15 @@ interface OlmMachine {
[Throws=MachineCreationError] [Throws=MachineCreationError]
constructor([ByRef] string user_id, [ByRef] string device_id, [ByRef] string path); constructor([ByRef] string user_id, [ByRef] string device_id, [ByRef] string path);
void receive_sync_changes([ByRef] string events,
DeviceLists device_changes,
record<DOMString, i32> key_counts);
[Throws=DecryptionError]
DecryptedEvent decrypt_room_event([ByRef] string event, [ByRef] string room_id);
string encrypt([ByRef] string room_id, [ByRef] string event_type, [ByRef] string content);
record<DOMString, string> identity_keys(); record<DOMString, string> identity_keys();
string user_id(); string user_id();
string device_id(); string device_id();
Device? get_device([ByRef] string user_id, [ByRef] string device_id);
sequence<Device> get_user_devices([ByRef] string user_id);
sequence<Request> outgoing_requests();
void update_tracked_users(sequence<string> users);
[Throws=CryptoStoreError] [Throws=CryptoStoreError]
Request? get_missing_sessions(sequence<string> users); string receive_sync_changes([ByRef] string events,
sequence<Request> share_group_session([ByRef] string room_id, sequence<string> users); DeviceLists device_changes,
record<DOMString, i32> key_counts);
sequence<Request> outgoing_requests();
[Throws=CryptoStoreError] [Throws=CryptoStoreError]
void mark_request_as_sent( void mark_request_as_sent(
[ByRef] string request_id, [ByRef] string request_id,
@ -119,6 +106,22 @@ interface OlmMachine {
[ByRef] string response [ByRef] string response
); );
[Throws=DecryptionError]
DecryptedEvent decrypt_room_event([ByRef] string event, [ByRef] string room_id);
[Throws=CryptoStoreError]
string encrypt([ByRef] string room_id, [ByRef] string event_type, [ByRef] string content);
[Throws=CryptoStoreError]
Device? get_device([ByRef] string user_id, [ByRef] string device_id);
[Throws=CryptoStoreError]
sequence<Device> get_user_devices([ByRef] string user_id);
void update_tracked_users(sequence<string> users);
[Throws=CryptoStoreError]
Request? get_missing_sessions(sequence<string> users);
[Throws=CryptoStoreError]
sequence<Request> share_group_session([ByRef] string room_id, sequence<string> users);
[Throws=CryptoStoreError] [Throws=CryptoStoreError]
Sas start_verification([ByRef] Device device); Sas start_verification([ByRef] Device device);
@ -130,5 +133,6 @@ interface OlmMachine {
[ByRef] string passphrase, [ByRef] string passphrase,
ProgressListener progress_listener ProgressListener progress_listener
); );
[Throws=CryptoStoreError]
void discard_room_key([ByRef] string room_id); void discard_room_key([ByRef] string room_id);
}; };