Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add commit bundle support #2688

Merged
merged 18 commits into from
Sep 19, 2022
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
1 change: 1 addition & 0 deletions changelog.d/1-api-changes/FS-922-post-commit-bundle
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add new endpoint `/mls/commit-bundles` for submitting MLS `CommitBundle`s. A `CommitBundle` is a triple consisting of a commit message, an optional welcome message and a public group state.
3 changes: 3 additions & 0 deletions charts/nginz/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,9 @@ nginx_conf:
- path: /mls/messages
envs:
- all
- path: /mls/commit-bundles
envs:
- all
- path: /mls/public-keys
envs:
- all
Expand Down
5 changes: 5 additions & 0 deletions deploy/services-demo/conf/nginz/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,11 @@ http {
proxy_pass http://galley;
}

location /mls/commit-bundles {
include common_response_with_zauth.conf;
proxy_pass http://galley;
}

location /mls/public-keys {
include common_response_with_zauth.conf;
proxy_pass http://galley;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ type GalleyApi =
:<|> FedEndpoint "mls-welcome" MLSWelcomeRequest EmptyResponse
:<|> FedEndpoint "on-mls-message-sent" RemoteMLSMessage EmptyResponse
:<|> FedEndpoint "send-mls-message" MessageSendRequest MLSMessageResponse
:<|> FedEndpoint "send-mls-commit-bundle" MessageSendRequest MLSMessageResponse
:<|> FedEndpoint "on-client-removed" ClientRemovedRequest EmptyResponse

data ClientRemovedRequest = ClientRemovedRequest
Expand Down
11 changes: 7 additions & 4 deletions libs/wire-api/src/Wire/API/Error/Galley.hs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ data GalleyError
| MLSSelfRemovalNotAllowed
| MLSGroupConversationMismatch
| MLSClientSenderUserMismatch
| MLSWelcomeMismatch
| --
NoBindingTeamMembers
| NoBindingTeam
Expand Down Expand Up @@ -192,13 +193,15 @@ type instance MapError 'MLSClientMismatch = 'StaticError 409 "mls-client-mismatc

type instance MapError 'MLSStaleMessage = 'StaticError 409 "mls-stale-message" "The conversation epoch in a message is too old"

type instance MapError 'MLSCommitMissingReferences = 'StaticError 409 "mls-commit-missing-references" "The commit is not referencing all pending proposals"
type instance MapError 'MLSCommitMissingReferences = 'StaticError 400 "mls-commit-missing-references" "The commit is not referencing all pending proposals"

type instance MapError 'MLSSelfRemovalNotAllowed = 'StaticError 409 "mls-self-removal-not-allowed" "Self removal from group is not allowed"
type instance MapError 'MLSSelfRemovalNotAllowed = 'StaticError 400 "mls-self-removal-not-allowed" "Self removal from group is not allowed"

type instance MapError 'MLSGroupConversationMismatch = 'StaticError 409 "mls-group-conversation-mismatch" "Conversation ID resolved from Group ID does not match submitted Conversation ID"
type instance MapError 'MLSGroupConversationMismatch = 'StaticError 400 "mls-group-conversation-mismatch" "Conversation ID resolved from Group ID does not match submitted Conversation ID"

type instance MapError 'MLSClientSenderUserMismatch = 'StaticError 409 "mls-client-sender-user-mismatch" "User ID resolved from Client ID does not match message's sender user ID"
type instance MapError 'MLSClientSenderUserMismatch = 'StaticError 400 "mls-client-sender-user-mismatch" "User ID resolved from Client ID does not match message's sender user ID"

type instance MapError 'MLSWelcomeMismatch = 'StaticError 400 "mls-welcome-mismatch" "The list of targets of a welcome message does not match the list of new clients in a group"

type instance MapError 'NoBindingTeamMembers = 'StaticError 403 "non-binding-team-members" "Both users must be members of the same binding team"

Expand Down
2 changes: 1 addition & 1 deletion libs/wire-api/src/Wire/API/MLS/CipherSuite.hs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import Wire.Arbitrary

newtype CipherSuite = CipherSuite {cipherSuiteNumber :: Word16}
deriving stock (Eq, Show)
deriving newtype (ParseMLS, Arbitrary)
deriving newtype (ParseMLS, SerialiseMLS, Arbitrary)

instance ToSchema CipherSuite where
schema =
Expand Down
9 changes: 8 additions & 1 deletion libs/wire-api/src/Wire/API/MLS/Commit.hs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import Imports
import Wire.API.MLS.KeyPackage
import Wire.API.MLS.Proposal
import Wire.API.MLS.Serialisation
import Wire.Arbitrary

data Commit = Commit
{ cProposals :: [ProposalOrRef],
Expand Down Expand Up @@ -53,7 +54,13 @@ data HPKECiphertext = HPKECiphertext
{ hcOutput :: ByteString,
hcCiphertext :: ByteString
}
deriving (Eq, Show)
deriving (Eq, Show, Generic)
deriving (Arbitrary) via (GenericUniform HPKECiphertext)

instance ParseMLS HPKECiphertext where
parseMLS = HPKECiphertext <$> parseMLSBytes @Word16 <*> parseMLSBytes @Word16

instance SerialiseMLS HPKECiphertext where
serialiseMLS (HPKECiphertext out ct) = do
serialiseMLSBytes @Word16 out
serialiseMLSBytes @Word16 ct
45 changes: 45 additions & 0 deletions libs/wire-api/src/Wire/API/MLS/CommitBundle.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
-- This file is part of the Wire Server implementation.
--
-- Copyright (C) 2022 Wire Swiss GmbH <[email protected]>
--
-- This program is free software: you can redistribute it and/or modify it under
-- the terms of the GNU Affero General Public License as published by the Free
-- Software Foundation, either version 3 of the License, or (at your option) any
-- later version.
--
-- This program is distributed in the hope that it will be useful, but WITHOUT
-- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-- FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
-- details.
--
-- You should have received a copy of the GNU Affero General Public License along
-- with this program. If not, see <https://www.gnu.org/licenses/>.
{-# LANGUAGE RecordWildCards #-}

module Wire.API.MLS.CommitBundle where

import qualified Data.Swagger as S
import Imports
import Wire.API.MLS.GroupInfoBundle
import Wire.API.MLS.Message
import Wire.API.MLS.Serialisation
import Wire.API.MLS.Welcome

data CommitBundle = CommitBundle
{ cbCommitMsg :: RawMLS (Message 'MLSPlainText),
cbWelcome :: Maybe (RawMLS Welcome),
cbGroupInfoBundle :: GroupInfoBundle
}
deriving (Eq, Show)

instance ParseMLS CommitBundle where
parseMLS = CommitBundle <$> parseMLS <*> parseMLSOptional parseMLS <*> parseMLS

instance S.ToSchema CommitBundle where
declareNamedSchema _ = pure (mlsSwagger "CommitBundle")

instance SerialiseMLS CommitBundle where
serialiseMLS (CommitBundle commit welcome gi) = do
serialiseMLS commit
serialiseMLSOptional serialiseMLS welcome
serialiseMLS gi
3 changes: 1 addition & 2 deletions libs/wire-api/src/Wire/API/MLS/Extension.hs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,7 @@ import Wire.API.MLS.Serialisation
import Wire.Arbitrary

newtype ProtocolVersion = ProtocolVersion {pvNumber :: Word8}
deriving newtype (Eq, Ord, Show, Binary, Arbitrary)
deriving (ParseMLS) via (BinaryMLS ProtocolVersion)
deriving newtype (Eq, Ord, Show, Binary, Arbitrary, ParseMLS, SerialiseMLS)

data ProtocolVersionTag = ProtocolMLS10 | ProtocolMLSDraft11
deriving stock (Bounded, Enum, Eq, Show, Generic)
Expand Down
53 changes: 53 additions & 0 deletions libs/wire-api/src/Wire/API/MLS/GroupInfoBundle.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
-- This file is part of the Wire Server implementation.
--
-- Copyright (C) 2022 Wire Swiss GmbH <[email protected]>
--
-- This program is free software: you can redistribute it and/or modify it under
-- the terms of the GNU Affero General Public License as published by the Free
-- Software Foundation, either version 3 of the License, or (at your option) any
-- later version.
--
-- This program is distributed in the hope that it will be useful, but WITHOUT
-- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-- FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
-- details.
--
-- You should have received a copy of the GNU Affero General Public License along
-- with this program. If not, see <https://www.gnu.org/licenses/>.

module Wire.API.MLS.GroupInfoBundle where

import Imports
import Test.QuickCheck
import Wire.API.MLS.PublicGroupState
import Wire.API.MLS.Serialisation
import Wire.Arbitrary

data GroupInfoEncryption = UnencryptedGroupInfo | JweEncryptedGroupInfo
deriving stock (Eq, Show, Generic, Bounded, Enum)
deriving (Arbitrary) via (GenericUniform GroupInfoEncryption)

data GroupInfoTreeType = TreeFull | TreeDelta | TreeByRef
deriving stock (Eq, Show, Generic, Bounded, Enum)
deriving (Arbitrary) via (GenericUniform GroupInfoTreeType)

data GroupInfoBundle = GroupInfoBundle
{ gipEncryptionType :: GroupInfoEncryption,
gipTreeType :: GroupInfoTreeType,
gipGroupState :: PublicGroupState
}
deriving stock (Eq, Show, Generic)
deriving (Arbitrary) via GenericUniform GroupInfoBundle

instance ParseMLS GroupInfoBundle where
parseMLS =
GroupInfoBundle
<$> parseMLSEnum @Word8 "GroupInfoEncryptionEnum"
<*> parseMLSEnum @Word8 "RatchetTreeEnum"
<*> parseMLS

instance SerialiseMLS GroupInfoBundle where
serialiseMLS (GroupInfoBundle e t pgs) = do
serialiseMLSEnum @Word8 e
serialiseMLSEnum @Word8 t
serialiseMLS pgs
98 changes: 98 additions & 0 deletions libs/wire-api/src/Wire/API/MLS/PublicGroupState.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
-- This file is part of the Wire Server implementation.
--
-- Copyright (C) 2022 Wire Swiss GmbH <[email protected]>
--
-- This program is free software: you can redistribute it and/or modify it under
-- the terms of the GNU Affero General Public License as published by the Free
-- Software Foundation, either version 3 of the License, or (at your option) any
-- later version.
--
-- This program is distributed in the hope that it will be useful, but WITHOUT
-- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-- FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
-- details.
--
-- You should have received a copy of the GNU Affero General Public License along
-- with this program. If not, see <https://www.gnu.org/licenses/>.
{-# LANGUAGE RecordWildCards #-}

module Wire.API.MLS.PublicGroupState where

import Data.Binary.Get (label)
import Imports
import Test.QuickCheck hiding (label)
import Wire.API.MLS.CipherSuite
import Wire.API.MLS.Epoch
import Wire.API.MLS.Extension
import Wire.API.MLS.Group
import Wire.API.MLS.KeyPackage
import Wire.API.MLS.Serialisation
import Wire.Arbitrary

data PublicGroupStateTBS = PublicGroupStateTBS
{ pgsVersion :: ProtocolVersion,
pgsCipherSuite :: CipherSuite,
pgsGroupId :: GroupId,
pgsEpoch :: Epoch,
pgsTreeHash :: ByteString,
pgsInterimTranscriptHash :: ByteString,
pgsConfirmedInterimTranscriptHash :: ByteString,
pgsGroupContextExtensions :: ByteString,
pgsOtherExtensions :: ByteString,
pgsExternalPub :: ByteString,
pgsSigner :: KeyPackageRef
}
deriving stock (Eq, Show, Generic)
deriving (Arbitrary) via (GenericUniform PublicGroupStateTBS)

instance ParseMLS PublicGroupStateTBS where
parseMLS =
PublicGroupStateTBS
<$> label "pgsVersion" parseMLS
<*> label "pgsCipherSuite" parseMLS
<*> label "pgsGroupId" parseMLS
<*> label "pgsEpoch" parseMLS
<*> label "pgsTreeHash" (parseMLSBytes @Word8)
<*> label "pgsInterimTranscriptHash" (parseMLSBytes @Word8)
<*> label "pgsConfirmedInterimTranscriptHash" (parseMLSBytes @Word8)
<*> label "pgsGroupContextExtensions" (parseMLSBytes @Word32)
<*> label "pgsOtherExtensions" (parseMLSBytes @Word32)
<*> label "pgsExternalPub" (parseMLSBytes @Word16)
<*> label "pgsSigner" parseMLS

instance SerialiseMLS PublicGroupStateTBS where
serialiseMLS (PublicGroupStateTBS {..}) = do
serialiseMLS pgsVersion
serialiseMLS pgsCipherSuite
serialiseMLS pgsGroupId
serialiseMLS pgsEpoch
serialiseMLSBytes @Word8 pgsTreeHash
serialiseMLSBytes @Word8 pgsInterimTranscriptHash
serialiseMLSBytes @Word8 pgsConfirmedInterimTranscriptHash
serialiseMLSBytes @Word32 pgsGroupContextExtensions
serialiseMLSBytes @Word32 pgsOtherExtensions
serialiseMLSBytes @Word16 pgsExternalPub
serialiseMLS pgsSigner

data PublicGroupState = PublicGroupState
{ pgTBS :: RawMLS PublicGroupStateTBS,
pgSignature :: ByteString
}
deriving stock (Eq, Show, Generic)

instance Arbitrary PublicGroupState where
arbitrary =
PublicGroupState
<$> (mkRawMLS <$> arbitrary)
<*> arbitrary

instance ParseMLS PublicGroupState where
parseMLS =
PublicGroupState
<$> label "pgTBS" parseMLS
<*> label "pgSignature" (parseMLSBytes @Word16)

instance SerialiseMLS PublicGroupState where
serialiseMLS PublicGroupState {..} = do
serialiseMLS pgTBS
serialiseMLSBytes @Word16 pgSignature
9 changes: 3 additions & 6 deletions libs/wire-api/src/Wire/API/MLS/Serialisation.hs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ module Wire.API.MLS.Serialisation
serialiseMLSOptional,
parseMLSEnum,
serialiseMLSEnum,
BinaryMLS (..),
MLSEnumError (..),
fromMLSEnum,
toMLSEnum',
Expand Down Expand Up @@ -165,15 +164,13 @@ instance ParseMLS Word32 where parseMLS = get

instance ParseMLS Word64 where parseMLS = get

instance SerialiseMLS Word8 where serialiseMLS = put

instance SerialiseMLS Word16 where serialiseMLS = put

instance SerialiseMLS Word32 where serialiseMLS = put

-- | A wrapper to generate a 'ParseMLS' instance given a 'Binary' instance.
newtype BinaryMLS a = BinaryMLS a

instance Binary a => ParseMLS (BinaryMLS a) where
parseMLS = BinaryMLS <$> get
instance SerialiseMLS Word64 where serialiseMLS = put

-- | Encode an MLS value to a lazy bytestring.
encodeMLS :: SerialiseMLS a => a -> LByteString
Expand Down
25 changes: 21 additions & 4 deletions libs/wire-api/src/Wire/API/MLS/Welcome.hs
Original file line number Diff line number Diff line change
Expand Up @@ -24,29 +24,46 @@ import Wire.API.MLS.Commit
import Wire.API.MLS.Extension
import Wire.API.MLS.KeyPackage
import Wire.API.MLS.Serialisation
import Wire.Arbitrary

data Welcome = Welcome
{ welCipherSuite :: CipherSuite,
{ welProtocolVersion :: ProtocolVersion,
welCipherSuite :: CipherSuite,
welSecrets :: [GroupSecrets],
welGroupInfo :: ByteString
}
deriving (Show, Eq, Generic)
deriving (Arbitrary) via (GenericUniform Welcome)

instance S.ToSchema Welcome where
declareNamedSchema _ = pure (mlsSwagger "Welcome")

instance ParseMLS Welcome where
parseMLS =
Welcome
-- Note: the extra protocol version at the beginning of the welcome
-- message is present in openmls-0.4.0-pre, but is not part of the spec
<$> (parseMLS @ProtocolVersion *> parseMLS)
<$> parseMLS @ProtocolVersion
<*> parseMLS
<*> parseMLSVector @Word32 parseMLS
<*> parseMLSBytes @Word32

instance SerialiseMLS Welcome where
serialiseMLS (Welcome pv cs ss gi) = do
serialiseMLS pv
serialiseMLS cs
serialiseMLSVector @Word32 serialiseMLS ss
serialiseMLSBytes @Word32 gi

data GroupSecrets = GroupSecrets
{ gsNewMember :: KeyPackageRef,
gsSecrets :: HPKECiphertext
}
deriving (Show, Eq, Generic)
deriving (Arbitrary) via (GenericUniform GroupSecrets)

instance ParseMLS GroupSecrets where
parseMLS = GroupSecrets <$> parseMLS <*> parseMLS

instance SerialiseMLS GroupSecrets where
serialiseMLS (GroupSecrets kp sec) = do
serialiseMLS kp
serialiseMLS sec
Loading