md-d2d-join.proto 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. // ## Device Join Protocol
  2. //
  3. // This protocol specifies how to add a new device to an existing device group.
  4. //
  5. // ### Terminology
  6. //
  7. // - `ED`: Existing device
  8. // - `ND`: New device to be added
  9. //
  10. // ### Blobs
  11. //
  12. // For binary data, the usual Blob scheme is being used by ED. However, instead
  13. // of transferring Blob data via the Blob server, the data is transmitted in
  14. // form of a `common.BlobData` message ahead of a message referencing that Blob
  15. // by the associated Blob ID.
  16. //
  17. // ND is supposed to cache received `common.BlobData` until it can associate the
  18. // data to a Blob referencing its ID. Once the rendezvous connection has been
  19. // closed, any remaining cached `common.BlobData` can be discarded.
  20. //
  21. // ### Protocol Kickoff Flow
  22. //
  23. // ND or ED may choose to start the protocol. If ND starts the protocol it is
  24. // _requesting to join the device group_. If ED starts the protocol it is
  25. // _offering to join the device group_.
  26. //
  27. // If ED started the protocol:
  28. //
  29. // - `variant` must be set to _offer to join the device group_.
  30. // - ED takes the role of RID
  31. // - ND takes the role of RRD
  32. //
  33. // If ND started the protocol:
  34. //
  35. // - `variant` must be set to _request to join the device group_.
  36. // - ND takes the role of RID
  37. // - ED takes the role of RRD
  38. //
  39. // #### Connection Setup
  40. //
  41. // RID creates a `rendezvous.RendezvousInit` by following the Connection
  42. // Rendezvous Protocol. It wraps it in a `url.DeviceGroupJoinRequestOrOffer` and
  43. // offers it in form of a URL or a QR code.
  44. //
  45. // RRD scans the QR code or decodes the URL and then parses the
  46. // `url.DeviceGroupJoinRequestOrOffer`. It will then receive the data over a
  47. // sufficiently secure channel (e.g. a QR code). Once decoded, the enclosed
  48. // `rendezvous.RendezvousInit` must be handled according to the Connection
  49. // Rendezvous Protocol.
  50. //
  51. // Once the Connection Rendezvous Protocol has established at least one
  52. // connection path, ED waits another 3s or until all connection paths have been
  53. // established. Nomination is then done by ED following the Connection
  54. // Rendezvous Protocol.
  55. //
  56. // Note that all messages on the nominated connection path must be end-to-end
  57. // encrypted as defined by the Connection Rendezvous Protocol. All transmitted
  58. // messages are to be wrapped in:
  59. //
  60. // - `NdToEd` when sending from ND to ED, and
  61. // - `EdToNd` when sending from ED to ND.
  62. //
  63. // #### Device Join Flow
  64. //
  65. // As soon as one of the connection paths has been nominated by ED, both devices
  66. // must calculate the Rendezvous Path Hash (RPH) as defined by the Rendezvous
  67. // Protocol and display it to the user.
  68. //
  69. // ED must ask the user for confirmation that RPH is equal on both devices. The
  70. // exact comparison mechanism is an implementation detail. If the user does not
  71. // confirm that RPH is equal on both devices, the process must be aborted.
  72. //
  73. // After confirmation, ED must stop displaying RPH and send a `Begin` message to
  74. // start the device join process.
  75. //
  76. // ED ------- Begin ------> ND [1]
  77. //
  78. // ND can now stop displaying RPH.
  79. //
  80. // ED -- common.BlobData -> ND [0..N]
  81. // ED --- EssentialData --> ND [1]
  82. //
  83. // Once ND successfully registered itself on the Mediator server, it sends a
  84. // `Registered` message.
  85. //
  86. // ED <---- Registered ---- ND [1]
  87. //
  88. // ND may now either close the connection or leave it open to transition to the
  89. // History Exchange Protocol. Any further messages ED receives from ND will
  90. // transition into the History Exchange Protocol.
  91. //
  92. // ### Security
  93. //
  94. // The `url.DeviceGroupJoinRequestOrOffer` must be exchanged over a sufficiently
  95. // secure channel. A QR code is considered sufficiently secure in a _safe
  96. // space_. If this can be ensured by the user, ensuring that the Rendezvous Path
  97. // Hash (RPH) is equal on both devices is not strictly necessary.
  98. //
  99. // If an attacker is however able to capture the
  100. // `url.DeviceGroupJoinRequestOrOffer`, the security of the protocol relies on
  101. // the user ensuring that RPH is equal on both devices to ensure authentication
  102. // and mitigate the following attacks:
  103. //
  104. // - If ED started the protocol (offers to join the device group), comparing RPH
  105. // is critical as otherwise the Client Key would become compromised if an
  106. // attacker were able to make a connection faster than the victim's other
  107. // device.
  108. // - If ND started the protocol (requests to join the device group), comparing
  109. // RPH is not as critical yet still vital to mitigate a more sophisticated
  110. // attack where the attacker makes it look as if the victim is connected to
  111. // its device group. Until the victim finds out that it isn't its device group
  112. // (because the process is stuck on ED), the victim may potentially leak
  113. // sensitive information by adding a contact or sending a message, etc.
  114. // - An attacker who also controls the relay server used for connection between
  115. // the victim's two devices could run a full MITM attack. Comparing RPH here
  116. // is critical to ensure that the victim's two devices have established an
  117. // end-to-end encrypted communication channel between each other.
  118. //
  119. // Letting ND start the protocol is considered more secure because of the above
  120. // implications.
  121. //
  122. // ED is always required to let the user confirm the equality of RPH on both
  123. // devices because it is ED who is to transmit the highly sensitive information.
  124. //
  125. // To prevent phishing attacks of a malicious web app claiming to be a Threema
  126. // App (typo squatting), the CORS `Access-Control-Allow-Origin` of any WebSocket
  127. // rendezvous relay server must be set to the bare minimum required by the use
  128. // case, so that a connection cannot be established. However, phishing
  129. // protection against a malicious non-web app claiming to be a Threema App is
  130. // not possible.
  131. syntax = "proto3";
  132. package join;
  133. option java_package = "ch.threema.protobuf.d2d.join";
  134. import "common.proto";
  135. import "md-d2d-sync.proto";
  136. // Root message envelope for messages from the new device (ND) to the existing
  137. // device (ED).
  138. message NdToEd {
  139. // The enveloped message
  140. oneof content {
  141. Registered registered = 1;
  142. }
  143. }
  144. // Root message envelope for messages from the existing device (ED) to the new
  145. // device (ND).
  146. message EdToNd {
  147. // The enveloped message
  148. oneof content {
  149. Begin begin = 1;
  150. // A Blob that is referenced as part of `EssentialData`.
  151. //
  152. // When receiving this variant:
  153. //
  154. // 1. If `EssentialData` has been received before, close the connection and
  155. // abort these steps.
  156. // 2. Store the Blob data temporarily or permanently and store its
  157. // associated Blob ID in the device's database.
  158. common.BlobData blob_data = 2;
  159. EssentialData essential_data = 3;
  160. }
  161. }
  162. // Initial message sent by ED after nomination and user confirmation that RPH is
  163. // identical on both devices.
  164. //
  165. // When creating this message, after confirmation by the user:
  166. //
  167. // 1. Stop displaying RPH and notify the user that the device join process is in
  168. // progress.
  169. // 2. Begin a transaction (scope `NEW_DEVICE_SYNC`, precondition: none) on the
  170. // D2M connection. This transaction is to be held until the connection to ND
  171. // drops or until a `Registered` message was received. While the transaction
  172. // is being held, no `Reflected` and no end-to-end encrypted message coming
  173. // from the chat server is allowed to be processed! If the D2M connection is
  174. // lost, the established connection must also be closed, aborting any running
  175. // steps of this protocol.
  176. // 3. Send the `Begin` message and continue with the steps for creating
  177. // `EssentialData`.
  178. //
  179. // When receiving this message:
  180. //
  181. // 1. If `Begin` has been received before, close the connection and abort these
  182. // steps.
  183. // 2. Stop displaying RPH and notify the user that the device join process is in
  184. // progress.
  185. message Begin {}
  186. // Essential data ND needs to be able to participate in the device group.
  187. //
  188. // Note: The transmitted used nonces are hashed with HMAC-SHA256 using the
  189. // identity as _key_.
  190. //
  191. // When creating this message:
  192. //
  193. // 1. Gather all blobs referenced for the user's profile picture, contact
  194. // profile pictures, etc. and send them as `common.BlobData` before this
  195. // message.
  196. // 2. Send the gathered `EssentialData`.
  197. //
  198. // When receiving this message:
  199. //
  200. // 1. If `EssentialData` has been received before, close the connection and
  201. // abort these steps.
  202. // 2. If any Blob ID is missing from the previously received set of
  203. // `common.BlobData`, close the connection and abort these steps.
  204. // 3. Store the data in the device's database.
  205. // 4. Generate a random D2M Device ID and a random CSP Device ID and store both
  206. // in the device's database.
  207. // 5. Establish a D2M connection by connecting to the provided mediator server.
  208. // 6. Wait until the `ServerInfo` has been received on the D2M connection.
  209. // Validate that the provided `DeviceSlotState` is `NEW`. Otherwise, close
  210. // both the D2M connection (normally) and the connection to ED and abort
  211. // these steps.
  212. // 7. Send a `Registered` message to ED.
  213. // 8. Ask the user whether conversation history data should be requested from
  214. // ND:
  215. // 1. If the user does not want to request conversation history data, wait
  216. // until all buffered data on the connection has been written. Then, close
  217. // the connection and abort these steps.
  218. // 2. If the user wants to request conversation history data from ED, leave
  219. // the connection running and start the History Exchange Protocol.
  220. message EssentialData {
  221. reserved 1; // Reserved for mediator server
  222. // User's identity data
  223. message IdentityData {
  224. // The user's Threema ID
  225. string identity = 1;
  226. // The permanent client key associated to the Threema ID (32 bytes)
  227. bytes ck = 2;
  228. // The device cookie used by the device group for the Threema ID (16 bytes)
  229. bytes csp_device_cookie = 3;
  230. // The CSP server group associated to the Threema ID (1 byte)
  231. string csp_server_group = 4;
  232. }
  233. IdentityData identity_data = 2;
  234. // Threema Work credentials
  235. //
  236. // Required for a Threema Work app. Must not be present in a Threema consumer
  237. // app.
  238. sync.ThreemaWorkCredentials work_credentials = 12;
  239. // Device group data
  240. message DeviceGroupData {
  241. // The device group key (32 bytes)
  242. bytes dgk = 1;
  243. }
  244. DeviceGroupData device_group_data = 3;
  245. // User's profile
  246. sync.UserProfile user_profile = 4;
  247. // Shared settings
  248. sync.Settings settings = 5;
  249. // MDM parameters
  250. sync.MdmParameters mdm_parameters = 6;
  251. // Contacts
  252. message AugmentedContact {
  253. // The contact's data.
  254. sync.Contact contact = 1;
  255. // Unix-ish timestamp in milliseconds when the conversation with this
  256. // contact was last updated.
  257. //
  258. // Optional if no conversation exists for this contact.
  259. optional uint64 last_update_at = 2;
  260. }
  261. repeated AugmentedContact contacts = 7;
  262. // Groups
  263. message AugmentedGroup {
  264. // The group's data.
  265. sync.Group group = 1;
  266. // Unix-ish timestamp in milliseconds when the conversation with this
  267. // group was last updated.
  268. uint64 last_update_at = 2;
  269. }
  270. repeated AugmentedGroup groups = 8;
  271. // Distribution lists
  272. message AugmentedDistributionList {
  273. // The distribution list's data.
  274. sync.DistributionList distribution_list = 1;
  275. // Unix-ish timestamp in milliseconds when the conversation of this
  276. // distribution list was last updated.
  277. uint64 last_update_at = 2;
  278. }
  279. repeated AugmentedDistributionList distribution_lists = 9;
  280. // Hashed nonces that were used for CSP messages.
  281. repeated bytes csp_hashed_nonces = 10;
  282. // Hashed nonces thate were used for D2D messages.
  283. repeated bytes d2d_hashed_nonces = 11;
  284. }
  285. // Lets ED know that ND has received all essential data and successfully
  286. // registered itself on the mediator server.
  287. //
  288. // When receiving this message:
  289. //
  290. // 1. Commit the transaction on the D2M connection. From this point on,
  291. // processing `Reflected` and end-to-end encrypted message coming from the
  292. // chat server is allowed again.
  293. // 2. Wait for ND to either close the connection or for ND to request
  294. // conversation history data. Any further messages from ND will move into
  295. // the History Exchange Protocol.
  296. message Registered {}