Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
fab0dc2
refactor: decouple session creation from client construction
fewerner Dec 8, 2025
0a80fc4
refactor: session init can't live on a session instance
fewerner Dec 8, 2025
84bbbb0
refactor: getting client id from session
fewerner Dec 16, 2025
cf45b88
refactor: adjust generate_history_secret
fewerner Dec 9, 2025
9d6cdc9
refactor: remove in_memory_cc
fewerner Dec 9, 2025
30d24f2
refactor: adjust history_client
fewerner Dec 9, 2025
6422456
test: refactor `SessionContext.new_with_identifier()`
fewerner Dec 10, 2025
319af58
refactor: use cc's keystore directly
fewerner Dec 10, 2025
fe20ba8
refactor: adjust transaction context to new mls session
fewerner Dec 11, 2025
fcd9a41
refactor: rename `mls_client` to `mls_session`
fewerner Dec 12, 2025
522fcd6
refactor: adjust transport getter
fewerner Dec 12, 2025
fbdc366
refactor: remove methods for inner session
fewerner Dec 12, 2025
170176d
refactor: remove deref from CoreCrypto to mls session
fewerner Dec 12, 2025
e477bff
refactor: lock identities
fewerner Dec 12, 2025
2df6b64
refactor: adjust e2ei_mls_init_only
fewerner Dec 15, 2025
5f3fbce
test: adjust cc_can_init tests
fewerner Dec 15, 2025
3a87da5
refactor: getter for mls session
fewerner Dec 15, 2025
219a885
refactor: ffi: access session methods via `mls_session()`
fewerner Dec 15, 2025
c79d7bf
refactor: ffi: remove `provide_transport()`
fewerner Dec 15, 2025
17e4b6d
refactor: rename keystore to database
fewerner Dec 15, 2025
5df497f
feat: ffi: provide transport with session initialization
fewerner Dec 15, 2025
002968a
test: adjust test to provide transport
fewerner Dec 15, 2025
2a582f9
refactor: close db without relying on session
fewerner Dec 15, 2025
7c06ddf
refactor: interop: adjust Session initialization
fewerner Dec 16, 2025
48ab9f4
refactor: benches: caller already passes in CoreCrypto instance
fewerner Dec 16, 2025
c52607c
refactor: benches: adjust session init
fewerner Dec 16, 2025
aa6cad1
test: adjust `identities_count()`
fewerner Dec 16, 2025
cd3ff8b
test: adjust session init
fewerner Dec 16, 2025
2000933
test: remove obsolete test
fewerner Dec 16, 2025
ff75095
test: wrap session in `Arc<RwLock<_>>`
fewerner Dec 17, 2025
057c465
test: use session getter and await `SessionContext.session()`
fewerner Dec 17, 2025
893e365
test: adjust replace transport
fewerner Dec 17, 2025
53ce1b2
test: transport is provided with session initialization
fewerner Dec 17, 2025
8afd3bb
style: access level and format
fewerner Dec 17, 2025
dda2548
test: remove `new_uninitialized()` helper for `SessionContext`
SimonThormeyer Dec 17, 2025
bf782fb
test: `e2ei_enrollment()` helper doesn't need a `SessionContext`
SimonThormeyer Dec 17, 2025
767c423
test: update tests to new api of helper function
SimonThormeyer Dec 17, 2025
1269e96
test: remove now unnecessary test
SimonThormeyer Dec 17, 2025
190a757
test: implement `SessionContext.reinit_session()`
fewerner Dec 17, 2025
c1f30af
test: move random generate to SessionContext
fewerner Dec 18, 2025
487eb6f
test: change `Session.reset()` usage to `SessionContext.reinit_sessio…
fewerner Dec 18, 2025
3478084
test: let sessionContext know it's cc instance
fewerner Dec 18, 2025
7abd401
test: remove obsolete test
fewerner Dec 18, 2025
e52185f
refactor: access database through keystore getter
fewerner Dec 19, 2025
ed36c02
test: refactor test
fewerner Dec 10, 2025
6d6601e
test: disable tests
fewerner Dec 19, 2025
f49edc8
feat!: ffi: ts: remove `.provide_transport()`, add transport to `.mls…
fewerner Jan 5, 2026
f2fe442
test: remove unwanted logs
fewerner Jan 5, 2026
a559df5
test: ts: remove provide transport from test utils
fewerner Jan 6, 2026
cf2f6f8
test: ts: set transport before ccInit
fewerner Jan 6, 2026
bc0e6a1
feat!: ffi: kotlin: remove `.provideTransport()`
fewerner Jan 6, 2026
c83aa24
test: kotlin: set transport on `mlsInit()`
fewerner Jan 6, 2026
de61b2f
test: temporarily disable test
fewerner Jan 6, 2026
6fa2097
feat!: ffi: swift: remove `.provide_transport()`
fewerner Jan 6, 2026
5821220
test: swift: set transport on `mlsInit()`
fewerner Jan 6, 2026
7070dec
test: interop: set transport on 'mlsInit()'.
fewerner Jan 6, 2026
23c906d
test: ts: set transport on `mlsInit()`
fewerner Jan 6, 2026
c173ace
test: ts: access conversation epoch through transaction
fewerner Jan 6, 2026
d78584b
docs: add ffi change to change log
fewerner Jan 7, 2026
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
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@

### Features

- removed `CoreCrypto.provideTransport()`, added `transport` parameter to `CoreCryptoContext.mlsInit()`

Instead of providing transport separately from session initialization it is now provided when initializing the MLS
session.

Affected platforms: android, ios, web

- renamed `CoreCrypto.reseedRng()` to `CoreCrypto.reseed()`

Affected platforms: web
Expand Down
25 changes: 20 additions & 5 deletions crypto-ffi/bindings/js/src/CoreCryptoContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ import {
import * as CoreCryptoFfiTypes from "./autogenerated/core_crypto_ffi";

import { CoreCryptoError } from "./CoreCryptoError";
import { CredentialType, WelcomeBundle } from "./CoreCryptoMLS";
import {
CredentialType,
mlsTransportToFfi,
WelcomeBundle,
type MlsTransport,
} from "./CoreCryptoMLS";

import {
type CRLRegistration,
Expand Down Expand Up @@ -74,16 +79,24 @@ export class CoreCryptoContext {

/**
* Use this after {@link CoreCrypto.init} when you have a clientId. It initializes MLS.
* Registers the transport callbacks for core crypto to give it access to backend endpoints for sending
* a commit bundle or a message, respectively.
*
* @param clientId - required
* @param ciphersuites - All the ciphersuites supported by this MLS client
* @param transport - Any implementor of the {@link MlsTransport} interface
*/
async mlsInit(
clientId: ClientId,
ciphersuites: Ciphersuite[]
ciphersuites: Ciphersuite[],
transport: MlsTransport
): Promise<void> {
return await CoreCryptoError.asyncMapErr(
this.#ctx.mlsInit(clientId, ciphersuites)
this.#ctx.mlsInit(
clientId,
ciphersuites,
mlsTransportToFfi(transport)
)
);
}

Expand Down Expand Up @@ -733,11 +746,13 @@ export class CoreCryptoContext {
*/
async e2eiMlsInitOnly(
enrollment: E2eiEnrollment,
certificateChain: string
certificateChain: string,
transport: MlsTransport
): Promise<NewCrlDistributionPoints> {
return await this.#ctx.e2eiMlsInitOnly(
enrollment.inner(),
certificateChain
certificateChain,
mlsTransportToFfi(transport)
);
}

Expand Down
23 changes: 1 addition & 22 deletions crypto-ffi/bindings/js/src/CoreCryptoInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,7 @@ import {
} from "./autogenerated/core_crypto_ffi";

import { CoreCryptoError, ErrorType } from "./CoreCryptoError";
import {
CredentialType,
type MlsTransport,
mlsTransportToFfi,
} from "./CoreCryptoMLS";
import { CredentialType } from "./CoreCryptoMLS";

import { CoreCryptoContext } from "./CoreCryptoContext";

Expand Down Expand Up @@ -162,23 +158,6 @@ export class CoreCrypto {
}
}

/**
* Registers the transport callbacks for core crypto to give it access to backend endpoints for sending
* a commit bundle or a message, respectively.
*
* @param transport - Any implementor of the {@link MlsTransport} interface
* @param _ctx - unused
*/
async provideTransport(
transport: MlsTransport,
_ctx: unknown = null
): Promise<void> {
const transport_ffi = mlsTransportToFfi(transport);
return await CoreCryptoError.asyncMapErr(
this.#cc.provideTransport(transport_ffi)
);
}

/**
* See {@link CoreCryptoContext.conversationExists}.
*/
Expand Down
2 changes: 1 addition & 1 deletion crypto-ffi/bindings/js/src/CoreCryptoMLS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ function mapTransportResponseToFfi(

/**
* An interface that must be implemented and provided to CoreCrypto via
* {@link CoreCrypto.provideTransport}.
* {@link CoreCryptoContext.mlsInit}.
*/
export interface MlsTransport {
/**
Expand Down
7 changes: 5 additions & 2 deletions crypto-ffi/bindings/js/test/bun/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,14 @@ export async function ccInit(clientId?: ClientId): Promise<CoreCrypto> {
const db = await inMemoryDatabase(key);

const cc = await CoreCrypto.init(db);
await cc.provideTransport(DELIVERY_SERVICE);

if (clientId) {
await cc.transaction(async (ctx) => {
await ctx.mlsInit(clientId, [ciphersuiteDefault()]);
await ctx.mlsInit(
clientId,
[ciphersuiteDefault()],
DELIVERY_SERVICE
);
});
}

Expand Down
26 changes: 17 additions & 9 deletions crypto-ffi/bindings/js/test/wdio/database.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,11 @@ describe("database", () => {
let cc = await window.ccModule.CoreCrypto.init(database);
cc.transaction(async (ctx) => {
const clientId = makeClientId();
await ctx.mlsInit(makeClientId(), [cipherSuite]);
await ctx.mlsInit(
makeClientId(),
[cipherSuite],
window.deliveryService
);
await ctx.addCredential(
window.ccModule.credentialBasic(cipherSuite, clientId)
);
Expand Down Expand Up @@ -91,7 +95,11 @@ describe("database", () => {

cc = await window.ccModule.CoreCrypto.init(newDatabase);
const pubkey2 = await cc.transaction(async (ctx) => {
await ctx.mlsInit(makeClientId(), [cipherSuite]);
await ctx.mlsInit(
makeClientId(),
[cipherSuite],
window.deliveryService
);
return await ctx.clientPublicKey(
cipherSuite,
window.ccModule.CredentialType.Basic
Expand Down Expand Up @@ -149,7 +157,6 @@ describe("database", () => {
}
}

console.log("before close");
// It is important to close the database here since otherwise the migration process
// will be stuck because we'd be holding a connection to the same database open.
db.close();
Expand All @@ -164,7 +171,6 @@ describe("database", () => {
old_key,
new_key
);
console.log("before open db");

// Reconstruct the client based on the migrated database and fetch the epoch.
const encoder = new TextEncoder();
Expand All @@ -174,11 +180,13 @@ describe("database", () => {
);

const instance = await window.ccModule.CoreCrypto.init(database);
const epoch = await instance.conversationEpoch(
new window.ccModule.ConversationId(
encoder.encode("convId").buffer
)
);
const epoch = await instance.transaction(async (ctx) => {
return await ctx.conversationEpoch(
new window.ccModule.ConversationId(
encoder.encode("convId").buffer
)
);
});
return epoch;
}, JSON.stringify(stores));

Expand Down
16 changes: 14 additions & 2 deletions crypto-ffi/bindings/js/test/wdio/errors.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,20 @@ describe("core crypto errors", () => {
it("should be correct when message rejected", async () => {
const alice = crypto.randomUUID();
const convId = crypto.randomUUID();

browser.execute((_) => {
const transport_override = {
async sendCommitBundle(_: CommitBundle) {
return { abort: { reason: "just testing" } };
},
};

window.deliveryService = {
...window.deliveryService,
...transport_override,
};
});

await ccInit(alice);
await createConversation(alice, convId);

Expand All @@ -145,8 +159,6 @@ describe("core crypto errors", () => {
},
};

cc.provideTransport(window.deliveryService);

const conversationId = new window.ccModule.ConversationId(
new TextEncoder().encode(convId).buffer
);
Expand Down
8 changes: 5 additions & 3 deletions crypto-ffi/bindings/js/test/wdio/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,16 +179,18 @@ export async function ccInit(

const instance = await window.ccModule.CoreCrypto.init(database);
await instance.transaction(async (ctx) => {
await ctx.mlsInit(clientId, [cipherSuite]);
await ctx.mlsInit(
clientId,
[cipherSuite],
window.deliveryService
);
if (withCredential) {
await ctx.addCredential(
window.ccModule.credentialBasic(cipherSuite, clientId)
);
}
});

await instance.provideTransport(window.deliveryService);

if (window.cc === undefined) {
window.cc = new Map();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,14 +93,6 @@ class CoreCrypto(private val cc: CoreCryptoFfi) {
return@withContext result as R
}

/** Provide an implementation of the MlsTransport interface.
* See [MlsTransport].
* @param transport the transport to be used
*/
suspend fun provideTransport(transport: MlsTransport) {
cc.provideTransport(transport)
}

/**
* Register an Epoch Observer which will be notified every time a conversation's epoch changes.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import org.assertj.core.api.AssertionsForInterfaceTypes.assertThat
import testutils.*
import java.nio.file.Files
import kotlin.test.BeforeTest
import kotlin.test.Ignore
import kotlin.test.Test

internal class E2EITest : HasMockDeliveryService() {
Expand All @@ -19,6 +20,7 @@ internal class E2EITest : HasMockDeliveryService() {
setupMocks()
}

@Ignore("Temporarily broken until PKI environment is decoupled from session initialization implemented with WPB-19578")
@Test
fun sample_e2ei_enrollment_should_succeed() = runTest {
val aliceId = genClientId()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package com.wire.crypto

import kotlinx.coroutines.test.runTest
import org.assertj.core.api.AssertionsForInterfaceTypes.assertThat
import testutils.MockMlsTransportSuccessProvider
import testutils.genDatabaseKey
import java.nio.file.Files
import kotlin.io.path.*
Expand Down Expand Up @@ -93,8 +94,9 @@ class DatabaseKeyTest {
val clientId = "alice".toClientId()
val db = openDatabase(path.absolutePathString(), oldKey)
var cc = CoreCrypto(db)
var transport = MockMlsTransportSuccessProvider()
val pubkey1 = cc.transaction {
it.mlsInit(clientId = clientId, ciphersuites = CIPHERSUITES_DEFAULT)
it.mlsInit(clientId = clientId, ciphersuites = CIPHERSUITES_DEFAULT, transport)
it.addCredential(Credential.basic(CIPHERSUITE_DEFAULT, clientId))
it.clientPublicKey(CIPHERSUITE_DEFAULT, CREDENTIAL_TYPE_DEFAULT)
}
Expand All @@ -107,7 +109,7 @@ class DatabaseKeyTest {
val newDb = openDatabase(path.absolutePathString(), newKey)
cc = CoreCrypto(newDb)
val pubkey2 = cc.transaction {
it.mlsInit(clientId = clientId, ciphersuites = CIPHERSUITES_DEFAULT)
it.mlsInit(clientId = clientId, ciphersuites = CIPHERSUITES_DEFAULT, transport)
it.clientPublicKey(CIPHERSUITE_DEFAULT, CREDENTIAL_TYPE_DEFAULT)
}
cc.close()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ fun initCc(_instance: HasMockDeliveryService): CoreCrypto = runBlocking {
val key = genDatabaseKey()
val db = openDatabase(path.absolutePath, key)
val cc = CoreCrypto(db)
cc.provideTransport(HasMockDeliveryService.mockDeliveryService)
cc
}

Expand All @@ -98,7 +97,9 @@ fun randomIdentifier(n: Int = 12): String {
}

/** Shorthand for initializing MLS with only a client id */
suspend fun CoreCryptoContext.mlsInitShort(clientId: ClientId) = mlsInit(clientId, CIPHERSUITES_DEFAULT)
suspend fun CoreCryptoContext.mlsInitShort(
clientId: ClientId
) = mlsInit(clientId, CIPHERSUITES_DEFAULT, HasMockDeliveryService.mockDeliveryService)

/** Shorthand for creating a conversation with defaults */
suspend fun CoreCryptoContext.createConversationShort(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,6 @@ public protocol CoreCryptoProtocol {
_ block: @escaping (_ context: CoreCryptoContextProtocol) async throws -> Result
) async throws -> Result

/// Register a callback which will be called when performing MLS operations which require communication
/// with the delivery service.
///
func provideTransport(transport: any MlsTransport) async throws

///
/// Register an Epoch Observer which will be notified every time a conversation's epoch changes.
///
Expand Down Expand Up @@ -134,11 +129,6 @@ public final class CoreCrypto: CoreCryptoProtocol {
return await transactionExecutor.result!
}

public func provideTransport(transport: any MlsTransport) async throws {
try await coreCrypto.provideTransport(
callbacks: transport)
}

public func registerEpochObserver(_ epochObserver: EpochObserver) async throws {
// we want to wrap the observer here to provide async indirection, so that no matter what
// the observer that makes its way to the Rust side of things doesn't end up blocking
Expand Down
Loading
Loading