crypto: Update to the latest rust-sdk version

This commit is contained in:
Damir Jelić 2021-11-17 13:22:15 +01:00
parent a3af73261c
commit 50cdbaf041
9 changed files with 105 additions and 57 deletions

View file

@ -47,7 +47,6 @@ import org.matrix.android.sdk.internal.session.sync.model.DeviceListResponse
import org.matrix.android.sdk.internal.session.sync.model.DeviceOneTimeKeysCountSyncResponse
import org.matrix.android.sdk.internal.session.sync.model.ToDeviceSyncResponse
import timber.log.Timber
import uniffi.olm.BackupKey
import uniffi.olm.BackupKeys
import uniffi.olm.CrossSigningKeyExport
import uniffi.olm.CrossSigningStatus
@ -56,6 +55,7 @@ import uniffi.olm.DecryptionException
import uniffi.olm.DeviceLists
import uniffi.olm.KeyRequestPair
import uniffi.olm.Logger
import uniffi.olm.MegolmV1BackupKey
import uniffi.olm.Request
import uniffi.olm.RequestType
import uniffi.olm.RoomKeyCounts
@ -790,10 +790,10 @@ internal class OlmMachine(
}
@Throws(CryptoStoreException::class)
suspend fun enableBackup(key: String, version: String) {
suspend fun enableBackupV1(key: String, version: String) {
return withContext(Dispatchers.Default) {
val backupKey = BackupKey(key, mapOf(), null)
inner.enableBackup(backupKey, version)
val backupKey = MegolmV1BackupKey(key, mapOf(), null, MXCRYPTO_ALGORITHM_MEGOLM_BACKUP)
inner.enableBackupV1(backupKey, version)
}
}

View file

@ -125,7 +125,7 @@ internal class RustKeyBackupService @Inject constructor(
BackupRecoveryKey()
}
val publicKey = key.publicKey()
val publicKey = key.megolmV1PublicKey()
val backupAuthData = SignalableMegolmBackupAuthData(
publicKey = publicKey.publicKey,
privateKeySalt = publicKey.passphraseInfo?.privateKeySalt,
@ -144,7 +144,7 @@ internal class RustKeyBackupService @Inject constructor(
)
MegolmBackupCreationInfo(
algorithm = MXCRYPTO_ALGORITHM_MEGOLM_BACKUP,
algorithm = publicKey.backupAlgorithm,
authData = signedMegolmBackupAuthData,
recoveryKey = key.toBase58()
)
@ -264,7 +264,8 @@ internal class RustKeyBackupService @Inject constructor(
override fun backupAllGroupSessions(progressListener: ProgressListener?,
callback: MatrixCallback<Unit>?) {
// This is only used in tests?
// This is only used in tests? While it's fine have methods that are
// only used for tests, this one has a lot of logic that is nowhere else used.
TODO()
}
@ -354,7 +355,7 @@ internal class RustKeyBackupService @Inject constructor(
// Check that the recovery key matches to the public key that we downloaded from the server.
// If they match, we can trust the public key and enable backups since we have the private key.
private fun checkRecoveryKey(recoveryKey: BackupRecoveryKey, keysBackupData: KeysVersionResult) {
val backupKey = recoveryKey.publicKey()
val backupKey = recoveryKey.megolmV1PublicKey()
val authData = getMegolmBackupAuthData(keysBackupData)
when {
@ -474,7 +475,7 @@ internal class RustKeyBackupService @Inject constructor(
if (ciphertext != null && mac != null && ephemeralKey != null) {
try {
val decrypted = key.decrypt(ephemeralKey, mac, ciphertext)
val decrypted = key.decryptV1(ephemeralKey, mac, ciphertext)
val moshi = MoshiProvider.providesMoshi()
val adapter = moshi.adapter(MegolmSessionData::class.java)
@ -729,7 +730,7 @@ internal class RustKeyBackupService @Inject constructor(
}
private fun isValidRecoveryKey(recoveryKey: BackupRecoveryKey, version: KeysVersionResult): Boolean {
val publicKey = recoveryKey.publicKey().publicKey
val publicKey = recoveryKey.megolmV1PublicKey().publicKey
val authData = getMegolmBackupAuthData(version) ?: return false
return authData.publicKey == publicKey
}
@ -800,7 +801,7 @@ internal class RustKeyBackupService @Inject constructor(
if (retrievedMegolmBackupAuthData != null) {
try {
olmMachine.enableBackup(retrievedMegolmBackupAuthData.publicKey, keysVersionResult.version)
olmMachine.enableBackupV1(retrievedMegolmBackupAuthData.publicKey, keysVersionResult.version)
keysBackupVersion = keysVersionResult
} catch (e: OlmException) {
Timber.e(e, "OlmException")

View file

@ -29,11 +29,11 @@ features = ["lax_deserialize"]
[dependencies.matrix-sdk-common]
git = "https://github.com/matrix-org/matrix-rust-sdk/"
rev = "1943840b82fd323455d9ca9ce27243d37a660569"
rev = "2e4d5f25cba03bd26415b91defd6e762e8c31b63"
[dependencies.matrix-sdk-crypto]
git = "https://github.com/matrix-org/matrix-rust-sdk/"
rev = "1943840b82fd323455d9ca9ce27243d37a660569"
rev = "2e4d5f25cba03bd26415b91defd6e762e8c31b63"
features = ["sled_cryptostore", "qrcode", "backups_v1"]
[dependencies.tokio]

View file

@ -5,7 +5,10 @@ use sha2::Sha512;
use std::{collections::HashMap, iter};
use thiserror::Error;
use matrix_sdk_crypto::backups::{OlmPkDecryptionError, RecoveryKey};
use matrix_sdk_crypto::{
backups::{OlmPkDecryptionError, RecoveryKey},
store::CryptoStoreError as InnerStoreError,
};
/// The private part of the backup key, the one used for recovery.
pub struct BackupRecoveryKey {
@ -26,6 +29,9 @@ pub enum DecodeError {
/// An error happened while decoding the recovery key.
#[error(transparent)]
Decode(#[from] matrix_sdk_crypto::backups::DecodeError),
/// An error happened in the storage layer,
#[error(transparent)]
CryptoStore(#[from] InnerStoreError),
}
/// Struct containing info about the way the backup key got derived from a
@ -39,13 +45,15 @@ pub struct PassphraseInfo {
}
/// The public part of the backup key.
pub struct BackupKey {
pub struct MegolmV1BackupKey {
/// The actuall base64 encoded public key.
pub public_key: String,
/// Signatures that have signed our backup key.
pub signatures: HashMap<String, HashMap<String, String>>,
/// The passphrase info, if the key was derived from one.
pub passphrase_info: Option<PassphraseInfo>,
/// Get the full name of the backup algorithm this backup key supports.
pub backup_algorithm: String,
}
impl BackupRecoveryKey {
@ -107,8 +115,8 @@ impl BackupRecoveryKey {
}
/// Get the public part of the backup key.
pub fn public_key(&self) -> BackupKey {
let public_key = self.inner.public_key();
pub fn megolm_v1_public_key(&self) -> MegolmV1BackupKey {
let public_key = self.inner.megolm_v1_public_key();
let signatures: HashMap<String, HashMap<String, String>> = public_key
.signatures()
@ -121,10 +129,11 @@ impl BackupRecoveryKey {
})
.collect();
BackupKey {
MegolmV1BackupKey {
public_key: public_key.to_base64(),
signatures,
passphrase_info: self.passphrase_info.clone(),
backup_algorithm: public_key.backup_algorithm().to_owned(),
}
}
@ -140,14 +149,14 @@ impl BackupRecoveryKey {
/// Try to decrypt a message that was encrypted using the public part of the
/// backup key.
pub fn decrypt(
pub fn decrypt_v1(
&self,
ephemeral_key: String,
mac: String,
ciphertext: String,
) -> Result<String, PkDecryptionError> {
self.inner
.decrypt(ephemeral_key, mac, ciphertext)
.decrypt_v1(ephemeral_key, mac, ciphertext)
.map_err(|e| e.into())
}
}

View file

@ -2,7 +2,7 @@
use matrix_sdk_crypto::{
store::CryptoStoreError as InnerStoreError, KeyExportError, MegolmError, OlmError,
SignatureError as InnerSignatureError, SecretImportError as RustSecretImportError,
SecretImportError as RustSecretImportError, SignatureError as InnerSignatureError,
};
use ruma::identifiers::Error as RumaIdentifierError;
@ -12,6 +12,8 @@ pub enum KeyImportError {
Export(#[from] KeyExportError),
#[error(transparent)]
CryptoStore(#[from] InnerStoreError),
#[error(transparent)]
Json(#[from] serde_json::Error),
}
#[derive(Debug, thiserror::Error)]

View file

@ -18,7 +18,7 @@ mod users;
mod verification;
pub use backup_recovery_key::{
BackupKey, BackupRecoveryKey, DecodeError, PassphraseInfo, PkDecryptionError,
BackupRecoveryKey, DecodeError, MegolmV1BackupKey, PassphraseInfo, PkDecryptionError,
};
pub use device::Device;
pub use error::{
@ -87,19 +87,19 @@ pub struct CrossSigningKeyExport {
pub user_signing_key: Option<String>,
}
/// TODO
/// Struct holding the number of room keys we have.
pub struct RoomKeyCounts {
/// TODO
/// The total number of room keys.
pub total: i64,
/// TODO
/// The number of backed up room keys.
pub backed_up: i64,
}
/// TODO
/// Backup keys and information we load from the store.
pub struct BackupKeys {
/// TODO
/// The recovery key as a base64 encoded string.
pub recovery_key: String,
/// TODO
/// The version that is used with the recovery key.
pub backup_version: String,
}

View file

@ -32,7 +32,7 @@ use tokio::runtime::Runtime;
use matrix_sdk_common::{deserialized_responses::AlgorithmInfo, uuid::Uuid};
use matrix_sdk_crypto::{
backups::{MegolmV1BackupKey, RecoveryKey},
backups::{MegolmV1BackupKey as RustBackupKey, RecoveryKey},
decrypt_key_export, encrypt_key_export,
matrix_qrcode::QrVerificationData,
olm::ExportedRoomKey,
@ -43,11 +43,11 @@ use matrix_sdk_crypto::{
use crate::{
error::{CryptoStoreError, DecryptionError, SecretImportError, SignatureError},
responses::{response_from_string, OutgoingVerificationRequest, OwnedResponse},
BackupKey, BackupKeys, BootstrapCrossSigningResult, ConfirmVerificationResult,
CrossSigningKeyExport, CrossSigningStatus, DecryptedEvent, Device, DeviceLists, KeyImportError,
KeysImportResult, ProgressListener, QrCode, Request, RequestType, RequestVerificationResult,
RoomKeyCounts, ScanResult, SignatureUploadRequest, StartSasResult, UserIdentity, Verification,
VerificationRequest,
BackupKeys, BootstrapCrossSigningResult, ConfirmVerificationResult, CrossSigningKeyExport,
CrossSigningStatus, DecodeError, DecryptedEvent, Device, DeviceLists, KeyImportError,
KeysImportResult, MegolmV1BackupKey, ProgressListener, QrCode, Request, RequestType,
RequestVerificationResult, RoomKeyCounts, ScanResult, SignatureUploadRequest, StartSasResult,
UserIdentity, Verification, VerificationRequest,
};
/// A high level state machine that handles E2EE for Matrix.
@ -79,7 +79,7 @@ impl OlmMachine {
pub fn new(user_id: &str, device_id: &str, path: &str) -> Result<Self, CryptoStoreError> {
let user_id = UserId::try_from(user_id)?;
let device_id = device_id.into();
let runtime = Runtime::new().unwrap();
let runtime = Runtime::new().expect("Couldn't create a tokio runtime");
Ok(OlmMachine {
inner: runtime.block_on(InnerMachine::new_with_default_store(
@ -499,7 +499,7 @@ impl OlmMachine {
let encrypted_content = self
.runtime
.block_on(self.inner.encrypt(&room_id, content))
.unwrap();
.expect("Encrypting an event produced an error");
Ok(serde_json::to_string(&encrypted_content)?)
}
@ -644,13 +644,24 @@ impl OlmMachine {
self.impor_keys_helper(keys, progress_listener)
}
/// TODO
/// Import room keys from the given serialized unencrypted key export.
///
/// This method is the same as [`OlmMachine::import_keys`] but the
/// decryption step is skipped and should be performed by the caller. This
/// may be useful for custom handling or for server-side key backups.
///
/// # Arguments
///
/// * `keys` - The serialized version of the unencrypted key export.
///
/// * `progress_listener` - A callback that can be used to introspect the
/// progress of the key import.
pub fn import_decrypted_keys(
&self,
keys: &str,
progress_listener: Box<dyn ProgressListener>,
) -> Result<KeysImportResult, KeyImportError> {
let keys: Vec<ExportedRoomKey> = serde_json::from_str(keys).unwrap();
let keys: Vec<ExportedRoomKey> = serde_json::from_str(keys)?;
self.impor_keys_helper(keys, progress_listener)
}
@ -1263,30 +1274,47 @@ impl OlmMachine {
Ok(())
}
/// TODO
pub fn enable_backup(&self, key: BackupKey, version: String) -> Result<(), CryptoStoreError> {
let backup_key = MegolmV1BackupKey::from_base64(&key.public_key).unwrap();
/// Activate the given backup key to be used with the given backup version.
///
/// **Warning**: The caller needs to make sure that the given `BackupKey` is
/// trusted, otherwise we might be encrypting room keys that a malicious
/// party could decrypt.
///
/// The [`OlmMachine::verify_backup`] method can be used to so.
pub fn enable_backup_v1(
&self,
key: MegolmV1BackupKey,
version: String,
) -> Result<(), DecodeError> {
let backup_key = RustBackupKey::from_base64(&key.public_key)?;
backup_key.set_version(version);
self.runtime
.block_on(self.inner.backup_machine().enable_backup(backup_key))?;
.block_on(self.inner.backup_machine().enable_backup_v1(backup_key))?;
Ok(())
}
/// TODO
/// Are we able to encrypt room keys.
///
/// This returns true if we have an active `BackupKey` and backup version
/// registered with the state machine.
pub fn backup_enabled(&self) -> bool {
self.runtime.block_on(self.inner.backup_machine().enabled())
}
/// TODO
/// Disable and reset our backup state.
///
/// This will remove any pending backup request, remove the backup key and
/// reset the backup state of each room key we have.
pub fn disable_backup(&self) -> Result<(), CryptoStoreError> {
Ok(self
.runtime
.block_on(self.inner.backup_machine().disable_backup())?)
}
/// TODO
/// Encrypt a batch of room keys and return a request that needs to be sent
/// out to backup the room keys.
pub fn backup_room_keys(&self) -> Result<Option<Request>, CryptoStoreError> {
let request = self
.runtime
@ -1297,7 +1325,7 @@ impl OlmMachine {
Ok(request)
}
/// TODO
/// Get the number of backed up room keys and the total number of room keys.
pub fn room_key_counts(&self) -> Result<RoomKeyCounts, CryptoStoreError> {
Ok(self
.runtime
@ -1305,7 +1333,10 @@ impl OlmMachine {
.into())
}
/// TODO
/// Store the recovery key in the cryptostore.
///
/// This is useful if the client wants to support gossiping of the backup
/// key.
pub fn save_recovery_key(
&self,
key: Option<String>,
@ -1321,7 +1352,7 @@ impl OlmMachine {
.block_on(self.inner.backup_machine().save_recovery_key(key, version))?)
}
/// TODO
/// Get the backup keys we have saved in our crypto store.
pub fn get_backup_keys(&self) -> Result<Option<BackupKeys>, CryptoStoreError> {
Ok(self
.runtime
@ -1330,7 +1361,8 @@ impl OlmMachine {
.ok())
}
/// TODO
/// Sign the given message using our device key and if available cross
/// signing master key.
pub fn sign(&self, message: &str) -> HashMap<String, HashMap<String, String>> {
self.runtime
.block_on(self.inner.sign(message))
@ -1344,7 +1376,8 @@ impl OlmMachine {
.collect()
}
/// TODO
/// Check if the given backup has been verified by us or by another of our
/// devices that we trust.
pub fn verify_backup(&self, auth_data: &str) -> Result<bool, CryptoStoreError> {
let auth_data = serde_json::from_str(auth_data)?;
Ok(self

View file

@ -19,6 +19,7 @@ enum PkDecryptionError {
enum KeyImportError {
"Export",
"CryptoStore",
"Json",
};
[Error]
@ -357,8 +358,8 @@ interface OlmMachine {
boolean is_identity_verified([ByRef] string user_id);
record<DOMString, record<DOMString, string>> sign([ByRef] string message);
[Throws=CryptoStoreError]
void enable_backup(BackupKey key, string version);
[Throws=DecodeError]
void enable_backup_v1(MegolmV1BackupKey key, string version);
[Throws=CryptoStoreError]
void disable_backup();
[Throws=CryptoStoreError]
@ -379,10 +380,11 @@ dictionary PassphraseInfo {
i32 private_key_iterations;
};
dictionary BackupKey {
dictionary MegolmV1BackupKey {
string public_key;
record<DOMString, record<DOMString, string>> signatures;
PassphraseInfo? passphrase_info;
string backup_algorithm;
};
dictionary BackupKeys {
@ -398,6 +400,7 @@ dictionary RoomKeyCounts {
[Error]
enum DecodeError {
"Decode",
"CryptoStore",
};
interface BackupRecoveryKey {
@ -412,7 +415,7 @@ interface BackupRecoveryKey {
constructor(string key);
string to_base58();
string to_base64();
BackupKey public_key();
MegolmV1BackupKey megolm_v1_public_key();
[Throws=PkDecryptionError]
string decrypt(string ephemeral_key, string mac, string ciphertext);
string decrypt_v1(string ephemeral_key, string mac, string ciphertext);
};

View file

@ -10,13 +10,13 @@ pub enum Verification {
/// The `m.sas.v1` verification flow.
SasV1 {
#[allow(missing_docs)]
sas: Sas
sas: Sas,
},
/// The `m.qr_code.scan.v1`, `m.qr_code.show.v1`, and `m.reciprocate.v1`
/// verification flow.
QrCodeV1 {
#[allow(missing_docs)]
qrcode: QrCode
qrcode: QrCode,
},
}