@zwave-js/cc 13.10.1 → 14.0.0-beta.0
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.
- package/build/cc/AlarmSensorCC.d.ts +31 -20
- package/build/cc/AlarmSensorCC.d.ts.map +1 -1
- package/build/cc/AlarmSensorCC.js +106 -87
- package/build/cc/AlarmSensorCC.js.map +1 -1
- package/build/cc/AssociationCC.d.ts +38 -32
- package/build/cc/AssociationCC.d.ts.map +1 -1
- package/build/cc/AssociationCC.js +193 -176
- package/build/cc/AssociationCC.js.map +1 -1
- package/build/cc/AssociationGroupInfoCC.d.ts +42 -36
- package/build/cc/AssociationGroupInfoCC.d.ts.map +1 -1
- package/build/cc/AssociationGroupInfoCC.js +218 -200
- package/build/cc/AssociationGroupInfoCC.js.map +1 -1
- package/build/cc/BarrierOperatorCC.d.ts +41 -24
- package/build/cc/BarrierOperatorCC.d.ts.map +1 -1
- package/build/cc/BarrierOperatorCC.js +143 -109
- package/build/cc/BarrierOperatorCC.js.map +1 -1
- package/build/cc/BasicCC.d.ts +22 -23
- package/build/cc/BasicCC.d.ts.map +1 -1
- package/build/cc/BasicCC.js +83 -77
- package/build/cc/BasicCC.js.map +1 -1
- package/build/cc/BatteryCC.d.ts +22 -14
- package/build/cc/BatteryCC.d.ts.map +1 -1
- package/build/cc/BatteryCC.js +116 -87
- package/build/cc/BatteryCC.js.map +1 -1
- package/build/cc/BinarySensorCC.d.ts +22 -19
- package/build/cc/BinarySensorCC.d.ts.map +1 -1
- package/build/cc/BinarySensorCC.js +103 -93
- package/build/cc/BinarySensorCC.js.map +1 -1
- package/build/cc/BinarySwitchCC.d.ts +20 -20
- package/build/cc/BinarySwitchCC.d.ts.map +1 -1
- package/build/cc/BinarySwitchCC.js +71 -59
- package/build/cc/BinarySwitchCC.js.map +1 -1
- package/build/cc/CRC16CC.d.ts +9 -9
- package/build/cc/CRC16CC.d.ts.map +1 -1
- package/build/cc/CRC16CC.js +36 -36
- package/build/cc/CRC16CC.js.map +1 -1
- package/build/cc/CentralSceneCC.d.ts +34 -16
- package/build/cc/CentralSceneCC.d.ts.map +1 -1
- package/build/cc/CentralSceneCC.js +116 -79
- package/build/cc/CentralSceneCC.js.map +1 -1
- package/build/cc/ClimateControlScheduleCC.d.ts +38 -21
- package/build/cc/ClimateControlScheduleCC.d.ts.map +1 -1
- package/build/cc/ClimateControlScheduleCC.js +113 -81
- package/build/cc/ClimateControlScheduleCC.js.map +1 -1
- package/build/cc/ClockCC.d.ts +18 -11
- package/build/cc/ClockCC.d.ts.map +1 -1
- package/build/cc/ClockCC.js +57 -43
- package/build/cc/ClockCC.js.map +1 -1
- package/build/cc/ColorSwitchCC.d.ts +37 -33
- package/build/cc/ColorSwitchCC.d.ts.map +1 -1
- package/build/cc/ColorSwitchCC.js +216 -189
- package/build/cc/ColorSwitchCC.js.map +1 -1
- package/build/cc/ConfigurationCC.d.ts +89 -74
- package/build/cc/ConfigurationCC.d.ts.map +1 -1
- package/build/cc/ConfigurationCC.js +541 -485
- package/build/cc/ConfigurationCC.js.map +1 -1
- package/build/cc/DeviceResetLocallyCC.d.ts +3 -3
- package/build/cc/DeviceResetLocallyCC.d.ts.map +1 -1
- package/build/cc/DeviceResetLocallyCC.js +14 -14
- package/build/cc/DeviceResetLocallyCC.js.map +1 -1
- package/build/cc/DoorLockCC.d.ts +66 -27
- package/build/cc/DoorLockCC.d.ts.map +1 -1
- package/build/cc/DoorLockCC.js +288 -197
- package/build/cc/DoorLockCC.js.map +1 -1
- package/build/cc/DoorLockLoggingCC.d.ts +23 -13
- package/build/cc/DoorLockLoggingCC.d.ts.map +1 -1
- package/build/cc/DoorLockLoggingCC.js +81 -63
- package/build/cc/DoorLockLoggingCC.js.map +1 -1
- package/build/cc/EnergyProductionCC.d.ts +16 -14
- package/build/cc/EnergyProductionCC.d.ts.map +1 -1
- package/build/cc/EnergyProductionCC.js +58 -52
- package/build/cc/EnergyProductionCC.js.map +1 -1
- package/build/cc/EntryControlCC.d.ts +44 -18
- package/build/cc/EntryControlCC.d.ts.map +1 -1
- package/build/cc/EntryControlCC.js +163 -112
- package/build/cc/EntryControlCC.js.map +1 -1
- package/build/cc/FirmwareUpdateMetaDataCC.d.ts +69 -34
- package/build/cc/FirmwareUpdateMetaDataCC.d.ts.map +1 -1
- package/build/cc/FirmwareUpdateMetaDataCC.js +311 -245
- package/build/cc/FirmwareUpdateMetaDataCC.js.map +1 -1
- package/build/cc/HumidityControlModeCC.d.ts +24 -16
- package/build/cc/HumidityControlModeCC.d.ts.map +1 -1
- package/build/cc/HumidityControlModeCC.js +80 -65
- package/build/cc/HumidityControlModeCC.js.map +1 -1
- package/build/cc/HumidityControlOperatingStateCC.d.ts +11 -7
- package/build/cc/HumidityControlOperatingStateCC.d.ts.map +1 -1
- package/build/cc/HumidityControlOperatingStateCC.js +31 -22
- package/build/cc/HumidityControlOperatingStateCC.js.map +1 -1
- package/build/cc/HumidityControlSetpointCC.d.ts +68 -49
- package/build/cc/HumidityControlSetpointCC.d.ts.map +1 -1
- package/build/cc/HumidityControlSetpointCC.js +203 -181
- package/build/cc/HumidityControlSetpointCC.js.map +1 -1
- package/build/cc/InclusionControllerCC.d.ts +13 -11
- package/build/cc/InclusionControllerCC.d.ts.map +1 -1
- package/build/cc/InclusionControllerCC.js +49 -42
- package/build/cc/InclusionControllerCC.js.map +1 -1
- package/build/cc/IndicatorCC.d.ts +46 -39
- package/build/cc/IndicatorCC.d.ts.map +1 -1
- package/build/cc/IndicatorCC.js +298 -277
- package/build/cc/IndicatorCC.js.map +1 -1
- package/build/cc/IrrigationCC.d.ts +127 -57
- package/build/cc/IrrigationCC.d.ts.map +1 -1
- package/build/cc/IrrigationCC.js +496 -352
- package/build/cc/IrrigationCC.js.map +1 -1
- package/build/cc/LanguageCC.d.ts +17 -11
- package/build/cc/LanguageCC.d.ts.map +1 -1
- package/build/cc/LanguageCC.js +54 -44
- package/build/cc/LanguageCC.js.map +1 -1
- package/build/cc/LockCC.d.ts +16 -11
- package/build/cc/LockCC.d.ts.map +1 -1
- package/build/cc/LockCC.js +48 -38
- package/build/cc/LockCC.js.map +1 -1
- package/build/cc/ManufacturerProprietaryCC.d.ts +12 -11
- package/build/cc/ManufacturerProprietaryCC.d.ts.map +1 -1
- package/build/cc/ManufacturerProprietaryCC.js +45 -50
- package/build/cc/ManufacturerProprietaryCC.js.map +1 -1
- package/build/cc/ManufacturerSpecificCC.d.ts +20 -13
- package/build/cc/ManufacturerSpecificCC.d.ts.map +1 -1
- package/build/cc/ManufacturerSpecificCC.js +79 -63
- package/build/cc/ManufacturerSpecificCC.js.map +1 -1
- package/build/cc/MeterCC.d.ts +30 -26
- package/build/cc/MeterCC.d.ts.map +1 -1
- package/build/cc/MeterCC.js +236 -204
- package/build/cc/MeterCC.js.map +1 -1
- package/build/cc/MultiChannelAssociationCC.d.ts +31 -26
- package/build/cc/MultiChannelAssociationCC.d.ts.map +1 -1
- package/build/cc/MultiChannelAssociationCC.js +177 -168
- package/build/cc/MultiChannelAssociationCC.js.map +1 -1
- package/build/cc/MultiChannelCC.d.ts +70 -49
- package/build/cc/MultiChannelCC.d.ts.map +1 -1
- package/build/cc/MultiChannelCC.js +377 -318
- package/build/cc/MultiChannelCC.js.map +1 -1
- package/build/cc/MultiCommandCC.d.ts +9 -9
- package/build/cc/MultiCommandCC.d.ts.map +1 -1
- package/build/cc/MultiCommandCC.js +35 -36
- package/build/cc/MultiCommandCC.js.map +1 -1
- package/build/cc/MultilevelSensorCC.d.ts +38 -33
- package/build/cc/MultilevelSensorCC.d.ts.map +1 -1
- package/build/cc/MultilevelSensorCC.js +172 -152
- package/build/cc/MultilevelSensorCC.js.map +1 -1
- package/build/cc/MultilevelSwitchCC.d.ts +29 -25
- package/build/cc/MultilevelSwitchCC.d.ts.map +1 -1
- package/build/cc/MultilevelSwitchCC.js +147 -127
- package/build/cc/MultilevelSwitchCC.js.map +1 -1
- package/build/cc/NoOperationCC.d.ts +0 -8
- package/build/cc/NoOperationCC.d.ts.map +1 -1
- package/build/cc/NoOperationCC.js +2 -11
- package/build/cc/NoOperationCC.js.map +1 -1
- package/build/cc/NodeNamingCC.d.ts +27 -17
- package/build/cc/NodeNamingCC.d.ts.map +1 -1
- package/build/cc/NodeNamingCC.js +86 -69
- package/build/cc/NodeNamingCC.js.map +1 -1
- package/build/cc/NotificationCC.d.ts +46 -43
- package/build/cc/NotificationCC.d.ts.map +1 -1
- package/build/cc/NotificationCC.js +317 -303
- package/build/cc/NotificationCC.js.map +1 -1
- package/build/cc/PowerlevelCC.d.ts +22 -18
- package/build/cc/PowerlevelCC.d.ts.map +1 -1
- package/build/cc/PowerlevelCC.js +125 -95
- package/build/cc/PowerlevelCC.js.map +1 -1
- package/build/cc/ProtectionCC.d.ts +49 -26
- package/build/cc/ProtectionCC.d.ts.map +1 -1
- package/build/cc/ProtectionCC.js +172 -126
- package/build/cc/ProtectionCC.js.map +1 -1
- package/build/cc/SceneActivationCC.d.ts +8 -7
- package/build/cc/SceneActivationCC.d.ts.map +1 -1
- package/build/cc/SceneActivationCC.js +28 -23
- package/build/cc/SceneActivationCC.js.map +1 -1
- package/build/cc/SceneActuatorConfigurationCC.d.ts +23 -15
- package/build/cc/SceneActuatorConfigurationCC.d.ts.map +1 -1
- package/build/cc/SceneActuatorConfigurationCC.js +79 -62
- package/build/cc/SceneActuatorConfigurationCC.js.map +1 -1
- package/build/cc/SceneControllerConfigurationCC.d.ts +25 -17
- package/build/cc/SceneControllerConfigurationCC.d.ts.map +1 -1
- package/build/cc/SceneControllerConfigurationCC.js +92 -78
- package/build/cc/SceneControllerConfigurationCC.js.map +1 -1
- package/build/cc/ScheduleEntryLockCC.d.ts +86 -72
- package/build/cc/ScheduleEntryLockCC.d.ts.map +1 -1
- package/build/cc/ScheduleEntryLockCC.js +607 -455
- package/build/cc/ScheduleEntryLockCC.js.map +1 -1
- package/build/cc/Security2CC.d.ts +78 -87
- package/build/cc/Security2CC.d.ts.map +1 -1
- package/build/cc/Security2CC.js +798 -765
- package/build/cc/Security2CC.js.map +1 -1
- package/build/cc/SecurityCC.d.ts +47 -42
- package/build/cc/SecurityCC.d.ts.map +1 -1
- package/build/cc/SecurityCC.js +240 -218
- package/build/cc/SecurityCC.js.map +1 -1
- package/build/cc/SoundSwitchCC.d.ts +36 -29
- package/build/cc/SoundSwitchCC.d.ts.map +1 -1
- package/build/cc/SoundSwitchCC.js +180 -157
- package/build/cc/SoundSwitchCC.js.map +1 -1
- package/build/cc/SupervisionCC.d.ts +17 -14
- package/build/cc/SupervisionCC.d.ts.map +1 -1
- package/build/cc/SupervisionCC.js +86 -66
- package/build/cc/SupervisionCC.js.map +1 -1
- package/build/cc/ThermostatFanModeCC.d.ts +25 -15
- package/build/cc/ThermostatFanModeCC.d.ts.map +1 -1
- package/build/cc/ThermostatFanModeCC.js +79 -60
- package/build/cc/ThermostatFanModeCC.js.map +1 -1
- package/build/cc/ThermostatFanStateCC.d.ts +11 -7
- package/build/cc/ThermostatFanStateCC.d.ts.map +1 -1
- package/build/cc/ThermostatFanStateCC.js +31 -22
- package/build/cc/ThermostatFanStateCC.js.map +1 -1
- package/build/cc/ThermostatModeCC.d.ts +24 -21
- package/build/cc/ThermostatModeCC.d.ts.map +1 -1
- package/build/cc/ThermostatModeCC.js +106 -90
- package/build/cc/ThermostatModeCC.js.map +1 -1
- package/build/cc/ThermostatOperatingStateCC.d.ts +11 -7
- package/build/cc/ThermostatOperatingStateCC.d.ts.map +1 -1
- package/build/cc/ThermostatOperatingStateCC.js +31 -22
- package/build/cc/ThermostatOperatingStateCC.js.map +1 -1
- package/build/cc/ThermostatSetbackCC.d.ts +14 -13
- package/build/cc/ThermostatSetbackCC.d.ts.map +1 -1
- package/build/cc/ThermostatSetbackCC.js +64 -57
- package/build/cc/ThermostatSetbackCC.js.map +1 -1
- package/build/cc/ThermostatSetpointCC.d.ts +38 -57
- package/build/cc/ThermostatSetpointCC.d.ts.map +1 -1
- package/build/cc/ThermostatSetpointCC.js +200 -264
- package/build/cc/ThermostatSetpointCC.js.map +1 -1
- package/build/cc/TimeCC.d.ts +24 -20
- package/build/cc/TimeCC.d.ts.map +1 -1
- package/build/cc/TimeCC.js +119 -108
- package/build/cc/TimeCC.js.map +1 -1
- package/build/cc/TimeParametersCC.d.ts +18 -14
- package/build/cc/TimeParametersCC.d.ts.map +1 -1
- package/build/cc/TimeParametersCC.js +77 -69
- package/build/cc/TimeParametersCC.js.map +1 -1
- package/build/cc/TransportServiceCC.d.ts +29 -32
- package/build/cc/TransportServiceCC.d.ts.map +1 -1
- package/build/cc/TransportServiceCC.js +159 -161
- package/build/cc/TransportServiceCC.js.map +1 -1
- package/build/cc/UserCodeCC.d.ts +83 -66
- package/build/cc/UserCodeCC.d.ts.map +1 -1
- package/build/cc/UserCodeCC.js +449 -402
- package/build/cc/UserCodeCC.js.map +1 -1
- package/build/cc/VersionCC.d.ts +36 -20
- package/build/cc/VersionCC.d.ts.map +1 -1
- package/build/cc/VersionCC.js +190 -149
- package/build/cc/VersionCC.js.map +1 -1
- package/build/cc/WakeUpCC.d.ts +27 -13
- package/build/cc/WakeUpCC.d.ts.map +1 -1
- package/build/cc/WakeUpCC.js +105 -77
- package/build/cc/WakeUpCC.js.map +1 -1
- package/build/cc/WindowCoveringCC.d.ts +39 -27
- package/build/cc/WindowCoveringCC.d.ts.map +1 -1
- package/build/cc/WindowCoveringCC.js +169 -137
- package/build/cc/WindowCoveringCC.js.map +1 -1
- package/build/cc/ZWavePlusCC.d.ts +8 -7
- package/build/cc/ZWavePlusCC.d.ts.map +1 -1
- package/build/cc/ZWavePlusCC.js +44 -37
- package/build/cc/ZWavePlusCC.js.map +1 -1
- package/build/cc/ZWaveProtocolCC.d.ts +111 -84
- package/build/cc/ZWaveProtocolCC.d.ts.map +1 -1
- package/build/cc/ZWaveProtocolCC.js +583 -508
- package/build/cc/ZWaveProtocolCC.js.map +1 -1
- package/build/cc/index.d.ts +37 -34
- package/build/cc/index.d.ts.map +1 -1
- package/build/cc/index.js +6 -7
- package/build/cc/index.js.map +1 -1
- package/build/cc/manufacturerProprietary/FibaroCC.d.ts +29 -24
- package/build/cc/manufacturerProprietary/FibaroCC.d.ts.map +1 -1
- package/build/cc/manufacturerProprietary/FibaroCC.js +109 -112
- package/build/cc/manufacturerProprietary/FibaroCC.js.map +1 -1
- package/build/index.d.ts +0 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +0 -1
- package/build/index.js.map +1 -1
- package/build/lib/API.d.ts +21 -18
- package/build/lib/API.d.ts.map +1 -1
- package/build/lib/API.js +25 -49
- package/build/lib/API.js.map +1 -1
- package/build/lib/CommandClass.d.ts +51 -89
- package/build/lib/CommandClass.d.ts.map +1 -1
- package/build/lib/CommandClass.js +177 -249
- package/build/lib/CommandClass.js.map +1 -1
- package/build/lib/EncapsulatingCommandClass.d.ts +1 -15
- package/build/lib/EncapsulatingCommandClass.d.ts.map +1 -1
- package/build/lib/EncapsulatingCommandClass.js.map +1 -1
- package/build/lib/ICommandClassContainer.d.ts +1 -8
- package/build/lib/ICommandClassContainer.d.ts.map +1 -1
- package/build/lib/ICommandClassContainer.js +0 -8
- package/build/lib/ICommandClassContainer.js.map +1 -1
- package/build/lib/Values.d.ts +3 -3
- package/build/lib/Values.d.ts.map +1 -1
- package/build/lib/_Types.d.ts.map +1 -1
- package/build/lib/_Types.js +1 -0
- package/build/lib/_Types.js.map +1 -1
- package/build/lib/utils.d.ts +14 -13
- package/build/lib/utils.d.ts.map +1 -1
- package/build/lib/utils.js +94 -92
- package/build/lib/utils.js.map +1 -1
- package/package.json +4 -5
package/build/cc/SecurityCC.js
CHANGED
|
@@ -5,7 +5,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
5
5
|
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;
|
|
6
6
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
7
|
};
|
|
8
|
-
var SecurityCC_1;
|
|
8
|
+
var SecurityCC_1, SecurityCCNonceReport_1, SecurityCCCommandEncapsulation_1, SecurityCCSchemeReport_1, SecurityCCNetworkKeySet_1, SecurityCCCommandsSupportedReport_1;
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.SecurityCCCommandsSupportedGet = exports.SecurityCCCommandsSupportedReport = exports.SecurityCCNetworkKeySet = exports.SecurityCCNetworkKeyVerify = exports.SecurityCCSchemeInherit = exports.SecurityCCSchemeGet = exports.SecurityCCSchemeReport = exports.SecurityCCCommandEncapsulationNonceGet = exports.SecurityCCCommandEncapsulation = exports.SecurityCCNonceGet = exports.SecurityCCNonceReport = exports.SecurityCC = exports.SecurityCCAPI = void 0;
|
|
11
11
|
const core_1 = require("@zwave-js/core");
|
|
@@ -40,6 +40,22 @@ function throwNoNonce(reason) {
|
|
|
40
40
|
throw new core_1.ZWaveError(message, core_1.ZWaveErrorCodes.SecurityCC_NoNonce);
|
|
41
41
|
}
|
|
42
42
|
const HALF_NONCE_SIZE = 8;
|
|
43
|
+
function assertSecurityRX(ctx) {
|
|
44
|
+
if (!ctx.ownNodeId) {
|
|
45
|
+
throw new core_1.ZWaveError(`Secure commands (S0) can only be decoded when the controller's node id is known!`, core_1.ZWaveErrorCodes.Driver_NotReady);
|
|
46
|
+
}
|
|
47
|
+
if (!ctx.securityManager) {
|
|
48
|
+
throw new core_1.ZWaveError(`Secure commands (S0) can only be decoded when the security manager is set up!`, core_1.ZWaveErrorCodes.Driver_NoSecurity);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function assertSecurityTX(ctx) {
|
|
52
|
+
if (!ctx.ownNodeId) {
|
|
53
|
+
throw new core_1.ZWaveError(`Secure commands (S0) can only be sent when the controller's node id is known!`, core_1.ZWaveErrorCodes.Driver_NotReady);
|
|
54
|
+
}
|
|
55
|
+
if (!ctx.securityManager) {
|
|
56
|
+
throw new core_1.ZWaveError(`Secure commands (S0) can only be sent when the security manager is set up!`, core_1.ZWaveErrorCodes.Driver_NoSecurity);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
43
59
|
// TODO: Ignore commands if received via multicast
|
|
44
60
|
// Encapsulation CCs are used internally and too frequently that we
|
|
45
61
|
// want to pay the cost of validating each call
|
|
@@ -58,22 +74,22 @@ let SecurityCCAPI = class SecurityCCAPI extends API_1.PhysicalCCAPI {
|
|
|
58
74
|
}
|
|
59
75
|
const cc = new (requestNextNonce
|
|
60
76
|
? SecurityCCCommandEncapsulationNonceGet
|
|
61
|
-
: SecurityCCCommandEncapsulation)(
|
|
77
|
+
: SecurityCCCommandEncapsulation)({
|
|
62
78
|
nodeId: this.endpoint.nodeId,
|
|
63
79
|
encapsulated,
|
|
64
80
|
});
|
|
65
|
-
await this.
|
|
81
|
+
await this.host.sendCommand(cc, this.commandOptions);
|
|
66
82
|
}
|
|
67
83
|
/**
|
|
68
84
|
* Requests a new nonce for Security CC encapsulation which is not directly linked to a specific command.
|
|
69
85
|
*/
|
|
70
86
|
async getNonce() {
|
|
71
87
|
this.assertSupportsCommand(_Types_1.SecurityCommand, _Types_1.SecurityCommand.NonceGet);
|
|
72
|
-
const cc = new SecurityCCNonceGet(
|
|
88
|
+
const cc = new SecurityCCNonceGet({
|
|
73
89
|
nodeId: this.endpoint.nodeId,
|
|
74
|
-
|
|
90
|
+
endpointIndex: this.endpoint.index,
|
|
75
91
|
});
|
|
76
|
-
const response = await this.
|
|
92
|
+
const response = await this.host.sendCommand(cc, {
|
|
77
93
|
...this.commandOptions,
|
|
78
94
|
// Only try getting a nonce once
|
|
79
95
|
maxSendAttempts: 1,
|
|
@@ -81,11 +97,11 @@ let SecurityCCAPI = class SecurityCCAPI extends API_1.PhysicalCCAPI {
|
|
|
81
97
|
if (!response)
|
|
82
98
|
return;
|
|
83
99
|
const nonce = response.nonce;
|
|
84
|
-
const secMan = this.
|
|
100
|
+
const secMan = this.host.securityManager;
|
|
85
101
|
secMan.setNonce({
|
|
86
102
|
issuer: this.endpoint.nodeId,
|
|
87
103
|
nonceId: secMan.getNonceId(nonce),
|
|
88
|
-
}, { nonce, receiver: this.
|
|
104
|
+
}, { nonce, receiver: this.host.ownNodeId }, { free: true });
|
|
89
105
|
return nonce;
|
|
90
106
|
}
|
|
91
107
|
/**
|
|
@@ -94,18 +110,18 @@ let SecurityCCAPI = class SecurityCCAPI extends API_1.PhysicalCCAPI {
|
|
|
94
110
|
*/
|
|
95
111
|
async sendNonce() {
|
|
96
112
|
this.assertSupportsCommand(_Types_1.SecurityCommand, _Types_1.SecurityCommand.NonceReport);
|
|
97
|
-
if (!this.
|
|
113
|
+
if (!this.host.securityManager) {
|
|
98
114
|
throw new core_1.ZWaveError(`Nonces can only be sent if secure communication is set up!`, core_1.ZWaveErrorCodes.Driver_NoSecurity);
|
|
99
115
|
}
|
|
100
|
-
const nonce = this.
|
|
101
|
-
const nonceId = this.
|
|
102
|
-
const cc = new SecurityCCNonceReport(
|
|
116
|
+
const nonce = this.host.securityManager.generateNonce(this.endpoint.nodeId, HALF_NONCE_SIZE);
|
|
117
|
+
const nonceId = this.host.securityManager.getNonceId(nonce);
|
|
118
|
+
const cc = new SecurityCCNonceReport({
|
|
103
119
|
nodeId: this.endpoint.nodeId,
|
|
104
|
-
|
|
120
|
+
endpointIndex: this.endpoint.index,
|
|
105
121
|
nonce,
|
|
106
122
|
});
|
|
107
123
|
try {
|
|
108
|
-
await this.
|
|
124
|
+
await this.host.sendCommand(cc, {
|
|
109
125
|
...this.commandOptions,
|
|
110
126
|
// Seems we need these options or some nodes won't accept the nonce
|
|
111
127
|
transmitOptions: core_1.TransmitOptions.ACK
|
|
@@ -121,7 +137,7 @@ let SecurityCCAPI = class SecurityCCAPI extends API_1.PhysicalCCAPI {
|
|
|
121
137
|
catch (e) {
|
|
122
138
|
if ((0, core_1.isTransmissionError)(e)) {
|
|
123
139
|
// The nonce could not be sent, invalidate it
|
|
124
|
-
this.
|
|
140
|
+
this.host.securityManager.deleteNonce(nonceId);
|
|
125
141
|
return false;
|
|
126
142
|
}
|
|
127
143
|
else {
|
|
@@ -133,82 +149,83 @@ let SecurityCCAPI = class SecurityCCAPI extends API_1.PhysicalCCAPI {
|
|
|
133
149
|
}
|
|
134
150
|
async getSecurityScheme() {
|
|
135
151
|
this.assertSupportsCommand(_Types_1.SecurityCommand, _Types_1.SecurityCommand.SchemeGet);
|
|
136
|
-
const cc = new SecurityCCSchemeGet(
|
|
152
|
+
const cc = new SecurityCCSchemeGet({
|
|
137
153
|
nodeId: this.endpoint.nodeId,
|
|
138
|
-
|
|
154
|
+
endpointIndex: this.endpoint.index,
|
|
139
155
|
});
|
|
140
|
-
await this.
|
|
156
|
+
await this.host.sendCommand(cc, this.commandOptions);
|
|
141
157
|
// There is only one scheme, so we hardcode it
|
|
142
158
|
return [0];
|
|
143
159
|
}
|
|
144
160
|
async reportSecurityScheme(encapsulated) {
|
|
145
161
|
this.assertSupportsCommand(_Types_1.SecurityCommand, _Types_1.SecurityCommand.SchemeReport);
|
|
146
|
-
let cc = new SecurityCCSchemeReport(
|
|
162
|
+
let cc = new SecurityCCSchemeReport({
|
|
147
163
|
nodeId: this.endpoint.nodeId,
|
|
148
|
-
|
|
164
|
+
endpointIndex: this.endpoint.index,
|
|
149
165
|
});
|
|
150
166
|
if (encapsulated) {
|
|
151
|
-
cc = new SecurityCCCommandEncapsulation(
|
|
167
|
+
cc = new SecurityCCCommandEncapsulation({
|
|
152
168
|
nodeId: this.endpoint.nodeId,
|
|
153
|
-
|
|
169
|
+
endpointIndex: this.endpoint.index,
|
|
154
170
|
encapsulated: cc,
|
|
155
171
|
});
|
|
156
172
|
}
|
|
157
|
-
await this.
|
|
173
|
+
await this.host.sendCommand(cc, this.commandOptions);
|
|
158
174
|
}
|
|
159
175
|
async inheritSecurityScheme() {
|
|
160
176
|
this.assertSupportsCommand(_Types_1.SecurityCommand, _Types_1.SecurityCommand.SchemeInherit);
|
|
161
|
-
const cc = new SecurityCCSchemeInherit(
|
|
177
|
+
const cc = new SecurityCCSchemeInherit({
|
|
162
178
|
nodeId: this.endpoint.nodeId,
|
|
163
|
-
|
|
179
|
+
endpointIndex: this.endpoint.index,
|
|
164
180
|
});
|
|
165
|
-
await this.
|
|
181
|
+
await this.host.sendCommand(cc, this.commandOptions);
|
|
166
182
|
// There is only one scheme, so we don't return anything here
|
|
167
183
|
}
|
|
168
184
|
async setNetworkKey(networkKey) {
|
|
169
185
|
this.assertSupportsCommand(_Types_1.SecurityCommand, _Types_1.SecurityCommand.NetworkKeySet);
|
|
170
|
-
const keySet = new SecurityCCNetworkKeySet(
|
|
186
|
+
const keySet = new SecurityCCNetworkKeySet({
|
|
171
187
|
nodeId: this.endpoint.nodeId,
|
|
172
|
-
|
|
188
|
+
endpointIndex: this.endpoint.index,
|
|
173
189
|
networkKey,
|
|
174
190
|
});
|
|
175
|
-
const cc = new SecurityCCCommandEncapsulation(
|
|
191
|
+
const cc = new SecurityCCCommandEncapsulation({
|
|
176
192
|
nodeId: this.endpoint.nodeId,
|
|
177
|
-
|
|
193
|
+
endpointIndex: this.endpoint.index,
|
|
178
194
|
encapsulated: keySet,
|
|
179
195
|
alternativeNetworkKey: Buffer.alloc(16, 0),
|
|
180
196
|
});
|
|
181
|
-
await this.
|
|
197
|
+
await this.host.sendCommand(cc, this.commandOptions);
|
|
182
198
|
}
|
|
183
199
|
async verifyNetworkKey() {
|
|
184
200
|
this.assertSupportsCommand(_Types_1.SecurityCommand, _Types_1.SecurityCommand.NetworkKeyVerify);
|
|
185
|
-
const cc = new SecurityCCNetworkKeyVerify(
|
|
201
|
+
const cc = new SecurityCCNetworkKeyVerify({
|
|
186
202
|
nodeId: this.endpoint.nodeId,
|
|
187
|
-
|
|
203
|
+
endpointIndex: this.endpoint.index,
|
|
188
204
|
});
|
|
189
|
-
await this.
|
|
205
|
+
await this.host.sendCommand(cc, this.commandOptions);
|
|
190
206
|
}
|
|
191
207
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
192
208
|
async getSupportedCommands() {
|
|
193
209
|
this.assertSupportsCommand(_Types_1.SecurityCommand, _Types_1.SecurityCommand.CommandsSupportedGet);
|
|
194
|
-
const cc = new SecurityCCCommandsSupportedGet(
|
|
210
|
+
const cc = new SecurityCCCommandsSupportedGet({
|
|
195
211
|
nodeId: this.endpoint.nodeId,
|
|
196
|
-
|
|
212
|
+
endpointIndex: this.endpoint.index,
|
|
197
213
|
});
|
|
198
|
-
const response = await this.
|
|
214
|
+
const response = await this.host.sendCommand(cc, this.commandOptions);
|
|
199
215
|
if (response) {
|
|
200
216
|
return (0, safe_1.pick)(response, ["supportedCCs", "controlledCCs"]);
|
|
201
217
|
}
|
|
202
218
|
}
|
|
203
219
|
async reportSupportedCommands(supportedCCs, controlledCCs) {
|
|
204
220
|
this.assertSupportsCommand(_Types_1.SecurityCommand, _Types_1.SecurityCommand.CommandsSupportedReport);
|
|
205
|
-
const cc = new SecurityCCCommandsSupportedReport(
|
|
221
|
+
const cc = new SecurityCCCommandsSupportedReport({
|
|
206
222
|
nodeId: this.endpoint.nodeId,
|
|
207
|
-
|
|
223
|
+
endpointIndex: this.endpoint.index,
|
|
208
224
|
supportedCCs,
|
|
209
225
|
controlledCCs,
|
|
226
|
+
reportsToFollow: 0,
|
|
210
227
|
});
|
|
211
|
-
await this.
|
|
228
|
+
await this.host.sendCommand(cc, this.commandOptions);
|
|
212
229
|
}
|
|
213
230
|
};
|
|
214
231
|
exports.SecurityCCAPI = SecurityCCAPI;
|
|
@@ -216,13 +233,13 @@ exports.SecurityCCAPI = SecurityCCAPI = __decorate([
|
|
|
216
233
|
(0, CommandClassDecorators_1.API)(core_1.CommandClasses.Security)
|
|
217
234
|
], SecurityCCAPI);
|
|
218
235
|
let SecurityCC = SecurityCC_1 = class SecurityCC extends CommandClass_1.CommandClass {
|
|
219
|
-
async interview(
|
|
220
|
-
const node = this.getNode(
|
|
221
|
-
const endpoint = this.getEndpoint(
|
|
222
|
-
const api = API_1.CCAPI.create(core_1.CommandClasses.Security,
|
|
236
|
+
async interview(ctx) {
|
|
237
|
+
const node = this.getNode(ctx);
|
|
238
|
+
const endpoint = this.getEndpoint(ctx);
|
|
239
|
+
const api = API_1.CCAPI.create(core_1.CommandClasses.Security, ctx, endpoint).withOptions({
|
|
223
240
|
priority: core_1.MessagePriority.NodeQuery,
|
|
224
241
|
});
|
|
225
|
-
|
|
242
|
+
ctx.logNode(node.id, {
|
|
226
243
|
message: "Querying securely supported commands (S0)...",
|
|
227
244
|
direction: "outbound",
|
|
228
245
|
});
|
|
@@ -238,7 +255,7 @@ let SecurityCC = SecurityCC_1 = class SecurityCC extends CommandClass_1.CommandC
|
|
|
238
255
|
break;
|
|
239
256
|
}
|
|
240
257
|
else if (attempts < MAX_ATTEMPTS) {
|
|
241
|
-
|
|
258
|
+
ctx.logNode(node.id, {
|
|
242
259
|
endpoint: this.endpointIndex,
|
|
243
260
|
message: `Querying securely supported commands (S0), attempt ${attempts}/${MAX_ATTEMPTS} failed. Retrying in 500ms...`,
|
|
244
261
|
level: "warn",
|
|
@@ -248,7 +265,7 @@ let SecurityCC = SecurityCC_1 = class SecurityCC extends CommandClass_1.CommandC
|
|
|
248
265
|
}
|
|
249
266
|
if (!supportedCCs || !controlledCCs) {
|
|
250
267
|
if (node.hasSecurityClass(core_1.SecurityClass.S0_Legacy) === true) {
|
|
251
|
-
|
|
268
|
+
ctx.logNode(node.id, {
|
|
252
269
|
endpoint: this.endpointIndex,
|
|
253
270
|
message: "Querying securely supported commands (S0) failed",
|
|
254
271
|
level: "warn",
|
|
@@ -258,7 +275,7 @@ let SecurityCC = SecurityCC_1 = class SecurityCC extends CommandClass_1.CommandC
|
|
|
258
275
|
else {
|
|
259
276
|
// We didn't know if the node was secure and it didn't respond,
|
|
260
277
|
// assume that it doesn't have the S0 security class
|
|
261
|
-
|
|
278
|
+
ctx.logNode(node.id, `The node was not granted the S0 security class. Continuing interview non-securely.`);
|
|
262
279
|
node.setSecurityClass(core_1.SecurityClass.S0_Legacy, false);
|
|
263
280
|
}
|
|
264
281
|
return;
|
|
@@ -274,7 +291,7 @@ let SecurityCC = SecurityCC_1 = class SecurityCC extends CommandClass_1.CommandC
|
|
|
274
291
|
for (const cc of controlledCCs) {
|
|
275
292
|
logLines.push(`· ${(0, core_1.getCCName)(cc)}`);
|
|
276
293
|
}
|
|
277
|
-
|
|
294
|
+
ctx.logNode(node.id, {
|
|
278
295
|
message: logLines.join("\n"),
|
|
279
296
|
direction: "inbound",
|
|
280
297
|
});
|
|
@@ -310,10 +327,10 @@ let SecurityCC = SecurityCC_1 = class SecurityCC extends CommandClass_1.CommandC
|
|
|
310
327
|
// We know for sure that the node is included securely
|
|
311
328
|
if (node.hasSecurityClass(core_1.SecurityClass.S0_Legacy) !== true) {
|
|
312
329
|
node.setSecurityClass(core_1.SecurityClass.S0_Legacy, true);
|
|
313
|
-
|
|
330
|
+
ctx.logNode(node.id, `The node was granted the S0 security class`);
|
|
314
331
|
}
|
|
315
332
|
// Remember that the interview is complete
|
|
316
|
-
this.setInterviewComplete(
|
|
333
|
+
this.setInterviewComplete(ctx, true);
|
|
317
334
|
}
|
|
318
335
|
/** Tests if a command should be sent secure and thus requires encapsulation */
|
|
319
336
|
static requiresEncapsulation(cc) {
|
|
@@ -348,9 +365,9 @@ let SecurityCC = SecurityCC_1 = class SecurityCC extends CommandClass_1.CommandC
|
|
|
348
365
|
return true;
|
|
349
366
|
}
|
|
350
367
|
/** Encapsulates a command that should be sent encrypted */
|
|
351
|
-
static encapsulate(
|
|
368
|
+
static encapsulate(ownNodeId, securityManager, cc) {
|
|
352
369
|
// TODO: When to return a SecurityCCCommandEncapsulationNonceGet?
|
|
353
|
-
const ret = new SecurityCCCommandEncapsulation(
|
|
370
|
+
const ret = new SecurityCCCommandEncapsulation({
|
|
354
371
|
nodeId: cc.nodeId,
|
|
355
372
|
encapsulated: cc,
|
|
356
373
|
});
|
|
@@ -366,34 +383,35 @@ exports.SecurityCC = SecurityCC = SecurityCC_1 = __decorate([
|
|
|
366
383
|
(0, CommandClassDecorators_1.commandClass)(core_1.CommandClasses.Security),
|
|
367
384
|
(0, CommandClassDecorators_1.implementedVersion)(1)
|
|
368
385
|
], SecurityCC);
|
|
369
|
-
let SecurityCCNonceReport = class SecurityCCNonceReport extends SecurityCC {
|
|
370
|
-
constructor(
|
|
371
|
-
super(
|
|
372
|
-
if (
|
|
373
|
-
core_1.
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
386
|
+
let SecurityCCNonceReport = SecurityCCNonceReport_1 = class SecurityCCNonceReport extends SecurityCC {
|
|
387
|
+
constructor(options) {
|
|
388
|
+
super(options);
|
|
389
|
+
if (options.nonce.length !== HALF_NONCE_SIZE) {
|
|
390
|
+
throw new core_1.ZWaveError(`Nonce must have length ${HALF_NONCE_SIZE}!`, core_1.ZWaveErrorCodes.Argument_Invalid);
|
|
391
|
+
}
|
|
392
|
+
this.nonce = options.nonce;
|
|
393
|
+
}
|
|
394
|
+
static from(raw, ctx) {
|
|
395
|
+
core_1.validatePayload.withReason("Invalid nonce length")(raw.payload.length === HALF_NONCE_SIZE);
|
|
396
|
+
return new SecurityCCNonceReport_1({
|
|
397
|
+
nodeId: ctx.sourceNodeId,
|
|
398
|
+
nonce: raw.payload,
|
|
399
|
+
});
|
|
382
400
|
}
|
|
383
401
|
nonce;
|
|
384
|
-
serialize() {
|
|
402
|
+
serialize(ctx) {
|
|
385
403
|
this.payload = this.nonce;
|
|
386
|
-
return super.serialize();
|
|
404
|
+
return super.serialize(ctx);
|
|
387
405
|
}
|
|
388
|
-
toLogEntry(
|
|
406
|
+
toLogEntry(ctx) {
|
|
389
407
|
return {
|
|
390
|
-
...super.toLogEntry(
|
|
408
|
+
...super.toLogEntry(ctx),
|
|
391
409
|
message: { nonce: (0, safe_1.buffer2hex)(this.nonce) },
|
|
392
410
|
};
|
|
393
411
|
}
|
|
394
412
|
};
|
|
395
413
|
exports.SecurityCCNonceReport = SecurityCCNonceReport;
|
|
396
|
-
exports.SecurityCCNonceReport = SecurityCCNonceReport = __decorate([
|
|
414
|
+
exports.SecurityCCNonceReport = SecurityCCNonceReport = SecurityCCNonceReport_1 = __decorate([
|
|
397
415
|
(0, CommandClassDecorators_1.CCCommand)(_Types_1.SecurityCommand.NonceReport)
|
|
398
416
|
], SecurityCCNonceReport);
|
|
399
417
|
let SecurityCCNonceGet = class SecurityCCNonceGet extends SecurityCC {
|
|
@@ -408,72 +426,70 @@ function getCCResponseForCommandEncapsulation(sent) {
|
|
|
408
426
|
return SecurityCCCommandEncapsulation;
|
|
409
427
|
}
|
|
410
428
|
}
|
|
411
|
-
let SecurityCCCommandEncapsulation = class SecurityCCCommandEncapsulation extends SecurityCC {
|
|
412
|
-
constructor(
|
|
413
|
-
super(
|
|
414
|
-
|
|
415
|
-
if (!this.host.ownNodeId) {
|
|
416
|
-
throw new core_1.ZWaveError(`Secure commands (S0) can only be ${verb} when the controller's node id is known!`, core_1.ZWaveErrorCodes.Driver_NotReady);
|
|
417
|
-
}
|
|
418
|
-
else if (!this.host.securityManager) {
|
|
419
|
-
throw new core_1.ZWaveError(`Secure commands (S0) can only be ${verb} when the network key for the applHost is set`, core_1.ZWaveErrorCodes.Driver_NoSecurity);
|
|
420
|
-
}
|
|
421
|
-
if ((0, CommandClass_1.gotDeserializationOptions)(options)) {
|
|
422
|
-
// HALF_NONCE_SIZE bytes iv, 1 byte frame control, at least 1 CC byte, 1 byte nonce id, 8 bytes auth code
|
|
423
|
-
(0, core_1.validatePayload)(this.payload.length >= HALF_NONCE_SIZE + 1 + 1 + 1 + 8);
|
|
424
|
-
const iv = this.payload.subarray(0, HALF_NONCE_SIZE);
|
|
425
|
-
const encryptedPayload = this.payload.subarray(HALF_NONCE_SIZE, -9);
|
|
426
|
-
const nonceId = this.payload.at(-9);
|
|
427
|
-
const authCode = this.payload.subarray(-8);
|
|
428
|
-
// Retrieve the used nonce from the nonce store
|
|
429
|
-
const nonce = this.host.securityManager.getNonce(nonceId);
|
|
430
|
-
// Only accept the message if the nonce hasn't expired
|
|
431
|
-
core_1.validatePayload.withReason(`Nonce ${(0, safe_1.num2hex)(nonceId)} expired, cannot decode security encapsulated command.`)(!!nonce);
|
|
432
|
-
// and mark the nonce as used
|
|
433
|
-
this.host.securityManager.deleteNonce(nonceId);
|
|
434
|
-
this.authKey = this.host.securityManager.authKey;
|
|
435
|
-
this.encryptionKey = this.host.securityManager.encryptionKey;
|
|
436
|
-
// Validate the encrypted data
|
|
437
|
-
const authData = getAuthenticationData(iv, nonce, this.ccCommand, this.nodeId, this.host.ownNodeId, encryptedPayload);
|
|
438
|
-
const expectedAuthCode = (0, core_1.computeMAC)(authData, this.authKey);
|
|
439
|
-
// Only accept messages with a correct auth code
|
|
440
|
-
core_1.validatePayload.withReason("Invalid auth code, won't accept security encapsulated command.")(authCode.equals(expectedAuthCode));
|
|
441
|
-
// Decrypt the encapsulated CC
|
|
442
|
-
const frameControlAndDecryptedCC = (0, core_1.decryptAES128OFB)(encryptedPayload, this.encryptionKey, Buffer.concat([iv, nonce]));
|
|
443
|
-
const frameControl = frameControlAndDecryptedCC[0];
|
|
444
|
-
this.sequenceCounter = frameControl & 0b1111;
|
|
445
|
-
this.sequenced = !!(frameControl & 0b1_0000);
|
|
446
|
-
this.secondFrame = !!(frameControl & 0b10_0000);
|
|
447
|
-
this.decryptedCCBytes = frameControlAndDecryptedCC.subarray(1);
|
|
448
|
-
// Remember for debugging purposes
|
|
449
|
-
this.authData = authData;
|
|
450
|
-
this.authCode = authCode;
|
|
451
|
-
this.iv = iv;
|
|
452
|
-
}
|
|
453
|
-
else {
|
|
429
|
+
let SecurityCCCommandEncapsulation = SecurityCCCommandEncapsulation_1 = class SecurityCCCommandEncapsulation extends SecurityCC {
|
|
430
|
+
constructor(options) {
|
|
431
|
+
super(options);
|
|
432
|
+
if ("encapsulated" in options) {
|
|
454
433
|
this.encapsulated = options.encapsulated;
|
|
455
|
-
|
|
456
|
-
if (options.alternativeNetworkKey) {
|
|
457
|
-
this.authKey = (0, core_1.generateAuthKey)(options.alternativeNetworkKey);
|
|
458
|
-
this.encryptionKey = (0, core_1.generateEncryptionKey)(options.alternativeNetworkKey);
|
|
459
|
-
}
|
|
460
|
-
else {
|
|
461
|
-
this.authKey = this.host.securityManager.authKey;
|
|
462
|
-
this.encryptionKey = this.host.securityManager.encryptionKey;
|
|
463
|
-
}
|
|
434
|
+
this.encapsulated.encapsulatingCC = this;
|
|
464
435
|
}
|
|
436
|
+
else {
|
|
437
|
+
this.decryptedCCBytes = options.decryptedCCBytes;
|
|
438
|
+
this.sequenced = options.sequenced;
|
|
439
|
+
this.secondFrame = options.secondFrame;
|
|
440
|
+
this.sequenceCounter = options.sequenceCounter;
|
|
441
|
+
}
|
|
442
|
+
this.alternativeNetworkKey = options.alternativeNetworkKey;
|
|
443
|
+
}
|
|
444
|
+
static from(raw, ctx) {
|
|
445
|
+
assertSecurityRX(ctx);
|
|
446
|
+
// HALF_NONCE_SIZE bytes iv, 1 byte frame control, at least 1 CC byte, 1 byte nonce id, 8 bytes auth code
|
|
447
|
+
(0, core_1.validatePayload)(raw.payload.length >= HALF_NONCE_SIZE + 1 + 1 + 1 + 8);
|
|
448
|
+
const iv = raw.payload.subarray(0, HALF_NONCE_SIZE);
|
|
449
|
+
const encryptedPayload = raw.payload.subarray(HALF_NONCE_SIZE, -9);
|
|
450
|
+
const nonceId = raw.payload.at(-9);
|
|
451
|
+
const authCode = raw.payload.subarray(-8);
|
|
452
|
+
// Retrieve the used nonce from the nonce store
|
|
453
|
+
const nonce = ctx.securityManager.getNonce(nonceId);
|
|
454
|
+
// Only accept the message if the nonce hasn't expired
|
|
455
|
+
if (!nonce) {
|
|
456
|
+
core_1.validatePayload.fail(`Nonce ${(0, safe_1.num2hex)(nonceId)} expired, cannot decode security encapsulated command.`);
|
|
457
|
+
}
|
|
458
|
+
// and mark the nonce as used
|
|
459
|
+
ctx.securityManager.deleteNonce(nonceId);
|
|
460
|
+
// Validate the encrypted data
|
|
461
|
+
const authData = getAuthenticationData(iv, nonce, _Types_1.SecurityCommand.CommandEncapsulation, ctx.sourceNodeId, ctx.ownNodeId, encryptedPayload);
|
|
462
|
+
const expectedAuthCode = (0, core_1.computeMAC)(authData, ctx.securityManager.authKey);
|
|
463
|
+
// Only accept messages with a correct auth code
|
|
464
|
+
core_1.validatePayload.withReason("Invalid auth code, won't accept security encapsulated command.")(authCode.equals(expectedAuthCode));
|
|
465
|
+
// Decrypt the encapsulated CC
|
|
466
|
+
const frameControlAndDecryptedCC = (0, core_1.decryptAES128OFB)(encryptedPayload, ctx.securityManager.encryptionKey, Buffer.concat([iv, nonce]));
|
|
467
|
+
const frameControl = frameControlAndDecryptedCC[0];
|
|
468
|
+
const sequenceCounter = frameControl & 0b1111;
|
|
469
|
+
const sequenced = !!(frameControl & 0b1_0000);
|
|
470
|
+
const secondFrame = !!(frameControl & 0b10_0000);
|
|
471
|
+
const decryptedCCBytes = frameControlAndDecryptedCC
|
|
472
|
+
.subarray(1);
|
|
473
|
+
const ret = new SecurityCCCommandEncapsulation_1({
|
|
474
|
+
nodeId: ctx.sourceNodeId,
|
|
475
|
+
sequenceCounter,
|
|
476
|
+
sequenced,
|
|
477
|
+
secondFrame,
|
|
478
|
+
decryptedCCBytes,
|
|
479
|
+
});
|
|
480
|
+
ret.authData = authData;
|
|
481
|
+
ret.authCode = authCode;
|
|
482
|
+
ret.iv = iv;
|
|
483
|
+
return ret;
|
|
465
484
|
}
|
|
466
485
|
sequenced;
|
|
467
486
|
secondFrame;
|
|
468
487
|
sequenceCounter;
|
|
469
488
|
decryptedCCBytes;
|
|
470
489
|
encapsulated;
|
|
471
|
-
|
|
472
|
-
encryptionKey;
|
|
490
|
+
alternativeNetworkKey;
|
|
473
491
|
get nonceId() {
|
|
474
|
-
|
|
475
|
-
return undefined;
|
|
476
|
-
return this.host.securityManager.getNonceId(this.nonce);
|
|
492
|
+
return this.nonce?.[0];
|
|
477
493
|
}
|
|
478
494
|
nonce;
|
|
479
495
|
// Only used testing/for debugging purposes
|
|
@@ -499,25 +515,33 @@ let SecurityCCCommandEncapsulation = class SecurityCCCommandEncapsulation extend
|
|
|
499
515
|
expectMoreMessages() {
|
|
500
516
|
return !!this.sequenced && !this.secondFrame;
|
|
501
517
|
}
|
|
502
|
-
mergePartialCCs(
|
|
518
|
+
mergePartialCCs(partials, ctx) {
|
|
503
519
|
// Concat the CC buffers
|
|
504
520
|
this.decryptedCCBytes = Buffer.concat([...partials, this].map((cc) => cc.decryptedCCBytes));
|
|
505
521
|
// make sure this contains a complete CC command that's worth splitting
|
|
506
522
|
(0, core_1.validatePayload)(this.decryptedCCBytes.length >= 2);
|
|
507
523
|
// and deserialize the CC
|
|
508
|
-
this.encapsulated = CommandClass_1.CommandClass.
|
|
509
|
-
|
|
510
|
-
fromEncapsulation: true,
|
|
511
|
-
encapCC: this,
|
|
512
|
-
});
|
|
524
|
+
this.encapsulated = CommandClass_1.CommandClass.parse(this.decryptedCCBytes, ctx);
|
|
525
|
+
this.encapsulated.encapsulatingCC = this;
|
|
513
526
|
}
|
|
514
|
-
serialize() {
|
|
527
|
+
serialize(ctx) {
|
|
515
528
|
if (!this.nonce)
|
|
516
529
|
throwNoNonce();
|
|
517
530
|
if (this.nonce.length !== HALF_NONCE_SIZE) {
|
|
518
531
|
throwNoNonce("Invalid nonce size");
|
|
519
532
|
}
|
|
520
|
-
|
|
533
|
+
assertSecurityTX(ctx);
|
|
534
|
+
let authKey;
|
|
535
|
+
let encryptionKey;
|
|
536
|
+
if (this.alternativeNetworkKey) {
|
|
537
|
+
authKey = (0, core_1.generateAuthKey)(this.alternativeNetworkKey);
|
|
538
|
+
encryptionKey = (0, core_1.generateEncryptionKey)(this.alternativeNetworkKey);
|
|
539
|
+
}
|
|
540
|
+
else {
|
|
541
|
+
authKey = ctx.securityManager.authKey;
|
|
542
|
+
encryptionKey = ctx.securityManager.encryptionKey;
|
|
543
|
+
}
|
|
544
|
+
const serializedCC = this.encapsulated.serialize(ctx);
|
|
521
545
|
const plaintext = Buffer.concat([
|
|
522
546
|
Buffer.from([0]), // TODO: frame control
|
|
523
547
|
serializedCC,
|
|
@@ -525,10 +549,10 @@ let SecurityCCCommandEncapsulation = class SecurityCCCommandEncapsulation extend
|
|
|
525
549
|
// Encrypt the payload
|
|
526
550
|
const senderNonce = (0, node_crypto_1.randomBytes)(HALF_NONCE_SIZE);
|
|
527
551
|
const iv = Buffer.concat([senderNonce, this.nonce]);
|
|
528
|
-
const ciphertext = (0, core_1.encryptAES128OFB)(plaintext,
|
|
552
|
+
const ciphertext = (0, core_1.encryptAES128OFB)(plaintext, encryptionKey, iv);
|
|
529
553
|
// And generate the auth code
|
|
530
|
-
const authData = getAuthenticationData(senderNonce, this.nonce, this.ccCommand,
|
|
531
|
-
const authCode = (0, core_1.computeMAC)(authData,
|
|
554
|
+
const authData = getAuthenticationData(senderNonce, this.nonce, this.ccCommand, ctx.ownNodeId, this.nodeId, ciphertext);
|
|
555
|
+
const authCode = (0, core_1.computeMAC)(authData, authKey);
|
|
532
556
|
// Remember for debugging purposes
|
|
533
557
|
this.iv = iv;
|
|
534
558
|
this.authData = authData;
|
|
@@ -540,13 +564,13 @@ let SecurityCCCommandEncapsulation = class SecurityCCCommandEncapsulation extend
|
|
|
540
564
|
Buffer.from([this.nonceId]),
|
|
541
565
|
authCode,
|
|
542
566
|
]);
|
|
543
|
-
return super.serialize();
|
|
567
|
+
return super.serialize(ctx);
|
|
544
568
|
}
|
|
545
569
|
computeEncapsulationOverhead() {
|
|
546
570
|
// Security CC adds 8 bytes IV, 1 byte frame control, 1 byte nonce ID, 8 bytes MAC
|
|
547
571
|
return super.computeEncapsulationOverhead() + 18;
|
|
548
572
|
}
|
|
549
|
-
toLogEntry(
|
|
573
|
+
toLogEntry(ctx) {
|
|
550
574
|
const message = {};
|
|
551
575
|
if (this.nonceId != undefined) {
|
|
552
576
|
message["nonce id"] = this.nonceId;
|
|
@@ -582,13 +606,13 @@ let SecurityCCCommandEncapsulation = class SecurityCCCommandEncapsulation extend
|
|
|
582
606
|
}
|
|
583
607
|
}
|
|
584
608
|
return {
|
|
585
|
-
...super.toLogEntry(
|
|
609
|
+
...super.toLogEntry(ctx),
|
|
586
610
|
message,
|
|
587
611
|
};
|
|
588
612
|
}
|
|
589
613
|
};
|
|
590
614
|
exports.SecurityCCCommandEncapsulation = SecurityCCCommandEncapsulation;
|
|
591
|
-
exports.SecurityCCCommandEncapsulation = SecurityCCCommandEncapsulation = __decorate([
|
|
615
|
+
exports.SecurityCCCommandEncapsulation = SecurityCCCommandEncapsulation = SecurityCCCommandEncapsulation_1 = __decorate([
|
|
592
616
|
(0, CommandClassDecorators_1.CCCommand)(_Types_1.SecurityCommand.CommandEncapsulation),
|
|
593
617
|
(0, CommandClassDecorators_1.expectedCCResponse)(getCCResponseForCommandEncapsulation, () => "checkEncapsulated")
|
|
594
618
|
], SecurityCCCommandEncapsulation);
|
|
@@ -599,44 +623,40 @@ exports.SecurityCCCommandEncapsulationNonceGet = SecurityCCCommandEncapsulationN
|
|
|
599
623
|
exports.SecurityCCCommandEncapsulationNonceGet = SecurityCCCommandEncapsulationNonceGet = __decorate([
|
|
600
624
|
(0, CommandClassDecorators_1.CCCommand)(_Types_1.SecurityCommand.CommandEncapsulationNonceGet)
|
|
601
625
|
], SecurityCCCommandEncapsulationNonceGet);
|
|
602
|
-
let SecurityCCSchemeReport = class SecurityCCSchemeReport extends SecurityCC {
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
}
|
|
626
|
+
let SecurityCCSchemeReport = SecurityCCSchemeReport_1 = class SecurityCCSchemeReport extends SecurityCC {
|
|
627
|
+
static from(raw, ctx) {
|
|
628
|
+
(0, core_1.validatePayload)(raw.payload.length >= 1);
|
|
629
|
+
// The including controller MUST NOT perform any validation of the Supported Security Schemes byte
|
|
630
|
+
return new SecurityCCSchemeReport_1({
|
|
631
|
+
nodeId: ctx.sourceNodeId,
|
|
632
|
+
});
|
|
609
633
|
}
|
|
610
|
-
serialize() {
|
|
634
|
+
serialize(ctx) {
|
|
611
635
|
// Since it is unlikely that any more schemes will be added to S0, we hardcode the default scheme here (bit 0 = 0)
|
|
612
636
|
this.payload = Buffer.from([0]);
|
|
613
|
-
return super.serialize();
|
|
637
|
+
return super.serialize(ctx);
|
|
614
638
|
}
|
|
615
|
-
toLogEntry(
|
|
639
|
+
toLogEntry(ctx) {
|
|
616
640
|
return {
|
|
617
|
-
...super.toLogEntry(
|
|
641
|
+
...super.toLogEntry(ctx),
|
|
618
642
|
// Hide the default payload line
|
|
619
643
|
message: undefined,
|
|
620
644
|
};
|
|
621
645
|
}
|
|
622
646
|
};
|
|
623
647
|
exports.SecurityCCSchemeReport = SecurityCCSchemeReport;
|
|
624
|
-
exports.SecurityCCSchemeReport = SecurityCCSchemeReport = __decorate([
|
|
648
|
+
exports.SecurityCCSchemeReport = SecurityCCSchemeReport = SecurityCCSchemeReport_1 = __decorate([
|
|
625
649
|
(0, CommandClassDecorators_1.CCCommand)(_Types_1.SecurityCommand.SchemeReport)
|
|
626
650
|
], SecurityCCSchemeReport);
|
|
627
651
|
let SecurityCCSchemeGet = class SecurityCCSchemeGet extends SecurityCC {
|
|
628
|
-
|
|
629
|
-
super(host, options);
|
|
630
|
-
// Don't care, we won't get sent this and we have no options
|
|
631
|
-
}
|
|
632
|
-
serialize() {
|
|
652
|
+
serialize(ctx) {
|
|
633
653
|
// Since it is unlikely that any more schemes will be added to S0, we hardcode the default scheme here (bit 0 = 0)
|
|
634
654
|
this.payload = Buffer.from([0]);
|
|
635
|
-
return super.serialize();
|
|
655
|
+
return super.serialize(ctx);
|
|
636
656
|
}
|
|
637
|
-
toLogEntry(
|
|
657
|
+
toLogEntry(ctx) {
|
|
638
658
|
return {
|
|
639
|
-
...super.toLogEntry(
|
|
659
|
+
...super.toLogEntry(ctx),
|
|
640
660
|
// Hide the default payload line
|
|
641
661
|
message: undefined,
|
|
642
662
|
};
|
|
@@ -648,18 +668,14 @@ exports.SecurityCCSchemeGet = SecurityCCSchemeGet = __decorate([
|
|
|
648
668
|
(0, CommandClassDecorators_1.expectedCCResponse)(SecurityCCSchemeReport)
|
|
649
669
|
], SecurityCCSchemeGet);
|
|
650
670
|
let SecurityCCSchemeInherit = class SecurityCCSchemeInherit extends SecurityCC {
|
|
651
|
-
|
|
652
|
-
super(host, options);
|
|
653
|
-
// Don't care, we won't get sent this and we have no options
|
|
654
|
-
}
|
|
655
|
-
serialize() {
|
|
671
|
+
serialize(ctx) {
|
|
656
672
|
// Since it is unlikely that any more schemes will be added to S0, we hardcode the default scheme here (bit 0 = 0)
|
|
657
673
|
this.payload = Buffer.from([0]);
|
|
658
|
-
return super.serialize();
|
|
674
|
+
return super.serialize(ctx);
|
|
659
675
|
}
|
|
660
|
-
toLogEntry(
|
|
676
|
+
toLogEntry(ctx) {
|
|
661
677
|
return {
|
|
662
|
-
...super.toLogEntry(
|
|
678
|
+
...super.toLogEntry(ctx),
|
|
663
679
|
// Hide the default payload line
|
|
664
680
|
message: undefined,
|
|
665
681
|
};
|
|
@@ -676,61 +692,62 @@ exports.SecurityCCNetworkKeyVerify = SecurityCCNetworkKeyVerify;
|
|
|
676
692
|
exports.SecurityCCNetworkKeyVerify = SecurityCCNetworkKeyVerify = __decorate([
|
|
677
693
|
(0, CommandClassDecorators_1.CCCommand)(_Types_1.SecurityCommand.NetworkKeyVerify)
|
|
678
694
|
], SecurityCCNetworkKeyVerify);
|
|
679
|
-
let SecurityCCNetworkKeySet = class SecurityCCNetworkKeySet extends SecurityCC {
|
|
680
|
-
constructor(
|
|
681
|
-
super(
|
|
682
|
-
if (
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
695
|
+
let SecurityCCNetworkKeySet = SecurityCCNetworkKeySet_1 = class SecurityCCNetworkKeySet extends SecurityCC {
|
|
696
|
+
constructor(options) {
|
|
697
|
+
super(options);
|
|
698
|
+
if (options.networkKey.length !== 16) {
|
|
699
|
+
throw new core_1.ZWaveError(`The network key must have length 16!`, core_1.ZWaveErrorCodes.Argument_Invalid);
|
|
700
|
+
}
|
|
701
|
+
this.networkKey = options.networkKey;
|
|
702
|
+
}
|
|
703
|
+
static from(raw, ctx) {
|
|
704
|
+
(0, core_1.validatePayload)(raw.payload.length >= 16);
|
|
705
|
+
const networkKey = raw.payload.subarray(0, 16);
|
|
706
|
+
return new SecurityCCNetworkKeySet_1({
|
|
707
|
+
nodeId: ctx.sourceNodeId,
|
|
708
|
+
networkKey,
|
|
709
|
+
});
|
|
692
710
|
}
|
|
693
711
|
networkKey;
|
|
694
|
-
serialize() {
|
|
712
|
+
serialize(ctx) {
|
|
695
713
|
this.payload = this.networkKey;
|
|
696
|
-
return super.serialize();
|
|
714
|
+
return super.serialize(ctx);
|
|
697
715
|
}
|
|
698
|
-
toLogEntry(
|
|
716
|
+
toLogEntry(ctx) {
|
|
699
717
|
// The network key shouldn't be logged, so users can safely post their logs online
|
|
700
|
-
const { message, ...log } = super.toLogEntry(
|
|
718
|
+
const { message, ...log } = super.toLogEntry(ctx);
|
|
701
719
|
return log;
|
|
702
720
|
}
|
|
703
721
|
};
|
|
704
722
|
exports.SecurityCCNetworkKeySet = SecurityCCNetworkKeySet;
|
|
705
|
-
exports.SecurityCCNetworkKeySet = SecurityCCNetworkKeySet = __decorate([
|
|
723
|
+
exports.SecurityCCNetworkKeySet = SecurityCCNetworkKeySet = SecurityCCNetworkKeySet_1 = __decorate([
|
|
706
724
|
(0, CommandClassDecorators_1.CCCommand)(_Types_1.SecurityCommand.NetworkKeySet),
|
|
707
725
|
(0, CommandClassDecorators_1.expectedCCResponse)(SecurityCCNetworkKeyVerify)
|
|
708
726
|
], SecurityCCNetworkKeySet);
|
|
709
|
-
let SecurityCCCommandsSupportedReport = class SecurityCCCommandsSupportedReport extends SecurityCC {
|
|
710
|
-
constructor(
|
|
711
|
-
super(
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
727
|
+
let SecurityCCCommandsSupportedReport = SecurityCCCommandsSupportedReport_1 = class SecurityCCCommandsSupportedReport extends SecurityCC {
|
|
728
|
+
constructor(options) {
|
|
729
|
+
super(options);
|
|
730
|
+
this.supportedCCs = options.supportedCCs;
|
|
731
|
+
this.controlledCCs = options.controlledCCs;
|
|
732
|
+
// TODO: properly split the CCs into multiple reports
|
|
733
|
+
this.reportsToFollow = options.reportsToFollow ?? 0;
|
|
734
|
+
}
|
|
735
|
+
static from(raw, ctx) {
|
|
736
|
+
(0, core_1.validatePayload)(raw.payload.length >= 1);
|
|
737
|
+
const reportsToFollow = raw.payload[0];
|
|
738
|
+
const list = (0, core_1.parseCCList)(raw.payload.subarray(1));
|
|
739
|
+
const supportedCCs = list.supportedCCs;
|
|
740
|
+
const controlledCCs = list.controlledCCs;
|
|
741
|
+
return new SecurityCCCommandsSupportedReport_1({
|
|
742
|
+
nodeId: ctx.sourceNodeId,
|
|
743
|
+
reportsToFollow,
|
|
744
|
+
supportedCCs,
|
|
745
|
+
controlledCCs,
|
|
746
|
+
});
|
|
725
747
|
}
|
|
726
748
|
reportsToFollow;
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
Buffer.from([this.reportsToFollow]),
|
|
730
|
-
(0, core_1.encodeCCList)(this.supportedCCs, this.controlledCCs),
|
|
731
|
-
]);
|
|
732
|
-
return super.serialize();
|
|
733
|
-
}
|
|
749
|
+
supportedCCs;
|
|
750
|
+
controlledCCs;
|
|
734
751
|
getPartialCCSessionId() {
|
|
735
752
|
// Nothing special we can distinguish sessions with
|
|
736
753
|
return {};
|
|
@@ -738,9 +755,7 @@ let SecurityCCCommandsSupportedReport = class SecurityCCCommandsSupportedReport
|
|
|
738
755
|
expectMoreMessages() {
|
|
739
756
|
return this.reportsToFollow > 0;
|
|
740
757
|
}
|
|
741
|
-
|
|
742
|
-
controlledCCs;
|
|
743
|
-
mergePartialCCs(applHost, partials) {
|
|
758
|
+
mergePartialCCs(partials) {
|
|
744
759
|
// Concat the lists of CCs
|
|
745
760
|
this.supportedCCs = [...partials, this]
|
|
746
761
|
.map((report) => report.supportedCCs)
|
|
@@ -749,9 +764,16 @@ let SecurityCCCommandsSupportedReport = class SecurityCCCommandsSupportedReport
|
|
|
749
764
|
.map((report) => report.controlledCCs)
|
|
750
765
|
.reduce((prev, cur) => prev.concat(...cur), []);
|
|
751
766
|
}
|
|
752
|
-
|
|
767
|
+
serialize(ctx) {
|
|
768
|
+
this.payload = Buffer.concat([
|
|
769
|
+
Buffer.from([this.reportsToFollow]),
|
|
770
|
+
(0, core_1.encodeCCList)(this.supportedCCs, this.controlledCCs),
|
|
771
|
+
]);
|
|
772
|
+
return super.serialize(ctx);
|
|
773
|
+
}
|
|
774
|
+
toLogEntry(ctx) {
|
|
753
775
|
return {
|
|
754
|
-
...super.toLogEntry(
|
|
776
|
+
...super.toLogEntry(ctx),
|
|
755
777
|
message: {
|
|
756
778
|
reportsToFollow: this.reportsToFollow,
|
|
757
779
|
supportedCCs: this.supportedCCs
|
|
@@ -767,7 +789,7 @@ let SecurityCCCommandsSupportedReport = class SecurityCCCommandsSupportedReport
|
|
|
767
789
|
}
|
|
768
790
|
};
|
|
769
791
|
exports.SecurityCCCommandsSupportedReport = SecurityCCCommandsSupportedReport;
|
|
770
|
-
exports.SecurityCCCommandsSupportedReport = SecurityCCCommandsSupportedReport = __decorate([
|
|
792
|
+
exports.SecurityCCCommandsSupportedReport = SecurityCCCommandsSupportedReport = SecurityCCCommandsSupportedReport_1 = __decorate([
|
|
771
793
|
(0, CommandClassDecorators_1.CCCommand)(_Types_1.SecurityCommand.CommandsSupportedReport)
|
|
772
794
|
], SecurityCCCommandsSupportedReport);
|
|
773
795
|
let SecurityCCCommandsSupportedGet = class SecurityCCCommandsSupportedGet extends SecurityCC {
|