@matter/protocol 0.14.1-alpha.0-20250605-9fc134af0 → 0.14.1-alpha.0-20250607-a93593303

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (312) hide show
  1. package/dist/cjs/action/server/AccessControl.d.ts +5 -7
  2. package/dist/cjs/action/server/AccessControl.d.ts.map +1 -1
  3. package/dist/cjs/action/server/AccessControl.js.map +1 -1
  4. package/dist/cjs/action/server/AttributeWriteResponse.d.ts.map +1 -1
  5. package/dist/cjs/action/server/AttributeWriteResponse.js +23 -0
  6. package/dist/cjs/action/server/AttributeWriteResponse.js.map +1 -1
  7. package/dist/cjs/action/server/CommandInvokeResponse.d.ts.map +1 -1
  8. package/dist/cjs/action/server/CommandInvokeResponse.js +24 -1
  9. package/dist/cjs/action/server/CommandInvokeResponse.js.map +1 -1
  10. package/dist/cjs/action/server/DataResponse.d.ts +1 -1
  11. package/dist/cjs/action/server/DataResponse.d.ts.map +1 -1
  12. package/dist/cjs/action/server/Subject.d.ts +25 -0
  13. package/dist/cjs/action/server/Subject.d.ts.map +1 -0
  14. package/dist/cjs/action/server/Subject.js +54 -0
  15. package/dist/cjs/action/server/Subject.js.map +6 -0
  16. package/dist/cjs/action/server/index.d.ts +1 -0
  17. package/dist/cjs/action/server/index.d.ts.map +1 -1
  18. package/dist/cjs/action/server/index.js +1 -0
  19. package/dist/cjs/action/server/index.js.map +1 -1
  20. package/dist/cjs/certificate/DeviceCertification.d.ts +2 -2
  21. package/dist/cjs/certificate/DeviceCertification.d.ts.map +1 -1
  22. package/dist/cjs/certificate/DeviceCertification.js.map +1 -1
  23. package/dist/cjs/cluster/client/AttributeClient.d.ts +3 -3
  24. package/dist/cjs/cluster/client/AttributeClient.d.ts.map +1 -1
  25. package/dist/cjs/cluster/client/AttributeClient.js +14 -2
  26. package/dist/cjs/cluster/client/AttributeClient.js.map +1 -1
  27. package/dist/cjs/cluster/client/ClusterClient.d.ts +3 -2
  28. package/dist/cjs/cluster/client/ClusterClient.d.ts.map +1 -1
  29. package/dist/cjs/cluster/client/ClusterClient.js +66 -1
  30. package/dist/cjs/cluster/client/ClusterClient.js.map +1 -1
  31. package/dist/cjs/cluster/client/ClusterClientTypes.d.ts +36 -8
  32. package/dist/cjs/cluster/client/ClusterClientTypes.d.ts.map +1 -1
  33. package/dist/cjs/cluster/client/EventClient.d.ts +3 -3
  34. package/dist/cjs/cluster/client/EventClient.d.ts.map +1 -1
  35. package/dist/cjs/cluster/client/EventClient.js +7 -0
  36. package/dist/cjs/cluster/client/EventClient.js.map +1 -1
  37. package/dist/cjs/codec/MessageCodec.d.ts.map +1 -1
  38. package/dist/cjs/codec/MessageCodec.js +31 -6
  39. package/dist/cjs/codec/MessageCodec.js.map +1 -1
  40. package/dist/cjs/fabric/Fabric.d.ts +20 -30
  41. package/dist/cjs/fabric/Fabric.d.ts.map +1 -1
  42. package/dist/cjs/fabric/Fabric.js +38 -62
  43. package/dist/cjs/fabric/Fabric.js.map +2 -2
  44. package/dist/cjs/fabric/FabricManager.d.ts.map +1 -1
  45. package/dist/cjs/fabric/FabricManager.js +10 -4
  46. package/dist/cjs/fabric/FabricManager.js.map +1 -1
  47. package/dist/cjs/groups/FabricGroupsManager.d.ts +46 -0
  48. package/dist/cjs/groups/FabricGroupsManager.d.ts.map +1 -0
  49. package/dist/cjs/groups/FabricGroupsManager.js +155 -0
  50. package/dist/cjs/groups/FabricGroupsManager.js.map +6 -0
  51. package/dist/cjs/groups/Groups.d.ts +34 -0
  52. package/dist/cjs/groups/Groups.d.ts.map +1 -0
  53. package/dist/cjs/groups/Groups.js +89 -0
  54. package/dist/cjs/groups/Groups.js.map +6 -0
  55. package/dist/cjs/groups/KeySets.d.ts +64 -0
  56. package/dist/cjs/groups/KeySets.d.ts.map +1 -0
  57. package/dist/cjs/groups/KeySets.js +179 -0
  58. package/dist/cjs/groups/KeySets.js.map +6 -0
  59. package/dist/cjs/groups/MessagingState.d.ts +24 -0
  60. package/dist/cjs/groups/MessagingState.d.ts.map +1 -0
  61. package/dist/cjs/groups/MessagingState.js +91 -0
  62. package/dist/cjs/groups/MessagingState.js.map +6 -0
  63. package/dist/cjs/groups/index.d.ts +8 -0
  64. package/dist/cjs/groups/index.d.ts.map +1 -0
  65. package/dist/cjs/groups/index.js +25 -0
  66. package/dist/cjs/groups/index.js.map +6 -0
  67. package/dist/cjs/index.d.ts +1 -0
  68. package/dist/cjs/index.d.ts.map +1 -1
  69. package/dist/cjs/index.js +1 -0
  70. package/dist/cjs/index.js.map +1 -1
  71. package/dist/cjs/interaction/AccessControlManager.d.ts +4 -13
  72. package/dist/cjs/interaction/AccessControlManager.d.ts.map +1 -1
  73. package/dist/cjs/interaction/AccessControlManager.js +38 -47
  74. package/dist/cjs/interaction/AccessControlManager.js.map +1 -1
  75. package/dist/cjs/interaction/InteractionClient.d.ts +5 -4
  76. package/dist/cjs/interaction/InteractionClient.d.ts.map +1 -1
  77. package/dist/cjs/interaction/InteractionClient.js +53 -3
  78. package/dist/cjs/interaction/InteractionClient.js.map +1 -1
  79. package/dist/cjs/interaction/InteractionMessenger.d.ts.map +1 -1
  80. package/dist/cjs/interaction/InteractionMessenger.js +15 -0
  81. package/dist/cjs/interaction/InteractionMessenger.js.map +1 -1
  82. package/dist/cjs/interaction/Subscription.d.ts +3 -3
  83. package/dist/cjs/interaction/Subscription.d.ts.map +1 -1
  84. package/dist/cjs/interaction/Subscription.js.map +1 -1
  85. package/dist/cjs/peer/PeerAddress.d.ts +1 -0
  86. package/dist/cjs/peer/PeerAddress.d.ts.map +1 -1
  87. package/dist/cjs/peer/PeerAddress.js +5 -0
  88. package/dist/cjs/peer/PeerAddress.js.map +1 -1
  89. package/dist/cjs/peer/PeerSet.d.ts.map +1 -1
  90. package/dist/cjs/peer/PeerSet.js +31 -2
  91. package/dist/cjs/peer/PeerSet.js.map +1 -1
  92. package/dist/cjs/protocol/ChannelManager.d.ts.map +1 -1
  93. package/dist/cjs/protocol/ChannelManager.js +7 -8
  94. package/dist/cjs/protocol/ChannelManager.js.map +1 -1
  95. package/dist/cjs/protocol/ExchangeManager.d.ts.map +1 -1
  96. package/dist/cjs/protocol/ExchangeManager.js +39 -25
  97. package/dist/cjs/protocol/ExchangeManager.js.map +1 -1
  98. package/dist/cjs/protocol/MessageExchange.d.ts +1 -1
  99. package/dist/cjs/protocol/MessageExchange.d.ts.map +1 -1
  100. package/dist/cjs/protocol/MessageExchange.js +32 -4
  101. package/dist/cjs/protocol/MessageExchange.js.map +1 -1
  102. package/dist/cjs/protocol/MessageReceptionState.d.ts +1 -1
  103. package/dist/cjs/securechannel/SecureChannelProtocol.js +1 -1
  104. package/dist/cjs/securechannel/SecureChannelProtocol.js.map +1 -1
  105. package/dist/cjs/session/GroupSession.d.ts +56 -0
  106. package/dist/cjs/session/GroupSession.d.ts.map +1 -0
  107. package/dist/cjs/session/GroupSession.js +188 -0
  108. package/dist/cjs/session/GroupSession.js.map +6 -0
  109. package/dist/cjs/session/InsecureSession.d.ts +2 -1
  110. package/dist/cjs/session/InsecureSession.d.ts.map +1 -1
  111. package/dist/cjs/session/InsecureSession.js +3 -2
  112. package/dist/cjs/session/InsecureSession.js.map +1 -1
  113. package/dist/cjs/session/NodeSession.d.ts +88 -0
  114. package/dist/cjs/session/NodeSession.d.ts.map +1 -0
  115. package/dist/cjs/session/NodeSession.js +318 -0
  116. package/dist/cjs/session/NodeSession.js.map +6 -0
  117. package/dist/cjs/session/SecureSession.d.ts +10 -75
  118. package/dist/cjs/session/SecureSession.d.ts.map +1 -1
  119. package/dist/cjs/session/SecureSession.js +9 -280
  120. package/dist/cjs/session/SecureSession.js.map +2 -2
  121. package/dist/cjs/session/Session.d.ts +6 -5
  122. package/dist/cjs/session/Session.d.ts.map +1 -1
  123. package/dist/cjs/session/Session.js +11 -1
  124. package/dist/cjs/session/Session.js.map +1 -1
  125. package/dist/cjs/session/SessionManager.d.ts +27 -9
  126. package/dist/cjs/session/SessionManager.d.ts.map +1 -1
  127. package/dist/cjs/session/SessionManager.js +83 -5
  128. package/dist/cjs/session/SessionManager.js.map +2 -2
  129. package/dist/cjs/session/case/CaseClient.d.ts +1 -1
  130. package/dist/cjs/session/case/CaseClient.js +2 -2
  131. package/dist/cjs/session/case/CaseClient.js.map +1 -1
  132. package/dist/cjs/session/index.d.ts +2 -0
  133. package/dist/cjs/session/index.d.ts.map +1 -1
  134. package/dist/cjs/session/index.js +2 -0
  135. package/dist/cjs/session/index.js.map +1 -1
  136. package/dist/cjs/session/pase/PaseClient.d.ts +1 -1
  137. package/dist/esm/action/server/AccessControl.d.ts +5 -7
  138. package/dist/esm/action/server/AccessControl.d.ts.map +1 -1
  139. package/dist/esm/action/server/AccessControl.js.map +1 -1
  140. package/dist/esm/action/server/AttributeWriteResponse.d.ts.map +1 -1
  141. package/dist/esm/action/server/AttributeWriteResponse.js +23 -0
  142. package/dist/esm/action/server/AttributeWriteResponse.js.map +1 -1
  143. package/dist/esm/action/server/CommandInvokeResponse.d.ts.map +1 -1
  144. package/dist/esm/action/server/CommandInvokeResponse.js +24 -1
  145. package/dist/esm/action/server/CommandInvokeResponse.js.map +1 -1
  146. package/dist/esm/action/server/DataResponse.d.ts +1 -1
  147. package/dist/esm/action/server/DataResponse.d.ts.map +1 -1
  148. package/dist/esm/action/server/Subject.d.ts +25 -0
  149. package/dist/esm/action/server/Subject.d.ts.map +1 -0
  150. package/dist/esm/action/server/Subject.js +34 -0
  151. package/dist/esm/action/server/Subject.js.map +6 -0
  152. package/dist/esm/action/server/index.d.ts +1 -0
  153. package/dist/esm/action/server/index.d.ts.map +1 -1
  154. package/dist/esm/action/server/index.js +1 -0
  155. package/dist/esm/action/server/index.js.map +1 -1
  156. package/dist/esm/certificate/DeviceCertification.d.ts +2 -2
  157. package/dist/esm/certificate/DeviceCertification.d.ts.map +1 -1
  158. package/dist/esm/certificate/DeviceCertification.js.map +1 -1
  159. package/dist/esm/cluster/client/AttributeClient.d.ts +3 -3
  160. package/dist/esm/cluster/client/AttributeClient.d.ts.map +1 -1
  161. package/dist/esm/cluster/client/AttributeClient.js +13 -1
  162. package/dist/esm/cluster/client/AttributeClient.js.map +1 -1
  163. package/dist/esm/cluster/client/ClusterClient.d.ts +3 -2
  164. package/dist/esm/cluster/client/ClusterClient.d.ts.map +1 -1
  165. package/dist/esm/cluster/client/ClusterClient.js +67 -2
  166. package/dist/esm/cluster/client/ClusterClient.js.map +1 -1
  167. package/dist/esm/cluster/client/ClusterClientTypes.d.ts +36 -8
  168. package/dist/esm/cluster/client/ClusterClientTypes.d.ts.map +1 -1
  169. package/dist/esm/cluster/client/EventClient.d.ts +3 -3
  170. package/dist/esm/cluster/client/EventClient.d.ts.map +1 -1
  171. package/dist/esm/cluster/client/EventClient.js +7 -0
  172. package/dist/esm/cluster/client/EventClient.js.map +1 -1
  173. package/dist/esm/codec/MessageCodec.d.ts.map +1 -1
  174. package/dist/esm/codec/MessageCodec.js +41 -7
  175. package/dist/esm/codec/MessageCodec.js.map +1 -1
  176. package/dist/esm/fabric/Fabric.d.ts +20 -30
  177. package/dist/esm/fabric/Fabric.d.ts.map +1 -1
  178. package/dist/esm/fabric/Fabric.js +38 -62
  179. package/dist/esm/fabric/Fabric.js.map +2 -2
  180. package/dist/esm/fabric/FabricManager.d.ts.map +1 -1
  181. package/dist/esm/fabric/FabricManager.js +10 -4
  182. package/dist/esm/fabric/FabricManager.js.map +1 -1
  183. package/dist/esm/groups/FabricGroupsManager.d.ts +46 -0
  184. package/dist/esm/groups/FabricGroupsManager.d.ts.map +1 -0
  185. package/dist/esm/groups/FabricGroupsManager.js +135 -0
  186. package/dist/esm/groups/FabricGroupsManager.js.map +6 -0
  187. package/dist/esm/groups/Groups.d.ts +34 -0
  188. package/dist/esm/groups/Groups.d.ts.map +1 -0
  189. package/dist/esm/groups/Groups.js +69 -0
  190. package/dist/esm/groups/Groups.js.map +6 -0
  191. package/dist/esm/groups/KeySets.d.ts +64 -0
  192. package/dist/esm/groups/KeySets.d.ts.map +1 -0
  193. package/dist/esm/groups/KeySets.js +159 -0
  194. package/dist/esm/groups/KeySets.js.map +6 -0
  195. package/dist/esm/groups/MessagingState.d.ts +24 -0
  196. package/dist/esm/groups/MessagingState.d.ts.map +1 -0
  197. package/dist/esm/groups/MessagingState.js +71 -0
  198. package/dist/esm/groups/MessagingState.js.map +6 -0
  199. package/dist/esm/groups/index.d.ts +8 -0
  200. package/dist/esm/groups/index.d.ts.map +1 -0
  201. package/dist/esm/groups/index.js +8 -0
  202. package/dist/esm/groups/index.js.map +6 -0
  203. package/dist/esm/index.d.ts +1 -0
  204. package/dist/esm/index.d.ts.map +1 -1
  205. package/dist/esm/index.js +1 -0
  206. package/dist/esm/index.js.map +1 -1
  207. package/dist/esm/interaction/AccessControlManager.d.ts +4 -13
  208. package/dist/esm/interaction/AccessControlManager.d.ts.map +1 -1
  209. package/dist/esm/interaction/AccessControlManager.js +39 -48
  210. package/dist/esm/interaction/AccessControlManager.js.map +1 -1
  211. package/dist/esm/interaction/InteractionClient.d.ts +5 -4
  212. package/dist/esm/interaction/InteractionClient.d.ts.map +1 -1
  213. package/dist/esm/interaction/InteractionClient.js +54 -4
  214. package/dist/esm/interaction/InteractionClient.js.map +1 -1
  215. package/dist/esm/interaction/InteractionMessenger.d.ts.map +1 -1
  216. package/dist/esm/interaction/InteractionMessenger.js +15 -0
  217. package/dist/esm/interaction/InteractionMessenger.js.map +1 -1
  218. package/dist/esm/interaction/Subscription.d.ts +3 -3
  219. package/dist/esm/interaction/Subscription.d.ts.map +1 -1
  220. package/dist/esm/interaction/Subscription.js.map +1 -1
  221. package/dist/esm/peer/PeerAddress.d.ts +1 -0
  222. package/dist/esm/peer/PeerAddress.d.ts.map +1 -1
  223. package/dist/esm/peer/PeerAddress.js +5 -0
  224. package/dist/esm/peer/PeerAddress.js.map +1 -1
  225. package/dist/esm/peer/PeerSet.d.ts.map +1 -1
  226. package/dist/esm/peer/PeerSet.js +33 -3
  227. package/dist/esm/peer/PeerSet.js.map +1 -1
  228. package/dist/esm/protocol/ChannelManager.d.ts.map +1 -1
  229. package/dist/esm/protocol/ChannelManager.js +7 -8
  230. package/dist/esm/protocol/ChannelManager.js.map +1 -1
  231. package/dist/esm/protocol/ExchangeManager.d.ts.map +1 -1
  232. package/dist/esm/protocol/ExchangeManager.js +41 -27
  233. package/dist/esm/protocol/ExchangeManager.js.map +1 -1
  234. package/dist/esm/protocol/MessageExchange.d.ts +1 -1
  235. package/dist/esm/protocol/MessageExchange.d.ts.map +1 -1
  236. package/dist/esm/protocol/MessageExchange.js +39 -5
  237. package/dist/esm/protocol/MessageExchange.js.map +1 -1
  238. package/dist/esm/protocol/MessageReceptionState.d.ts +1 -1
  239. package/dist/esm/securechannel/SecureChannelProtocol.js +2 -2
  240. package/dist/esm/securechannel/SecureChannelProtocol.js.map +1 -1
  241. package/dist/esm/session/GroupSession.d.ts +56 -0
  242. package/dist/esm/session/GroupSession.d.ts.map +1 -0
  243. package/dist/esm/session/GroupSession.js +177 -0
  244. package/dist/esm/session/GroupSession.js.map +6 -0
  245. package/dist/esm/session/InsecureSession.d.ts +2 -1
  246. package/dist/esm/session/InsecureSession.d.ts.map +1 -1
  247. package/dist/esm/session/InsecureSession.js +3 -2
  248. package/dist/esm/session/InsecureSession.js.map +1 -1
  249. package/dist/esm/session/NodeSession.d.ts +88 -0
  250. package/dist/esm/session/NodeSession.d.ts.map +1 -0
  251. package/dist/esm/session/NodeSession.js +298 -0
  252. package/dist/esm/session/NodeSession.js.map +6 -0
  253. package/dist/esm/session/SecureSession.d.ts +10 -75
  254. package/dist/esm/session/SecureSession.d.ts.map +1 -1
  255. package/dist/esm/session/SecureSession.js +10 -291
  256. package/dist/esm/session/SecureSession.js.map +2 -2
  257. package/dist/esm/session/Session.d.ts +6 -5
  258. package/dist/esm/session/Session.d.ts.map +1 -1
  259. package/dist/esm/session/Session.js +12 -2
  260. package/dist/esm/session/Session.js.map +1 -1
  261. package/dist/esm/session/SessionManager.d.ts +27 -9
  262. package/dist/esm/session/SessionManager.d.ts.map +1 -1
  263. package/dist/esm/session/SessionManager.js +84 -6
  264. package/dist/esm/session/SessionManager.js.map +1 -1
  265. package/dist/esm/session/case/CaseClient.d.ts +1 -1
  266. package/dist/esm/session/case/CaseClient.js +2 -2
  267. package/dist/esm/session/case/CaseClient.js.map +1 -1
  268. package/dist/esm/session/index.d.ts +2 -0
  269. package/dist/esm/session/index.d.ts.map +1 -1
  270. package/dist/esm/session/index.js +2 -0
  271. package/dist/esm/session/index.js.map +1 -1
  272. package/dist/esm/session/pase/PaseClient.d.ts +1 -1
  273. package/package.json +6 -6
  274. package/src/action/server/AccessControl.ts +4 -7
  275. package/src/action/server/AttributeWriteResponse.ts +29 -7
  276. package/src/action/server/CommandInvokeResponse.ts +28 -7
  277. package/src/action/server/DataResponse.ts +1 -1
  278. package/src/action/server/Subject.ts +45 -0
  279. package/src/action/server/index.ts +1 -0
  280. package/src/certificate/DeviceCertification.ts +2 -2
  281. package/src/cluster/client/AttributeClient.ts +15 -3
  282. package/src/cluster/client/ClusterClient.ts +97 -4
  283. package/src/cluster/client/ClusterClientTypes.ts +45 -9
  284. package/src/cluster/client/EventClient.ts +9 -2
  285. package/src/codec/MessageCodec.ts +49 -8
  286. package/src/fabric/Fabric.ts +51 -85
  287. package/src/fabric/FabricManager.ts +11 -4
  288. package/src/groups/FabricGroupsManager.ts +164 -0
  289. package/src/groups/Groups.ts +81 -0
  290. package/src/groups/KeySets.ts +194 -0
  291. package/src/groups/MessagingState.ts +76 -0
  292. package/src/groups/index.ts +8 -0
  293. package/src/index.ts +1 -0
  294. package/src/interaction/AccessControlManager.ts +49 -81
  295. package/src/interaction/InteractionClient.ts +66 -6
  296. package/src/interaction/InteractionMessenger.ts +15 -0
  297. package/src/interaction/Subscription.ts +3 -3
  298. package/src/peer/PeerAddress.ts +4 -0
  299. package/src/peer/PeerSet.ts +39 -4
  300. package/src/protocol/ChannelManager.ts +7 -9
  301. package/src/protocol/ExchangeManager.ts +51 -35
  302. package/src/protocol/MessageExchange.ts +42 -7
  303. package/src/protocol/MessageReceptionState.ts +2 -2
  304. package/src/securechannel/SecureChannelProtocol.ts +2 -2
  305. package/src/session/GroupSession.ts +223 -0
  306. package/src/session/InsecureSession.ts +3 -2
  307. package/src/session/NodeSession.ts +367 -0
  308. package/src/session/SecureSession.ts +14 -363
  309. package/src/session/Session.ts +17 -6
  310. package/src/session/SessionManager.ts +94 -14
  311. package/src/session/case/CaseClient.ts +2 -2
  312. package/src/session/index.ts +2 -3
@@ -0,0 +1,223 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2023 Project CHIP Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { Subject } from "#action/server/Subject.js";
7
+ import { DecodedMessage, DecodedPacket, Message, MessageCodec, Packet, SessionType } from "#codec/index.js";
8
+ import { Fabric } from "#fabric/Fabric.js";
9
+ import { FabricManager } from "#fabric/FabricManager.js";
10
+ import {
11
+ Bytes,
12
+ Crypto,
13
+ CryptoDecryptError,
14
+ ImplementationError,
15
+ InternalError,
16
+ Logger,
17
+ MatterFlowError,
18
+ UnexpectedDataError,
19
+ } from "#general";
20
+ import type { SessionManager } from "#session/SessionManager.js";
21
+ import { GroupId, NodeId } from "#types";
22
+ import { SecureSession } from "./SecureSession.js";
23
+ import { Session } from "./Session.js";
24
+
25
+ const logger = Logger.get("SecureGroupSession");
26
+
27
+ /** Secure Group session instance */
28
+ export class GroupSession extends SecureSession {
29
+ readonly #id: number;
30
+ readonly #fabric: Fabric;
31
+ readonly #peerNodeId: NodeId;
32
+ readonly #operationalGroupKey: Uint8Array;
33
+ readonly supportsMRP = false;
34
+ readonly closingAfterExchangeFinished = false; // Group sessions do not close after exchange finished, they are long-lived
35
+
36
+ readonly keySetId: number;
37
+
38
+ constructor(args: {
39
+ manager?: SessionManager;
40
+ id: number; // Records the Group Session ID derived from the Operational Group Key used to encrypt the message.
41
+ fabric: Fabric;
42
+ keySetId: number; // The Group Key Set ID that was used to encrypt the incoming group message.
43
+ peerNodeId: NodeId; //The Target Group Node Id
44
+ operationalGroupKey: Uint8Array; // The Operational Group Key that was used to encrypt the incoming group message.
45
+ }) {
46
+ const { manager, fabric, operationalGroupKey, id, peerNodeId, keySetId } = args;
47
+ super({
48
+ ...args,
49
+ setActiveTimestamp: false, // We always set the active timestamp for Secure sessions TODO Check
50
+ messageCounter: fabric.groups.messaging.counterFor(operationalGroupKey),
51
+ });
52
+ this.#id = id;
53
+ this.#fabric = fabric;
54
+ this.#peerNodeId = peerNodeId;
55
+ this.keySetId = keySetId;
56
+ this.#operationalGroupKey = operationalGroupKey;
57
+
58
+ manager?.registerGroupSession(this);
59
+ fabric.addSession(this);
60
+
61
+ logger.debug(`Created secure GROUP session for fabric index ${fabric.fabricIndex}`, this.name);
62
+ }
63
+
64
+ override get type() {
65
+ return SessionType.Group;
66
+ }
67
+
68
+ get fabric(): Fabric {
69
+ return this.#fabric;
70
+ }
71
+
72
+ get id() {
73
+ return this.#id;
74
+ }
75
+
76
+ get peerSessionId(): number {
77
+ return this.#id; // we use the same peer session ID then ours because should be the same keys
78
+ }
79
+
80
+ get name() {
81
+ return `group/${this.#id}`;
82
+ }
83
+
84
+ get nodeId() {
85
+ return this.#fabric.nodeId;
86
+ }
87
+
88
+ get peerNodeId() {
89
+ return this.#peerNodeId;
90
+ }
91
+
92
+ get associatedFabric(): Fabric {
93
+ return this.#fabric;
94
+ }
95
+
96
+ subjectFor(message?: Message): Subject {
97
+ if (message === undefined || message.packetHeader.destGroupId === undefined) {
98
+ throw new ImplementationError("GroupSession requires a message with destGroupId");
99
+ }
100
+ return this.fabric.groups.subjectForGroup(GroupId(message.packetHeader.destGroupId), this.keySetId);
101
+ }
102
+
103
+ override notifyActivity(_messageReceived: boolean) {
104
+ // Group sessions do not have a specific activity notification, so we do nothing here
105
+ }
106
+
107
+ override updateMessageCounter(messageCounter: number, sourceNodeId: NodeId, operationalKey: Uint8Array) {
108
+ if (sourceNodeId === undefined || operationalKey === undefined) {
109
+ throw new InternalError("Source Node ID is required for GroupSession updateMessageCounter.");
110
+ }
111
+ const receptionState = this.#fabric.groups.messaging.receptionStateFor(sourceNodeId, operationalKey);
112
+ receptionState.updateMessageCounter(messageCounter);
113
+ }
114
+
115
+ encode(message: Message): Packet {
116
+ message.packetHeader.sessionId = this.#id;
117
+ const { header, applicationPayload } = MessageCodec.encodePayload(message);
118
+ if (header.destGroupId === undefined) {
119
+ // Just to be sure
120
+ throw new UnexpectedDataError("Group ID is required for GroupSession encode.");
121
+ }
122
+
123
+ const headerBytes = MessageCodec.encodePacketHeader(message.packetHeader);
124
+ const securityFlags = headerBytes[3];
125
+ const nonce = Session.generateNonce(securityFlags, header.messageId, this.#fabric.nodeId);
126
+
127
+ return {
128
+ header,
129
+ applicationPayload: Crypto.encrypt(this.#operationalGroupKey, applicationPayload, nonce, headerBytes),
130
+ };
131
+ }
132
+
133
+ decode(): DecodedMessage {
134
+ throw new InternalError("GroupSession does not support decode on instance.");
135
+ }
136
+
137
+ static decode(
138
+ fabrics: FabricManager,
139
+ { header, applicationPayload, messageExtension }: DecodedPacket,
140
+ aad: Uint8Array,
141
+ ): {
142
+ message: DecodedMessage;
143
+ key: Uint8Array;
144
+ sessionId: number;
145
+ sourceNodeId: NodeId;
146
+ keySetId: number;
147
+ fabric: Fabric;
148
+ } {
149
+ if (header.hasMessageExtensions) {
150
+ logger.info(
151
+ `Message extensions are not supported. Ignoring ${messageExtension ? Bytes.toHex(messageExtension) : undefined}`,
152
+ );
153
+ }
154
+ const sourceNodeId = header.sourceNodeId;
155
+ if (sourceNodeId === undefined) {
156
+ // Already checked on decoding, but validate twice
157
+ throw new UnexpectedDataError("Source Node ID is required for GroupSession decode.");
158
+ }
159
+ const nonce = Session.generateNonce(header.securityFlags, header.messageId, sourceNodeId);
160
+ const sessionId = header.sessionId;
161
+ const keys = new Array<{ key: Uint8Array; keySetId: number; fabric: Fabric }>();
162
+ for (const fabric of fabrics) {
163
+ const sessions = fabric.groups.sessions.get(sessionId);
164
+ if (sessions?.length) {
165
+ for (const session of sessions) {
166
+ keys.push({ ...session, fabric });
167
+ }
168
+ }
169
+ }
170
+ if (keys.length === 0) {
171
+ throw new MatterFlowError("No key candidate found for group session decryption.");
172
+ }
173
+ let message: DecodedMessage | undefined;
174
+ let key: Uint8Array | undefined;
175
+ let fabric: Fabric | undefined;
176
+ let keySetId: number | undefined;
177
+ let found = false;
178
+ for ({ key, keySetId, fabric } of keys) {
179
+ try {
180
+ message = MessageCodec.decodePayload({
181
+ header,
182
+ applicationPayload: Crypto.decrypt(key, applicationPayload, nonce, aad),
183
+ });
184
+ found = true;
185
+ break; // Exit loop on first successful decryption
186
+ } catch (error) {
187
+ CryptoDecryptError.accept(error);
188
+ }
189
+ }
190
+ if (!found || !message || !key || !keySetId || !fabric) {
191
+ throw new MatterFlowError("Failed to decode group message with any key candidate.");
192
+ }
193
+
194
+ if (message.payloadHeader.hasSecuredExtension) {
195
+ logger.info(
196
+ `Secured extensions are not supported. Ignoring ${message.securityExtension ? Bytes.toHex(message.securityExtension) : undefined}`,
197
+ );
198
+ }
199
+
200
+ return { message, key, sessionId, sourceNodeId, keySetId, fabric };
201
+ }
202
+
203
+ async destroy() {
204
+ logger.info(`End group session ${this.name}`);
205
+ this.manager?.removeGroupSession(this);
206
+ }
207
+
208
+ end() {
209
+ return this.destroy();
210
+ }
211
+ }
212
+
213
+ export namespace GroupSession {
214
+ export function assert(session?: Session, errorText?: string): asserts session is GroupSession {
215
+ if (!is(session)) {
216
+ throw new MatterFlowError(errorText ?? "Insecure session in secure context");
217
+ }
218
+ }
219
+
220
+ export function is(session?: Session): session is GroupSession {
221
+ return session?.type === SessionType.Group;
222
+ }
223
+ }
@@ -6,11 +6,11 @@
6
6
 
7
7
  import { Logger, MatterFlowError } from "#general";
8
8
  import { NodeId } from "#types";
9
- import { DecodedMessage, DecodedPacket, Message, MessageCodec, Packet } from "../codec/MessageCodec.js";
9
+ import { DecodedMessage, DecodedPacket, Message, MessageCodec, Packet, SessionType } from "../codec/MessageCodec.js";
10
10
  import { Fabric } from "../fabric/Fabric.js";
11
11
  import { MessageCounter } from "../protocol/MessageCounter.js";
12
12
  import { MessageReceptionStateUnencryptedWithRollover } from "../protocol/MessageReceptionState.js";
13
- import { NoAssociatedFabricError } from "./SecureSession.js";
13
+ import { NoAssociatedFabricError } from "./NodeSession.js";
14
14
  import { Session, SessionParameterOptions } from "./Session.js";
15
15
  import { SessionManager, UNICAST_UNSECURE_SESSION_ID } from "./SessionManager.js";
16
16
 
@@ -20,6 +20,7 @@ export class InsecureSession extends Session {
20
20
  readonly #initiatorNodeId: NodeId;
21
21
  readonly closingAfterExchangeFinished = false;
22
22
  readonly supportsMRP = true;
23
+ readonly type = SessionType.Unicast;
23
24
 
24
25
  constructor(args: {
25
26
  manager?: SessionManager;
@@ -0,0 +1,367 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Matter.js Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { Subject } from "#action/server/Subject.js";
8
+ import { DecodedMessage, DecodedPacket, Message, MessageCodec, Packet, SessionType } from "#codec/MessageCodec.js";
9
+ import { Fabric } from "#fabric/Fabric.js";
10
+ import { BasicSet, Bytes, CRYPTO_SYMMETRIC_KEY_LENGTH, Crypto, Diagnostic, Logger, MatterFlowError } from "#general";
11
+ import { Subscription } from "#interaction/Subscription.js";
12
+ import { PeerAddress } from "#peer/PeerAddress.js";
13
+ import { NoChannelError } from "#protocol/ChannelManager.js";
14
+ import { MessageCounter } from "#protocol/MessageCounter.js";
15
+ import { MessageReceptionStateEncryptedWithoutRollover } from "#protocol/MessageReceptionState.js";
16
+ import { CaseAuthenticatedTag, FabricIndex, NodeId, StatusCode, StatusResponseError } from "#types";
17
+ import { SecureSession } from "./SecureSession.js";
18
+ import { Session, SessionParameterOptions } from "./Session.js";
19
+ import { type SessionManager } from "./SessionManager.js";
20
+
21
+ const logger = Logger.get("SecureSession");
22
+
23
+ const SESSION_KEYS_INFO = Bytes.fromString("SessionKeys");
24
+ const SESSION_RESUMPTION_KEYS_INFO = Bytes.fromString("SessionResumptionKeys");
25
+
26
+ export class NoAssociatedFabricError extends StatusResponseError {
27
+ constructor(message: string) {
28
+ super(message, StatusCode.UnsupportedAccess);
29
+ }
30
+ }
31
+
32
+ export class NodeSession extends SecureSession {
33
+ readonly #subscriptions = new BasicSet<Subscription>();
34
+ #closingAfterExchangeFinished = false;
35
+ #sendCloseMessageWhenClosing = true;
36
+ readonly #id: number;
37
+ readonly #isInitiator: boolean;
38
+ #fabric: Fabric | undefined;
39
+ readonly #peerNodeId: NodeId;
40
+ readonly #peerSessionId: number;
41
+ readonly #decryptKey: Uint8Array;
42
+ readonly #encryptKey: Uint8Array;
43
+ readonly #attestationKey: Uint8Array;
44
+ #caseAuthenticatedTags: CaseAuthenticatedTag[];
45
+ #isClosing = false;
46
+ readonly supportsMRP = true;
47
+ readonly type = SessionType.Unicast;
48
+
49
+ static async create(args: {
50
+ manager?: SessionManager;
51
+ id: number;
52
+ fabric: Fabric | undefined;
53
+ peerNodeId: NodeId;
54
+ peerSessionId: number;
55
+ sharedSecret: Uint8Array;
56
+ salt: Uint8Array;
57
+ isInitiator: boolean;
58
+ isResumption: boolean;
59
+ peerSessionParameters?: SessionParameterOptions;
60
+ caseAuthenticatedTags?: CaseAuthenticatedTag[];
61
+ }) {
62
+ const {
63
+ manager,
64
+ id,
65
+ fabric,
66
+ peerNodeId,
67
+ peerSessionId,
68
+ sharedSecret,
69
+ salt,
70
+ isInitiator,
71
+ isResumption,
72
+ peerSessionParameters,
73
+ caseAuthenticatedTags,
74
+ } = args;
75
+ const keys = await Crypto.hkdf(
76
+ sharedSecret,
77
+ salt,
78
+ isResumption ? SESSION_RESUMPTION_KEYS_INFO : SESSION_KEYS_INFO,
79
+ CRYPTO_SYMMETRIC_KEY_LENGTH * 3,
80
+ );
81
+ const decryptKey = isInitiator ? keys.slice(16, 32) : keys.slice(0, 16);
82
+ const encryptKey = isInitiator ? keys.slice(0, 16) : keys.slice(16, 32);
83
+ const attestationKey = keys.slice(32, 48);
84
+ return new NodeSession({
85
+ manager,
86
+ id,
87
+ fabric,
88
+ peerNodeId,
89
+ peerSessionId,
90
+ decryptKey,
91
+ encryptKey,
92
+ attestationKey,
93
+ sessionParameters: peerSessionParameters,
94
+ isInitiator,
95
+ caseAuthenticatedTags,
96
+ });
97
+ }
98
+
99
+ constructor(args: {
100
+ manager?: SessionManager;
101
+ id: number;
102
+ fabric: Fabric | undefined;
103
+ peerNodeId: NodeId;
104
+ peerSessionId: number;
105
+ decryptKey: Uint8Array;
106
+ encryptKey: Uint8Array;
107
+ attestationKey: Uint8Array;
108
+ sessionParameters?: SessionParameterOptions;
109
+ caseAuthenticatedTags?: CaseAuthenticatedTag[];
110
+ isInitiator: boolean;
111
+ }) {
112
+ super({
113
+ ...args,
114
+ setActiveTimestamp: true, // We always set the active timestamp for Secure sessions
115
+ // Can be changed to a PersistedMessageCounter if we implement session storage
116
+ messageCounter: new MessageCounter(() => {
117
+ // Secure Session Message Counter
118
+ // Expire/End the session before the counter rolls over
119
+ this.end(true, true).catch(error => logger.error(`Error while closing session: ${error}`));
120
+ }),
121
+ messageReceptionState: new MessageReceptionStateEncryptedWithoutRollover(),
122
+ });
123
+ const {
124
+ manager,
125
+ id,
126
+ fabric,
127
+ peerNodeId,
128
+ peerSessionId,
129
+ decryptKey,
130
+ encryptKey,
131
+ attestationKey,
132
+ caseAuthenticatedTags,
133
+ isInitiator,
134
+ } = args;
135
+
136
+ this.#id = id;
137
+ this.#fabric = fabric;
138
+ this.#peerNodeId = peerNodeId;
139
+ this.#peerSessionId = peerSessionId;
140
+ this.#decryptKey = decryptKey;
141
+ this.#encryptKey = encryptKey;
142
+ this.#attestationKey = attestationKey;
143
+ this.#caseAuthenticatedTags = caseAuthenticatedTags ?? [];
144
+ this.#isInitiator = isInitiator;
145
+
146
+ manager?.sessions.add(this);
147
+ fabric?.addSession(this);
148
+
149
+ logger.debug(
150
+ `Created secure ${this.isPase ? "PASE" : "CASE"} session for fabric index ${fabric?.fabricIndex}`,
151
+ this.name,
152
+ this.parameterDiagnostics(),
153
+ );
154
+ }
155
+
156
+ parameterDiagnostics() {
157
+ return Diagnostic.dict(
158
+ {
159
+ SII: this.idleIntervalMs,
160
+ SAI: this.activeIntervalMs,
161
+ SAT: this.activeThresholdMs,
162
+ DMRev: this.dataModelRevision,
163
+ IMRev: this.interactionModelRevision,
164
+ spec: Diagnostic.hex(this.specificationVersion),
165
+ maxPaths: this.maxPathsPerInvoke,
166
+ CATs: this.#caseAuthenticatedTags,
167
+ },
168
+ true,
169
+ );
170
+ }
171
+
172
+ get caseAuthenticatedTags() {
173
+ return this.#caseAuthenticatedTags;
174
+ }
175
+
176
+ get closingAfterExchangeFinished() {
177
+ return this.#closingAfterExchangeFinished;
178
+ }
179
+
180
+ get sendCloseMessageWhenClosing() {
181
+ return this.#sendCloseMessageWhenClosing;
182
+ }
183
+
184
+ get isPase(): boolean {
185
+ return this.#peerNodeId === NodeId.UNSPECIFIED_NODE_ID;
186
+ }
187
+
188
+ get subscriptions() {
189
+ return this.#subscriptions;
190
+ }
191
+
192
+ get isInitiator() {
193
+ return this.#isInitiator;
194
+ }
195
+
196
+ get isClosing() {
197
+ return this.#isClosing;
198
+ }
199
+
200
+ subjectFor(_message?: Message): Subject {
201
+ return Subject.Node({
202
+ id: this.peerNodeId,
203
+ catSubjects: this.#caseAuthenticatedTags.map(cat => NodeId.fromCaseAuthenticatedTag(cat)),
204
+ });
205
+ }
206
+
207
+ async close(closeAfterExchangeFinished?: boolean) {
208
+ if (closeAfterExchangeFinished === undefined) {
209
+ closeAfterExchangeFinished = this.isPeerActive(); // We delay session close if the peer is actively communicating with us
210
+ }
211
+ await this.end(true, closeAfterExchangeFinished);
212
+ }
213
+
214
+ decode({ header, applicationPayload, messageExtension }: DecodedPacket, aad: Uint8Array): DecodedMessage {
215
+ if (header.hasMessageExtensions) {
216
+ logger.info(
217
+ `Message extensions are not supported. Ignoring ${messageExtension ? Bytes.toHex(messageExtension) : undefined}`,
218
+ );
219
+ }
220
+ const nonce = Session.generateNonce(header.securityFlags, header.messageId, this.#peerNodeId);
221
+ const message = MessageCodec.decodePayload({
222
+ header,
223
+ applicationPayload: Crypto.decrypt(this.#decryptKey, applicationPayload, nonce, aad),
224
+ });
225
+
226
+ if (message.payloadHeader.hasSecuredExtension) {
227
+ logger.info(
228
+ `Secured extensions are not supported. Ignoring ${message.securityExtension ? Bytes.toHex(message.securityExtension) : undefined}`,
229
+ );
230
+ }
231
+
232
+ return message;
233
+ }
234
+
235
+ encode(message: Message): Packet {
236
+ message.packetHeader.sessionId = this.#peerSessionId;
237
+ const { header, applicationPayload } = MessageCodec.encodePayload(message);
238
+ const headerBytes = MessageCodec.encodePacketHeader(message.packetHeader);
239
+ const securityFlags = headerBytes[3];
240
+ const sessionNodeId = this.isPase
241
+ ? NodeId.UNSPECIFIED_NODE_ID
242
+ : (this.#fabric?.nodeId ?? NodeId.UNSPECIFIED_NODE_ID);
243
+ const nonce = Session.generateNonce(securityFlags, header.messageId, sessionNodeId);
244
+ return { header, applicationPayload: Crypto.encrypt(this.#encryptKey, applicationPayload, nonce, headerBytes) };
245
+ }
246
+
247
+ get attestationChallengeKey(): Uint8Array {
248
+ return this.#attestationKey;
249
+ }
250
+
251
+ get fabric() {
252
+ return this.#fabric;
253
+ }
254
+
255
+ addAssociatedFabric(fabric: Fabric) {
256
+ if (this.#fabric !== undefined) {
257
+ throw new MatterFlowError("Session already has an associated Fabric. Cannot change this.");
258
+ }
259
+ this.#fabric = fabric;
260
+ }
261
+
262
+ get id() {
263
+ return this.#id;
264
+ }
265
+
266
+ get name() {
267
+ return `secure/${this.#id}`;
268
+ }
269
+
270
+ get peerSessionId(): number {
271
+ return this.#peerSessionId;
272
+ }
273
+
274
+ get nodeId() {
275
+ return this.#fabric?.nodeId ?? NodeId.UNSPECIFIED_NODE_ID;
276
+ }
277
+
278
+ get peerNodeId() {
279
+ return this.#peerNodeId;
280
+ }
281
+
282
+ get associatedFabric(): Fabric {
283
+ if (this.#fabric === undefined) {
284
+ throw new NoAssociatedFabricError(
285
+ `${this.isPase ? "PASE " : ""}Session needs to have an associated Fabric for fabric sensitive data handling.`,
286
+ );
287
+ }
288
+ return this.#fabric;
289
+ }
290
+
291
+ async clearSubscriptions(flushSubscriptions = false, cancelledByPeer = false) {
292
+ const subscriptions = [...this.#subscriptions]; // get all values because subscriptions will remove themselves when cancelled
293
+ for (const subscription of subscriptions) {
294
+ await subscription.close(flushSubscriptions, cancelledByPeer);
295
+ }
296
+ return subscriptions.length;
297
+ }
298
+
299
+ /** Ends a session. Outstanding subscription data will be flushed before the session is destroyed. */
300
+ async end(sendClose: boolean, closeAfterExchangeFinished = false) {
301
+ await this.clearSubscriptions(true);
302
+ await this.destroy(sendClose, closeAfterExchangeFinished);
303
+ }
304
+
305
+ /** Destroys a session. Outstanding subscription data will be discarded. */
306
+ async destroy(sendClose = false, closeAfterExchangeFinished = true) {
307
+ await this.clearSubscriptions(false);
308
+ this.#fabric?.removeSession(this);
309
+ if (!sendClose) {
310
+ this.#sendCloseMessageWhenClosing = false;
311
+ }
312
+
313
+ if (closeAfterExchangeFinished) {
314
+ logger.info(`Register Session ${this.name} to close when exchange is ended.`);
315
+ this.#closingAfterExchangeFinished = true;
316
+ } else {
317
+ this.#isClosing = true;
318
+ logger.info(`End ${this.isPase ? "PASE" : "CASE"} session ${this.name}`);
319
+ this.manager?.sessions.delete(this);
320
+
321
+ // Wait for the exchange to finish closing, but ignore errors if channel is already closed
322
+ if (this.closer) {
323
+ try {
324
+ await this.closer;
325
+ } catch (error) {
326
+ NoChannelError.accept(error);
327
+ } finally {
328
+ await this.destroyed.emit();
329
+ }
330
+ return;
331
+ }
332
+ await this.destroyed.emit();
333
+ }
334
+ }
335
+
336
+ /**
337
+ * The peer node's address.
338
+ */
339
+ get peerAddress() {
340
+ return PeerAddress({
341
+ fabricIndex: this.#fabric?.fabricIndex ?? FabricIndex.NO_FABRIC,
342
+ nodeId: this.#peerNodeId,
343
+ });
344
+ }
345
+
346
+ /**
347
+ * Indicates whether a peer matches a specific address.
348
+ */
349
+ peerIs(address: PeerAddress) {
350
+ return (
351
+ (this.#fabric?.fabricIndex ?? FabricIndex.NO_FABRIC) === address.fabricIndex &&
352
+ this.#peerNodeId === address.nodeId
353
+ );
354
+ }
355
+ }
356
+
357
+ export namespace NodeSession {
358
+ export function assert(session?: Session, errorText?: string): asserts session is NodeSession {
359
+ if (!is(session)) {
360
+ throw new MatterFlowError(errorText ?? "Insecure session in secure context");
361
+ }
362
+ }
363
+
364
+ export function is(session?: Session): session is NodeSession {
365
+ return session?.type === SessionType.Unicast;
366
+ }
367
+ }