Skip to content

Commit

Permalink
feat: CoreCrypto draft-20 upgrade
Browse files Browse the repository at this point in the history
  • Loading branch information
OtaK authored and beltram committed Jun 9, 2023
1 parent 19fd4c0 commit 4e7d907
Show file tree
Hide file tree
Showing 117 changed files with 5,020 additions and 5,244 deletions.
41 changes: 19 additions & 22 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ exclude = [
]
resolver = "2"

[workspace.dependencies]
tls_codec = "0.3.0-pre.3"

[patch.crates-io.schnellru]
git = "https://github.com/otak/schnellru"
branch = "feat/try-insert"
Expand All @@ -39,33 +42,32 @@ branch = "otak/2.0-error-codes"
[patch.crates-io.openmls]
package = "openmls"
git = "https://github.com/wireapp/openmls"
tag = "v0.5.6-pre.core-crypto-0.7.0"
tag = "v0.20.0-pre.core-crypto-1.0.0"

[patch.crates-io.openmls_traits]
package = "openmls_traits"
git = "https://github.com/wireapp/openmls"
tag = "v0.5.6-pre.core-crypto-0.7.0"
tag = "v0.20.0-pre.core-crypto-1.0.0"

[patch.crates-io.openmls_basic_credential]
package = "openmls_basic_credential"
git = "https://github.com/wireapp/openmls"
tag = "v0.20.0-pre.core-crypto-1.0.0"

[patch.crates-io.openmls_x509_credential]
package = "openmls_x509_credential"
git = "https://github.com/wireapp/openmls"
tag = "v0.20.0-pre.core-crypto-1.0.0"

[patch.crates-io.hpke]
git = "https://github.com/rozbb/rust-hpke.git"
rev = "2867b0ae90a36f27e2c312fe741f268ad558abbd"

[patch.crates-io.wire-e2e-identity]
git = "https://github.com/wireapp/rusty-jwt-tools"
package = "wire-e2e-identity"
tag = "v0.4.3"

[patch.crates-io.hpke-rs]
git = "https://github.com/wireapp/hpke-rs"
branch = "feat/0.2"
package = "hpke-rs"

[patch.crates-io.hpke-rs-crypto]
git = "https://github.com/wireapp/hpke-rs"
branch = "feat/0.2"
package = "hpke-rs-crypto"

[patch.crates-io.hpke-rs-rust-crypto]
git = "https://github.com/wireapp/hpke-rs"
branch = "feat/0.2"
package = "hpke-rs-rust-crypto"

# aarch64-apple-ios-sim target support has not yet been released
[patch.crates-io.openssl-src]
git = "https://github.com/alexcrichton/openssl-src-rs.git"
Expand All @@ -76,11 +78,6 @@ package = "openssl-src"
git = "https://github.com/wireapp/rust-jwt-simple"
tag = "v0.11.4-pre.core-crypto-0.7.0"

# Needed for quick mode and (later) result comparison see (https://www.tweag.io/blog/2022-03-03-criterion-rs/)
# TODO: remove once branch got merged in 0.4 release
[patch.crates-io.criterion]
git = "https://github.com/bheisler/criterion.rs"
branch = "version-0.4"

[profile.release]
lto = true
Expand Down
1 change: 1 addition & 0 deletions crypto-ffi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ thiserror = "1.0"
cfg-if = "1.0"
futures-util = "0.3"
async-trait = "0.1"
tls_codec = { workspace = true }

# UniFFI - Android + iOS bindings - Runtime support
uniffi = { version = "0.23", optional = true }
Expand Down
122 changes: 49 additions & 73 deletions crypto-ffi/bindings/js/CoreCrypto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,11 +240,11 @@ export interface MemberAddedMessages {
*/
welcome: Uint8Array;
/**
* MLS PublicGroupState (GroupInfo in draft-15) which is required for joining a group by external commit
* MLS GroupInfo which is required for joining a group by external commit
*
* @readonly
*/
publicGroupState: PublicGroupStateBundle;
groupInfo: GroupInfoBundle;
}

/**
Expand All @@ -264,37 +264,37 @@ export interface CommitBundle {
*/
welcome?: Uint8Array;
/**
* MLS PublicGroupState (GroupInfo in draft-15) which is required for joining a group by external commit
* MLS GroupInfo which is required for joining a group by external commit
*
* @readonly
*/
publicGroupState: PublicGroupStateBundle;
groupInfo: GroupInfoBundle;
}

/**
* Wraps a PublicGroupState in order to efficiently upload it to the Delivery Service.
* Wraps a GroupInfo in order to efficiently upload it to the Delivery Service.
* This is not part of MLS protocol but parts might be standardized at some point.
*/
export interface PublicGroupStateBundle {
export interface GroupInfoBundle {
/**
* see {@link PublicGroupStateEncryptionType}
* see {@link GroupInfoEncryptionType}
*/
encryptionType: PublicGroupStateEncryptionType,
encryptionType: GroupInfoEncryptionType,
/**
* see {@link RatchetTreeType}
*/
ratchetTreeType: RatchetTreeType,
/**
* TLS-serialized PublicGroupState
* TLS-serialized GroupInfo
*/
payload: Uint8Array,
}

/**
* Informs whether the PublicGroupState is confidential
* see [core_crypto::mls::conversation::public_group_state::PublicGroupStateEncryptionType]
* Informs whether the GroupInfo is confidential
* see [core_crypto::mls::conversation::group_info::GroupInfoEncryptionType]
*/
export enum PublicGroupStateEncryptionType {
export enum GroupInfoEncryptionType {
/**
* Unencrypted
*/
Expand All @@ -307,11 +307,11 @@ export enum PublicGroupStateEncryptionType {

/**
* Represents different ways of carrying the Ratchet Tree with some optimizations to save some space
* see [core_crypto::mls::conversation::public_group_state::RatchetTreeType]
* see [core_crypto::mls::conversation::group_info::RatchetTreeType]
*/
export enum RatchetTreeType {
/**
* Complete PublicGroupState
* Complete GroupInfo
*/
Full = 0x01,
/**
Expand Down Expand Up @@ -398,7 +398,7 @@ export interface ConversationInitBundle {
*
* @readonly
*/
publicGroupState: PublicGroupStateBundle;
groupInfo: GroupInfoBundle;
}

/**
Expand Down Expand Up @@ -536,10 +536,6 @@ export enum ExternalProposalType {
* This allows to propose the addition of other clients to the MLS group/conversation
*/
Add,
/**
* This allows to propose the removal of clients from the MLS group/conversation
*/
Remove,
}

export interface ExternalProposalArgs {
Expand All @@ -554,13 +550,6 @@ export interface ExternalProposalArgs {
epoch: number;
}

export interface ExternalRemoveProposalArgs extends ExternalProposalArgs {
/**
* KeyPackageRef of the client that needs to be removed in the proposal
*/
keyPackageRef: Uint8Array;
}

export interface ExternalAddProposalArgs extends ExternalProposalArgs {
/**
* {@link Ciphersuite} to propose to join the MLS group with.
Expand Down Expand Up @@ -994,15 +983,15 @@ export class CoreCrypto {

ffiClients.forEach(c => c.free());

const pgs = ffiRet.public_group_state;
const gi = ffiRet.group_info;

const ret: MemberAddedMessages = {
welcome: ffiRet.welcome,
commit: ffiRet.commit,
publicGroupState: {
encryptionType: pgs.encryption_type,
ratchetTreeType: pgs.ratchet_tree_type,
payload: pgs.payload
groupInfo: {
encryptionType: gi.encryption_type,
ratchetTreeType: gi.ratchet_tree_type,
payload: gi.payload
},
};

Expand Down Expand Up @@ -1035,15 +1024,15 @@ export class CoreCrypto {
clientIds
));

const pgs = ffiRet.public_group_state;
const gi = ffiRet.group_info;

const ret: CommitBundle = {
welcome: ffiRet.welcome,
commit: ffiRet.commit,
publicGroupState: {
encryptionType: pgs.encryption_type,
ratchetTreeType: pgs.ratchet_tree_type,
payload: pgs.payload
groupInfo: {
encryptionType: gi.encryption_type,
ratchetTreeType: gi.ratchet_tree_type,
payload: gi.payload
},
};

Expand All @@ -1070,15 +1059,15 @@ export class CoreCrypto {
conversationId
));

const pgs = ffiRet.public_group_state;
const gi = ffiRet.group_info;

const ret: CommitBundle = {
welcome: ffiRet.welcome,
commit: ffiRet.commit,
publicGroupState: {
encryptionType: pgs.encryption_type,
ratchetTreeType: pgs.ratchet_tree_type,
payload: pgs.payload
groupInfo: {
encryptionType: gi.encryption_type,
ratchetTreeType: gi.ratchet_tree_type,
payload: gi.payload
},
};

Expand Down Expand Up @@ -1109,15 +1098,15 @@ export class CoreCrypto {
return undefined;
}

const pgs = ffiCommitBundle.public_group_state;
const gi = ffiCommitBundle.group_info;

return {
welcome: ffiCommitBundle.welcome,
commit: ffiCommitBundle.commit,
publicGroupState: {
encryptionType: pgs.encryption_type,
ratchetTreeType: pgs.ratchet_tree_type,
payload: pgs.payload
groupInfo: {
encryptionType: gi.encryption_type,
ratchetTreeType: gi.ratchet_tree_type,
payload: gi.payload
},
};
} catch(e) {
Expand Down Expand Up @@ -1170,41 +1159,30 @@ export class CoreCrypto {

async newExternalProposal(
externalProposalType: ExternalProposalType,
args: ExternalAddProposalArgs | ExternalRemoveProposalArgs
args: ExternalAddProposalArgs
): Promise<Uint8Array> {
switch (externalProposalType) {
case ExternalProposalType.Add: {
let addArgs = (args as ExternalAddProposalArgs);
return await CoreCryptoError.asyncMapErr(this.#cc.new_external_add_proposal(args.conversationId, args.epoch, addArgs.ciphersuite, addArgs.credentialType));
}
case ExternalProposalType.Remove: {
if (!(args as ExternalRemoveProposalArgs).keyPackageRef) {
throw new Error("keyPackageRef is not contained in the external proposal arguments");
}

return await CoreCryptoError.asyncMapErr(this.#cc.new_external_remove_proposal(
args.conversationId,
args.epoch,
(args as ExternalRemoveProposalArgs).keyPackageRef
));
}
default:
throw new Error("Invalid external proposal type!");
}
}

/**
* Exports public group state for use in external commits
* Exports GroupInfo for use in external commits
*
* @param conversationId - MLS Conversation ID
* @returns TLS-serialized MLS public group state
* @returns TLS-serialized MLS GroupInfo
*/
async exportGroupState(conversationId: ConversationId): Promise<Uint8Array> {
return await CoreCryptoError.asyncMapErr(this.#cc.export_group_state(conversationId));
async exportGroupInfo(conversationId: ConversationId): Promise<Uint8Array> {
return await CoreCryptoError.asyncMapErr(this.#cc.export_group_info(conversationId));
}

/**
* Allows to create an external commit to "apply" to join a group through its public group state.
* Allows to create an external commit to "apply" to join a group through its GroupInfo.
*
* If the Delivery Service accepts the external commit, you have to {@link CoreCrypto.mergePendingGroupFromExternalCommit}
* in order to get back a functional MLS group. On the opposite, if it rejects it, you can either retry by just
Expand All @@ -1213,28 +1191,28 @@ export class CoreCrypto {
* {@link CoreCrypto.clearPendingGroupFromExternalCommit} in order not to bloat the user's storage but nothing
* bad can happen if you forget to except some storage space wasted.
*
* @param publicGroupState - a TLS encoded PublicGroupState fetched from the Delivery Service
* @param groupInfo - a TLS encoded GroupInfo fetched from the Delivery Service
* @param credentialType - kind of Credential to use for joining this group. If {@link CredentialType.Basic} is
* chosen and no Credential has been created yet for it, a new one will be generated.
* @param configuration - configuration of the MLS group
* When {@link CredentialType.X509} is chosen, it fails when no Credential has been created for the given {@link Ciphersuite}.
* @returns see {@link ConversationInitBundle}
*/
async joinByExternalCommit(publicGroupState: Uint8Array, credentialType: CredentialType, configuration: CustomConfiguration = {}): Promise<ConversationInitBundle> {
async joinByExternalCommit(groupInfo: Uint8Array, credentialType: CredentialType, configuration: CustomConfiguration = {}): Promise<ConversationInitBundle> {
try {
const {keyRotationSpan, wirePolicy} = configuration || {};
const config = new CoreCrypto.#module.CustomConfiguration(keyRotationSpan, wirePolicy);
const ffiInitMessage: CoreCryptoFfiTypes.ConversationInitBundle = await CoreCryptoError.asyncMapErr(this.#cc.join_by_external_commit(publicGroupState, config, credentialType));
const ffiInitMessage: CoreCryptoFfiTypes.ConversationInitBundle = await CoreCryptoError.asyncMapErr(this.#cc.join_by_external_commit(groupInfo, config, credentialType));

const pgs = ffiInitMessage.public_group_state;
const gi = ffiInitMessage.group_info;

const ret: ConversationInitBundle = {
conversationId: ffiInitMessage.conversation_id,
commit: ffiInitMessage.commit,
publicGroupState: {
encryptionType: pgs.encryption_type,
ratchetTreeType: pgs.ratchet_tree_type,
payload: pgs.payload
groupInfo: {
encryptionType: gi.encryption_type,
ratchetTreeType: gi.ratchet_tree_type,
payload: gi.payload
},
};

Expand Down Expand Up @@ -1806,7 +1784,6 @@ export class WireE2eIdentity {
* Verifies that the previous challenge has been completed.
*
* @param orderUrl `location` header from http response you got from {@link newOrderResponse}
* @param account you found after {@link newAccountResponse}
* @param previousNonce `replay-nonce` response header from `POST /acme/{provisioner-name}/challenge/{challenge-id}`
* @see https://www.rfc-editor.org/rfc/rfc8555.html#section-7.4
*/
Expand Down Expand Up @@ -1836,7 +1813,6 @@ export class WireE2eIdentity {
/**
* Final step before fetching the certificate.
*
* @param order - order you got from {@link checkOrderResponse}
* @param previousNonce - `replay-nonce` response header from `POST /acme/{provisioner-name}/order/{order-id}`
* @see https://www.rfc-editor.org/rfc/rfc8555.html#section-7.4
*/
Expand Down
Loading

0 comments on commit 4e7d907

Please sign in to comment.