Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

### Features

- expose enitre read-only API in Kotlin on the `CoreCrypto` type. This allows reading data without opening a
transaction.

- replaced `CoreCrypto.init(database: Database)` with class constructor `new CoreCrypto(database: Database)`

Affected platforms: web
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ fun CoreCryptoFfi.lift() = CoreCrypto(this)
* This wrapper should be largely transparent to end users. It exists to improve the
* callback interfaces: `.transaction(...)`, `.registerFooObserver(...)`, etc.
*/
class CoreCrypto(private val cc: CoreCryptoFfi) {
class CoreCrypto(private val cc: CoreCryptoFfi) : CoreCryptoFfiInterface by cc {
companion object {
/** Opens a core crypto client with the specified database, previously instantiated via [openDatabase]. */
operator fun invoke(
Expand Down Expand Up @@ -128,26 +128,6 @@ class CoreCrypto(private val cc: CoreCryptoFfi) {
return cc.registerHistoryObserver(observerIndirector)
}

/**
* See [CoreCryptoContext.isHistorySharingEnabled]
*
* @param conversationId conversation identifier
* @return true if history sharing is enabled
*/
suspend fun isHistorySharingEnabled(conversationId: ConversationId): Boolean = cc.isHistorySharingEnabled(conversationId)

/**
* Set the PkiEnvironment of the CoreCrypto instance
* @param pkiEnvironment the pki environment to set
*/
suspend fun setPkiEnvironment(pkiEnvironment: PkiEnvironment?) = cc.setPkiEnvironment(pkiEnvironment)

/**
* Get the Pki Environment of the CoreCrypto instance
* @return the pki environment or null if not set
*/
suspend fun getPkiEnvironment(): PkiEnvironment? = cc.getPkiEnvironment()

/**
* Closes this [CoreCrypto] instance and deallocates all loaded resources.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,42 @@ class MLSTest : HasMockDeliveryService() {
}
}

@Test
fun epochObserverEvent_shouldAllowReadingData(): TestResult {
val scope = TestScope()
return scope.runTest {
val (alice) = newClients(this@MLSTest, genClientId())

data class ObserverEvent(val eventEpoch: ULong, val conversationEpoch: ULong)

class Observer : EpochObserver {
val observedEvents = emptyList<ObserverEvent>().toMutableList()

override suspend fun epochChanged(conversationId: ConversationId, epoch: ULong) {
val conversationEpoch = alice.conversationEpoch(conversationId)
observedEvents.add(ObserverEvent(epoch, conversationEpoch))
}
}

val aliceObserver = Observer()

alice.transaction { it.createConversationShort(id) }
val initialEpoch = alice.conversationEpoch(id)

alice.registerEpochObserver(scope, aliceObserver)

alice.transaction { it.updateKeyingMaterial(id) }
val laterEpoch = alice.conversationEpoch(id)

assertEquals(initialEpoch + 1U, laterEpoch)
assertEquals(1, aliceObserver.observedEvents.size, "we triggered exactly 1 epoch change and must have observed that")
assertTrue(
aliceObserver.observedEvents.all { it.eventEpoch == it.conversationEpoch && it.eventEpoch == laterEpoch },
"event epoch must equal the epoch read during the event"
)
}
}

@Test
fun registerHistoryObserver_should_notify_observer_on_new_secret(): TestResult {
val scope = TestScope()
Expand Down
21 changes: 19 additions & 2 deletions crypto-ffi/src/core_crypto/e2ei/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use core_crypto::RecursiveError;
use core_crypto::{RecursiveError, mls::conversation::Conversation as _};

use crate::{Ciphersuite, CoreCryptoFfi, CoreCryptoResult};
use crate::{Ciphersuite, ConversationId, CoreCryptoFfi, CoreCryptoResult, E2eiConversationState};

pub(crate) mod identities;

Expand All @@ -26,4 +26,21 @@ impl CoreCryptoFfi {
.map_err(RecursiveError::mls_client("checking if e2ei is enabled"))
.map_err(Into::into)
}

/// See [core_crypto::mls::conversation::Conversation::e2ei_conversation_state]
pub async fn e2ei_conversation_state(
&self,
conversation_id: &ConversationId,
) -> CoreCryptoResult<E2eiConversationState> {
self.inner
.mls_session()
.await?
.get_raw_conversation(conversation_id.as_ref())
.await
.map_err(RecursiveError::mls_client("getting conversation by id"))?
.e2ei_conversation_state()
.await
.map(Into::into)
.map_err(Into::into)
}
}
Loading