@zwave-js/cc 14.0.0-beta.4 → 14.0.0-beta.5

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 (331) hide show
  1. package/build/cjs/cc/AlarmSensorCC.js +381 -266
  2. package/build/cjs/cc/AlarmSensorCC.js.map +3 -3
  3. package/build/cjs/cc/AssociationCC.js +669 -503
  4. package/build/cjs/cc/AssociationCC.js.map +3 -3
  5. package/build/cjs/cc/AssociationGroupInfoCC.js +633 -492
  6. package/build/cjs/cc/AssociationGroupInfoCC.js.map +3 -3
  7. package/build/cjs/cc/BarrierOperatorCC.js +595 -429
  8. package/build/cjs/cc/BarrierOperatorCC.js.map +3 -3
  9. package/build/cjs/cc/BasicCC.js +354 -260
  10. package/build/cjs/cc/BasicCC.js.map +3 -3
  11. package/build/cjs/cc/BatteryCC.js +427 -345
  12. package/build/cjs/cc/BatteryCC.js.map +3 -3
  13. package/build/cjs/cc/BinarySensorCC.js +391 -276
  14. package/build/cjs/cc/BinarySensorCC.js.map +3 -3
  15. package/build/cjs/cc/BinarySwitchCC.js +347 -253
  16. package/build/cjs/cc/BinarySwitchCC.js.map +3 -3
  17. package/build/cjs/cc/CRC16CC.js +160 -85
  18. package/build/cjs/cc/CRC16CC.js.map +3 -3
  19. package/build/cjs/cc/CentralSceneCC.js +459 -324
  20. package/build/cjs/cc/CentralSceneCC.js.map +3 -3
  21. package/build/cjs/cc/ClimateControlScheduleCC.js +459 -293
  22. package/build/cjs/cc/ClimateControlScheduleCC.js.map +3 -3
  23. package/build/cjs/cc/ClockCC.js +254 -150
  24. package/build/cjs/cc/ClockCC.js.map +3 -3
  25. package/build/cjs/cc/ColorSwitchCC.js +758 -610
  26. package/build/cjs/cc/ColorSwitchCC.js.map +3 -3
  27. package/build/cjs/cc/ConfigurationCC.js +1700 -1453
  28. package/build/cjs/cc/ConfigurationCC.js.map +3 -3
  29. package/build/cjs/cc/DeviceResetLocallyCC.js +125 -49
  30. package/build/cjs/cc/DeviceResetLocallyCC.js.map +3 -3
  31. package/build/cjs/cc/DoorLockCC.js +904 -777
  32. package/build/cjs/cc/DoorLockCC.js.map +3 -3
  33. package/build/cjs/cc/DoorLockLoggingCC.js +321 -206
  34. package/build/cjs/cc/DoorLockLoggingCC.js.map +3 -3
  35. package/build/cjs/cc/EnergyProductionCC.js +249 -160
  36. package/build/cjs/cc/EnergyProductionCC.js.map +3 -3
  37. package/build/cjs/cc/EntryControlCC.js +619 -458
  38. package/build/cjs/cc/EntryControlCC.js.map +3 -3
  39. package/build/cjs/cc/FirmwareUpdateMetaDataCC.js +898 -698
  40. package/build/cjs/cc/FirmwareUpdateMetaDataCC.js.map +3 -3
  41. package/build/cjs/cc/HailCC.js +57 -11
  42. package/build/cjs/cc/HailCC.js.map +2 -2
  43. package/build/cjs/cc/HumidityControlModeCC.js +359 -233
  44. package/build/cjs/cc/HumidityControlModeCC.js.map +3 -3
  45. package/build/cjs/cc/HumidityControlOperatingStateCC.js +189 -103
  46. package/build/cjs/cc/HumidityControlOperatingStateCC.js.map +3 -3
  47. package/build/cjs/cc/HumidityControlSetpointCC.js +682 -495
  48. package/build/cjs/cc/HumidityControlSetpointCC.js.map +3 -3
  49. package/build/cjs/cc/InclusionControllerCC.js +205 -114
  50. package/build/cjs/cc/InclusionControllerCC.js.map +3 -3
  51. package/build/cjs/cc/IndicatorCC.js +897 -736
  52. package/build/cjs/cc/IndicatorCC.js.map +3 -3
  53. package/build/cjs/cc/IrrigationCC.js +1651 -1405
  54. package/build/cjs/cc/IrrigationCC.js.map +3 -3
  55. package/build/cjs/cc/LanguageCC.js +268 -171
  56. package/build/cjs/cc/LanguageCC.js.map +3 -3
  57. package/build/cjs/cc/LockCC.js +254 -154
  58. package/build/cjs/cc/LockCC.js.map +3 -3
  59. package/build/cjs/cc/ManufacturerProprietaryCC.js +189 -129
  60. package/build/cjs/cc/ManufacturerProprietaryCC.js.map +2 -2
  61. package/build/cjs/cc/ManufacturerSpecificCC.js +319 -213
  62. package/build/cjs/cc/ManufacturerSpecificCC.js.map +3 -3
  63. package/build/cjs/cc/MeterCC.js +827 -707
  64. package/build/cjs/cc/MeterCC.js.map +3 -3
  65. package/build/cjs/cc/MultiChannelAssociationCC.js +612 -478
  66. package/build/cjs/cc/MultiChannelAssociationCC.js.map +3 -3
  67. package/build/cjs/cc/MultiChannelCC.js +1037 -819
  68. package/build/cjs/cc/MultiChannelCC.js.map +3 -3
  69. package/build/cjs/cc/MultiCommandCC.js +172 -97
  70. package/build/cjs/cc/MultiCommandCC.js.map +3 -3
  71. package/build/cjs/cc/MultilevelSensorCC.js +589 -449
  72. package/build/cjs/cc/MultilevelSensorCC.js.map +3 -3
  73. package/build/cjs/cc/MultilevelSwitchCC.js +587 -439
  74. package/build/cjs/cc/MultilevelSwitchCC.js.map +3 -3
  75. package/build/cjs/cc/NoOperationCC.js +89 -27
  76. package/build/cjs/cc/NoOperationCC.js.map +2 -2
  77. package/build/cjs/cc/NodeNamingCC.js +417 -277
  78. package/build/cjs/cc/NodeNamingCC.js.map +3 -3
  79. package/build/cjs/cc/NotificationCC.js +972 -818
  80. package/build/cjs/cc/NotificationCC.js.map +3 -3
  81. package/build/cjs/cc/PowerlevelCC.js +450 -303
  82. package/build/cjs/cc/PowerlevelCC.js.map +3 -3
  83. package/build/cjs/cc/ProtectionCC.js +686 -494
  84. package/build/cjs/cc/ProtectionCC.js.map +3 -3
  85. package/build/cjs/cc/SceneActivationCC.js +165 -97
  86. package/build/cjs/cc/SceneActivationCC.js.map +3 -3
  87. package/build/cjs/cc/SceneActuatorConfigurationCC.js +346 -243
  88. package/build/cjs/cc/SceneActuatorConfigurationCC.js.map +3 -3
  89. package/build/cjs/cc/SceneControllerConfigurationCC.js +401 -298
  90. package/build/cjs/cc/SceneControllerConfigurationCC.js.map +3 -3
  91. package/build/cjs/cc/ScheduleEntryLockCC.js +1552 -1272
  92. package/build/cjs/cc/ScheduleEntryLockCC.js.map +3 -3
  93. package/build/cjs/cc/Security2CC.js +1483 -1219
  94. package/build/cjs/cc/Security2CC.js.map +3 -3
  95. package/build/cjs/cc/SecurityCC.js +839 -619
  96. package/build/cjs/cc/SecurityCC.js.map +3 -3
  97. package/build/cjs/cc/SoundSwitchCC.js +707 -515
  98. package/build/cjs/cc/SoundSwitchCC.js.map +3 -3
  99. package/build/cjs/cc/SupervisionCC.js +327 -237
  100. package/build/cjs/cc/SupervisionCC.js.map +3 -3
  101. package/build/cjs/cc/ThermostatFanModeCC.js +386 -263
  102. package/build/cjs/cc/ThermostatFanModeCC.js.map +3 -3
  103. package/build/cjs/cc/ThermostatFanStateCC.js +192 -106
  104. package/build/cjs/cc/ThermostatFanStateCC.js.map +3 -3
  105. package/build/cjs/cc/ThermostatModeCC.js +425 -302
  106. package/build/cjs/cc/ThermostatModeCC.js.map +3 -3
  107. package/build/cjs/cc/ThermostatOperatingStateCC.js +188 -102
  108. package/build/cjs/cc/ThermostatOperatingStateCC.js.map +3 -3
  109. package/build/cjs/cc/ThermostatSetbackCC.js +277 -173
  110. package/build/cjs/cc/ThermostatSetbackCC.js.map +3 -3
  111. package/build/cjs/cc/ThermostatSetpointCC.js +645 -491
  112. package/build/cjs/cc/ThermostatSetpointCC.js.map +3 -3
  113. package/build/cjs/cc/TimeCC.js +515 -353
  114. package/build/cjs/cc/TimeCC.js.map +3 -3
  115. package/build/cjs/cc/TimeParametersCC.js +302 -202
  116. package/build/cjs/cc/TimeParametersCC.js.map +3 -3
  117. package/build/cjs/cc/TransportServiceCC.js +433 -315
  118. package/build/cjs/cc/TransportServiceCC.js.map +3 -3
  119. package/build/cjs/cc/UserCodeCC.js +1385 -1102
  120. package/build/cjs/cc/UserCodeCC.js.map +3 -3
  121. package/build/cjs/cc/VersionCC.js +696 -562
  122. package/build/cjs/cc/VersionCC.js.map +3 -3
  123. package/build/cjs/cc/WakeUpCC.js +499 -346
  124. package/build/cjs/cc/WakeUpCC.js.map +3 -3
  125. package/build/cjs/cc/WindowCoveringCC.js +626 -478
  126. package/build/cjs/cc/WindowCoveringCC.js.map +3 -3
  127. package/build/cjs/cc/ZWaveLongRangeCC.js +57 -10
  128. package/build/cjs/cc/ZWaveLongRangeCC.js.map +2 -2
  129. package/build/cjs/cc/ZWavePlusCC.js +233 -159
  130. package/build/cjs/cc/ZWavePlusCC.js.map +3 -3
  131. package/build/cjs/cc/ZWaveProtocolCC.js +1515 -948
  132. package/build/cjs/cc/ZWaveProtocolCC.js.map +3 -3
  133. package/build/cjs/cc/manufacturerProprietary/Decorators.d.ts +4 -4
  134. package/build/cjs/cc/manufacturerProprietary/Decorators.js.map +1 -1
  135. package/build/cjs/cc/manufacturerProprietary/FibaroCC.js +395 -274
  136. package/build/cjs/cc/manufacturerProprietary/FibaroCC.js.map +3 -3
  137. package/build/cjs/lib/CommandClassDecorators.d.ts +11 -15
  138. package/build/cjs/lib/CommandClassDecorators.js +19 -20
  139. package/build/cjs/lib/CommandClassDecorators.js.map +2 -2
  140. package/build/cjs/lib/Security2/Extension.d.ts +1 -1
  141. package/build/cjs/lib/Security2/Extension.js +217 -126
  142. package/build/cjs/lib/Security2/Extension.js.map +3 -3
  143. package/build/esm/cc/AlarmSensorCC.d.ts.map +1 -1
  144. package/build/esm/cc/AlarmSensorCC.js +389 -291
  145. package/build/esm/cc/AlarmSensorCC.js.map +1 -1
  146. package/build/esm/cc/AssociationCC.d.ts.map +1 -1
  147. package/build/esm/cc/AssociationCC.js +678 -537
  148. package/build/esm/cc/AssociationCC.js.map +1 -1
  149. package/build/esm/cc/AssociationGroupInfoCC.d.ts.map +1 -1
  150. package/build/esm/cc/AssociationGroupInfoCC.js +659 -539
  151. package/build/esm/cc/AssociationGroupInfoCC.js.map +1 -1
  152. package/build/esm/cc/BarrierOperatorCC.d.ts.map +1 -1
  153. package/build/esm/cc/BarrierOperatorCC.js +634 -493
  154. package/build/esm/cc/BarrierOperatorCC.js.map +1 -1
  155. package/build/esm/cc/BasicCC.d.ts.map +1 -1
  156. package/build/esm/cc/BasicCC.js +380 -302
  157. package/build/esm/cc/BasicCC.js.map +1 -1
  158. package/build/esm/cc/BatteryCC.d.ts.map +1 -1
  159. package/build/esm/cc/BatteryCC.js +449 -384
  160. package/build/esm/cc/BatteryCC.js.map +1 -1
  161. package/build/esm/cc/BinarySensorCC.d.ts.map +1 -1
  162. package/build/esm/cc/BinarySensorCC.js +395 -297
  163. package/build/esm/cc/BinarySensorCC.js.map +1 -1
  164. package/build/esm/cc/BinarySwitchCC.d.ts.map +1 -1
  165. package/build/esm/cc/BinarySwitchCC.js +353 -274
  166. package/build/esm/cc/BinarySwitchCC.js.map +1 -1
  167. package/build/esm/cc/CRC16CC.js +162 -98
  168. package/build/esm/cc/CRC16CC.js.map +1 -1
  169. package/build/esm/cc/CentralSceneCC.d.ts.map +1 -1
  170. package/build/esm/cc/CentralSceneCC.js +465 -351
  171. package/build/esm/cc/CentralSceneCC.js.map +1 -1
  172. package/build/esm/cc/ClimateControlScheduleCC.d.ts.map +1 -1
  173. package/build/esm/cc/ClimateControlScheduleCC.js +454 -313
  174. package/build/esm/cc/ClimateControlScheduleCC.js.map +1 -1
  175. package/build/esm/cc/ClockCC.js +248 -159
  176. package/build/esm/cc/ClockCC.js.map +1 -1
  177. package/build/esm/cc/ColorSwitchCC.d.ts.map +1 -1
  178. package/build/esm/cc/ColorSwitchCC.js +802 -677
  179. package/build/esm/cc/ColorSwitchCC.js.map +1 -1
  180. package/build/esm/cc/ConfigurationCC.js +1899 -1687
  181. package/build/esm/cc/ConfigurationCC.js.map +1 -1
  182. package/build/esm/cc/DeviceResetLocallyCC.js +124 -59
  183. package/build/esm/cc/DeviceResetLocallyCC.js.map +1 -1
  184. package/build/esm/cc/DoorLockCC.d.ts.map +1 -1
  185. package/build/esm/cc/DoorLockCC.js +951 -849
  186. package/build/esm/cc/DoorLockCC.js.map +1 -1
  187. package/build/esm/cc/DoorLockLoggingCC.d.ts.map +1 -1
  188. package/build/esm/cc/DoorLockLoggingCC.js +316 -218
  189. package/build/esm/cc/DoorLockLoggingCC.js.map +1 -1
  190. package/build/esm/cc/EnergyProductionCC.js +240 -164
  191. package/build/esm/cc/EnergyProductionCC.js.map +1 -1
  192. package/build/esm/cc/EntryControlCC.d.ts.map +1 -1
  193. package/build/esm/cc/EntryControlCC.js +629 -493
  194. package/build/esm/cc/EntryControlCC.js.map +1 -1
  195. package/build/esm/cc/FirmwareUpdateMetaDataCC.d.ts.map +1 -1
  196. package/build/esm/cc/FirmwareUpdateMetaDataCC.js +938 -769
  197. package/build/esm/cc/FirmwareUpdateMetaDataCC.js.map +1 -1
  198. package/build/esm/cc/HailCC.js +51 -12
  199. package/build/esm/cc/HailCC.js.map +1 -1
  200. package/build/esm/cc/HumidityControlModeCC.d.ts.map +1 -1
  201. package/build/esm/cc/HumidityControlModeCC.js +357 -250
  202. package/build/esm/cc/HumidityControlModeCC.js.map +1 -1
  203. package/build/esm/cc/HumidityControlOperatingStateCC.d.ts.map +1 -1
  204. package/build/esm/cc/HumidityControlOperatingStateCC.js +182 -109
  205. package/build/esm/cc/HumidityControlOperatingStateCC.js.map +1 -1
  206. package/build/esm/cc/HumidityControlSetpointCC.d.ts.map +1 -1
  207. package/build/esm/cc/HumidityControlSetpointCC.js +706 -546
  208. package/build/esm/cc/HumidityControlSetpointCC.js.map +1 -1
  209. package/build/esm/cc/InclusionControllerCC.js +197 -119
  210. package/build/esm/cc/InclusionControllerCC.js.map +1 -1
  211. package/build/esm/cc/IndicatorCC.js +973 -835
  212. package/build/esm/cc/IndicatorCC.js.map +1 -1
  213. package/build/esm/cc/IrrigationCC.d.ts.map +1 -1
  214. package/build/esm/cc/IrrigationCC.js +1697 -1496
  215. package/build/esm/cc/IrrigationCC.js.map +1 -1
  216. package/build/esm/cc/LanguageCC.d.ts.map +1 -1
  217. package/build/esm/cc/LanguageCC.js +266 -184
  218. package/build/esm/cc/LanguageCC.js.map +1 -1
  219. package/build/esm/cc/LockCC.d.ts.map +1 -1
  220. package/build/esm/cc/LockCC.js +247 -162
  221. package/build/esm/cc/LockCC.js.map +1 -1
  222. package/build/esm/cc/ManufacturerProprietaryCC.js +192 -141
  223. package/build/esm/cc/ManufacturerProprietaryCC.js.map +1 -1
  224. package/build/esm/cc/ManufacturerSpecificCC.d.ts.map +1 -1
  225. package/build/esm/cc/ManufacturerSpecificCC.js +312 -223
  226. package/build/esm/cc/ManufacturerSpecificCC.js.map +1 -1
  227. package/build/esm/cc/MeterCC.d.ts.map +1 -1
  228. package/build/esm/cc/MeterCC.js +896 -795
  229. package/build/esm/cc/MeterCC.js.map +1 -1
  230. package/build/esm/cc/MultiChannelAssociationCC.d.ts.map +1 -1
  231. package/build/esm/cc/MultiChannelAssociationCC.js +631 -518
  232. package/build/esm/cc/MultiChannelAssociationCC.js.map +1 -1
  233. package/build/esm/cc/MultiChannelCC.d.ts.map +1 -1
  234. package/build/esm/cc/MultiChannelCC.js +1106 -921
  235. package/build/esm/cc/MultiChannelCC.js.map +1 -1
  236. package/build/esm/cc/MultiCommandCC.js +166 -102
  237. package/build/esm/cc/MultiCommandCC.js.map +1 -1
  238. package/build/esm/cc/MultilevelSensorCC.d.ts.map +1 -1
  239. package/build/esm/cc/MultilevelSensorCC.js +616 -497
  240. package/build/esm/cc/MultilevelSensorCC.js.map +1 -1
  241. package/build/esm/cc/MultilevelSwitchCC.d.ts.map +1 -1
  242. package/build/esm/cc/MultilevelSwitchCC.js +621 -496
  243. package/build/esm/cc/MultilevelSwitchCC.js.map +1 -1
  244. package/build/esm/cc/NoOperationCC.js +82 -29
  245. package/build/esm/cc/NoOperationCC.js.map +1 -1
  246. package/build/esm/cc/NodeNamingCC.d.ts.map +1 -1
  247. package/build/esm/cc/NodeNamingCC.js +413 -294
  248. package/build/esm/cc/NodeNamingCC.js.map +1 -1
  249. package/build/esm/cc/NotificationCC.d.ts.map +1 -1
  250. package/build/esm/cc/NotificationCC.js +1097 -966
  251. package/build/esm/cc/NotificationCC.js.map +1 -1
  252. package/build/esm/cc/PowerlevelCC.js +437 -311
  253. package/build/esm/cc/PowerlevelCC.js.map +1 -1
  254. package/build/esm/cc/ProtectionCC.d.ts.map +1 -1
  255. package/build/esm/cc/ProtectionCC.js +704 -543
  256. package/build/esm/cc/ProtectionCC.js.map +1 -1
  257. package/build/esm/cc/SceneActivationCC.d.ts.map +1 -1
  258. package/build/esm/cc/SceneActivationCC.js +157 -100
  259. package/build/esm/cc/SceneActivationCC.js.map +1 -1
  260. package/build/esm/cc/SceneActuatorConfigurationCC.js +357 -269
  261. package/build/esm/cc/SceneActuatorConfigurationCC.js.map +1 -1
  262. package/build/esm/cc/SceneControllerConfigurationCC.js +434 -346
  263. package/build/esm/cc/SceneControllerConfigurationCC.js.map +1 -1
  264. package/build/esm/cc/ScheduleEntryLockCC.d.ts.map +1 -1
  265. package/build/esm/cc/ScheduleEntryLockCC.js +1596 -1357
  266. package/build/esm/cc/ScheduleEntryLockCC.js.map +1 -1
  267. package/build/esm/cc/Security2CC.js +1633 -1406
  268. package/build/esm/cc/Security2CC.js.map +1 -1
  269. package/build/esm/cc/SecurityCC.js +876 -687
  270. package/build/esm/cc/SecurityCC.js.map +1 -1
  271. package/build/esm/cc/SoundSwitchCC.d.ts.map +1 -1
  272. package/build/esm/cc/SoundSwitchCC.js +689 -526
  273. package/build/esm/cc/SoundSwitchCC.js.map +1 -1
  274. package/build/esm/cc/SupervisionCC.js +349 -272
  275. package/build/esm/cc/SupervisionCC.js.map +1 -1
  276. package/build/esm/cc/ThermostatFanModeCC.d.ts.map +1 -1
  277. package/build/esm/cc/ThermostatFanModeCC.js +388 -284
  278. package/build/esm/cc/ThermostatFanModeCC.js.map +1 -1
  279. package/build/esm/cc/ThermostatFanStateCC.d.ts.map +1 -1
  280. package/build/esm/cc/ThermostatFanStateCC.js +184 -111
  281. package/build/esm/cc/ThermostatFanStateCC.js.map +1 -1
  282. package/build/esm/cc/ThermostatModeCC.d.ts.map +1 -1
  283. package/build/esm/cc/ThermostatModeCC.js +435 -331
  284. package/build/esm/cc/ThermostatModeCC.js.map +1 -1
  285. package/build/esm/cc/ThermostatOperatingStateCC.d.ts.map +1 -1
  286. package/build/esm/cc/ThermostatOperatingStateCC.js +180 -107
  287. package/build/esm/cc/ThermostatOperatingStateCC.js.map +1 -1
  288. package/build/esm/cc/ThermostatSetbackCC.js +274 -185
  289. package/build/esm/cc/ThermostatSetbackCC.js.map +1 -1
  290. package/build/esm/cc/ThermostatSetpointCC.d.ts.map +1 -1
  291. package/build/esm/cc/ThermostatSetpointCC.js +674 -543
  292. package/build/esm/cc/ThermostatSetpointCC.js.map +1 -1
  293. package/build/esm/cc/TimeCC.js +499 -360
  294. package/build/esm/cc/TimeCC.js.map +1 -1
  295. package/build/esm/cc/TimeParametersCC.d.ts.map +1 -1
  296. package/build/esm/cc/TimeParametersCC.js +296 -211
  297. package/build/esm/cc/TimeParametersCC.js.map +1 -1
  298. package/build/esm/cc/TransportServiceCC.js +464 -363
  299. package/build/esm/cc/TransportServiceCC.js.map +1 -1
  300. package/build/esm/cc/UserCodeCC.d.ts.map +1 -1
  301. package/build/esm/cc/UserCodeCC.js +1443 -1205
  302. package/build/esm/cc/UserCodeCC.js.map +1 -1
  303. package/build/esm/cc/VersionCC.d.ts.map +1 -1
  304. package/build/esm/cc/VersionCC.js +744 -635
  305. package/build/esm/cc/VersionCC.js.map +1 -1
  306. package/build/esm/cc/WakeUpCC.d.ts.map +1 -1
  307. package/build/esm/cc/WakeUpCC.js +494 -364
  308. package/build/esm/cc/WakeUpCC.js.map +1 -1
  309. package/build/esm/cc/WindowCoveringCC.d.ts.map +1 -1
  310. package/build/esm/cc/WindowCoveringCC.js +655 -530
  311. package/build/esm/cc/WindowCoveringCC.js.map +1 -1
  312. package/build/esm/cc/ZWaveLongRangeCC.js +51 -11
  313. package/build/esm/cc/ZWaveLongRangeCC.js.map +1 -1
  314. package/build/esm/cc/ZWavePlusCC.d.ts.map +1 -1
  315. package/build/esm/cc/ZWavePlusCC.js +223 -162
  316. package/build/esm/cc/ZWavePlusCC.js.map +1 -1
  317. package/build/esm/cc/ZWaveProtocolCC.js +1443 -953
  318. package/build/esm/cc/ZWaveProtocolCC.js.map +1 -1
  319. package/build/esm/cc/manufacturerProprietary/Decorators.d.ts +4 -4
  320. package/build/esm/cc/manufacturerProprietary/Decorators.d.ts.map +1 -1
  321. package/build/esm/cc/manufacturerProprietary/FibaroCC.js +390 -286
  322. package/build/esm/cc/manufacturerProprietary/FibaroCC.js.map +1 -1
  323. package/build/esm/lib/CommandClassDecorators.d.ts +11 -15
  324. package/build/esm/lib/CommandClassDecorators.d.ts.map +1 -1
  325. package/build/esm/lib/CommandClassDecorators.js +24 -24
  326. package/build/esm/lib/CommandClassDecorators.js.map +1 -1
  327. package/build/esm/lib/Security2/Extension.d.ts +1 -1
  328. package/build/esm/lib/Security2/Extension.d.ts.map +1 -1
  329. package/build/esm/lib/Security2/Extension.js +207 -123
  330. package/build/esm/lib/Security2/Extension.js.map +1 -1
  331. package/package.json +6 -6
@@ -1,10 +1,37 @@
1
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
- return c > 3 && r && Object.defineProperty(target, key, r), r;
1
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
2
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
3
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
4
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
5
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
6
+ var _, done = false;
7
+ for (var i = decorators.length - 1; i >= 0; i--) {
8
+ var context = {};
9
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
10
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
11
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
12
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
13
+ if (kind === "accessor") {
14
+ if (result === void 0) continue;
15
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
16
+ if (_ = accept(result.get)) descriptor.get = _;
17
+ if (_ = accept(result.set)) descriptor.set = _;
18
+ if (_ = accept(result.init)) initializers.unshift(_);
19
+ }
20
+ else if (_ = accept(result)) {
21
+ if (kind === "field") initializers.unshift(_);
22
+ else descriptor[key] = _;
23
+ }
24
+ }
25
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
26
+ done = true;
27
+ };
28
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
29
+ var useValue = arguments.length > 2;
30
+ for (var i = 0; i < initializers.length; i++) {
31
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
32
+ }
33
+ return useValue ? value : void 0;
6
34
  };
7
- var Security2CC_1, Security2CCMessageEncapsulation_1, Security2CCNonceReport_1, Security2CCNonceGet_1, Security2CCKEXReport_1, Security2CCKEXSet_1, Security2CCKEXFail_1, Security2CCPublicKeyReport_1, Security2CCNetworkKeyReport_1, Security2CCNetworkKeyGet_1, Security2CCTransferEnd_1, Security2CCCommandsSupportedReport_1;
8
35
  import { CommandClasses, MPANState, MessagePriority, SECURITY_S2_AUTH_TAG_LENGTH, SPANState, SecurityClass, TransmitOptions, ZWaveError, ZWaveErrorCodes, decryptAES128CCM, encodeBitMask, encryptAES128CCM, getCCName, highResTimestamp, isLongRangeNodeId, isTransmissionError, isZWaveError, parseBitMask, parseCCList, securityClassIsS2, securityClassOrder, validatePayload, } from "@zwave-js/core";
9
36
  import { EncapsulationFlags, NODE_ID_BROADCAST, NODE_ID_BROADCAST_LR, encodeCCList, } from "@zwave-js/core/safe";
10
37
  import { Bytes } from "@zwave-js/shared/safe";
@@ -245,563 +272,588 @@ function getSenderEI(extensions) {
245
272
  // Encapsulation CCs are used internally and too frequently that we
246
273
  // want to pay the cost of validating each call
247
274
  /* eslint-disable @zwave-js/ccapi-validate-args */
248
- let Security2CCAPI = class Security2CCAPI extends CCAPI {
249
- supportsCommand(_cmd) {
250
- // All commands are mandatory
251
- return true;
252
- }
253
- /**
254
- * Sends a nonce to the node, either in response to a NonceGet request or a message that failed to decrypt. The message is sent without any retransmission etc.
255
- * The return value indicates whether a nonce was successfully sent
256
- */
257
- async sendNonce() {
258
- this.assertSupportsCommand(Security2Command, Security2Command.NonceReport);
259
- this.assertPhysicalEndpoint(this.endpoint);
260
- const securityManager = getSecurityManager(this.host.ownNodeId, this.host, this.endpoint.nodeId);
261
- if (!securityManager) {
262
- throw new ZWaveError(`Nonces can only be sent if secure communication is set up!`, ZWaveErrorCodes.Driver_NoSecurity);
263
- }
264
- const receiverEI = securityManager.generateNonce(this.endpoint.nodeId);
265
- const cc = new Security2CCNonceReport({
266
- nodeId: this.endpoint.nodeId,
267
- endpointIndex: this.endpoint.index,
268
- SOS: true,
269
- MOS: false,
270
- receiverEI,
271
- });
272
- try {
273
- await this.host.sendCommand(cc, {
274
- ...this.commandOptions,
275
- // Seems we need these options or some nodes won't accept the nonce
276
- transmitOptions: TransmitOptions.ACK
277
- | TransmitOptions.AutoRoute,
278
- // Only try sending a nonce once
279
- maxSendAttempts: 1,
280
- // Nonce requests must be handled immediately
281
- priority: MessagePriority.Immediate,
282
- // We don't want failures causing us to treat the node as asleep or dead
283
- changeNodeStatusOnMissingACK: false,
284
- // And we need to react to
285
- });
275
+ let Security2CCAPI = (() => {
276
+ let _classDecorators = [API(CommandClasses["Security 2"])];
277
+ let _classDescriptor;
278
+ let _classExtraInitializers = [];
279
+ let _classThis;
280
+ let _classSuper = CCAPI;
281
+ var Security2CCAPI = class extends _classSuper {
282
+ static { _classThis = this; }
283
+ static {
284
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
285
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
286
+ Security2CCAPI = _classThis = _classDescriptor.value;
287
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
288
+ __runInitializers(_classThis, _classExtraInitializers);
286
289
  }
287
- catch (e) {
288
- if (isTransmissionError(e)) {
289
- // The nonce could not be sent, invalidate it
290
- securityManager.deleteNonce(this.endpoint.nodeId);
291
- return false;
290
+ supportsCommand(_cmd) {
291
+ // All commands are mandatory
292
+ return true;
293
+ }
294
+ /**
295
+ * Sends a nonce to the node, either in response to a NonceGet request or a message that failed to decrypt. The message is sent without any retransmission etc.
296
+ * The return value indicates whether a nonce was successfully sent
297
+ */
298
+ async sendNonce() {
299
+ this.assertSupportsCommand(Security2Command, Security2Command.NonceReport);
300
+ this.assertPhysicalEndpoint(this.endpoint);
301
+ const securityManager = getSecurityManager(this.host.ownNodeId, this.host, this.endpoint.nodeId);
302
+ if (!securityManager) {
303
+ throw new ZWaveError(`Nonces can only be sent if secure communication is set up!`, ZWaveErrorCodes.Driver_NoSecurity);
292
304
  }
293
- else {
294
- // Pass other errors through
295
- throw e;
305
+ const receiverEI = securityManager.generateNonce(this.endpoint.nodeId);
306
+ const cc = new Security2CCNonceReport({
307
+ nodeId: this.endpoint.nodeId,
308
+ endpointIndex: this.endpoint.index,
309
+ SOS: true,
310
+ MOS: false,
311
+ receiverEI,
312
+ });
313
+ try {
314
+ await this.host.sendCommand(cc, {
315
+ ...this.commandOptions,
316
+ // Seems we need these options or some nodes won't accept the nonce
317
+ transmitOptions: TransmitOptions.ACK
318
+ | TransmitOptions.AutoRoute,
319
+ // Only try sending a nonce once
320
+ maxSendAttempts: 1,
321
+ // Nonce requests must be handled immediately
322
+ priority: MessagePriority.Immediate,
323
+ // We don't want failures causing us to treat the node as asleep or dead
324
+ changeNodeStatusOnMissingACK: false,
325
+ // And we need to react to
326
+ });
296
327
  }
328
+ catch (e) {
329
+ if (isTransmissionError(e)) {
330
+ // The nonce could not be sent, invalidate it
331
+ securityManager.deleteNonce(this.endpoint.nodeId);
332
+ return false;
333
+ }
334
+ else {
335
+ // Pass other errors through
336
+ throw e;
337
+ }
338
+ }
339
+ return true;
297
340
  }
298
- return true;
299
- }
300
- /** Notifies the target node that the MPAN state is out of sync */
301
- async sendMOS() {
302
- this.assertSupportsCommand(Security2Command, Security2Command.NonceReport);
303
- this.assertPhysicalEndpoint(this.endpoint);
304
- const cc = new Security2CCNonceReport({
305
- nodeId: this.endpoint.nodeId,
306
- endpointIndex: this.endpoint.index,
307
- SOS: false,
308
- MOS: true,
309
- });
310
- try {
311
- await this.host.sendCommand(cc, {
312
- ...this.commandOptions,
313
- // Seems we need these options or some nodes won't accept the nonce
314
- transmitOptions: TransmitOptions.ACK
315
- | TransmitOptions.AutoRoute,
316
- // Only try sending a nonce once
317
- maxSendAttempts: 1,
318
- // Nonce requests must be handled immediately
319
- priority: MessagePriority.Immediate,
320
- // We don't want failures causing us to treat the node as asleep or dead
321
- changeNodeStatusOnMissingACK: false,
341
+ /** Notifies the target node that the MPAN state is out of sync */
342
+ async sendMOS() {
343
+ this.assertSupportsCommand(Security2Command, Security2Command.NonceReport);
344
+ this.assertPhysicalEndpoint(this.endpoint);
345
+ const cc = new Security2CCNonceReport({
346
+ nodeId: this.endpoint.nodeId,
347
+ endpointIndex: this.endpoint.index,
348
+ SOS: false,
349
+ MOS: true,
322
350
  });
351
+ try {
352
+ await this.host.sendCommand(cc, {
353
+ ...this.commandOptions,
354
+ // Seems we need these options or some nodes won't accept the nonce
355
+ transmitOptions: TransmitOptions.ACK
356
+ | TransmitOptions.AutoRoute,
357
+ // Only try sending a nonce once
358
+ maxSendAttempts: 1,
359
+ // Nonce requests must be handled immediately
360
+ priority: MessagePriority.Immediate,
361
+ // We don't want failures causing us to treat the node as asleep or dead
362
+ changeNodeStatusOnMissingACK: false,
363
+ });
364
+ }
365
+ catch (e) {
366
+ if (isTransmissionError(e)) {
367
+ return false;
368
+ }
369
+ else {
370
+ // Pass other errors through
371
+ throw e;
372
+ }
373
+ }
374
+ return true;
323
375
  }
324
- catch (e) {
325
- if (isTransmissionError(e)) {
326
- return false;
376
+ /** Sends the given MPAN to the node */
377
+ async sendMPAN(groupId, innerMPANState) {
378
+ this.assertSupportsCommand(Security2Command, Security2Command.MessageEncapsulation);
379
+ this.assertPhysicalEndpoint(this.endpoint);
380
+ const cc = new Security2CCMessageEncapsulation({
381
+ nodeId: this.endpoint.nodeId,
382
+ endpointIndex: this.endpoint.index,
383
+ extensions: [
384
+ new MPANExtension({
385
+ groupId,
386
+ innerMPANState,
387
+ }),
388
+ ],
389
+ });
390
+ try {
391
+ await this.host.sendCommand(cc, {
392
+ ...this.commandOptions,
393
+ // Seems we need these options or some nodes won't accept the nonce
394
+ transmitOptions: TransmitOptions.ACK
395
+ | TransmitOptions.AutoRoute,
396
+ // Only try sending a nonce once
397
+ maxSendAttempts: 1,
398
+ // Nonce requests must be handled immediately
399
+ priority: MessagePriority.Immediate,
400
+ // We don't want failures causing us to treat the node as asleep or dead
401
+ changeNodeStatusOnMissingACK: false,
402
+ });
327
403
  }
328
- else {
329
- // Pass other errors through
330
- throw e;
404
+ catch (e) {
405
+ if (isTransmissionError(e)) {
406
+ return false;
407
+ }
408
+ else {
409
+ // Pass other errors through
410
+ throw e;
411
+ }
331
412
  }
413
+ return true;
332
414
  }
333
- return true;
334
- }
335
- /** Sends the given MPAN to the node */
336
- async sendMPAN(groupId, innerMPANState) {
337
- this.assertSupportsCommand(Security2Command, Security2Command.MessageEncapsulation);
338
- this.assertPhysicalEndpoint(this.endpoint);
339
- const cc = new Security2CCMessageEncapsulation({
340
- nodeId: this.endpoint.nodeId,
341
- endpointIndex: this.endpoint.index,
342
- extensions: [
343
- new MPANExtension({
344
- groupId,
345
- innerMPANState,
346
- }),
347
- ],
348
- });
349
- try {
350
- await this.host.sendCommand(cc, {
415
+ /**
416
+ * Queries the securely supported commands for the current security class
417
+ * @param securityClass Can be used to overwrite the security class to use. If this doesn't match the current one, new nonces will need to be exchanged.
418
+ */
419
+ async getSupportedCommands(securityClass) {
420
+ this.assertSupportsCommand(Security2Command, Security2Command.CommandsSupportedGet);
421
+ let cc = new Security2CCCommandsSupportedGet({
422
+ nodeId: this.endpoint.nodeId,
423
+ endpointIndex: this.endpoint.index,
424
+ });
425
+ // Security2CCCommandsSupportedGet is special because we cannot reply on the applHost to do the automatic
426
+ // encapsulation because it would use a different security class. Therefore the entire possible stack
427
+ // of encapsulation needs to be done here
428
+ if (MultiChannelCC.requiresEncapsulation(cc)) {
429
+ const multiChannelCCVersion = this.host.getSupportedCCVersion(CommandClasses["Multi Channel"], this.endpoint.nodeId);
430
+ cc = multiChannelCCVersion === 1
431
+ ? MultiChannelCC.encapsulateV1(cc)
432
+ : MultiChannelCC.encapsulate(cc);
433
+ }
434
+ cc = Security2CC.encapsulate(cc, this.host.ownNodeId, this.host, { securityClass });
435
+ const response = await this.host.sendCommand(cc, {
351
436
  ...this.commandOptions,
352
- // Seems we need these options or some nodes won't accept the nonce
353
- transmitOptions: TransmitOptions.ACK
354
- | TransmitOptions.AutoRoute,
355
- // Only try sending a nonce once
356
- maxSendAttempts: 1,
357
- // Nonce requests must be handled immediately
358
- priority: MessagePriority.Immediate,
359
- // We don't want failures causing us to treat the node as asleep or dead
360
- changeNodeStatusOnMissingACK: false,
437
+ autoEncapsulate: false,
361
438
  });
439
+ return response?.supportedCCs;
362
440
  }
363
- catch (e) {
364
- if (isTransmissionError(e)) {
365
- return false;
366
- }
367
- else {
368
- // Pass other errors through
369
- throw e;
441
+ async reportSupportedCommands(supportedCCs) {
442
+ this.assertSupportsCommand(Security2Command, Security2Command.CommandsSupportedReport);
443
+ const cc = new Security2CCCommandsSupportedReport({
444
+ nodeId: this.endpoint.nodeId,
445
+ endpointIndex: this.endpoint.index,
446
+ supportedCCs,
447
+ });
448
+ await this.host.sendCommand(cc, this.commandOptions);
449
+ }
450
+ // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
451
+ async getKeyExchangeParameters() {
452
+ this.assertSupportsCommand(Security2Command, Security2Command.KEXGet);
453
+ const cc = new Security2CCKEXGet({
454
+ nodeId: this.endpoint.nodeId,
455
+ endpointIndex: this.endpoint.index,
456
+ });
457
+ const response = await this.host.sendCommand(cc, this.commandOptions);
458
+ if (response) {
459
+ return pick(response, [
460
+ "requestCSA",
461
+ "echo",
462
+ "supportedKEXSchemes",
463
+ "supportedECDHProfiles",
464
+ "requestedKeys",
465
+ "_reserved",
466
+ ]);
370
467
  }
371
468
  }
372
- return true;
373
- }
374
- /**
375
- * Queries the securely supported commands for the current security class
376
- * @param securityClass Can be used to overwrite the security class to use. If this doesn't match the current one, new nonces will need to be exchanged.
377
- */
378
- async getSupportedCommands(securityClass) {
379
- this.assertSupportsCommand(Security2Command, Security2Command.CommandsSupportedGet);
380
- let cc = new Security2CCCommandsSupportedGet({
381
- nodeId: this.endpoint.nodeId,
382
- endpointIndex: this.endpoint.index,
383
- });
384
- // Security2CCCommandsSupportedGet is special because we cannot reply on the applHost to do the automatic
385
- // encapsulation because it would use a different security class. Therefore the entire possible stack
386
- // of encapsulation needs to be done here
387
- if (MultiChannelCC.requiresEncapsulation(cc)) {
388
- const multiChannelCCVersion = this.host.getSupportedCCVersion(CommandClasses["Multi Channel"], this.endpoint.nodeId);
389
- cc = multiChannelCCVersion === 1
390
- ? MultiChannelCC.encapsulateV1(cc)
391
- : MultiChannelCC.encapsulate(cc);
392
- }
393
- cc = Security2CC.encapsulate(cc, this.host.ownNodeId, this.host, { securityClass });
394
- const response = await this.host.sendCommand(cc, {
395
- ...this.commandOptions,
396
- autoEncapsulate: false,
397
- });
398
- return response?.supportedCCs;
399
- }
400
- async reportSupportedCommands(supportedCCs) {
401
- this.assertSupportsCommand(Security2Command, Security2Command.CommandsSupportedReport);
402
- const cc = new Security2CCCommandsSupportedReport({
403
- nodeId: this.endpoint.nodeId,
404
- endpointIndex: this.endpoint.index,
405
- supportedCCs,
406
- });
407
- await this.host.sendCommand(cc, this.commandOptions);
408
- }
409
- // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
410
- async getKeyExchangeParameters() {
411
- this.assertSupportsCommand(Security2Command, Security2Command.KEXGet);
412
- const cc = new Security2CCKEXGet({
413
- nodeId: this.endpoint.nodeId,
414
- endpointIndex: this.endpoint.index,
415
- });
416
- const response = await this.host.sendCommand(cc, this.commandOptions);
417
- if (response) {
418
- return pick(response, [
419
- "requestCSA",
420
- "echo",
421
- "supportedKEXSchemes",
422
- "supportedECDHProfiles",
423
- "requestedKeys",
424
- "_reserved",
425
- ]);
469
+ /** Requests the given keys from an including node */
470
+ async requestKeys(params) {
471
+ this.assertSupportsCommand(Security2Command, Security2Command.KEXReport);
472
+ const cc = new Security2CCKEXReport({
473
+ nodeId: this.endpoint.nodeId,
474
+ endpointIndex: this.endpoint.index,
475
+ ...params,
476
+ echo: false,
477
+ });
478
+ await this.host.sendCommand(cc, this.commandOptions);
426
479
  }
427
- }
428
- /** Requests the given keys from an including node */
429
- async requestKeys(params) {
430
- this.assertSupportsCommand(Security2Command, Security2Command.KEXReport);
431
- const cc = new Security2CCKEXReport({
432
- nodeId: this.endpoint.nodeId,
433
- endpointIndex: this.endpoint.index,
434
- ...params,
435
- echo: false,
436
- });
437
- await this.host.sendCommand(cc, this.commandOptions);
438
- }
439
- /** Grants the joining node the given keys */
440
- async grantKeys(params) {
441
- this.assertSupportsCommand(Security2Command, Security2Command.KEXSet);
442
- const cc = new Security2CCKEXSet({
443
- nodeId: this.endpoint.nodeId,
444
- endpointIndex: this.endpoint.index,
445
- ...params,
446
- echo: false,
447
- });
448
- await this.host.sendCommand(cc, this.commandOptions);
449
- }
450
- /** Confirms the keys that were requested by a node */
451
- async confirmRequestedKeys(params) {
452
- this.assertSupportsCommand(Security2Command, Security2Command.KEXReport);
453
- const cc = new Security2CCKEXReport({
454
- nodeId: this.endpoint.nodeId,
455
- endpointIndex: this.endpoint.index,
456
- ...params,
457
- echo: true,
458
- });
459
- await this.host.sendCommand(cc, this.commandOptions);
460
- }
461
- /** Confirms the keys that were granted by the including node */
462
- async confirmGrantedKeys(params) {
463
- this.assertSupportsCommand(Security2Command, Security2Command.KEXSet);
464
- const cc = new Security2CCKEXSet({
465
- nodeId: this.endpoint.nodeId,
466
- endpointIndex: this.endpoint.index,
467
- ...params,
468
- echo: true,
469
- });
470
- return this.host.sendCommand(cc, this.commandOptions);
471
- }
472
- /** Notifies the other node that the ongoing key exchange was aborted */
473
- async abortKeyExchange(failType) {
474
- this.assertSupportsCommand(Security2Command, Security2Command.KEXFail);
475
- const cc = new Security2CCKEXFail({
476
- nodeId: this.endpoint.nodeId,
477
- endpointIndex: this.endpoint.index,
478
- failType,
479
- });
480
- await this.host.sendCommand(cc, this.commandOptions);
481
- }
482
- async sendPublicKey(publicKey, includingNode = true) {
483
- this.assertSupportsCommand(Security2Command, Security2Command.PublicKeyReport);
484
- const cc = new Security2CCPublicKeyReport({
485
- nodeId: this.endpoint.nodeId,
486
- endpointIndex: this.endpoint.index,
487
- includingNode,
488
- publicKey,
489
- });
490
- await this.host.sendCommand(cc, this.commandOptions);
491
- }
492
- async requestNetworkKey(securityClass) {
493
- this.assertSupportsCommand(Security2Command, Security2Command.NetworkKeyGet);
494
- const cc = new Security2CCNetworkKeyGet({
495
- nodeId: this.endpoint.nodeId,
496
- endpointIndex: this.endpoint.index,
497
- requestedKey: securityClass,
498
- });
499
- await this.host.sendCommand(cc, this.commandOptions);
500
- }
501
- async sendNetworkKey(securityClass, networkKey) {
502
- this.assertSupportsCommand(Security2Command, Security2Command.NetworkKeyReport);
503
- const cc = new Security2CCNetworkKeyReport({
504
- nodeId: this.endpoint.nodeId,
505
- endpointIndex: this.endpoint.index,
506
- grantedKey: securityClass,
507
- networkKey,
508
- });
509
- await this.host.sendCommand(cc, this.commandOptions);
510
- }
511
- async verifyNetworkKey() {
512
- this.assertSupportsCommand(Security2Command, Security2Command.NetworkKeyVerify);
513
- const cc = new Security2CCNetworkKeyVerify({
514
- nodeId: this.endpoint.nodeId,
515
- endpointIndex: this.endpoint.index,
516
- });
517
- await this.host.sendCommand(cc, this.commandOptions);
518
- }
519
- async confirmKeyVerification() {
520
- this.assertSupportsCommand(Security2Command, Security2Command.TransferEnd);
521
- const cc = new Security2CCTransferEnd({
522
- nodeId: this.endpoint.nodeId,
523
- endpointIndex: this.endpoint.index,
524
- keyVerified: true,
525
- keyRequestComplete: false,
526
- });
527
- await this.host.sendCommand(cc, {
528
- ...this.commandOptions,
529
- // Don't wait for an ACK from the node
530
- transmitOptions: TransmitOptions.DEFAULT & ~TransmitOptions.ACK,
531
- });
532
- }
533
- async endKeyExchange() {
534
- this.assertSupportsCommand(Security2Command, Security2Command.TransferEnd);
535
- const cc = new Security2CCTransferEnd({
536
- nodeId: this.endpoint.nodeId,
537
- endpointIndex: this.endpoint.index,
538
- keyVerified: false,
539
- keyRequestComplete: true,
540
- });
541
- await this.host.sendCommand(cc, this.commandOptions);
542
- }
543
- };
544
- Security2CCAPI = __decorate([
545
- API(CommandClasses["Security 2"])
546
- ], Security2CCAPI);
547
- export { Security2CCAPI };
548
- let Security2CC = Security2CC_1 = class Security2CC extends CommandClass {
549
- async interview(ctx) {
550
- const securityManager = getSecurityManager(ctx.ownNodeId, ctx, this.nodeId);
551
- const node = this.getNode(ctx);
552
- const endpoint = this.getEndpoint(ctx);
553
- const api = CCAPI.create(CommandClasses["Security 2"], ctx, endpoint).withOptions({
554
- priority: MessagePriority.NodeQuery,
555
- });
556
- // Only on the highest security class the response includes the supported commands
557
- const secClass = node.getHighestSecurityClass();
558
- let hasReceivedSecureCommands = false;
559
- let possibleSecurityClasses;
560
- if (securityClassIsS2(secClass)) {
561
- // The highest security class is known to be S2, only query that one
562
- possibleSecurityClasses = [secClass];
563
- }
564
- else if (endpoint.index === 0) {
565
- // If the highest security class isn't known, query all possible security classes
566
- // but only on the root device
567
- possibleSecurityClasses = [
568
- SecurityClass.S2_Unauthenticated,
569
- SecurityClass.S2_Authenticated,
570
- SecurityClass.S2_AccessControl,
571
- ];
480
+ /** Grants the joining node the given keys */
481
+ async grantKeys(params) {
482
+ this.assertSupportsCommand(Security2Command, Security2Command.KEXSet);
483
+ const cc = new Security2CCKEXSet({
484
+ nodeId: this.endpoint.nodeId,
485
+ endpointIndex: this.endpoint.index,
486
+ ...params,
487
+ echo: false,
488
+ });
489
+ await this.host.sendCommand(cc, this.commandOptions);
572
490
  }
573
- else {
574
- // For endpoint interviews, the security class MUST be known
575
- ctx.logNode(node.id, {
576
- endpoint: endpoint.index,
577
- message: `Cannot query securely supported commands for endpoint because the node's security class isn't known...`,
578
- level: "error",
491
+ /** Confirms the keys that were requested by a node */
492
+ async confirmRequestedKeys(params) {
493
+ this.assertSupportsCommand(Security2Command, Security2Command.KEXReport);
494
+ const cc = new Security2CCKEXReport({
495
+ nodeId: this.endpoint.nodeId,
496
+ endpointIndex: this.endpoint.index,
497
+ ...params,
498
+ echo: true,
579
499
  });
580
- return;
500
+ await this.host.sendCommand(cc, this.commandOptions);
581
501
  }
582
- for (const secClass of possibleSecurityClasses) {
583
- // We might not know all assigned security classes yet, so we work our way up from low to high and try to request the supported commands.
584
- // This way, each command is encrypted with the security class we're currently testing.
585
- // If the node does not respond, it wasn't assigned the security class.
586
- // If it responds with a non-empty list, we know this is the highest class it supports.
587
- // If the list is empty, the security class is still supported.
588
- // If we already know the class is not supported, skip it
589
- if (node.hasSecurityClass(secClass) === false)
590
- continue;
591
- // If no key is configured for this security class, skip it
592
- if (!securityManager?.hasKeysForSecurityClass(secClass)) {
502
+ /** Confirms the keys that were granted by the including node */
503
+ async confirmGrantedKeys(params) {
504
+ this.assertSupportsCommand(Security2Command, Security2Command.KEXSet);
505
+ const cc = new Security2CCKEXSet({
506
+ nodeId: this.endpoint.nodeId,
507
+ endpointIndex: this.endpoint.index,
508
+ ...params,
509
+ echo: true,
510
+ });
511
+ return this.host.sendCommand(cc, this.commandOptions);
512
+ }
513
+ /** Notifies the other node that the ongoing key exchange was aborted */
514
+ async abortKeyExchange(failType) {
515
+ this.assertSupportsCommand(Security2Command, Security2Command.KEXFail);
516
+ const cc = new Security2CCKEXFail({
517
+ nodeId: this.endpoint.nodeId,
518
+ endpointIndex: this.endpoint.index,
519
+ failType,
520
+ });
521
+ await this.host.sendCommand(cc, this.commandOptions);
522
+ }
523
+ async sendPublicKey(publicKey, includingNode = true) {
524
+ this.assertSupportsCommand(Security2Command, Security2Command.PublicKeyReport);
525
+ const cc = new Security2CCPublicKeyReport({
526
+ nodeId: this.endpoint.nodeId,
527
+ endpointIndex: this.endpoint.index,
528
+ includingNode,
529
+ publicKey,
530
+ });
531
+ await this.host.sendCommand(cc, this.commandOptions);
532
+ }
533
+ async requestNetworkKey(securityClass) {
534
+ this.assertSupportsCommand(Security2Command, Security2Command.NetworkKeyGet);
535
+ const cc = new Security2CCNetworkKeyGet({
536
+ nodeId: this.endpoint.nodeId,
537
+ endpointIndex: this.endpoint.index,
538
+ requestedKey: securityClass,
539
+ });
540
+ await this.host.sendCommand(cc, this.commandOptions);
541
+ }
542
+ async sendNetworkKey(securityClass, networkKey) {
543
+ this.assertSupportsCommand(Security2Command, Security2Command.NetworkKeyReport);
544
+ const cc = new Security2CCNetworkKeyReport({
545
+ nodeId: this.endpoint.nodeId,
546
+ endpointIndex: this.endpoint.index,
547
+ grantedKey: securityClass,
548
+ networkKey,
549
+ });
550
+ await this.host.sendCommand(cc, this.commandOptions);
551
+ }
552
+ async verifyNetworkKey() {
553
+ this.assertSupportsCommand(Security2Command, Security2Command.NetworkKeyVerify);
554
+ const cc = new Security2CCNetworkKeyVerify({
555
+ nodeId: this.endpoint.nodeId,
556
+ endpointIndex: this.endpoint.index,
557
+ });
558
+ await this.host.sendCommand(cc, this.commandOptions);
559
+ }
560
+ async confirmKeyVerification() {
561
+ this.assertSupportsCommand(Security2Command, Security2Command.TransferEnd);
562
+ const cc = new Security2CCTransferEnd({
563
+ nodeId: this.endpoint.nodeId,
564
+ endpointIndex: this.endpoint.index,
565
+ keyVerified: true,
566
+ keyRequestComplete: false,
567
+ });
568
+ await this.host.sendCommand(cc, {
569
+ ...this.commandOptions,
570
+ // Don't wait for an ACK from the node
571
+ transmitOptions: TransmitOptions.DEFAULT & ~TransmitOptions.ACK,
572
+ });
573
+ }
574
+ async endKeyExchange() {
575
+ this.assertSupportsCommand(Security2Command, Security2Command.TransferEnd);
576
+ const cc = new Security2CCTransferEnd({
577
+ nodeId: this.endpoint.nodeId,
578
+ endpointIndex: this.endpoint.index,
579
+ keyVerified: false,
580
+ keyRequestComplete: true,
581
+ });
582
+ await this.host.sendCommand(cc, this.commandOptions);
583
+ }
584
+ };
585
+ return Security2CCAPI = _classThis;
586
+ })();
587
+ export { Security2CCAPI };
588
+ let Security2CC = (() => {
589
+ let _classDecorators = [commandClass(CommandClasses["Security 2"]), implementedVersion(1)];
590
+ let _classDescriptor;
591
+ let _classExtraInitializers = [];
592
+ let _classThis;
593
+ let _classSuper = CommandClass;
594
+ var Security2CC = class extends _classSuper {
595
+ static { _classThis = this; }
596
+ static {
597
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
598
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
599
+ Security2CC = _classThis = _classDescriptor.value;
600
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
601
+ __runInitializers(_classThis, _classExtraInitializers);
602
+ }
603
+ async interview(ctx) {
604
+ const securityManager = getSecurityManager(ctx.ownNodeId, ctx, this.nodeId);
605
+ const node = this.getNode(ctx);
606
+ const endpoint = this.getEndpoint(ctx);
607
+ const api = CCAPI.create(CommandClasses["Security 2"], ctx, endpoint).withOptions({
608
+ priority: MessagePriority.NodeQuery,
609
+ });
610
+ // Only on the highest security class the response includes the supported commands
611
+ const secClass = node.getHighestSecurityClass();
612
+ let hasReceivedSecureCommands = false;
613
+ let possibleSecurityClasses;
614
+ if (securityClassIsS2(secClass)) {
615
+ // The highest security class is known to be S2, only query that one
616
+ possibleSecurityClasses = [secClass];
617
+ }
618
+ else if (endpoint.index === 0) {
619
+ // If the highest security class isn't known, query all possible security classes
620
+ // but only on the root device
621
+ possibleSecurityClasses = [
622
+ SecurityClass.S2_Unauthenticated,
623
+ SecurityClass.S2_Authenticated,
624
+ SecurityClass.S2_AccessControl,
625
+ ];
626
+ }
627
+ else {
628
+ // For endpoint interviews, the security class MUST be known
593
629
  ctx.logNode(node.id, {
594
630
  endpoint: endpoint.index,
595
- message: `Cannot query securely supported commands (${getEnumMemberName(SecurityClass, secClass)}) - network key is not configured...`,
596
- level: "warn",
631
+ message: `Cannot query securely supported commands for endpoint because the node's security class isn't known...`,
632
+ level: "error",
597
633
  });
598
- continue;
634
+ return;
599
635
  }
600
- ctx.logNode(node.id, {
601
- endpoint: endpoint.index,
602
- message: `Querying securely supported commands (${getEnumMemberName(SecurityClass, secClass)})...`,
603
- direction: "outbound",
604
- });
605
- // Query the supported commands but avoid remembering the wrong security class in case of a failure
606
- let supportedCCs;
607
- // Try up to 3 times on the root device. We REALLY don't want a spurious timeout or collision to cause us to discard a known good security class
608
- const MAX_ATTEMPTS = this.endpointIndex === 0 ? 3 : 1;
609
- for (let attempts = 1; attempts <= MAX_ATTEMPTS; attempts++) {
610
- try {
611
- supportedCCs = await api.getSupportedCommands(secClass);
636
+ for (const secClass of possibleSecurityClasses) {
637
+ // We might not know all assigned security classes yet, so we work our way up from low to high and try to request the supported commands.
638
+ // This way, each command is encrypted with the security class we're currently testing.
639
+ // If the node does not respond, it wasn't assigned the security class.
640
+ // If it responds with a non-empty list, we know this is the highest class it supports.
641
+ // If the list is empty, the security class is still supported.
642
+ // If we already know the class is not supported, skip it
643
+ if (node.hasSecurityClass(secClass) === false)
644
+ continue;
645
+ // If no key is configured for this security class, skip it
646
+ if (!securityManager?.hasKeysForSecurityClass(secClass)) {
647
+ ctx.logNode(node.id, {
648
+ endpoint: endpoint.index,
649
+ message: `Cannot query securely supported commands (${getEnumMemberName(SecurityClass, secClass)}) - network key is not configured...`,
650
+ level: "warn",
651
+ });
652
+ continue;
612
653
  }
613
- catch (e) {
614
- if (isZWaveError(e)
615
- && e.code === ZWaveErrorCodes.Security2CC_CannotDecode) {
616
- // Either we were using a non-granted security class,
617
- // or querying with the known highest security class had an issue
618
- supportedCCs = undefined;
619
- }
620
- else {
621
- throw e;
654
+ ctx.logNode(node.id, {
655
+ endpoint: endpoint.index,
656
+ message: `Querying securely supported commands (${getEnumMemberName(SecurityClass, secClass)})...`,
657
+ direction: "outbound",
658
+ });
659
+ // Query the supported commands but avoid remembering the wrong security class in case of a failure
660
+ let supportedCCs;
661
+ // Try up to 3 times on the root device. We REALLY don't want a spurious timeout or collision to cause us to discard a known good security class
662
+ const MAX_ATTEMPTS = this.endpointIndex === 0 ? 3 : 1;
663
+ for (let attempts = 1; attempts <= MAX_ATTEMPTS; attempts++) {
664
+ try {
665
+ supportedCCs = await api.getSupportedCommands(secClass);
622
666
  }
623
- }
624
- if (supportedCCs == undefined
625
- && possibleSecurityClasses.length === 1) {
626
- if (attempts < MAX_ATTEMPTS) {
627
- // We definitely know the highest security class
628
- ctx.logNode(node.id, {
629
- endpoint: endpoint.index,
630
- message: `Querying securely supported commands (${getEnumMemberName(SecurityClass, secClass)}), attempt ${attempts}/${MAX_ATTEMPTS} failed. Retrying in 500ms...`,
631
- level: "warn",
632
- });
633
- await wait(500);
634
- continue;
667
+ catch (e) {
668
+ if (isZWaveError(e)
669
+ && e.code === ZWaveErrorCodes.Security2CC_CannotDecode) {
670
+ // Either we were using a non-granted security class,
671
+ // or querying with the known highest security class had an issue
672
+ supportedCCs = undefined;
673
+ }
674
+ else {
675
+ throw e;
676
+ }
635
677
  }
636
- else if (endpoint.index > 0) {
637
- ctx.logNode(node.id, {
638
- endpoint: endpoint.index,
639
- message: `Querying securely supported commands (${getEnumMemberName(SecurityClass, secClass)}) failed. Assuming the endpoint supports all its mandatory CCs securely...`,
640
- level: "warn",
641
- });
642
- // Just mark all endpoint CCs as secure. Without this we would attempt
643
- // unencrypted communication with the endpoint, which will likely fail.
644
- for (const [ccId] of endpoint.getCCs()) {
645
- endpoint.addCC(ccId, { secure: true });
678
+ if (supportedCCs == undefined
679
+ && possibleSecurityClasses.length === 1) {
680
+ if (attempts < MAX_ATTEMPTS) {
681
+ // We definitely know the highest security class
682
+ ctx.logNode(node.id, {
683
+ endpoint: endpoint.index,
684
+ message: `Querying securely supported commands (${getEnumMemberName(SecurityClass, secClass)}), attempt ${attempts}/${MAX_ATTEMPTS} failed. Retrying in 500ms...`,
685
+ level: "warn",
686
+ });
687
+ await wait(500);
688
+ continue;
689
+ }
690
+ else if (endpoint.index > 0) {
691
+ ctx.logNode(node.id, {
692
+ endpoint: endpoint.index,
693
+ message: `Querying securely supported commands (${getEnumMemberName(SecurityClass, secClass)}) failed. Assuming the endpoint supports all its mandatory CCs securely...`,
694
+ level: "warn",
695
+ });
696
+ // Just mark all endpoint CCs as secure. Without this we would attempt
697
+ // unencrypted communication with the endpoint, which will likely fail.
698
+ for (const [ccId] of endpoint.getCCs()) {
699
+ endpoint.addCC(ccId, { secure: true });
700
+ }
701
+ break;
702
+ }
703
+ else {
704
+ ctx.logNode(node.id, {
705
+ endpoint: endpoint.index,
706
+ message: `Querying securely supported commands (${getEnumMemberName(SecurityClass, secClass)}) failed. Let's hope for the best...`,
707
+ level: "warn",
708
+ });
709
+ break;
646
710
  }
647
- break;
648
711
  }
649
712
  else {
650
- ctx.logNode(node.id, {
651
- endpoint: endpoint.index,
652
- message: `Querying securely supported commands (${getEnumMemberName(SecurityClass, secClass)}) failed. Let's hope for the best...`,
653
- level: "warn",
654
- });
713
+ // In any other case, we can stop trying
655
714
  break;
656
715
  }
657
716
  }
658
- else {
659
- // In any other case, we can stop trying
660
- break;
717
+ if (supportedCCs == undefined) {
718
+ if (endpoint.index === 0
719
+ && possibleSecurityClasses.length > 1) {
720
+ // No supported commands found, mark the security class as not granted
721
+ // unless we were sure about the security class
722
+ node.setSecurityClass(secClass, false);
723
+ ctx.logNode(node.id, {
724
+ message: `The node was NOT granted the security class ${getEnumMemberName(SecurityClass, secClass)}`,
725
+ direction: "inbound",
726
+ });
727
+ }
728
+ continue;
661
729
  }
662
- }
663
- if (supportedCCs == undefined) {
664
- if (endpoint.index === 0
665
- && possibleSecurityClasses.length > 1) {
666
- // No supported commands found, mark the security class as not granted
667
- // unless we were sure about the security class
668
- node.setSecurityClass(secClass, false);
730
+ if (endpoint.index === 0 && possibleSecurityClasses.length > 1) {
731
+ // Mark the security class as granted unless we were sure about the security class
732
+ node.setSecurityClass(secClass, true);
669
733
  ctx.logNode(node.id, {
670
- message: `The node was NOT granted the security class ${getEnumMemberName(SecurityClass, secClass)}`,
734
+ message: `The node was granted the security class ${getEnumMemberName(SecurityClass, secClass)}`,
671
735
  direction: "inbound",
672
736
  });
673
737
  }
674
- continue;
675
- }
676
- if (endpoint.index === 0 && possibleSecurityClasses.length > 1) {
677
- // Mark the security class as granted unless we were sure about the security class
678
- node.setSecurityClass(secClass, true);
679
- ctx.logNode(node.id, {
680
- message: `The node was granted the security class ${getEnumMemberName(SecurityClass, secClass)}`,
681
- direction: "inbound",
682
- });
683
- }
684
- if (!hasReceivedSecureCommands && supportedCCs.length > 0) {
685
- hasReceivedSecureCommands = true;
686
- const logLines = [
687
- `received secure commands (${getEnumMemberName(SecurityClass, secClass)})`,
688
- "supported CCs:",
689
- ];
690
- for (const cc of supportedCCs) {
691
- logLines.push(`· ${getCCName(cc)}`);
692
- }
693
- ctx.logNode(node.id, {
694
- endpoint: endpoint.index,
695
- message: logLines.join("\n"),
696
- direction: "inbound",
697
- });
698
- // Remember which commands are supported securely
699
- for (const cc of supportedCCs) {
700
- // Basic CC has special rules for when it is considered supported
701
- // Therefore we mark all other CCs as supported, but not Basic CC,
702
- // for which support is determined later.
703
- if (cc === CommandClasses.Basic) {
704
- endpoint.addCC(cc, { secure: true });
738
+ if (!hasReceivedSecureCommands && supportedCCs.length > 0) {
739
+ hasReceivedSecureCommands = true;
740
+ const logLines = [
741
+ `received secure commands (${getEnumMemberName(SecurityClass, secClass)})`,
742
+ "supported CCs:",
743
+ ];
744
+ for (const cc of supportedCCs) {
745
+ logLines.push(`· ${getCCName(cc)}`);
705
746
  }
706
- else {
707
- endpoint.addCC(cc, {
708
- isSupported: true,
709
- secure: true,
710
- });
747
+ ctx.logNode(node.id, {
748
+ endpoint: endpoint.index,
749
+ message: logLines.join("\n"),
750
+ direction: "inbound",
751
+ });
752
+ // Remember which commands are supported securely
753
+ for (const cc of supportedCCs) {
754
+ // Basic CC has special rules for when it is considered supported
755
+ // Therefore we mark all other CCs as supported, but not Basic CC,
756
+ // for which support is determined later.
757
+ if (cc === CommandClasses.Basic) {
758
+ endpoint.addCC(cc, { secure: true });
759
+ }
760
+ else {
761
+ endpoint.addCC(cc, {
762
+ isSupported: true,
763
+ secure: true,
764
+ });
765
+ }
711
766
  }
712
767
  }
713
768
  }
769
+ // Remember that the interview is complete
770
+ this.setInterviewComplete(ctx, true);
714
771
  }
715
- // Remember that the interview is complete
716
- this.setInterviewComplete(ctx, true);
717
- }
718
- /** Tests if a command should be sent secure and thus requires encapsulation */
719
- static requiresEncapsulation(cc) {
720
- // No security flag -> no encapsulation
721
- if (!(cc.encapsulationFlags & EncapsulationFlags.Security)) {
722
- return false;
723
- }
724
- // S0, CRC16, Transport Service -> no S2 encapsulation
725
- if (cc instanceof SecurityCC
726
- || cc instanceof CRC16CC
727
- || cc instanceof TransportServiceCC) {
728
- return false;
729
- }
730
- // S2: check command
731
- if (cc instanceof Security2CC_1) {
732
- // These S2 commands need additional encapsulation
733
- switch (cc.ccCommand) {
734
- case Security2Command.CommandsSupportedGet:
735
- case Security2Command.CommandsSupportedReport:
736
- case Security2Command.NetworkKeyGet:
737
- case Security2Command.NetworkKeyReport:
738
- case Security2Command.NetworkKeyVerify:
739
- case Security2Command.TransferEnd:
740
- return true;
741
- case Security2Command.KEXSet:
742
- case Security2Command.KEXReport:
743
- // KEXSet/Report need to be encrypted for the confirmation only
744
- return cc
745
- .echo;
746
- case Security2Command.KEXFail: {
747
- switch (cc.failType) {
748
- case KEXFailType.Decrypt:
749
- case KEXFailType.WrongSecurityLevel:
750
- case KEXFailType.KeyNotGranted:
751
- case KEXFailType.NoVerify:
752
- return true;
753
- default:
754
- return false;
772
+ /** Tests if a command should be sent secure and thus requires encapsulation */
773
+ static requiresEncapsulation(cc) {
774
+ // No security flag -> no encapsulation
775
+ if (!(cc.encapsulationFlags & EncapsulationFlags.Security)) {
776
+ return false;
777
+ }
778
+ // S0, CRC16, Transport Service -> no S2 encapsulation
779
+ if (cc instanceof SecurityCC
780
+ || cc instanceof CRC16CC
781
+ || cc instanceof TransportServiceCC) {
782
+ return false;
783
+ }
784
+ // S2: check command
785
+ if (cc instanceof Security2CC) {
786
+ // These S2 commands need additional encapsulation
787
+ switch (cc.ccCommand) {
788
+ case Security2Command.CommandsSupportedGet:
789
+ case Security2Command.CommandsSupportedReport:
790
+ case Security2Command.NetworkKeyGet:
791
+ case Security2Command.NetworkKeyReport:
792
+ case Security2Command.NetworkKeyVerify:
793
+ case Security2Command.TransferEnd:
794
+ return true;
795
+ case Security2Command.KEXSet:
796
+ case Security2Command.KEXReport:
797
+ // KEXSet/Report need to be encrypted for the confirmation only
798
+ return cc
799
+ .echo;
800
+ case Security2Command.KEXFail: {
801
+ switch (cc.failType) {
802
+ case KEXFailType.Decrypt:
803
+ case KEXFailType.WrongSecurityLevel:
804
+ case KEXFailType.KeyNotGranted:
805
+ case KEXFailType.NoVerify:
806
+ return true;
807
+ default:
808
+ return false;
809
+ }
755
810
  }
756
811
  }
812
+ return false;
757
813
  }
758
- return false;
814
+ // Everything else needs to be encapsulated if the CC is secure
815
+ return true;
759
816
  }
760
- // Everything else needs to be encapsulated if the CC is secure
761
- return true;
762
- }
763
- /** Encapsulates a command that should be sent encrypted */
764
- static encapsulate(cc, ownNodeId, securityManagers, options) {
765
- // Determine which extensions must be used on the command
766
- const extensions = [];
767
- if (options?.multicastOutOfSync) {
768
- extensions.push(new MOSExtension());
769
- }
770
- if (options?.multicastGroupId != undefined) {
771
- extensions.push(new MGRPExtension({ groupId: options.multicastGroupId }));
772
- }
773
- // Make sure that S2 multicast uses broadcasts. While the specs mention that both multicast and broadcast
774
- // are possible, it has been found that devices treat multicasts like singlecast followups and respond incorrectly.
775
- let nodeId;
776
- if (cc.isMulticast()) {
777
- if (cc.nodeId.some((nodeId) => isLongRangeNodeId(nodeId))) {
778
- nodeId = NODE_ID_BROADCAST_LR;
817
+ /** Encapsulates a command that should be sent encrypted */
818
+ static encapsulate(cc, ownNodeId, securityManagers, options) {
819
+ // Determine which extensions must be used on the command
820
+ const extensions = [];
821
+ if (options?.multicastOutOfSync) {
822
+ extensions.push(new MOSExtension());
823
+ }
824
+ if (options?.multicastGroupId != undefined) {
825
+ extensions.push(new MGRPExtension({ groupId: options.multicastGroupId }));
826
+ }
827
+ // Make sure that S2 multicast uses broadcasts. While the specs mention that both multicast and broadcast
828
+ // are possible, it has been found that devices treat multicasts like singlecast followups and respond incorrectly.
829
+ let nodeId;
830
+ if (cc.isMulticast()) {
831
+ if (cc.nodeId.some((nodeId) => isLongRangeNodeId(nodeId))) {
832
+ nodeId = NODE_ID_BROADCAST_LR;
833
+ }
834
+ else {
835
+ nodeId = NODE_ID_BROADCAST;
836
+ }
779
837
  }
780
838
  else {
781
- nodeId = NODE_ID_BROADCAST;
839
+ nodeId = cc.nodeId;
782
840
  }
841
+ const ret = new Security2CCMessageEncapsulation({
842
+ nodeId,
843
+ encapsulated: cc,
844
+ securityClass: options?.securityClass,
845
+ extensions,
846
+ verifyDelivery: options?.verifyDelivery,
847
+ });
848
+ // Copy the encapsulation flags from the encapsulated command
849
+ // but omit Security, since we're doing that right now
850
+ ret.encapsulationFlags = cc.encapsulationFlags
851
+ & ~EncapsulationFlags.Security;
852
+ return ret;
783
853
  }
784
- else {
785
- nodeId = cc.nodeId;
786
- }
787
- const ret = new Security2CCMessageEncapsulation({
788
- nodeId,
789
- encapsulated: cc,
790
- securityClass: options?.securityClass,
791
- extensions,
792
- verifyDelivery: options?.verifyDelivery,
793
- });
794
- // Copy the encapsulation flags from the encapsulated command
795
- // but omit Security, since we're doing that right now
796
- ret.encapsulationFlags = cc.encapsulationFlags
797
- & ~EncapsulationFlags.Security;
798
- return ret;
799
- }
800
- };
801
- Security2CC = Security2CC_1 = __decorate([
802
- commandClass(CommandClasses["Security 2"]),
803
- implementedVersion(1)
804
- ], Security2CC);
854
+ };
855
+ return Security2CC = _classThis;
856
+ })();
805
857
  export { Security2CC };
806
858
  function failNoSPAN() {
807
859
  validatePayload.fail(ZWaveErrorCodes.Security2CC_NoSPAN);
@@ -837,657 +889,719 @@ function testCCResponseForMessageEncapsulation(sent, received) {
837
889
  return received.SOS && !!received.receiverEI;
838
890
  }
839
891
  }
840
- let Security2CCMessageEncapsulation = Security2CCMessageEncapsulation_1 = class Security2CCMessageEncapsulation extends Security2CC {
841
- constructor(options) {
842
- super(options);
843
- if (!options.encapsulated && !options.extensions?.length) {
844
- throw new ZWaveError("Security S2 encapsulation requires an encapsulated CC and/or extensions", ZWaveErrorCodes.Argument_Invalid);
845
- }
846
- this.sequenceNumber = options.sequenceNumber;
847
- this.securityClass = options.securityClass;
848
- if (options.encapsulated) {
849
- this.encapsulated = options.encapsulated;
850
- options.encapsulated.encapsulatingCC = this;
851
- }
852
- this.verifyDelivery = options.verifyDelivery !== false;
853
- this.extensions = options.extensions ?? [];
854
- if (typeof this.nodeId !== "number"
855
- && !this.extensions.some((e) => e instanceof MGRPExtension)) {
856
- throw new ZWaveError("Multicast Security S2 encapsulation requires the MGRP extension", ZWaveErrorCodes.Security2CC_MissingExtension);
892
+ let Security2CCMessageEncapsulation = (() => {
893
+ let _classDecorators = [CCCommand(Security2Command.MessageEncapsulation), expectedCCResponse(getCCResponseForMessageEncapsulation, testCCResponseForMessageEncapsulation)];
894
+ let _classDescriptor;
895
+ let _classExtraInitializers = [];
896
+ let _classThis;
897
+ let _classSuper = Security2CC;
898
+ var Security2CCMessageEncapsulation = class extends _classSuper {
899
+ static { _classThis = this; }
900
+ static {
901
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
902
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
903
+ Security2CCMessageEncapsulation = _classThis = _classDescriptor.value;
904
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
905
+ __runInitializers(_classThis, _classExtraInitializers);
857
906
  }
858
- }
859
- static from(raw, ctx) {
860
- const securityManager = assertSecurityRX(ctx);
861
- validatePayload(raw.payload.length >= 2);
862
- // Check the sequence number to avoid duplicates
863
- const sequenceNumber = raw.payload[0];
864
- // Ensure the node has a security class
865
- validatePayload.withReason("No security class granted")(ctx.getHighestSecurityClass(ctx.sourceNodeId) !== SecurityClass.None);
866
- const hasExtensions = !!(raw.payload[1] & 0b1);
867
- const hasEncryptedExtensions = !!(raw.payload[1] & 0b10);
868
- let offset = 2;
869
- const extensions = [];
870
- let mustDiscardCommand = false;
871
- const parseExtensions = (buffer, wasEncrypted) => {
872
- while (true) {
873
- if (buffer.length < offset + 2) {
874
- // An S2 extension was expected, but the buffer is too short
875
- mustDiscardCommand = true;
876
- return;
907
+ constructor(options) {
908
+ super(options);
909
+ if (!options.encapsulated && !options.extensions?.length) {
910
+ throw new ZWaveError("Security S2 encapsulation requires an encapsulated CC and/or extensions", ZWaveErrorCodes.Argument_Invalid);
911
+ }
912
+ this.sequenceNumber = options.sequenceNumber;
913
+ this.securityClass = options.securityClass;
914
+ if (options.encapsulated) {
915
+ this.encapsulated = options.encapsulated;
916
+ options.encapsulated.encapsulatingCC = this;
917
+ }
918
+ this.verifyDelivery = options.verifyDelivery !== false;
919
+ this.extensions = options.extensions ?? [];
920
+ if (typeof this.nodeId !== "number"
921
+ && !this.extensions.some((e) => e instanceof MGRPExtension)) {
922
+ throw new ZWaveError("Multicast Security S2 encapsulation requires the MGRP extension", ZWaveErrorCodes.Security2CC_MissingExtension);
923
+ }
924
+ }
925
+ static from(raw, ctx) {
926
+ const securityManager = assertSecurityRX(ctx);
927
+ validatePayload(raw.payload.length >= 2);
928
+ // Check the sequence number to avoid duplicates
929
+ const sequenceNumber = raw.payload[0];
930
+ // Ensure the node has a security class
931
+ validatePayload.withReason("No security class granted")(ctx.getHighestSecurityClass(ctx.sourceNodeId) !== SecurityClass.None);
932
+ const hasExtensions = !!(raw.payload[1] & 0b1);
933
+ const hasEncryptedExtensions = !!(raw.payload[1] & 0b10);
934
+ let offset = 2;
935
+ const extensions = [];
936
+ let mustDiscardCommand = false;
937
+ const parseExtensions = (buffer, wasEncrypted) => {
938
+ while (true) {
939
+ if (buffer.length < offset + 2) {
940
+ // An S2 extension was expected, but the buffer is too short
941
+ mustDiscardCommand = true;
942
+ return;
943
+ }
944
+ // The length field could be too large, which would cause part of the actual ciphertext
945
+ // to be ignored. Try to avoid this for known extensions by checking the actual and expected length.
946
+ const { actual: actualLength, expected: expectedLength } = Security2Extension
947
+ .getExtensionLength(buffer.subarray(offset));
948
+ // Parse the extension using the expected length if possible
949
+ const extensionLength = expectedLength ?? actualLength;
950
+ if (extensionLength < 2) {
951
+ // An S2 extension was expected, but the length is too short
952
+ mustDiscardCommand = true;
953
+ return;
954
+ }
955
+ else if (extensionLength
956
+ > buffer.length
957
+ - offset
958
+ - (wasEncrypted
959
+ ? 0
960
+ : SECURITY_S2_AUTH_TAG_LENGTH)) {
961
+ // The supposed length is longer than the space the extensions may occupy
962
+ mustDiscardCommand = true;
963
+ return;
964
+ }
965
+ const extensionData = buffer.subarray(offset, offset + extensionLength);
966
+ offset += extensionLength;
967
+ const ext = Security2Extension.parse(extensionData);
968
+ switch (validateS2Extension(ext, wasEncrypted)) {
969
+ case ValidateS2ExtensionResult.OK:
970
+ if (expectedLength != undefined
971
+ && actualLength !== expectedLength) {
972
+ // The extension length field does not match, ignore the extension
973
+ }
974
+ else {
975
+ extensions.push(ext);
976
+ }
977
+ break;
978
+ case ValidateS2ExtensionResult.DiscardExtension:
979
+ // Do nothing
980
+ break;
981
+ case ValidateS2ExtensionResult.DiscardCommand:
982
+ mustDiscardCommand = true;
983
+ break;
984
+ }
985
+ // Check if that was the last extension
986
+ if (!ext.moreToFollow)
987
+ break;
877
988
  }
878
- // The length field could be too large, which would cause part of the actual ciphertext
879
- // to be ignored. Try to avoid this for known extensions by checking the actual and expected length.
880
- const { actual: actualLength, expected: expectedLength } = Security2Extension
881
- .getExtensionLength(buffer.subarray(offset));
882
- // Parse the extension using the expected length if possible
883
- const extensionLength = expectedLength ?? actualLength;
884
- if (extensionLength < 2) {
885
- // An S2 extension was expected, but the length is too short
886
- mustDiscardCommand = true;
887
- return;
989
+ };
990
+ if (hasExtensions)
991
+ parseExtensions(raw.payload, false);
992
+ const mcctx = (() => {
993
+ const multicastGroupId = getMulticastGroupId(extensions);
994
+ if (ctx.frameType === "multicast" || ctx.frameType === "broadcast") {
995
+ if (multicastGroupId == undefined) {
996
+ validatePayload.fail("Multicast frames without MGRP extension");
997
+ }
998
+ return {
999
+ isMulticast: true,
1000
+ groupId: multicastGroupId,
1001
+ };
888
1002
  }
889
- else if (extensionLength
890
- > buffer.length
891
- - offset
892
- - (wasEncrypted
893
- ? 0
894
- : SECURITY_S2_AUTH_TAG_LENGTH)) {
895
- // The supposed length is longer than the space the extensions may occupy
896
- mustDiscardCommand = true;
897
- return;
1003
+ else {
1004
+ return { isMulticast: false, groupId: multicastGroupId };
898
1005
  }
899
- const extensionData = buffer.subarray(offset, offset + extensionLength);
900
- offset += extensionLength;
901
- const ext = Security2Extension.parse(extensionData);
902
- switch (validateS2Extension(ext, wasEncrypted)) {
903
- case ValidateS2ExtensionResult.OK:
904
- if (expectedLength != undefined
905
- && actualLength !== expectedLength) {
906
- // The extension length field does not match, ignore the extension
907
- }
908
- else {
909
- extensions.push(ext);
910
- }
911
- break;
912
- case ValidateS2ExtensionResult.DiscardExtension:
913
- // Do nothing
914
- break;
915
- case ValidateS2ExtensionResult.DiscardCommand:
916
- mustDiscardCommand = true;
917
- break;
1006
+ })();
1007
+ // If a command is to be discarded before decryption,
1008
+ // we still need to increment the SPAN or MPAN state
1009
+ if (mustDiscardCommand) {
1010
+ if (mcctx.isMulticast) {
1011
+ securityManager.nextPeerMPAN(ctx.sourceNodeId, mcctx.groupId);
918
1012
  }
919
- // Check if that was the last extension
920
- if (!ext.moreToFollow)
921
- break;
922
- }
923
- };
924
- if (hasExtensions)
925
- parseExtensions(raw.payload, false);
926
- const mcctx = (() => {
927
- const multicastGroupId = getMulticastGroupId(extensions);
928
- if (ctx.frameType === "multicast" || ctx.frameType === "broadcast") {
929
- if (multicastGroupId == undefined) {
930
- validatePayload.fail("Multicast frames without MGRP extension");
1013
+ else {
1014
+ securityManager.nextNonce(ctx.sourceNodeId);
931
1015
  }
932
- return {
933
- isMulticast: true,
934
- groupId: multicastGroupId,
935
- };
1016
+ validatePayload.fail("Invalid S2 extension");
1017
+ }
1018
+ let prevSequenceNumber;
1019
+ let mpanState;
1020
+ if (mcctx.isMulticast) {
1021
+ mpanState = securityManager.getPeerMPAN(ctx.sourceNodeId, mcctx.groupId);
936
1022
  }
937
1023
  else {
938
- return { isMulticast: false, groupId: multicastGroupId };
1024
+ // Don't accept duplicate Singlecast commands
1025
+ prevSequenceNumber = validateSequenceNumber(securityManager, ctx.sourceNodeId, sequenceNumber);
1026
+ // When a node receives a singlecast message after a multicast group was marked out of sync,
1027
+ // it must forget about the group.
1028
+ if (mcctx.groupId == undefined) {
1029
+ securityManager.resetOutOfSyncMPANs(ctx.sourceNodeId);
1030
+ }
939
1031
  }
940
- })();
941
- // If a command is to be discarded before decryption,
942
- // we still need to increment the SPAN or MPAN state
943
- if (mustDiscardCommand) {
1032
+ const unencryptedPayload = raw.payload.subarray(0, offset);
1033
+ const ciphertext = raw.payload.subarray(offset, -SECURITY_S2_AUTH_TAG_LENGTH);
1034
+ const authTag = raw.payload.subarray(-SECURITY_S2_AUTH_TAG_LENGTH);
1035
+ const messageLength = 2 /* CommandClass.computeEncapsulationOverhead() */
1036
+ + raw.payload.length;
1037
+ const authData = getAuthenticationData(ctx.sourceNodeId, getDestinationIDRX(ctx, extensions), ctx.homeId, messageLength, unencryptedPayload);
1038
+ let decrypt;
944
1039
  if (mcctx.isMulticast) {
945
- securityManager.nextPeerMPAN(ctx.sourceNodeId, mcctx.groupId);
1040
+ // For incoming multicast commands, make sure we have an MPAN
1041
+ if (mpanState?.type !== MPANState.MPAN) {
1042
+ // If we don't, mark the MPAN as out of sync, so we can respond accordingly on the singlecast followup
1043
+ securityManager.storePeerMPAN(ctx.sourceNodeId, mcctx.groupId, { type: MPANState.OutOfSync });
1044
+ failNoMPAN();
1045
+ }
1046
+ decrypt = () => decryptMulticast(ctx.sourceNodeId, securityManager, mcctx.groupId, ciphertext, authData, authTag);
946
1047
  }
947
1048
  else {
948
- securityManager.nextNonce(ctx.sourceNodeId);
1049
+ // Decrypt payload and verify integrity
1050
+ const spanState = securityManager.getSPANState(ctx.sourceNodeId);
1051
+ // If we are not able to establish an SPAN yet, fail the decryption
1052
+ if (spanState.type === SPANState.None) {
1053
+ failNoSPAN();
1054
+ }
1055
+ else if (spanState.type === SPANState.RemoteEI) {
1056
+ // TODO: The specs are not clear how to handle this case
1057
+ // For now, do the same as if we didn't have any EI
1058
+ failNoSPAN();
1059
+ }
1060
+ decrypt = () => decryptSinglecast(ctx, securityManager, ctx.sourceNodeId, sequenceNumber, prevSequenceNumber, ciphertext, authData, authTag, spanState, extensions);
949
1061
  }
950
- validatePayload.fail("Invalid S2 extension");
951
- }
952
- let prevSequenceNumber;
953
- let mpanState;
954
- if (mcctx.isMulticast) {
955
- mpanState = securityManager.getPeerMPAN(ctx.sourceNodeId, mcctx.groupId);
956
- }
957
- else {
958
- // Don't accept duplicate Singlecast commands
959
- prevSequenceNumber = validateSequenceNumber(securityManager, ctx.sourceNodeId, sequenceNumber);
960
- // When a node receives a singlecast message after a multicast group was marked out of sync,
961
- // it must forget about the group.
962
- if (mcctx.groupId == undefined) {
963
- securityManager.resetOutOfSyncMPANs(ctx.sourceNodeId);
1062
+ let plaintext;
1063
+ let authOK = false;
1064
+ let key;
1065
+ let iv;
1066
+ let decryptionSecurityClass;
1067
+ // If the Receiver is unable to authenticate the singlecast message with the current SPAN,
1068
+ // the Receiver SHOULD try decrypting the message with one or more of the following SPAN values,
1069
+ // stopping when decryption is successful or the maximum number of iterations is reached.
1070
+ // If the Receiver is unable to decrypt the S2 MC frame with the current MPAN, the Receiver MAY try
1071
+ // decrypting the frame with one or more of the subsequent MPAN values, stopping when decryption is
1072
+ // successful or the maximum number of iterations is reached.
1073
+ const decryptAttempts = mcctx.isMulticast
1074
+ ? MAX_DECRYPT_ATTEMPTS_MULTICAST
1075
+ : mcctx.groupId != undefined
1076
+ ? MAX_DECRYPT_ATTEMPTS_SC_FOLLOWUP
1077
+ : MAX_DECRYPT_ATTEMPTS_SINGLECAST;
1078
+ for (let i = 0; i < decryptAttempts; i++) {
1079
+ ({
1080
+ plaintext,
1081
+ authOK,
1082
+ key,
1083
+ iv,
1084
+ securityClass: decryptionSecurityClass,
1085
+ } = decrypt());
1086
+ if (!!authOK && !!plaintext)
1087
+ break;
1088
+ // No need to try further SPANs if we just got the sender's EI
1089
+ if (!!getSenderEI(extensions))
1090
+ break;
964
1091
  }
965
- }
966
- const unencryptedPayload = raw.payload.subarray(0, offset);
967
- const ciphertext = raw.payload.subarray(offset, -SECURITY_S2_AUTH_TAG_LENGTH);
968
- const authTag = raw.payload.subarray(-SECURITY_S2_AUTH_TAG_LENGTH);
969
- const messageLength = 2 /* CommandClass.computeEncapsulationOverhead() */
970
- + raw.payload.length;
971
- const authData = getAuthenticationData(ctx.sourceNodeId, getDestinationIDRX(ctx, extensions), ctx.homeId, messageLength, unencryptedPayload);
972
- let decrypt;
973
- if (mcctx.isMulticast) {
974
- // For incoming multicast commands, make sure we have an MPAN
975
- if (mpanState?.type !== MPANState.MPAN) {
976
- // If we don't, mark the MPAN as out of sync, so we can respond accordingly on the singlecast followup
977
- securityManager.storePeerMPAN(ctx.sourceNodeId, mcctx.groupId, { type: MPANState.OutOfSync });
978
- failNoMPAN();
1092
+ // If authentication fails, do so with an error code that instructs the
1093
+ // applHost to tell the node we have no nonce
1094
+ if (!authOK || !plaintext) {
1095
+ if (mcctx.isMulticast) {
1096
+ // Mark the MPAN as out of sync
1097
+ securityManager.storePeerMPAN(ctx.sourceNodeId, mcctx.groupId, { type: MPANState.OutOfSync });
1098
+ validatePayload.fail(ZWaveErrorCodes.Security2CC_CannotDecodeMulticast);
1099
+ }
1100
+ else {
1101
+ validatePayload.fail(ZWaveErrorCodes.Security2CC_CannotDecode);
1102
+ }
979
1103
  }
980
- decrypt = () => decryptMulticast(ctx.sourceNodeId, securityManager, mcctx.groupId, ciphertext, authData, authTag);
981
- }
982
- else {
983
- // Decrypt payload and verify integrity
984
- const spanState = securityManager.getSPANState(ctx.sourceNodeId);
985
- // If we are not able to establish an SPAN yet, fail the decryption
986
- if (spanState.type === SPANState.None) {
987
- failNoSPAN();
1104
+ else if (!mcctx.isMulticast && mcctx.groupId != undefined) {
1105
+ // After reception of a singlecast followup, the MPAN state must be increased
1106
+ securityManager.tryIncrementPeerMPAN(ctx.sourceNodeId, mcctx.groupId);
988
1107
  }
989
- else if (spanState.type === SPANState.RemoteEI) {
990
- // TODO: The specs are not clear how to handle this case
991
- // For now, do the same as if we didn't have any EI
992
- failNoSPAN();
1108
+ // Remember which security class was used to decrypt this message, so we can discard it later
1109
+ const securityClass = decryptionSecurityClass;
1110
+ offset = 0;
1111
+ if (hasEncryptedExtensions)
1112
+ parseExtensions(plaintext, true);
1113
+ // Before we can continue, check if the command must be discarded
1114
+ if (mustDiscardCommand) {
1115
+ validatePayload.fail("Invalid extension");
993
1116
  }
994
- decrypt = () => decryptSinglecast(ctx, securityManager, ctx.sourceNodeId, sequenceNumber, prevSequenceNumber, ciphertext, authData, authTag, spanState, extensions);
995
- }
996
- let plaintext;
997
- let authOK = false;
998
- let key;
999
- let iv;
1000
- let decryptionSecurityClass;
1001
- // If the Receiver is unable to authenticate the singlecast message with the current SPAN,
1002
- // the Receiver SHOULD try decrypting the message with one or more of the following SPAN values,
1003
- // stopping when decryption is successful or the maximum number of iterations is reached.
1004
- // If the Receiver is unable to decrypt the S2 MC frame with the current MPAN, the Receiver MAY try
1005
- // decrypting the frame with one or more of the subsequent MPAN values, stopping when decryption is
1006
- // successful or the maximum number of iterations is reached.
1007
- const decryptAttempts = mcctx.isMulticast
1008
- ? MAX_DECRYPT_ATTEMPTS_MULTICAST
1009
- : mcctx.groupId != undefined
1010
- ? MAX_DECRYPT_ATTEMPTS_SC_FOLLOWUP
1011
- : MAX_DECRYPT_ATTEMPTS_SINGLECAST;
1012
- for (let i = 0; i < decryptAttempts; i++) {
1013
- ({
1014
- plaintext,
1015
- authOK,
1016
- key,
1017
- iv,
1018
- securityClass: decryptionSecurityClass,
1019
- } = decrypt());
1020
- if (!!authOK && !!plaintext)
1021
- break;
1022
- // No need to try further SPANs if we just got the sender's EI
1023
- if (!!getSenderEI(extensions))
1024
- break;
1025
- }
1026
- // If authentication fails, do so with an error code that instructs the
1027
- // applHost to tell the node we have no nonce
1028
- if (!authOK || !plaintext) {
1029
- if (mcctx.isMulticast) {
1030
- // Mark the MPAN as out of sync
1031
- securityManager.storePeerMPAN(ctx.sourceNodeId, mcctx.groupId, { type: MPANState.OutOfSync });
1032
- validatePayload.fail(ZWaveErrorCodes.Security2CC_CannotDecodeMulticast);
1117
+ // If the MPAN extension was received, store the MPAN
1118
+ if (!mcctx.isMulticast) {
1119
+ const mpanExtension = extensions.find((e) => e instanceof MPANExtension);
1120
+ if (mpanExtension) {
1121
+ securityManager.storePeerMPAN(ctx.sourceNodeId, mpanExtension.groupId, {
1122
+ type: MPANState.MPAN,
1123
+ currentMPAN: mpanExtension.innerMPANState,
1124
+ });
1125
+ }
1033
1126
  }
1034
- else {
1035
- validatePayload.fail(ZWaveErrorCodes.Security2CC_CannotDecode);
1127
+ // Not every S2 message includes an encapsulated CC
1128
+ const decryptedCCBytes = plaintext.subarray(offset);
1129
+ let encapsulated;
1130
+ if (decryptedCCBytes.length > 0) {
1131
+ // make sure this contains a complete CC command that's worth splitting
1132
+ validatePayload(decryptedCCBytes.length >= 2);
1133
+ // and deserialize the CC
1134
+ encapsulated = CommandClass.parse(decryptedCCBytes, ctx);
1036
1135
  }
1136
+ const ret = new Security2CCMessageEncapsulation({
1137
+ nodeId: ctx.sourceNodeId,
1138
+ sequenceNumber,
1139
+ securityClass,
1140
+ extensions,
1141
+ encapsulated,
1142
+ });
1143
+ // Remember for debugging purposes
1144
+ ret.key = key;
1145
+ ret.iv = iv;
1146
+ ret.authData = authData;
1147
+ ret.authTag = authTag;
1148
+ ret.plaintext = decryptedCCBytes;
1149
+ return ret;
1037
1150
  }
1038
- else if (!mcctx.isMulticast && mcctx.groupId != undefined) {
1039
- // After reception of a singlecast followup, the MPAN state must be increased
1040
- securityManager.tryIncrementPeerMPAN(ctx.sourceNodeId, mcctx.groupId);
1041
- }
1042
- // Remember which security class was used to decrypt this message, so we can discard it later
1043
- const securityClass = decryptionSecurityClass;
1044
- offset = 0;
1045
- if (hasEncryptedExtensions)
1046
- parseExtensions(plaintext, true);
1047
- // Before we can continue, check if the command must be discarded
1048
- if (mustDiscardCommand) {
1049
- validatePayload.fail("Invalid extension");
1050
- }
1051
- // If the MPAN extension was received, store the MPAN
1052
- if (!mcctx.isMulticast) {
1053
- const mpanExtension = extensions.find((e) => e instanceof MPANExtension);
1054
- if (mpanExtension) {
1055
- securityManager.storePeerMPAN(ctx.sourceNodeId, mpanExtension.groupId, {
1056
- type: MPANState.MPAN,
1057
- currentMPAN: mpanExtension.innerMPANState,
1058
- });
1151
+ securityClass;
1152
+ // Only used for testing/debugging purposes
1153
+ key;
1154
+ iv;
1155
+ authData;
1156
+ authTag;
1157
+ ciphertext;
1158
+ plaintext;
1159
+ verifyDelivery = true;
1160
+ sequenceNumber;
1161
+ ensureSequenceNumber(securityManager) {
1162
+ if (this.sequenceNumber == undefined) {
1163
+ if (this.isSinglecast()) {
1164
+ this.sequenceNumber = securityManager.nextSequenceNumber(this.nodeId);
1165
+ }
1166
+ else {
1167
+ const groupId = getDestinationIDTX.call(this);
1168
+ this.sequenceNumber = securityManager
1169
+ .nextMulticastSequenceNumber(groupId);
1170
+ }
1059
1171
  }
1060
1172
  }
1061
- // Not every S2 message includes an encapsulated CC
1062
- const decryptedCCBytes = plaintext.subarray(offset);
1063
- let encapsulated;
1064
- if (decryptedCCBytes.length > 0) {
1065
- // make sure this contains a complete CC command that's worth splitting
1066
- validatePayload(decryptedCCBytes.length >= 2);
1067
- // and deserialize the CC
1068
- encapsulated = CommandClass.parse(decryptedCCBytes, ctx);
1069
- }
1070
- const ret = new Security2CCMessageEncapsulation_1({
1071
- nodeId: ctx.sourceNodeId,
1072
- sequenceNumber,
1073
- securityClass,
1074
- extensions,
1075
- encapsulated,
1076
- });
1077
- // Remember for debugging purposes
1078
- ret.key = key;
1079
- ret.iv = iv;
1080
- ret.authData = authData;
1081
- ret.authTag = authTag;
1082
- ret.plaintext = decryptedCCBytes;
1083
- return ret;
1084
- }
1085
- securityClass;
1086
- // Only used for testing/debugging purposes
1087
- key;
1088
- iv;
1089
- authData;
1090
- authTag;
1091
- ciphertext;
1092
- plaintext;
1093
- verifyDelivery = true;
1094
- sequenceNumber;
1095
- ensureSequenceNumber(securityManager) {
1096
- if (this.sequenceNumber == undefined) {
1173
+ encapsulated;
1174
+ extensions;
1175
+ prepareRetransmission() {
1176
+ super.prepareRetransmission();
1177
+ this.sequenceNumber = undefined;
1178
+ }
1179
+ hasMOSExtension() {
1180
+ return this.extensions.some((e) => e instanceof MOSExtension);
1181
+ }
1182
+ /** Returns the Sender's Entropy Input if this command contains an SPAN extension */
1183
+ getSenderEI() {
1184
+ return getSenderEI(this.extensions);
1185
+ }
1186
+ /** Returns the multicast group ID if this command contains an MGRP extension */
1187
+ getMulticastGroupId() {
1188
+ return getMulticastGroupId(this.extensions);
1189
+ }
1190
+ maybeAddSPANExtension(ctx, securityManager) {
1191
+ if (!this.isSinglecast())
1192
+ return;
1193
+ const receiverNodeId = this.nodeId;
1194
+ const spanState = securityManager.getSPANState(receiverNodeId);
1195
+ if (spanState.type === SPANState.None
1196
+ || spanState.type === SPANState.LocalEI) {
1197
+ // Can't do anything here if we don't have the receiver's EI
1198
+ throw new ZWaveError(`Security S2 CC requires the receiver's nonce to be sent!`, ZWaveErrorCodes.Security2CC_NoSPAN);
1199
+ }
1200
+ else if (spanState.type === SPANState.RemoteEI) {
1201
+ // We have the receiver's EI, generate our input and send it over
1202
+ // With both, we can create an SPAN
1203
+ const senderEI = securityManager.generateNonce(undefined);
1204
+ const receiverEI = spanState.receiverEI;
1205
+ // While bootstrapping a node, prefer the temporary key, unless the
1206
+ // specific command specifies a security class
1207
+ if (this.securityClass == undefined
1208
+ && securityManager.tempKeys.has(receiverNodeId)) {
1209
+ securityManager.initializeTempSPAN(receiverNodeId, senderEI, receiverEI);
1210
+ }
1211
+ else {
1212
+ const securityClass = this.securityClass
1213
+ ?? ctx.getHighestSecurityClass(receiverNodeId);
1214
+ if (securityClass == undefined) {
1215
+ throw new ZWaveError("No security class defined for this command!", ZWaveErrorCodes.Security2CC_NoSPAN);
1216
+ }
1217
+ securityManager.initializeSPAN(receiverNodeId, securityClass, senderEI, receiverEI);
1218
+ }
1219
+ // Add or update the SPAN extension
1220
+ let spanExtension = this.extensions.find((e) => e instanceof SPANExtension);
1221
+ if (spanExtension) {
1222
+ spanExtension.senderEI = senderEI;
1223
+ }
1224
+ else {
1225
+ spanExtension = new SPANExtension({ senderEI });
1226
+ this.extensions.push(spanExtension);
1227
+ }
1228
+ }
1229
+ }
1230
+ serialize(ctx) {
1231
+ const securityManager = assertSecurityTX(ctx, this.nodeId);
1232
+ this.ensureSequenceNumber(securityManager);
1233
+ // Include Sender EI in the command if we only have the receiver's EI
1234
+ this.maybeAddSPANExtension(ctx, securityManager);
1235
+ const unencryptedExtensions = this.extensions.filter((e) => !e.isEncrypted());
1236
+ const encryptedExtensions = this.extensions.filter((e) => e.isEncrypted());
1237
+ const unencryptedPayload = Bytes.concat([
1238
+ Bytes.from([
1239
+ this.sequenceNumber,
1240
+ (encryptedExtensions.length > 0 ? 0b10 : 0)
1241
+ | (unencryptedExtensions.length > 0 ? 1 : 0),
1242
+ ]),
1243
+ ...unencryptedExtensions.map((e, index) => e.serialize(index < unencryptedExtensions.length - 1)),
1244
+ ]);
1245
+ const serializedCC = this.encapsulated?.serialize(ctx)
1246
+ ?? new Bytes();
1247
+ const plaintextPayload = Bytes.concat([
1248
+ ...encryptedExtensions.map((e, index) => e.serialize(index < encryptedExtensions.length - 1)),
1249
+ serializedCC,
1250
+ ]);
1251
+ // Generate the authentication data for CCM encryption
1252
+ const destinationTag = getDestinationIDTX.call(this);
1253
+ const messageLength = this.computeEncapsulationOverhead()
1254
+ + serializedCC.length;
1255
+ const authData = getAuthenticationData(ctx.ownNodeId, destinationTag, ctx.homeId, messageLength, unencryptedPayload);
1256
+ let key;
1257
+ let iv;
1097
1258
  if (this.isSinglecast()) {
1098
- this.sequenceNumber = securityManager.nextSequenceNumber(this.nodeId);
1259
+ // Singlecast:
1260
+ // Generate a nonce for encryption, and remember it to attempt decryption
1261
+ // of potential in-flight messages from the target node.
1262
+ iv = securityManager.nextNonce(this.nodeId, true);
1263
+ const { keyCCM } =
1264
+ // Prefer the overridden security class if it was given
1265
+ this.securityClass != undefined
1266
+ ? securityManager.getKeysForSecurityClass(this.securityClass)
1267
+ : securityManager.getKeysForNode(this.nodeId);
1268
+ key = keyCCM;
1099
1269
  }
1100
1270
  else {
1101
- const groupId = getDestinationIDTX.call(this);
1102
- this.sequenceNumber = securityManager
1103
- .nextMulticastSequenceNumber(groupId);
1271
+ // Multicast:
1272
+ const keyAndIV = securityManager.getMulticastKeyAndIV(destinationTag);
1273
+ key = keyAndIV.key;
1274
+ iv = keyAndIV.iv;
1104
1275
  }
1276
+ const { ciphertext: ciphertextPayload, authTag } = encryptAES128CCM(key, iv, plaintextPayload, authData, SECURITY_S2_AUTH_TAG_LENGTH);
1277
+ // Remember key and IV for debugging purposes
1278
+ this.key = key;
1279
+ this.iv = iv;
1280
+ this.authData = authData;
1281
+ this.authTag = authTag;
1282
+ this.ciphertext = ciphertextPayload;
1283
+ this.payload = Bytes.concat([
1284
+ unencryptedPayload,
1285
+ ciphertextPayload,
1286
+ authTag,
1287
+ ]);
1288
+ return super.serialize(ctx);
1105
1289
  }
1106
- }
1107
- encapsulated;
1108
- extensions;
1109
- prepareRetransmission() {
1110
- super.prepareRetransmission();
1111
- this.sequenceNumber = undefined;
1112
- }
1113
- hasMOSExtension() {
1114
- return this.extensions.some((e) => e instanceof MOSExtension);
1115
- }
1116
- /** Returns the Sender's Entropy Input if this command contains an SPAN extension */
1117
- getSenderEI() {
1118
- return getSenderEI(this.extensions);
1119
- }
1120
- /** Returns the multicast group ID if this command contains an MGRP extension */
1121
- getMulticastGroupId() {
1122
- return getMulticastGroupId(this.extensions);
1123
- }
1124
- maybeAddSPANExtension(ctx, securityManager) {
1125
- if (!this.isSinglecast())
1126
- return;
1127
- const receiverNodeId = this.nodeId;
1128
- const spanState = securityManager.getSPANState(receiverNodeId);
1129
- if (spanState.type === SPANState.None
1130
- || spanState.type === SPANState.LocalEI) {
1131
- // Can't do anything here if we don't have the receiver's EI
1132
- throw new ZWaveError(`Security S2 CC requires the receiver's nonce to be sent!`, ZWaveErrorCodes.Security2CC_NoSPAN);
1133
- }
1134
- else if (spanState.type === SPANState.RemoteEI) {
1135
- // We have the receiver's EI, generate our input and send it over
1136
- // With both, we can create an SPAN
1137
- const senderEI = securityManager.generateNonce(undefined);
1138
- const receiverEI = spanState.receiverEI;
1139
- // While bootstrapping a node, prefer the temporary key, unless the
1140
- // specific command specifies a security class
1141
- if (this.securityClass == undefined
1142
- && securityManager.tempKeys.has(receiverNodeId)) {
1143
- securityManager.initializeTempSPAN(receiverNodeId, senderEI, receiverEI);
1290
+ computeEncapsulationOverhead() {
1291
+ // Security S2 adds:
1292
+ // * 1 byte sequence number
1293
+ // * 1 byte control
1294
+ // * N bytes extensions
1295
+ // * SECURITY_S2_AUTH_TAG_LENGTH bytes auth tag
1296
+ const extensionBytes = this.extensions
1297
+ .map((e) => e.computeLength())
1298
+ .reduce((a, b) => a + b, 0);
1299
+ return (super.computeEncapsulationOverhead()
1300
+ + 2
1301
+ + SECURITY_S2_AUTH_TAG_LENGTH
1302
+ + extensionBytes);
1303
+ }
1304
+ toLogEntry(ctx) {
1305
+ const message = {
1306
+ "sequence number": this.sequenceNumber ?? "(not set)",
1307
+ };
1308
+ if (this.extensions.length > 0) {
1309
+ message.extensions = this.extensions
1310
+ .map((e) => e.toLogEntry())
1311
+ .join("");
1144
1312
  }
1145
- else {
1146
- const securityClass = this.securityClass
1147
- ?? ctx.getHighestSecurityClass(receiverNodeId);
1148
- if (securityClass == undefined) {
1149
- throw new ZWaveError("No security class defined for this command!", ZWaveErrorCodes.Security2CC_NoSPAN);
1313
+ // Log the used keys in integration tests
1314
+ if (process.env.NODE_ENV === "test"
1315
+ || process.env.NODE_ENV === "development") {
1316
+ if (this.key) {
1317
+ message.key = buffer2hex(this.key);
1318
+ }
1319
+ if (this.iv) {
1320
+ message.IV = buffer2hex(this.iv);
1321
+ }
1322
+ if (this.ciphertext) {
1323
+ message.ciphertext = buffer2hex(this.ciphertext);
1324
+ }
1325
+ else if (this.plaintext) {
1326
+ message.plaintext = buffer2hex(this.plaintext);
1327
+ }
1328
+ if (this.authData) {
1329
+ message["auth data"] = buffer2hex(this.authData);
1330
+ }
1331
+ if (this.authTag) {
1332
+ message["auth tag"] = buffer2hex(this.authTag);
1150
1333
  }
1151
- securityManager.initializeSPAN(receiverNodeId, securityClass, senderEI, receiverEI);
1152
- }
1153
- // Add or update the SPAN extension
1154
- let spanExtension = this.extensions.find((e) => e instanceof SPANExtension);
1155
- if (spanExtension) {
1156
- spanExtension.senderEI = senderEI;
1157
1334
  }
1158
- else {
1159
- spanExtension = new SPANExtension({ senderEI });
1160
- this.extensions.push(spanExtension);
1335
+ if (this.securityClass != undefined) {
1336
+ message["security class"] = getEnumMemberName(SecurityClass, this.securityClass);
1161
1337
  }
1338
+ return {
1339
+ ...super.toLogEntry(ctx),
1340
+ message,
1341
+ };
1162
1342
  }
1163
- }
1164
- serialize(ctx) {
1165
- const securityManager = assertSecurityTX(ctx, this.nodeId);
1166
- this.ensureSequenceNumber(securityManager);
1167
- // Include Sender EI in the command if we only have the receiver's EI
1168
- this.maybeAddSPANExtension(ctx, securityManager);
1169
- const unencryptedExtensions = this.extensions.filter((e) => !e.isEncrypted());
1170
- const encryptedExtensions = this.extensions.filter((e) => e.isEncrypted());
1171
- const unencryptedPayload = Bytes.concat([
1172
- Bytes.from([
1173
- this.sequenceNumber,
1174
- (encryptedExtensions.length > 0 ? 0b10 : 0)
1175
- | (unencryptedExtensions.length > 0 ? 1 : 0),
1176
- ]),
1177
- ...unencryptedExtensions.map((e, index) => e.serialize(index < unencryptedExtensions.length - 1)),
1178
- ]);
1179
- const serializedCC = this.encapsulated?.serialize(ctx)
1180
- ?? new Bytes();
1181
- const plaintextPayload = Bytes.concat([
1182
- ...encryptedExtensions.map((e, index) => e.serialize(index < encryptedExtensions.length - 1)),
1183
- serializedCC,
1184
- ]);
1185
- // Generate the authentication data for CCM encryption
1186
- const destinationTag = getDestinationIDTX.call(this);
1187
- const messageLength = this.computeEncapsulationOverhead()
1188
- + serializedCC.length;
1189
- const authData = getAuthenticationData(ctx.ownNodeId, destinationTag, ctx.homeId, messageLength, unencryptedPayload);
1190
- let key;
1191
- let iv;
1192
- if (this.isSinglecast()) {
1193
- // Singlecast:
1194
- // Generate a nonce for encryption, and remember it to attempt decryption
1195
- // of potential in-flight messages from the target node.
1196
- iv = securityManager.nextNonce(this.nodeId, true);
1197
- const { keyCCM } =
1198
- // Prefer the overridden security class if it was given
1199
- this.securityClass != undefined
1200
- ? securityManager.getKeysForSecurityClass(this.securityClass)
1201
- : securityManager.getKeysForNode(this.nodeId);
1202
- key = keyCCM;
1343
+ };
1344
+ return Security2CCMessageEncapsulation = _classThis;
1345
+ })();
1346
+ export { Security2CCMessageEncapsulation };
1347
+ let Security2CCNonceReport = (() => {
1348
+ let _classDecorators = [CCCommand(Security2Command.NonceReport)];
1349
+ let _classDescriptor;
1350
+ let _classExtraInitializers = [];
1351
+ let _classThis;
1352
+ let _classSuper = Security2CC;
1353
+ var Security2CCNonceReport = class extends _classSuper {
1354
+ static { _classThis = this; }
1355
+ static {
1356
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
1357
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
1358
+ Security2CCNonceReport = _classThis = _classDescriptor.value;
1359
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
1360
+ __runInitializers(_classThis, _classExtraInitializers);
1203
1361
  }
1204
- else {
1205
- // Multicast:
1206
- const keyAndIV = securityManager.getMulticastKeyAndIV(destinationTag);
1207
- key = keyAndIV.key;
1208
- iv = keyAndIV.iv;
1209
- }
1210
- const { ciphertext: ciphertextPayload, authTag } = encryptAES128CCM(key, iv, plaintextPayload, authData, SECURITY_S2_AUTH_TAG_LENGTH);
1211
- // Remember key and IV for debugging purposes
1212
- this.key = key;
1213
- this.iv = iv;
1214
- this.authData = authData;
1215
- this.authTag = authTag;
1216
- this.ciphertext = ciphertextPayload;
1217
- this.payload = Bytes.concat([
1218
- unencryptedPayload,
1219
- ciphertextPayload,
1220
- authTag,
1221
- ]);
1222
- return super.serialize(ctx);
1223
- }
1224
- computeEncapsulationOverhead() {
1225
- // Security S2 adds:
1226
- // * 1 byte sequence number
1227
- // * 1 byte control
1228
- // * N bytes extensions
1229
- // * SECURITY_S2_AUTH_TAG_LENGTH bytes auth tag
1230
- const extensionBytes = this.extensions
1231
- .map((e) => e.computeLength())
1232
- .reduce((a, b) => a + b, 0);
1233
- return (super.computeEncapsulationOverhead()
1234
- + 2
1235
- + SECURITY_S2_AUTH_TAG_LENGTH
1236
- + extensionBytes);
1237
- }
1238
- toLogEntry(ctx) {
1239
- const message = {
1240
- "sequence number": this.sequenceNumber ?? "(not set)",
1241
- };
1242
- if (this.extensions.length > 0) {
1243
- message.extensions = this.extensions
1244
- .map((e) => e.toLogEntry())
1245
- .join("");
1246
- }
1247
- // Log the used keys in integration tests
1248
- if (process.env.NODE_ENV === "test"
1249
- || process.env.NODE_ENV === "development") {
1250
- if (this.key) {
1251
- message.key = buffer2hex(this.key);
1362
+ constructor(options) {
1363
+ super(options);
1364
+ this.SOS = options.SOS;
1365
+ this.MOS = options.MOS;
1366
+ this.sequenceNumber = options.sequenceNumber;
1367
+ if (options.SOS)
1368
+ this.receiverEI = options.receiverEI;
1369
+ }
1370
+ static from(raw, ctx) {
1371
+ // Make sure that we can send/receive secure commands
1372
+ const securityManager = assertSecurityRX(ctx);
1373
+ validatePayload(raw.payload.length >= 2);
1374
+ const sequenceNumber = raw.payload[0];
1375
+ // Don't accept duplicate commands
1376
+ validateSequenceNumber(securityManager, ctx.sourceNodeId, sequenceNumber);
1377
+ const MOS = !!(raw.payload[1] & 0b10);
1378
+ const SOS = !!(raw.payload[1] & 0b1);
1379
+ if (SOS) {
1380
+ // If the SOS flag is set, the REI field MUST be included in the command
1381
+ validatePayload(raw.payload.length >= 18);
1382
+ const receiverEI = raw.payload.subarray(2, 18);
1383
+ // In that case we also need to store it, so the next sent command
1384
+ // can use it for encryption
1385
+ securityManager.storeRemoteEI(ctx.sourceNodeId, receiverEI);
1386
+ return new this({
1387
+ nodeId: ctx.sourceNodeId,
1388
+ sequenceNumber,
1389
+ MOS,
1390
+ SOS,
1391
+ receiverEI,
1392
+ });
1252
1393
  }
1253
- if (this.iv) {
1254
- message.IV = buffer2hex(this.iv);
1394
+ else if (MOS) {
1395
+ return new this({
1396
+ nodeId: ctx.sourceNodeId,
1397
+ sequenceNumber,
1398
+ MOS,
1399
+ SOS: false,
1400
+ });
1255
1401
  }
1256
- if (this.ciphertext) {
1257
- message.ciphertext = buffer2hex(this.ciphertext);
1402
+ else {
1403
+ validatePayload.fail("Either MOS or SOS must be set");
1258
1404
  }
1259
- else if (this.plaintext) {
1260
- message.plaintext = buffer2hex(this.plaintext);
1405
+ }
1406
+ sequenceNumber;
1407
+ ensureSequenceNumber(securityManager) {
1408
+ if (this.sequenceNumber == undefined) {
1409
+ this.sequenceNumber = securityManager.nextSequenceNumber(this.nodeId);
1261
1410
  }
1262
- if (this.authData) {
1263
- message["auth data"] = buffer2hex(this.authData);
1411
+ }
1412
+ SOS;
1413
+ MOS;
1414
+ receiverEI;
1415
+ serialize(ctx) {
1416
+ const securityManager = assertSecurityTX(ctx, this.nodeId);
1417
+ this.ensureSequenceNumber(securityManager);
1418
+ this.payload = Bytes.from([
1419
+ this.sequenceNumber,
1420
+ (this.MOS ? 0b10 : 0) + (this.SOS ? 0b1 : 0),
1421
+ ]);
1422
+ if (this.SOS) {
1423
+ this.payload = Bytes.concat([this.payload, this.receiverEI]);
1264
1424
  }
1265
- if (this.authTag) {
1266
- message["auth tag"] = buffer2hex(this.authTag);
1425
+ return super.serialize(ctx);
1426
+ }
1427
+ toLogEntry(ctx) {
1428
+ const message = {
1429
+ "sequence number": this.sequenceNumber ?? "(not set)",
1430
+ SOS: this.SOS,
1431
+ MOS: this.MOS,
1432
+ };
1433
+ if (this.receiverEI) {
1434
+ message["receiver entropy"] = buffer2hex(this.receiverEI);
1267
1435
  }
1436
+ return {
1437
+ ...super.toLogEntry(ctx),
1438
+ message,
1439
+ };
1268
1440
  }
1269
- if (this.securityClass != undefined) {
1270
- message["security class"] = getEnumMemberName(SecurityClass, this.securityClass);
1441
+ };
1442
+ return Security2CCNonceReport = _classThis;
1443
+ })();
1444
+ export { Security2CCNonceReport };
1445
+ let Security2CCNonceGet = (() => {
1446
+ let _classDecorators = [CCCommand(Security2Command.NonceGet), expectedCCResponse(Security2CCNonceReport)];
1447
+ let _classDescriptor;
1448
+ let _classExtraInitializers = [];
1449
+ let _classThis;
1450
+ let _classSuper = Security2CC;
1451
+ var Security2CCNonceGet = class extends _classSuper {
1452
+ static { _classThis = this; }
1453
+ static {
1454
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
1455
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
1456
+ Security2CCNonceGet = _classThis = _classDescriptor.value;
1457
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
1458
+ __runInitializers(_classThis, _classExtraInitializers);
1271
1459
  }
1272
- return {
1273
- ...super.toLogEntry(ctx),
1274
- message,
1275
- };
1276
- }
1277
- };
1278
- Security2CCMessageEncapsulation = Security2CCMessageEncapsulation_1 = __decorate([
1279
- CCCommand(Security2Command.MessageEncapsulation),
1280
- expectedCCResponse(getCCResponseForMessageEncapsulation, testCCResponseForMessageEncapsulation)
1281
- ], Security2CCMessageEncapsulation);
1282
- export { Security2CCMessageEncapsulation };
1283
- let Security2CCNonceReport = Security2CCNonceReport_1 = class Security2CCNonceReport extends Security2CC {
1284
- constructor(options) {
1285
- super(options);
1286
- this.SOS = options.SOS;
1287
- this.MOS = options.MOS;
1288
- this.sequenceNumber = options.sequenceNumber;
1289
- if (options.SOS)
1290
- this.receiverEI = options.receiverEI;
1291
- }
1292
- static from(raw, ctx) {
1293
- // Make sure that we can send/receive secure commands
1294
- const securityManager = assertSecurityRX(ctx);
1295
- validatePayload(raw.payload.length >= 2);
1296
- const sequenceNumber = raw.payload[0];
1297
- // Don't accept duplicate commands
1298
- validateSequenceNumber(securityManager, ctx.sourceNodeId, sequenceNumber);
1299
- const MOS = !!(raw.payload[1] & 0b10);
1300
- const SOS = !!(raw.payload[1] & 0b1);
1301
- if (SOS) {
1302
- // If the SOS flag is set, the REI field MUST be included in the command
1303
- validatePayload(raw.payload.length >= 18);
1304
- const receiverEI = raw.payload.subarray(2, 18);
1305
- // In that case we also need to store it, so the next sent command
1306
- // can use it for encryption
1307
- securityManager.storeRemoteEI(ctx.sourceNodeId, receiverEI);
1308
- return new Security2CCNonceReport_1({
1309
- nodeId: ctx.sourceNodeId,
1310
- sequenceNumber,
1311
- MOS,
1312
- SOS,
1313
- receiverEI,
1314
- });
1460
+ // TODO: A node sending this command MUST accept a delay up to <Previous Round-trip-time to peer node> +
1461
+ // 250 ms before receiving the Security 2 Nonce Report Command.
1462
+ constructor(options) {
1463
+ super(options);
1464
+ this.sequenceNumber = options.sequenceNumber;
1315
1465
  }
1316
- else if (MOS) {
1317
- return new Security2CCNonceReport_1({
1466
+ static from(raw, ctx) {
1467
+ const securityManager = assertSecurityRX(ctx);
1468
+ validatePayload(raw.payload.length >= 1);
1469
+ const sequenceNumber = raw.payload[0];
1470
+ // Don't accept duplicate commands
1471
+ validateSequenceNumber(securityManager, ctx.sourceNodeId, sequenceNumber);
1472
+ return new this({
1318
1473
  nodeId: ctx.sourceNodeId,
1319
1474
  sequenceNumber,
1320
- MOS,
1321
- SOS: false,
1322
1475
  });
1323
1476
  }
1324
- else {
1325
- validatePayload.fail("Either MOS or SOS must be set");
1326
- }
1327
- }
1328
- sequenceNumber;
1329
- ensureSequenceNumber(securityManager) {
1330
- if (this.sequenceNumber == undefined) {
1331
- this.sequenceNumber = securityManager.nextSequenceNumber(this.nodeId);
1477
+ sequenceNumber;
1478
+ ensureSequenceNumber(securityManager) {
1479
+ if (this.sequenceNumber == undefined) {
1480
+ this.sequenceNumber = securityManager.nextSequenceNumber(this.nodeId);
1481
+ }
1332
1482
  }
1333
- }
1334
- SOS;
1335
- MOS;
1336
- receiverEI;
1337
- serialize(ctx) {
1338
- const securityManager = assertSecurityTX(ctx, this.nodeId);
1339
- this.ensureSequenceNumber(securityManager);
1340
- this.payload = Bytes.from([
1341
- this.sequenceNumber,
1342
- (this.MOS ? 0b10 : 0) + (this.SOS ? 0b1 : 0),
1343
- ]);
1344
- if (this.SOS) {
1345
- this.payload = Bytes.concat([this.payload, this.receiverEI]);
1346
- }
1347
- return super.serialize(ctx);
1348
- }
1349
- toLogEntry(ctx) {
1350
- const message = {
1351
- "sequence number": this.sequenceNumber ?? "(not set)",
1352
- SOS: this.SOS,
1353
- MOS: this.MOS,
1354
- };
1355
- if (this.receiverEI) {
1356
- message["receiver entropy"] = buffer2hex(this.receiverEI);
1483
+ serialize(ctx) {
1484
+ const securityManager = assertSecurityTX(ctx, this.nodeId);
1485
+ this.ensureSequenceNumber(securityManager);
1486
+ this.payload = Bytes.from([this.sequenceNumber]);
1487
+ return super.serialize(ctx);
1357
1488
  }
1358
- return {
1359
- ...super.toLogEntry(ctx),
1360
- message,
1361
- };
1362
- }
1363
- };
1364
- Security2CCNonceReport = Security2CCNonceReport_1 = __decorate([
1365
- CCCommand(Security2Command.NonceReport)
1366
- ], Security2CCNonceReport);
1367
- export { Security2CCNonceReport };
1368
- let Security2CCNonceGet = Security2CCNonceGet_1 = class Security2CCNonceGet extends Security2CC {
1369
- // TODO: A node sending this command MUST accept a delay up to <Previous Round-trip-time to peer node> +
1370
- // 250 ms before receiving the Security 2 Nonce Report Command.
1371
- constructor(options) {
1372
- super(options);
1373
- this.sequenceNumber = options.sequenceNumber;
1374
- }
1375
- static from(raw, ctx) {
1376
- const securityManager = assertSecurityRX(ctx);
1377
- validatePayload(raw.payload.length >= 1);
1378
- const sequenceNumber = raw.payload[0];
1379
- // Don't accept duplicate commands
1380
- validateSequenceNumber(securityManager, ctx.sourceNodeId, sequenceNumber);
1381
- return new Security2CCNonceGet_1({
1382
- nodeId: ctx.sourceNodeId,
1383
- sequenceNumber,
1384
- });
1385
- }
1386
- sequenceNumber;
1387
- ensureSequenceNumber(securityManager) {
1388
- if (this.sequenceNumber == undefined) {
1389
- this.sequenceNumber = securityManager.nextSequenceNumber(this.nodeId);
1489
+ toLogEntry(ctx) {
1490
+ return {
1491
+ ...super.toLogEntry(ctx),
1492
+ message: {
1493
+ "sequence number": this.sequenceNumber ?? "(not set)",
1494
+ },
1495
+ };
1390
1496
  }
1391
- }
1392
- serialize(ctx) {
1393
- const securityManager = assertSecurityTX(ctx, this.nodeId);
1394
- this.ensureSequenceNumber(securityManager);
1395
- this.payload = Bytes.from([this.sequenceNumber]);
1396
- return super.serialize(ctx);
1397
- }
1398
- toLogEntry(ctx) {
1399
- return {
1400
- ...super.toLogEntry(ctx),
1401
- message: {
1402
- "sequence number": this.sequenceNumber ?? "(not set)",
1403
- },
1404
- };
1405
- }
1406
- };
1407
- Security2CCNonceGet = Security2CCNonceGet_1 = __decorate([
1408
- CCCommand(Security2Command.NonceGet),
1409
- expectedCCResponse(Security2CCNonceReport)
1410
- ], Security2CCNonceGet);
1497
+ };
1498
+ return Security2CCNonceGet = _classThis;
1499
+ })();
1411
1500
  export { Security2CCNonceGet };
1412
- let Security2CCKEXReport = Security2CCKEXReport_1 = class Security2CCKEXReport extends Security2CC {
1413
- constructor(options) {
1414
- super(options);
1415
- this.requestCSA = options.requestCSA;
1416
- this.echo = options.echo;
1417
- this._reserved = options._reserved ?? 0;
1418
- this.supportedKEXSchemes = options.supportedKEXSchemes;
1419
- this.supportedECDHProfiles = options.supportedECDHProfiles;
1420
- this.requestedKeys = options.requestedKeys;
1421
- }
1422
- static from(raw, ctx) {
1423
- validatePayload(raw.payload.length >= 4);
1424
- const requestCSA = !!(raw.payload[0] & 0b10);
1425
- const echo = !!(raw.payload[0] & 0b1);
1426
- // Remember the reserved bits for the echo
1427
- const _reserved = raw.payload[0] & 0b1111_1100;
1428
- // The bit mask starts at 0, but bit 0 is not used
1429
- const supportedKEXSchemes = parseBitMask(raw.payload.subarray(1, 2), 0).filter((s) => s !== 0);
1430
- const supportedECDHProfiles = parseBitMask(raw.payload.subarray(2, 3), ECDHProfiles.Curve25519);
1431
- const requestedKeys = parseBitMask(raw.payload.subarray(3, 4), SecurityClass.S2_Unauthenticated);
1432
- return new Security2CCKEXReport_1({
1433
- nodeId: ctx.sourceNodeId,
1434
- requestCSA,
1435
- echo,
1436
- _reserved,
1437
- supportedKEXSchemes,
1438
- supportedECDHProfiles,
1439
- requestedKeys,
1440
- });
1441
- }
1442
- _reserved;
1443
- requestCSA;
1444
- echo;
1445
- supportedKEXSchemes;
1446
- supportedECDHProfiles;
1447
- requestedKeys;
1448
- serialize(ctx) {
1449
- this.payload = Bytes.concat([
1450
- Bytes.from([
1451
- this._reserved
1452
- + (this.requestCSA ? 0b10 : 0)
1453
- + (this.echo ? 0b1 : 0),
1454
- ]),
1501
+ let Security2CCKEXReport = (() => {
1502
+ let _classDecorators = [CCCommand(Security2Command.KEXReport)];
1503
+ let _classDescriptor;
1504
+ let _classExtraInitializers = [];
1505
+ let _classThis;
1506
+ let _classSuper = Security2CC;
1507
+ var Security2CCKEXReport = class extends _classSuper {
1508
+ static { _classThis = this; }
1509
+ static {
1510
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
1511
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
1512
+ Security2CCKEXReport = _classThis = _classDescriptor.value;
1513
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
1514
+ __runInitializers(_classThis, _classExtraInitializers);
1515
+ }
1516
+ constructor(options) {
1517
+ super(options);
1518
+ this.requestCSA = options.requestCSA;
1519
+ this.echo = options.echo;
1520
+ this._reserved = options._reserved ?? 0;
1521
+ this.supportedKEXSchemes = options.supportedKEXSchemes;
1522
+ this.supportedECDHProfiles = options.supportedECDHProfiles;
1523
+ this.requestedKeys = options.requestedKeys;
1524
+ }
1525
+ static from(raw, ctx) {
1526
+ validatePayload(raw.payload.length >= 4);
1527
+ const requestCSA = !!(raw.payload[0] & 0b10);
1528
+ const echo = !!(raw.payload[0] & 0b1);
1529
+ // Remember the reserved bits for the echo
1530
+ const _reserved = raw.payload[0] & 0b1111_1100;
1455
1531
  // The bit mask starts at 0, but bit 0 is not used
1456
- encodeBitMask(this.supportedKEXSchemes, 7, 0),
1457
- encodeBitMask(this.supportedECDHProfiles, 7, ECDHProfiles.Curve25519),
1458
- encodeBitMask(this.requestedKeys, SecurityClass.S0_Legacy, SecurityClass.S2_Unauthenticated),
1459
- ]);
1460
- return super.serialize(ctx);
1461
- }
1462
- toLogEntry(ctx) {
1463
- return {
1464
- ...super.toLogEntry(ctx),
1465
- message: {
1466
- echo: this.echo,
1467
- "supported schemes": this.supportedKEXSchemes
1468
- .map((s) => `\n· ${getEnumMemberName(KEXSchemes, s)}`)
1469
- .join(""),
1470
- "supported ECDH profiles": this.supportedECDHProfiles
1471
- .map((s) => `\n· ${getEnumMemberName(ECDHProfiles, s)}`)
1472
- .join(""),
1473
- "CSA requested": this.requestCSA,
1474
- "requested security classes": this.requestedKeys
1475
- .map((s) => `\n· ${getEnumMemberName(SecurityClass, s)}`)
1476
- .join(""),
1477
- },
1478
- };
1479
- }
1480
- };
1481
- Security2CCKEXReport = Security2CCKEXReport_1 = __decorate([
1482
- CCCommand(Security2Command.KEXReport)
1483
- ], Security2CCKEXReport);
1532
+ const supportedKEXSchemes = parseBitMask(raw.payload.subarray(1, 2), 0).filter((s) => s !== 0);
1533
+ const supportedECDHProfiles = parseBitMask(raw.payload.subarray(2, 3), ECDHProfiles.Curve25519);
1534
+ const requestedKeys = parseBitMask(raw.payload.subarray(3, 4), SecurityClass.S2_Unauthenticated);
1535
+ return new this({
1536
+ nodeId: ctx.sourceNodeId,
1537
+ requestCSA,
1538
+ echo,
1539
+ _reserved,
1540
+ supportedKEXSchemes,
1541
+ supportedECDHProfiles,
1542
+ requestedKeys,
1543
+ });
1544
+ }
1545
+ _reserved;
1546
+ requestCSA;
1547
+ echo;
1548
+ supportedKEXSchemes;
1549
+ supportedECDHProfiles;
1550
+ requestedKeys;
1551
+ serialize(ctx) {
1552
+ this.payload = Bytes.concat([
1553
+ Bytes.from([
1554
+ this._reserved
1555
+ + (this.requestCSA ? 0b10 : 0)
1556
+ + (this.echo ? 0b1 : 0),
1557
+ ]),
1558
+ // The bit mask starts at 0, but bit 0 is not used
1559
+ encodeBitMask(this.supportedKEXSchemes, 7, 0),
1560
+ encodeBitMask(this.supportedECDHProfiles, 7, ECDHProfiles.Curve25519),
1561
+ encodeBitMask(this.requestedKeys, SecurityClass.S0_Legacy, SecurityClass.S2_Unauthenticated),
1562
+ ]);
1563
+ return super.serialize(ctx);
1564
+ }
1565
+ toLogEntry(ctx) {
1566
+ return {
1567
+ ...super.toLogEntry(ctx),
1568
+ message: {
1569
+ echo: this.echo,
1570
+ "supported schemes": this.supportedKEXSchemes
1571
+ .map((s) => `\n· ${getEnumMemberName(KEXSchemes, s)}`)
1572
+ .join(""),
1573
+ "supported ECDH profiles": this.supportedECDHProfiles
1574
+ .map((s) => `\n· ${getEnumMemberName(ECDHProfiles, s)}`)
1575
+ .join(""),
1576
+ "CSA requested": this.requestCSA,
1577
+ "requested security classes": this.requestedKeys
1578
+ .map((s) => `\n· ${getEnumMemberName(SecurityClass, s)}`)
1579
+ .join(""),
1580
+ },
1581
+ };
1582
+ }
1583
+ };
1584
+ return Security2CCKEXReport = _classThis;
1585
+ })();
1484
1586
  export { Security2CCKEXReport };
1485
- let Security2CCKEXGet = class Security2CCKEXGet extends Security2CC {
1486
- };
1487
- Security2CCKEXGet = __decorate([
1488
- CCCommand(Security2Command.KEXGet),
1489
- expectedCCResponse(Security2CCKEXReport)
1490
- ], Security2CCKEXGet);
1587
+ let Security2CCKEXGet = (() => {
1588
+ let _classDecorators = [CCCommand(Security2Command.KEXGet), expectedCCResponse(Security2CCKEXReport)];
1589
+ let _classDescriptor;
1590
+ let _classExtraInitializers = [];
1591
+ let _classThis;
1592
+ let _classSuper = Security2CC;
1593
+ var Security2CCKEXGet = class extends _classSuper {
1594
+ static { _classThis = this; }
1595
+ static {
1596
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
1597
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
1598
+ Security2CCKEXGet = _classThis = _classDescriptor.value;
1599
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
1600
+ __runInitializers(_classThis, _classExtraInitializers);
1601
+ }
1602
+ };
1603
+ return Security2CCKEXGet = _classThis;
1604
+ })();
1491
1605
  export { Security2CCKEXGet };
1492
1606
  function getExpectedResponseForKEXSet(sent) {
1493
1607
  if (sent.echo) {
@@ -1508,307 +1622,420 @@ function testExpectedResponseForKEXSet(sent, received) {
1508
1622
  }
1509
1623
  return false;
1510
1624
  }
1511
- let Security2CCKEXSet = Security2CCKEXSet_1 = class Security2CCKEXSet extends Security2CC {
1512
- constructor(options) {
1513
- super(options);
1514
- this.permitCSA = options.permitCSA;
1515
- this.echo = options.echo;
1516
- this._reserved = options._reserved ?? 0;
1517
- this.selectedKEXScheme = options.selectedKEXScheme;
1518
- this.selectedECDHProfile = options.selectedECDHProfile;
1519
- this.grantedKeys = options.grantedKeys;
1520
- }
1521
- static from(raw, ctx) {
1522
- validatePayload(raw.payload.length >= 4);
1523
- const _reserved = raw.payload[0] & 0b1111_1100;
1524
- const permitCSA = !!(raw.payload[0] & 0b10);
1525
- const echo = !!(raw.payload[0] & 0b1);
1526
- // The bit mask starts at 0, but bit 0 is not used
1527
- const selectedKEXSchemes = parseBitMask(raw.payload.subarray(1, 2), 0).filter((s) => s !== 0);
1528
- validatePayload(selectedKEXSchemes.length === 1);
1529
- const selectedKEXScheme = selectedKEXSchemes[0];
1530
- const selectedECDHProfiles = parseBitMask(raw.payload.subarray(2, 3), ECDHProfiles.Curve25519);
1531
- validatePayload(selectedECDHProfiles.length === 1);
1532
- const selectedECDHProfile = selectedECDHProfiles[0];
1533
- const grantedKeys = parseBitMask(raw.payload.subarray(3, 4), SecurityClass.S2_Unauthenticated);
1534
- return new Security2CCKEXSet_1({
1535
- nodeId: ctx.sourceNodeId,
1536
- _reserved,
1537
- permitCSA,
1538
- echo,
1539
- selectedKEXScheme,
1540
- selectedECDHProfile,
1541
- grantedKeys,
1542
- });
1543
- }
1544
- _reserved;
1545
- permitCSA;
1546
- echo;
1547
- selectedKEXScheme;
1548
- selectedECDHProfile;
1549
- grantedKeys;
1550
- serialize(ctx) {
1551
- this.payload = Bytes.concat([
1552
- Bytes.from([
1553
- this._reserved
1554
- + (this.permitCSA ? 0b10 : 0)
1555
- + (this.echo ? 0b1 : 0),
1556
- ]),
1625
+ let Security2CCKEXSet = (() => {
1626
+ let _classDecorators = [CCCommand(Security2Command.KEXSet), expectedCCResponse(getExpectedResponseForKEXSet, testExpectedResponseForKEXSet)];
1627
+ let _classDescriptor;
1628
+ let _classExtraInitializers = [];
1629
+ let _classThis;
1630
+ let _classSuper = Security2CC;
1631
+ var Security2CCKEXSet = class extends _classSuper {
1632
+ static { _classThis = this; }
1633
+ static {
1634
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
1635
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
1636
+ Security2CCKEXSet = _classThis = _classDescriptor.value;
1637
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
1638
+ __runInitializers(_classThis, _classExtraInitializers);
1639
+ }
1640
+ constructor(options) {
1641
+ super(options);
1642
+ this.permitCSA = options.permitCSA;
1643
+ this.echo = options.echo;
1644
+ this._reserved = options._reserved ?? 0;
1645
+ this.selectedKEXScheme = options.selectedKEXScheme;
1646
+ this.selectedECDHProfile = options.selectedECDHProfile;
1647
+ this.grantedKeys = options.grantedKeys;
1648
+ }
1649
+ static from(raw, ctx) {
1650
+ validatePayload(raw.payload.length >= 4);
1651
+ const _reserved = raw.payload[0] & 0b1111_1100;
1652
+ const permitCSA = !!(raw.payload[0] & 0b10);
1653
+ const echo = !!(raw.payload[0] & 0b1);
1557
1654
  // The bit mask starts at 0, but bit 0 is not used
1558
- encodeBitMask([this.selectedKEXScheme], 7, 0),
1559
- encodeBitMask([this.selectedECDHProfile], 7, ECDHProfiles.Curve25519),
1560
- encodeBitMask(this.grantedKeys, SecurityClass.S0_Legacy, SecurityClass.S2_Unauthenticated),
1561
- ]);
1562
- return super.serialize(ctx);
1563
- }
1564
- toLogEntry(ctx) {
1565
- return {
1566
- ...super.toLogEntry(ctx),
1567
- message: {
1568
- echo: this.echo,
1569
- "selected scheme": getEnumMemberName(KEXSchemes, this.selectedKEXScheme),
1570
- "selected ECDH profile": getEnumMemberName(ECDHProfiles, this.selectedECDHProfile),
1571
- "CSA permitted": this.permitCSA,
1572
- "granted security classes": this.grantedKeys
1573
- .map((s) => `\n· ${getEnumMemberName(SecurityClass, s)}`)
1574
- .join(""),
1575
- },
1576
- };
1577
- }
1578
- };
1579
- Security2CCKEXSet = Security2CCKEXSet_1 = __decorate([
1580
- CCCommand(Security2Command.KEXSet),
1581
- expectedCCResponse(getExpectedResponseForKEXSet, testExpectedResponseForKEXSet)
1582
- ], Security2CCKEXSet);
1655
+ const selectedKEXSchemes = parseBitMask(raw.payload.subarray(1, 2), 0).filter((s) => s !== 0);
1656
+ validatePayload(selectedKEXSchemes.length === 1);
1657
+ const selectedKEXScheme = selectedKEXSchemes[0];
1658
+ const selectedECDHProfiles = parseBitMask(raw.payload.subarray(2, 3), ECDHProfiles.Curve25519);
1659
+ validatePayload(selectedECDHProfiles.length === 1);
1660
+ const selectedECDHProfile = selectedECDHProfiles[0];
1661
+ const grantedKeys = parseBitMask(raw.payload.subarray(3, 4), SecurityClass.S2_Unauthenticated);
1662
+ return new this({
1663
+ nodeId: ctx.sourceNodeId,
1664
+ _reserved,
1665
+ permitCSA,
1666
+ echo,
1667
+ selectedKEXScheme,
1668
+ selectedECDHProfile,
1669
+ grantedKeys,
1670
+ });
1671
+ }
1672
+ _reserved;
1673
+ permitCSA;
1674
+ echo;
1675
+ selectedKEXScheme;
1676
+ selectedECDHProfile;
1677
+ grantedKeys;
1678
+ serialize(ctx) {
1679
+ this.payload = Bytes.concat([
1680
+ Bytes.from([
1681
+ this._reserved
1682
+ + (this.permitCSA ? 0b10 : 0)
1683
+ + (this.echo ? 0b1 : 0),
1684
+ ]),
1685
+ // The bit mask starts at 0, but bit 0 is not used
1686
+ encodeBitMask([this.selectedKEXScheme], 7, 0),
1687
+ encodeBitMask([this.selectedECDHProfile], 7, ECDHProfiles.Curve25519),
1688
+ encodeBitMask(this.grantedKeys, SecurityClass.S0_Legacy, SecurityClass.S2_Unauthenticated),
1689
+ ]);
1690
+ return super.serialize(ctx);
1691
+ }
1692
+ toLogEntry(ctx) {
1693
+ return {
1694
+ ...super.toLogEntry(ctx),
1695
+ message: {
1696
+ echo: this.echo,
1697
+ "selected scheme": getEnumMemberName(KEXSchemes, this.selectedKEXScheme),
1698
+ "selected ECDH profile": getEnumMemberName(ECDHProfiles, this.selectedECDHProfile),
1699
+ "CSA permitted": this.permitCSA,
1700
+ "granted security classes": this.grantedKeys
1701
+ .map((s) => `\n· ${getEnumMemberName(SecurityClass, s)}`)
1702
+ .join(""),
1703
+ },
1704
+ };
1705
+ }
1706
+ };
1707
+ return Security2CCKEXSet = _classThis;
1708
+ })();
1583
1709
  export { Security2CCKEXSet };
1584
- let Security2CCKEXFail = Security2CCKEXFail_1 = class Security2CCKEXFail extends Security2CC {
1585
- constructor(options) {
1586
- super(options);
1587
- this.failType = options.failType;
1588
- }
1589
- static from(raw, ctx) {
1590
- validatePayload(raw.payload.length >= 1);
1591
- const failType = raw.payload[0];
1592
- return new Security2CCKEXFail_1({
1593
- nodeId: ctx.sourceNodeId,
1594
- failType,
1595
- });
1596
- }
1597
- failType;
1598
- serialize(ctx) {
1599
- this.payload = Bytes.from([this.failType]);
1600
- return super.serialize(ctx);
1601
- }
1602
- toLogEntry(ctx) {
1603
- return {
1604
- ...super.toLogEntry(ctx),
1605
- message: { reason: getEnumMemberName(KEXFailType, this.failType) },
1606
- };
1607
- }
1608
- };
1609
- Security2CCKEXFail = Security2CCKEXFail_1 = __decorate([
1610
- CCCommand(Security2Command.KEXFail)
1611
- ], Security2CCKEXFail);
1710
+ let Security2CCKEXFail = (() => {
1711
+ let _classDecorators = [CCCommand(Security2Command.KEXFail)];
1712
+ let _classDescriptor;
1713
+ let _classExtraInitializers = [];
1714
+ let _classThis;
1715
+ let _classSuper = Security2CC;
1716
+ var Security2CCKEXFail = class extends _classSuper {
1717
+ static { _classThis = this; }
1718
+ static {
1719
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
1720
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
1721
+ Security2CCKEXFail = _classThis = _classDescriptor.value;
1722
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
1723
+ __runInitializers(_classThis, _classExtraInitializers);
1724
+ }
1725
+ constructor(options) {
1726
+ super(options);
1727
+ this.failType = options.failType;
1728
+ }
1729
+ static from(raw, ctx) {
1730
+ validatePayload(raw.payload.length >= 1);
1731
+ const failType = raw.payload[0];
1732
+ return new this({
1733
+ nodeId: ctx.sourceNodeId,
1734
+ failType,
1735
+ });
1736
+ }
1737
+ failType;
1738
+ serialize(ctx) {
1739
+ this.payload = Bytes.from([this.failType]);
1740
+ return super.serialize(ctx);
1741
+ }
1742
+ toLogEntry(ctx) {
1743
+ return {
1744
+ ...super.toLogEntry(ctx),
1745
+ message: { reason: getEnumMemberName(KEXFailType, this.failType) },
1746
+ };
1747
+ }
1748
+ };
1749
+ return Security2CCKEXFail = _classThis;
1750
+ })();
1612
1751
  export { Security2CCKEXFail };
1613
- let Security2CCPublicKeyReport = Security2CCPublicKeyReport_1 = class Security2CCPublicKeyReport extends Security2CC {
1614
- constructor(options) {
1615
- super(options);
1616
- this.includingNode = options.includingNode;
1617
- this.publicKey = options.publicKey;
1618
- }
1619
- static from(raw, ctx) {
1620
- validatePayload(raw.payload.length >= 17);
1621
- const includingNode = !!(raw.payload[0] & 0b1);
1622
- const publicKey = raw.payload.subarray(1);
1623
- return new Security2CCPublicKeyReport_1({
1624
- nodeId: ctx.sourceNodeId,
1625
- includingNode,
1626
- publicKey,
1627
- });
1628
- }
1629
- includingNode;
1630
- publicKey;
1631
- serialize(ctx) {
1632
- this.payload = Bytes.concat([
1633
- Bytes.from([this.includingNode ? 1 : 0]),
1634
- this.publicKey,
1635
- ]);
1636
- return super.serialize(ctx);
1637
- }
1638
- toLogEntry(ctx) {
1639
- return {
1640
- ...super.toLogEntry(ctx),
1641
- message: {
1642
- "is including node": this.includingNode,
1643
- "public key": buffer2hex(this.publicKey),
1644
- },
1645
- };
1646
- }
1647
- };
1648
- Security2CCPublicKeyReport = Security2CCPublicKeyReport_1 = __decorate([
1649
- CCCommand(Security2Command.PublicKeyReport)
1650
- ], Security2CCPublicKeyReport);
1752
+ let Security2CCPublicKeyReport = (() => {
1753
+ let _classDecorators = [CCCommand(Security2Command.PublicKeyReport)];
1754
+ let _classDescriptor;
1755
+ let _classExtraInitializers = [];
1756
+ let _classThis;
1757
+ let _classSuper = Security2CC;
1758
+ var Security2CCPublicKeyReport = class extends _classSuper {
1759
+ static { _classThis = this; }
1760
+ static {
1761
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
1762
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
1763
+ Security2CCPublicKeyReport = _classThis = _classDescriptor.value;
1764
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
1765
+ __runInitializers(_classThis, _classExtraInitializers);
1766
+ }
1767
+ constructor(options) {
1768
+ super(options);
1769
+ this.includingNode = options.includingNode;
1770
+ this.publicKey = options.publicKey;
1771
+ }
1772
+ static from(raw, ctx) {
1773
+ validatePayload(raw.payload.length >= 17);
1774
+ const includingNode = !!(raw.payload[0] & 0b1);
1775
+ const publicKey = raw.payload.subarray(1);
1776
+ return new this({
1777
+ nodeId: ctx.sourceNodeId,
1778
+ includingNode,
1779
+ publicKey,
1780
+ });
1781
+ }
1782
+ includingNode;
1783
+ publicKey;
1784
+ serialize(ctx) {
1785
+ this.payload = Bytes.concat([
1786
+ Bytes.from([this.includingNode ? 1 : 0]),
1787
+ this.publicKey,
1788
+ ]);
1789
+ return super.serialize(ctx);
1790
+ }
1791
+ toLogEntry(ctx) {
1792
+ return {
1793
+ ...super.toLogEntry(ctx),
1794
+ message: {
1795
+ "is including node": this.includingNode,
1796
+ "public key": buffer2hex(this.publicKey),
1797
+ },
1798
+ };
1799
+ }
1800
+ };
1801
+ return Security2CCPublicKeyReport = _classThis;
1802
+ })();
1651
1803
  export { Security2CCPublicKeyReport };
1652
- let Security2CCNetworkKeyReport = Security2CCNetworkKeyReport_1 = class Security2CCNetworkKeyReport extends Security2CC {
1653
- constructor(options) {
1654
- super(options);
1655
- this.grantedKey = options.grantedKey;
1656
- this.networkKey = options.networkKey;
1657
- }
1658
- static from(raw, ctx) {
1659
- validatePayload(raw.payload.length >= 17);
1660
- const grantedKey = bitMaskToSecurityClass(raw.payload, 0);
1661
- const networkKey = raw.payload.subarray(1, 17);
1662
- return new Security2CCNetworkKeyReport_1({
1663
- nodeId: ctx.sourceNodeId,
1664
- grantedKey,
1665
- networkKey,
1666
- });
1667
- }
1668
- grantedKey;
1669
- networkKey;
1670
- serialize(ctx) {
1671
- this.payload = Bytes.concat([
1672
- securityClassToBitMask(this.grantedKey),
1673
- this.networkKey,
1674
- ]);
1675
- return super.serialize(ctx);
1676
- }
1677
- toLogEntry(ctx) {
1678
- return {
1679
- ...super.toLogEntry(ctx),
1680
- message: {
1681
- "security class": getEnumMemberName(SecurityClass, this.grantedKey),
1682
- // This shouldn't be logged, so users can safely post their logs online
1683
- // "network key": buffer2hex(this.networkKey),
1684
- },
1685
- };
1686
- }
1687
- };
1688
- Security2CCNetworkKeyReport = Security2CCNetworkKeyReport_1 = __decorate([
1689
- CCCommand(Security2Command.NetworkKeyReport)
1690
- ], Security2CCNetworkKeyReport);
1804
+ let Security2CCNetworkKeyReport = (() => {
1805
+ let _classDecorators = [CCCommand(Security2Command.NetworkKeyReport)];
1806
+ let _classDescriptor;
1807
+ let _classExtraInitializers = [];
1808
+ let _classThis;
1809
+ let _classSuper = Security2CC;
1810
+ var Security2CCNetworkKeyReport = class extends _classSuper {
1811
+ static { _classThis = this; }
1812
+ static {
1813
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
1814
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
1815
+ Security2CCNetworkKeyReport = _classThis = _classDescriptor.value;
1816
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
1817
+ __runInitializers(_classThis, _classExtraInitializers);
1818
+ }
1819
+ constructor(options) {
1820
+ super(options);
1821
+ this.grantedKey = options.grantedKey;
1822
+ this.networkKey = options.networkKey;
1823
+ }
1824
+ static from(raw, ctx) {
1825
+ validatePayload(raw.payload.length >= 17);
1826
+ const grantedKey = bitMaskToSecurityClass(raw.payload, 0);
1827
+ const networkKey = raw.payload.subarray(1, 17);
1828
+ return new this({
1829
+ nodeId: ctx.sourceNodeId,
1830
+ grantedKey,
1831
+ networkKey,
1832
+ });
1833
+ }
1834
+ grantedKey;
1835
+ networkKey;
1836
+ serialize(ctx) {
1837
+ this.payload = Bytes.concat([
1838
+ securityClassToBitMask(this.grantedKey),
1839
+ this.networkKey,
1840
+ ]);
1841
+ return super.serialize(ctx);
1842
+ }
1843
+ toLogEntry(ctx) {
1844
+ return {
1845
+ ...super.toLogEntry(ctx),
1846
+ message: {
1847
+ "security class": getEnumMemberName(SecurityClass, this.grantedKey),
1848
+ // This shouldn't be logged, so users can safely post their logs online
1849
+ // "network key": buffer2hex(this.networkKey),
1850
+ },
1851
+ };
1852
+ }
1853
+ };
1854
+ return Security2CCNetworkKeyReport = _classThis;
1855
+ })();
1691
1856
  export { Security2CCNetworkKeyReport };
1692
- let Security2CCNetworkKeyGet = Security2CCNetworkKeyGet_1 = class Security2CCNetworkKeyGet extends Security2CC {
1693
- constructor(options) {
1694
- super(options);
1695
- this.requestedKey = options.requestedKey;
1696
- }
1697
- static from(raw, ctx) {
1698
- validatePayload(raw.payload.length >= 1);
1699
- const requestedKey = bitMaskToSecurityClass(raw.payload, 0);
1700
- return new Security2CCNetworkKeyGet_1({
1701
- nodeId: ctx.sourceNodeId,
1702
- requestedKey,
1703
- });
1704
- }
1705
- requestedKey;
1706
- serialize(ctx) {
1707
- this.payload = securityClassToBitMask(this.requestedKey);
1708
- return super.serialize(ctx);
1709
- }
1710
- toLogEntry(ctx) {
1711
- return {
1712
- ...super.toLogEntry(ctx),
1713
- message: {
1714
- "security class": getEnumMemberName(SecurityClass, this.requestedKey),
1715
- },
1716
- };
1717
- }
1718
- };
1719
- Security2CCNetworkKeyGet = Security2CCNetworkKeyGet_1 = __decorate([
1720
- CCCommand(Security2Command.NetworkKeyGet)
1721
- // Don't expect a response - we need to distinguish between Report and Fail
1722
- // FIXME: maybe use the dynamic @expectedCCResponse instead?
1723
- ], Security2CCNetworkKeyGet);
1857
+ let Security2CCNetworkKeyGet = (() => {
1858
+ let _classDecorators = [CCCommand(Security2Command.NetworkKeyGet)];
1859
+ let _classDescriptor;
1860
+ let _classExtraInitializers = [];
1861
+ let _classThis;
1862
+ let _classSuper = Security2CC;
1863
+ var Security2CCNetworkKeyGet = class extends _classSuper {
1864
+ static { _classThis = this; }
1865
+ static {
1866
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
1867
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
1868
+ Security2CCNetworkKeyGet = _classThis = _classDescriptor.value;
1869
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
1870
+ __runInitializers(_classThis, _classExtraInitializers);
1871
+ }
1872
+ constructor(options) {
1873
+ super(options);
1874
+ this.requestedKey = options.requestedKey;
1875
+ }
1876
+ static from(raw, ctx) {
1877
+ validatePayload(raw.payload.length >= 1);
1878
+ const requestedKey = bitMaskToSecurityClass(raw.payload, 0);
1879
+ return new this({
1880
+ nodeId: ctx.sourceNodeId,
1881
+ requestedKey,
1882
+ });
1883
+ }
1884
+ requestedKey;
1885
+ serialize(ctx) {
1886
+ this.payload = securityClassToBitMask(this.requestedKey);
1887
+ return super.serialize(ctx);
1888
+ }
1889
+ toLogEntry(ctx) {
1890
+ return {
1891
+ ...super.toLogEntry(ctx),
1892
+ message: {
1893
+ "security class": getEnumMemberName(SecurityClass, this.requestedKey),
1894
+ },
1895
+ };
1896
+ }
1897
+ };
1898
+ return Security2CCNetworkKeyGet = _classThis;
1899
+ })();
1724
1900
  export { Security2CCNetworkKeyGet };
1725
- let Security2CCNetworkKeyVerify = class Security2CCNetworkKeyVerify extends Security2CC {
1726
- };
1727
- Security2CCNetworkKeyVerify = __decorate([
1728
- CCCommand(Security2Command.NetworkKeyVerify)
1729
- ], Security2CCNetworkKeyVerify);
1901
+ let Security2CCNetworkKeyVerify = (() => {
1902
+ let _classDecorators = [CCCommand(Security2Command.NetworkKeyVerify)];
1903
+ let _classDescriptor;
1904
+ let _classExtraInitializers = [];
1905
+ let _classThis;
1906
+ let _classSuper = Security2CC;
1907
+ var Security2CCNetworkKeyVerify = class extends _classSuper {
1908
+ static { _classThis = this; }
1909
+ static {
1910
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
1911
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
1912
+ Security2CCNetworkKeyVerify = _classThis = _classDescriptor.value;
1913
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
1914
+ __runInitializers(_classThis, _classExtraInitializers);
1915
+ }
1916
+ };
1917
+ return Security2CCNetworkKeyVerify = _classThis;
1918
+ })();
1730
1919
  export { Security2CCNetworkKeyVerify };
1731
- let Security2CCTransferEnd = Security2CCTransferEnd_1 = class Security2CCTransferEnd extends Security2CC {
1732
- constructor(options) {
1733
- super(options);
1734
- this.keyVerified = options.keyVerified;
1735
- this.keyRequestComplete = options.keyRequestComplete;
1736
- }
1737
- static from(raw, ctx) {
1738
- validatePayload(raw.payload.length >= 1);
1739
- const keyVerified = !!(raw.payload[0] & 0b10);
1740
- const keyRequestComplete = !!(raw.payload[0] & 0b1);
1741
- return new Security2CCTransferEnd_1({
1742
- nodeId: ctx.sourceNodeId,
1743
- keyVerified,
1744
- keyRequestComplete,
1745
- });
1746
- }
1747
- keyVerified;
1748
- keyRequestComplete;
1749
- serialize(ctx) {
1750
- this.payload = Bytes.from([
1751
- (this.keyVerified ? 0b10 : 0) + (this.keyRequestComplete ? 0b1 : 0),
1752
- ]);
1753
- return super.serialize(ctx);
1754
- }
1755
- toLogEntry(ctx) {
1756
- return {
1757
- ...super.toLogEntry(ctx),
1758
- message: {
1759
- "key verified": this.keyVerified,
1760
- "request complete": this.keyRequestComplete,
1761
- },
1762
- };
1763
- }
1764
- };
1765
- Security2CCTransferEnd = Security2CCTransferEnd_1 = __decorate([
1766
- CCCommand(Security2Command.TransferEnd)
1767
- ], Security2CCTransferEnd);
1920
+ let Security2CCTransferEnd = (() => {
1921
+ let _classDecorators = [CCCommand(Security2Command.TransferEnd)];
1922
+ let _classDescriptor;
1923
+ let _classExtraInitializers = [];
1924
+ let _classThis;
1925
+ let _classSuper = Security2CC;
1926
+ var Security2CCTransferEnd = class extends _classSuper {
1927
+ static { _classThis = this; }
1928
+ static {
1929
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
1930
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
1931
+ Security2CCTransferEnd = _classThis = _classDescriptor.value;
1932
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
1933
+ __runInitializers(_classThis, _classExtraInitializers);
1934
+ }
1935
+ constructor(options) {
1936
+ super(options);
1937
+ this.keyVerified = options.keyVerified;
1938
+ this.keyRequestComplete = options.keyRequestComplete;
1939
+ }
1940
+ static from(raw, ctx) {
1941
+ validatePayload(raw.payload.length >= 1);
1942
+ const keyVerified = !!(raw.payload[0] & 0b10);
1943
+ const keyRequestComplete = !!(raw.payload[0] & 0b1);
1944
+ return new this({
1945
+ nodeId: ctx.sourceNodeId,
1946
+ keyVerified,
1947
+ keyRequestComplete,
1948
+ });
1949
+ }
1950
+ keyVerified;
1951
+ keyRequestComplete;
1952
+ serialize(ctx) {
1953
+ this.payload = Bytes.from([
1954
+ (this.keyVerified ? 0b10 : 0) + (this.keyRequestComplete ? 0b1 : 0),
1955
+ ]);
1956
+ return super.serialize(ctx);
1957
+ }
1958
+ toLogEntry(ctx) {
1959
+ return {
1960
+ ...super.toLogEntry(ctx),
1961
+ message: {
1962
+ "key verified": this.keyVerified,
1963
+ "request complete": this.keyRequestComplete,
1964
+ },
1965
+ };
1966
+ }
1967
+ };
1968
+ return Security2CCTransferEnd = _classThis;
1969
+ })();
1768
1970
  export { Security2CCTransferEnd };
1769
- let Security2CCCommandsSupportedReport = Security2CCCommandsSupportedReport_1 = class Security2CCCommandsSupportedReport extends Security2CC {
1770
- constructor(options) {
1771
- super(options);
1772
- this.supportedCCs = options.supportedCCs;
1773
- }
1774
- static from(raw, ctx) {
1775
- const CCs = parseCCList(raw.payload);
1776
- // SDS13783: A sending node MAY terminate the list of supported command classes with the
1777
- // COMMAND_CLASS_MARK command class identifier.
1778
- // A receiving node MUST stop parsing the list of supported command classes if it detects the
1779
- // COMMAND_CLASS_MARK command class identifier in the Security 2 Commands Supported Report
1780
- const supportedCCs = CCs.supportedCCs;
1781
- return new Security2CCCommandsSupportedReport_1({
1782
- nodeId: ctx.sourceNodeId,
1783
- supportedCCs,
1784
- });
1785
- }
1786
- supportedCCs;
1787
- serialize(ctx) {
1788
- this.payload = encodeCCList(this.supportedCCs, []);
1789
- return super.serialize(ctx);
1790
- }
1791
- toLogEntry(ctx) {
1792
- return {
1793
- ...super.toLogEntry(ctx),
1794
- message: {
1795
- "supported CCs": this.supportedCCs
1796
- .map((cc) => getCCName(cc))
1797
- .map((cc) => `\n· ${cc}`)
1798
- .join(""),
1799
- },
1800
- };
1801
- }
1802
- };
1803
- Security2CCCommandsSupportedReport = Security2CCCommandsSupportedReport_1 = __decorate([
1804
- CCCommand(Security2Command.CommandsSupportedReport)
1805
- ], Security2CCCommandsSupportedReport);
1971
+ let Security2CCCommandsSupportedReport = (() => {
1972
+ let _classDecorators = [CCCommand(Security2Command.CommandsSupportedReport)];
1973
+ let _classDescriptor;
1974
+ let _classExtraInitializers = [];
1975
+ let _classThis;
1976
+ let _classSuper = Security2CC;
1977
+ var Security2CCCommandsSupportedReport = class extends _classSuper {
1978
+ static { _classThis = this; }
1979
+ static {
1980
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
1981
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
1982
+ Security2CCCommandsSupportedReport = _classThis = _classDescriptor.value;
1983
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
1984
+ __runInitializers(_classThis, _classExtraInitializers);
1985
+ }
1986
+ constructor(options) {
1987
+ super(options);
1988
+ this.supportedCCs = options.supportedCCs;
1989
+ }
1990
+ static from(raw, ctx) {
1991
+ const CCs = parseCCList(raw.payload);
1992
+ // SDS13783: A sending node MAY terminate the list of supported command classes with the
1993
+ // COMMAND_CLASS_MARK command class identifier.
1994
+ // A receiving node MUST stop parsing the list of supported command classes if it detects the
1995
+ // COMMAND_CLASS_MARK command class identifier in the Security 2 Commands Supported Report
1996
+ const supportedCCs = CCs.supportedCCs;
1997
+ return new this({
1998
+ nodeId: ctx.sourceNodeId,
1999
+ supportedCCs,
2000
+ });
2001
+ }
2002
+ supportedCCs;
2003
+ serialize(ctx) {
2004
+ this.payload = encodeCCList(this.supportedCCs, []);
2005
+ return super.serialize(ctx);
2006
+ }
2007
+ toLogEntry(ctx) {
2008
+ return {
2009
+ ...super.toLogEntry(ctx),
2010
+ message: {
2011
+ "supported CCs": this.supportedCCs
2012
+ .map((cc) => getCCName(cc))
2013
+ .map((cc) => `\n· ${cc}`)
2014
+ .join(""),
2015
+ },
2016
+ };
2017
+ }
2018
+ };
2019
+ return Security2CCCommandsSupportedReport = _classThis;
2020
+ })();
1806
2021
  export { Security2CCCommandsSupportedReport };
1807
- let Security2CCCommandsSupportedGet = class Security2CCCommandsSupportedGet extends Security2CC {
1808
- };
1809
- Security2CCCommandsSupportedGet = __decorate([
1810
- CCCommand(Security2Command.CommandsSupportedGet),
1811
- expectedCCResponse(Security2CCCommandsSupportedReport)
1812
- ], Security2CCCommandsSupportedGet);
2022
+ let Security2CCCommandsSupportedGet = (() => {
2023
+ let _classDecorators = [CCCommand(Security2Command.CommandsSupportedGet), expectedCCResponse(Security2CCCommandsSupportedReport)];
2024
+ let _classDescriptor;
2025
+ let _classExtraInitializers = [];
2026
+ let _classThis;
2027
+ let _classSuper = Security2CC;
2028
+ var Security2CCCommandsSupportedGet = class extends _classSuper {
2029
+ static { _classThis = this; }
2030
+ static {
2031
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
2032
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
2033
+ Security2CCCommandsSupportedGet = _classThis = _classDescriptor.value;
2034
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
2035
+ __runInitializers(_classThis, _classExtraInitializers);
2036
+ }
2037
+ };
2038
+ return Security2CCCommandsSupportedGet = _classThis;
2039
+ })();
1813
2040
  export { Security2CCCommandsSupportedGet };
1814
2041
  //# sourceMappingURL=Security2CC.js.map