From 58d37932aa8b0e3db7cc2b2e2b37e347a9a3fd87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20K=C3=B6sters?= Date: Tue, 7 Jan 2025 13:00:10 +0100 Subject: [PATCH] feat: add remaining mimi-protocol structures --- Cargo.lock | 144 ++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/consent.rs | 36 ++++++++++ src/frank.rs | 5 ++ src/group_info.rs | 30 +++++++-- src/identifier_query.rs | 71 ++++++++++++++++++++ src/key_material.rs | 8 ++- src/lib.rs | 33 +++------ src/notify.rs | 16 ++--- src/report_abuse.rs | 20 ++++++ src/submit_message.rs | 6 +- src/update.rs | 10 +-- 12 files changed, 329 insertions(+), 51 deletions(-) create mode 100644 src/consent.rs create mode 100644 src/frank.rs create mode 100644 src/identifier_query.rs create mode 100644 src/report_abuse.rs diff --git a/Cargo.lock b/Cargo.lock index 21c462e..d4b721a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,13 +2,75 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + [[package]] name = "mimi-protocol" version = "0.1.0" dependencies = [ + "openmls", "serde_bytes", ] +[[package]] +name = "openmls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f1295188c6665fb9e96466180ac0a919ef52b5861cf7e86523823661348a597" +dependencies = [ + "log", + "openmls_traits", + "rayon", + "serde", + "thiserror", + "tls_codec", +] + +[[package]] +name = "openmls_traits" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "443afa05406adc75fbfa0c3e04db93c5647b763861a474ae1aa8a99c362b80f8" +dependencies = [ + "serde", + "tls_codec", +] + [[package]] name = "proc-macro2" version = "1.0.92" @@ -27,6 +89,26 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "serde" version = "1.0.216" @@ -67,8 +149,70 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tls_codec" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e78c9c330f8c85b2bae7c8368f2739157db9991235123aa1b15ef9502bfb6a" +dependencies = [ + "serde", + "tls_codec_derive", + "zeroize", +] + +[[package]] +name = "tls_codec_derive" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d9ef545650e79f30233c0003bcc2504d7efac6dad25fca40744de773fe2049c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "unicode-ident" version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/Cargo.toml b/Cargo.toml index b8a0ebe..8d9fe9f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,4 +8,5 @@ version = "0.1.0" edition = "2021" [dependencies] +openmls = "0.6.0" serde_bytes = "0.11.15" diff --git a/src/consent.rs b/src/consent.rs new file mode 100644 index 0000000..78252d1 --- /dev/null +++ b/src/consent.rs @@ -0,0 +1,36 @@ +use openmls::prelude::KeyPackage; +use serde_bytes::ByteBuf; + +use crate::IdentifierUri; + +#[repr(u8)] +pub enum ConsentEntry { + // TODO: Factor our common fields + Cancel { + requester_uri: IdentifierUri, + target_uri: IdentifierUri, + room_id: Option, + } = 0, + Request { + requester_uri: IdentifierUri, + target_uri: IdentifierUri, + room_id: Option, + } = 1, + Grant { + requester_uri: IdentifierUri, + target_uri: IdentifierUri, + room_id: Option, + client_key_packages: KeyPackage, + } = 2, + Revoke { + requester_uri: IdentifierUri, + target_uri: IdentifierUri, + room_id: Option, + } = 3, +} + +pub struct ConsentScope { + requester_uri: IdentifierUri, + target_uri: IdentifierUri, + room_id: Option, +} diff --git a/src/frank.rs b/src/frank.rs new file mode 100644 index 0000000..3c938ed --- /dev/null +++ b/src/frank.rs @@ -0,0 +1,5 @@ +pub struct Frank { + franking_tag: [u8; 32], // TODO: The RFC starts mixing camelCase and snake_case + server_frank: [u8; 32], + server_frank_context_hash: [u8; 32], +} diff --git a/src/group_info.rs b/src/group_info.rs index 7365481..b223b56 100644 --- a/src/group_info.rs +++ b/src/group_info.rs @@ -2,24 +2,39 @@ // // SPDX-License-Identifier: AGPL-3.0-or-later +use openmls::prelude::{ + group_info::GroupInfo, Ciphersuite, Credential, ExternalSender, HpkePublicKey, + SignaturePublicKey, +}; use serde_bytes::ByteBuf; -use super::{CipherSuite, GroupInfo, RatchetTreeOption}; +use super::RatchetTreeOption; -// "to-be-signed" #[repr(u8)] -pub enum GroupInfoRequestTBS { +pub enum GroupInfoRequest { Mls10 { - cipher_suite: CipherSuite, + cipher_suite: Ciphersuite, requesting_signature_key: SignaturePublicKey, requesting_credential: Credential, - group_info_public_key: HPKEPublicKey, + group_info_public_key: HpkePublicKey, joining_code: Option, // TODO: Or ByteBuf? + signature: ByteBuf, // TODO: Or only create signature when serializing, for example macro #[signature]? } = 1, } // TODO: The signed variant's joining code is not optional? +// TODO: typo groupInfoPubl[i]cKey + +#[repr(u8)] +pub enum GroupInfoCode { + Reserved = 0, + Success = 1, + NotAuthorized = 2, + NoSuchRoom = 3, + Custom(u8), +} + // "to-be-encrypted" pub struct GroupInfoRatchetTreeTBE { group_info: GroupInfo, @@ -28,13 +43,14 @@ pub struct GroupInfoRatchetTreeTBE { // "to-be-signed" #[repr(u8)] -pub enum GroupInfoResponseTBS { +pub enum GroupInfoResponse { Mls10 { status: GroupInfoCode, - cipher_suite: CipherSuite, + cipher_suite: Ciphersuite, room_id: ByteBuf, hub_sender: ExternalSender, encrypted_groupinfo_and_tree: ByteBuf, + signature: ByteBuf, // TODO: Or only create signature when serializing, for example macro #[signature]? } = 1, } diff --git a/src/identifier_query.rs b/src/identifier_query.rs new file mode 100644 index 0000000..8571aa9 --- /dev/null +++ b/src/identifier_query.rs @@ -0,0 +1,71 @@ +use serde_bytes::ByteBuf; + +use crate::IdentifierUri; + +#[repr(u8)] +pub enum IdentifierRequest { + Reserved { + search_value: String, + } = 0, + Handle { + search_value: String, + } = 1, + Nick { + search_value: String, + } = 2, + Email { + search_value: String, + } = 3, + Phone { + search_value: String, + } = 4, + PartialName { + search_value: String, + } = 5, + WholeProfile { + search_value: String, + } = 6, + OidcStdClaim { + search_value: String, + claim_name: String, + } = 7, + VcardField { + search_value: String, + field_name: String, + } = 8, +} + +#[repr(u8)] +pub enum IdentifierQueryCode { + Success = 0, + NotFound = 1, + Ambiguous = 2, + Forbidden = 3, + UnsupportedField = 4, + Custom(u8), +} + +#[repr(u8)] +pub enum FieldSource { + Reserved = 0, + OidcStdClaim = 7, + VCardField = 8, + Custom(u8), +} + +struct ProfileField { + field_source: FieldSource, + field_name: String, // TODO: Why does it say string in the rfc instead of opaque + field_value: ByteBuf, +} + +struct UserProfile { + stable_uri: IdentifierUri, + fields: Vec, +} + +pub struct IdentifierResponse { + response_code: IdentifierQueryCode, + uri: Vec, + found_profiles: Vec, +} diff --git a/src/key_material.rs b/src/key_material.rs index 1c34707..dd20a71 100644 --- a/src/key_material.rs +++ b/src/key_material.rs @@ -2,7 +2,9 @@ // // SPDX-License-Identifier: AGPL-3.0-or-later -use super::{Capabilities, CipherSuite, IdentifierUri, KeyPackage, RequiredCapabilities}; +use openmls::prelude::{Capabilities, Ciphersuite, KeyPackage, RequiredCapabilitiesExtension}; + +use super::IdentifierUri; #[repr(u8)] pub enum KeyMaterialRequest { @@ -10,8 +12,8 @@ pub enum KeyMaterialRequest { requesting_user: IdentifierUri, target_user: IdentifierUri, room_id: IdentifierUri, - acceptable_ciphersuites: Vec, - required_capabilities: RequiredCapabilities, + acceptable_ciphersuites: Vec, + required_capabilities: RequiredCapabilitiesExtension, } = 1, } diff --git a/src/lib.rs b/src/lib.rs index 171dadf..80378d0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,37 +2,20 @@ // // SPDX-License-Identifier: AGPL-3.0-or-later +mod consent; +mod frank; mod group_info; +mod identifier_query; mod key_material; mod notify; +mod report_abuse; mod submit_message; mod update; -// TODO: Import this from mls crate -#[repr(u16)] -pub enum CipherSuite { - Reserved = 0, - MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519 = 1, - Custom(u16), -} -// TODO: Import this from mls crate -pub type RequiredCapabilities = (); -// TODO: Import this from mls crate -pub type Capabilities = (); -// TODO: Import this from mls crate -pub type KeyPackage = (); -// TODO: Import this from mls crate -pub type MlsMessage = (); -// TODO: Import this from mls crate -pub type Welcome = (); -// TODO: Import this from mls crate -pub type GroupInfo = (); -// TODO: Import this from mls crate -pub type PartialGroupInfo = (); -// TODO: Import this from mls crate -pub type RatchetTreeOption = (); -// TODO: Import this from mls crate -pub type ProposalRef = (); +// TODO: openmls doesn't implement this yet? +// https://datatracker.ietf.org/doc/draft-mahy-mls-ratchet-tree-options/ +type RatchetTreeOption = (); +type PartialGroupInfo = (); #[repr(u8)] pub enum Protocol { diff --git a/src/notify.rs b/src/notify.rs index 9d9ccef..f2684cf 100644 --- a/src/notify.rs +++ b/src/notify.rs @@ -2,23 +2,19 @@ // // SPDX-License-Identifier: AGPL-3.0-or-later -use super::{MlsMessage, RatchetTreeOption}; +use openmls::prelude::MlsMessageBodyOut; -struct Frank { - franking_tag: [u8; 32], // TODO: The RFC starts mixing camelCase and snake_case - server_frank: [u8; 32], - server_frank_context_hash: [u8; 32], -} +use crate::{frank::Frank, RatchetTreeOption}; -enum Mls10FanoutMessage { +pub enum Mls10FanoutMessage { Application { timestamp: u64, - message: MlsMessage, // Must have wire_format = Application - frank: Option, // In RFC, optional doesn't have the <> + message: MlsMessageBodyOut, // Must have wire_format = Application + frank: Option, // TODO: In RFC, optional doesn't have the <> }, Welcome { timestamp: u64, - message: MlsMessage, // Must have wire_format = Welcome + message: MlsMessageBodyOut, // Must have wire_format = Welcome ratchet_tree_option: RatchetTreeOption, }, } diff --git a/src/report_abuse.rs b/src/report_abuse.rs new file mode 100644 index 0000000..74daa27 --- /dev/null +++ b/src/report_abuse.rs @@ -0,0 +1,20 @@ +use serde_bytes::ByteBuf; + +use crate::{frank::Frank, IdentifierUri}; + +pub struct AbusiveMessage { + mimi_content: ByteBuf, // TODO: Why camelcase in rfc? + frank: Frank, +} + +pub enum AbuseType { + Reserved = 0, +} + +pub struct AbuseReport { + reporting_user: IdentifierUri, + alleged_abuser_uri: IdentifierUri, // TODO: Why uri in field name? + reason_code: AbuseType, + note: String, // TODO: Or ByteBuf? + messages: Vec, +} diff --git a/src/submit_message.rs b/src/submit_message.rs index 1d732bd..0b724f1 100644 --- a/src/submit_message.rs +++ b/src/submit_message.rs @@ -2,12 +2,14 @@ // // SPDX-License-Identifier: AGPL-3.0-or-later -use super::{IdentifierUri, MlsMessage}; +use openmls::prelude::MlsMessageBodyOut; + +use super::IdentifierUri; #[repr(u8)] pub enum SubmitMessageRequest { Mls10 { - app_message: MlsMessage, + app_message: MlsMessageBodyOut, // Must be PrivateMessage sending_uri: IdentifierUri, } = 1, } diff --git a/src/update.rs b/src/update.rs index 3cfcb96..2bb479f 100644 --- a/src/update.rs +++ b/src/update.rs @@ -2,18 +2,20 @@ // // SPDX-License-Identifier: AGPL-3.0-or-later -use super::{GroupInfo, MlsMessage, PartialGroupInfo, ProposalRef, RatchetTreeOption, Welcome}; +use openmls::prelude::{group_info::GroupInfo, hash_ref::ProposalRef, MlsMessageBodyOut, Welcome}; + +use crate::{PartialGroupInfo, RatchetTreeOption}; pub enum HandshakeBundle { Commit { - proposal_or_commit: MlsMessage, // TODO: This must be a commit. Can we make this type safe? + proposal_or_commit: MlsMessageBodyOut, // TODO: This must be a commit. Can we make this type safe? welcome: Option, group_info_option: GroupInfoOption, ratchet_tree_option: RatchetTreeOption, }, Proposal { - proposal_or_commit: MlsMessage, // This must be a proposal - more_proposals: Vec, + proposal_or_commit: MlsMessageBodyOut, // This must be a proposal + more_proposals: Vec, }, }