@zwave-js/cc 14.1.0 → 14.3.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/cjs/cc/AlarmSensorCC.js.map +2 -2
- package/build/cjs/cc/AssociationCC.d.ts +2 -0
- package/build/cjs/cc/AssociationCC.js +5 -0
- package/build/cjs/cc/AssociationCC.js.map +2 -2
- package/build/cjs/cc/AssociationGroupInfoCC.js.map +2 -2
- package/build/cjs/cc/BarrierOperatorCC.js.map +2 -2
- package/build/cjs/cc/BasicCC.js.map +2 -2
- package/build/cjs/cc/BatteryCC.js.map +2 -2
- package/build/cjs/cc/BinarySensorCC.js.map +2 -2
- package/build/cjs/cc/BinarySwitchCC.js.map +2 -2
- package/build/cjs/cc/CRC16CC.d.ts +4 -0
- package/build/cjs/cc/CRC16CC.js +23 -0
- package/build/cjs/cc/CRC16CC.js.map +2 -2
- package/build/cjs/cc/CentralSceneCC.js.map +2 -2
- package/build/cjs/cc/ClimateControlScheduleCC.js.map +2 -2
- package/build/cjs/cc/ClockCC.js.map +2 -2
- package/build/cjs/cc/ColorSwitchCC.js.map +2 -2
- package/build/cjs/cc/ConfigurationCC.d.ts +4 -0
- package/build/cjs/cc/ConfigurationCC.js +10 -0
- package/build/cjs/cc/ConfigurationCC.js.map +2 -2
- package/build/cjs/cc/DoorLockCC.js.map +2 -2
- package/build/cjs/cc/DoorLockLoggingCC.js.map +2 -2
- package/build/cjs/cc/EnergyProductionCC.js.map +2 -2
- package/build/cjs/cc/EntryControlCC.js.map +2 -2
- package/build/cjs/cc/FirmwareUpdateMetaDataCC.js.map +2 -2
- package/build/cjs/cc/HumidityControlModeCC.js.map +2 -2
- package/build/cjs/cc/HumidityControlSetpointCC.js.map +2 -2
- package/build/cjs/cc/InclusionControllerCC.js.map +2 -2
- package/build/cjs/cc/IndicatorCC.js.map +2 -2
- package/build/cjs/cc/IrrigationCC.js.map +2 -2
- package/build/cjs/cc/LanguageCC.js.map +2 -2
- package/build/cjs/cc/LockCC.js.map +2 -2
- package/build/cjs/cc/ManufacturerProprietaryCC.js.map +2 -2
- package/build/cjs/cc/ManufacturerSpecificCC.js.map +2 -2
- package/build/cjs/cc/MeterCC.js.map +2 -2
- package/build/cjs/cc/MultiChannelAssociationCC.d.ts +2 -0
- package/build/cjs/cc/MultiChannelAssociationCC.js +6 -0
- package/build/cjs/cc/MultiChannelAssociationCC.js.map +2 -2
- package/build/cjs/cc/MultiChannelCC.d.ts +10 -0
- package/build/cjs/cc/MultiChannelCC.js +65 -0
- package/build/cjs/cc/MultiChannelCC.js.map +2 -2
- package/build/cjs/cc/MultiCommandCC.d.ts +4 -0
- package/build/cjs/cc/MultiCommandCC.js +34 -1
- package/build/cjs/cc/MultiCommandCC.js.map +2 -2
- package/build/cjs/cc/MultilevelSensorCC.js.map +2 -2
- package/build/cjs/cc/MultilevelSwitchCC.js.map +2 -2
- package/build/cjs/cc/NodeNamingCC.js.map +2 -2
- package/build/cjs/cc/NotificationCC.js.map +2 -2
- package/build/cjs/cc/PowerlevelCC.js.map +2 -2
- package/build/cjs/cc/ProtectionCC.js.map +2 -2
- package/build/cjs/cc/SceneActivationCC.js.map +2 -2
- package/build/cjs/cc/SceneActuatorConfigurationCC.js.map +2 -2
- package/build/cjs/cc/SceneControllerConfigurationCC.js.map +2 -2
- package/build/cjs/cc/ScheduleEntryLockCC.js.map +2 -2
- package/build/cjs/cc/Security2CC.d.ts +7 -1
- package/build/cjs/cc/Security2CC.js +383 -52
- package/build/cjs/cc/Security2CC.js.map +2 -2
- package/build/cjs/cc/SecurityCC.d.ts +7 -0
- package/build/cjs/cc/SecurityCC.js +101 -6
- package/build/cjs/cc/SecurityCC.js.map +2 -2
- package/build/cjs/cc/SoundSwitchCC.js.map +2 -2
- package/build/cjs/cc/SupervisionCC.d.ts +4 -0
- package/build/cjs/cc/SupervisionCC.js +25 -0
- package/build/cjs/cc/SupervisionCC.js.map +2 -2
- package/build/cjs/cc/ThermostatFanModeCC.js.map +2 -2
- package/build/cjs/cc/ThermostatModeCC.js.map +2 -2
- package/build/cjs/cc/ThermostatSetbackCC.js.map +2 -2
- package/build/cjs/cc/ThermostatSetpointCC.js.map +2 -2
- package/build/cjs/cc/TimeCC.js.map +2 -2
- package/build/cjs/cc/TimeParametersCC.js.map +2 -2
- package/build/cjs/cc/TransportServiceCC.d.ts +5 -0
- package/build/cjs/cc/TransportServiceCC.js +13 -0
- package/build/cjs/cc/TransportServiceCC.js.map +2 -2
- package/build/cjs/cc/UserCodeCC.js.map +2 -2
- package/build/cjs/cc/VersionCC.js.map +2 -2
- package/build/cjs/cc/WakeUpCC.js.map +2 -2
- package/build/cjs/cc/WindowCoveringCC.js.map +2 -2
- package/build/cjs/cc/ZWavePlusCC.js.map +2 -2
- package/build/cjs/cc/ZWaveProtocolCC.js.map +2 -2
- package/build/cjs/cc/manufacturerProprietary/Decorators.js +6 -5
- package/build/cjs/cc/manufacturerProprietary/Decorators.js.map +2 -2
- package/build/cjs/cc/manufacturerProprietary/FibaroCC.js.map +2 -2
- package/build/cjs/lib/CommandClass.d.ts +15 -1
- package/build/cjs/lib/CommandClass.js +56 -1
- package/build/cjs/lib/CommandClass.js.map +2 -2
- package/build/cjs/lib/CommandClassDecorators.js +7 -6
- package/build/cjs/lib/CommandClassDecorators.js.map +2 -2
- package/build/cjs/lib/Security2/Extension.js +2 -2
- package/build/cjs/lib/Security2/Extension.js.map +2 -2
- package/build/esm/cc/AlarmSensorCC.d.ts.map +1 -1
- package/build/esm/cc/AlarmSensorCC.js +1 -0
- package/build/esm/cc/AlarmSensorCC.js.map +1 -1
- package/build/esm/cc/AssociationCC.d.ts +2 -0
- package/build/esm/cc/AssociationCC.d.ts.map +1 -1
- package/build/esm/cc/AssociationCC.js +14 -0
- package/build/esm/cc/AssociationCC.js.map +1 -1
- package/build/esm/cc/AssociationGroupInfoCC.d.ts.map +1 -1
- package/build/esm/cc/AssociationGroupInfoCC.js +6 -0
- package/build/esm/cc/AssociationGroupInfoCC.js.map +1 -1
- package/build/esm/cc/BarrierOperatorCC.d.ts.map +1 -1
- package/build/esm/cc/BarrierOperatorCC.js +3 -0
- package/build/esm/cc/BarrierOperatorCC.js.map +1 -1
- package/build/esm/cc/BasicCC.d.ts.map +1 -1
- package/build/esm/cc/BasicCC.js +2 -0
- package/build/esm/cc/BasicCC.js.map +1 -1
- package/build/esm/cc/BatteryCC.d.ts.map +1 -1
- package/build/esm/cc/BatteryCC.js +1 -0
- package/build/esm/cc/BatteryCC.js.map +1 -1
- package/build/esm/cc/BinarySensorCC.d.ts.map +1 -1
- package/build/esm/cc/BinarySensorCC.js +3 -0
- package/build/esm/cc/BinarySensorCC.js.map +1 -1
- package/build/esm/cc/BinarySwitchCC.d.ts.map +1 -1
- package/build/esm/cc/BinarySwitchCC.js +2 -0
- package/build/esm/cc/BinarySwitchCC.js.map +1 -1
- package/build/esm/cc/CRC16CC.d.ts +4 -0
- package/build/esm/cc/CRC16CC.d.ts.map +1 -1
- package/build/esm/cc/CRC16CC.js +30 -0
- package/build/esm/cc/CRC16CC.js.map +1 -1
- package/build/esm/cc/CentralSceneCC.d.ts.map +1 -1
- package/build/esm/cc/CentralSceneCC.js +1 -0
- package/build/esm/cc/CentralSceneCC.js.map +1 -1
- package/build/esm/cc/ClimateControlScheduleCC.d.ts.map +1 -1
- package/build/esm/cc/ClimateControlScheduleCC.js +3 -0
- package/build/esm/cc/ClimateControlScheduleCC.js.map +1 -1
- package/build/esm/cc/ClockCC.d.ts.map +1 -1
- package/build/esm/cc/ClockCC.js +1 -0
- package/build/esm/cc/ClockCC.js.map +1 -1
- package/build/esm/cc/ColorSwitchCC.d.ts.map +1 -1
- package/build/esm/cc/ColorSwitchCC.js +6 -0
- package/build/esm/cc/ColorSwitchCC.js.map +1 -1
- package/build/esm/cc/ConfigurationCC.d.ts +4 -0
- package/build/esm/cc/ConfigurationCC.d.ts.map +1 -1
- package/build/esm/cc/ConfigurationCC.js +27 -0
- package/build/esm/cc/ConfigurationCC.js.map +1 -1
- package/build/esm/cc/DoorLockCC.d.ts.map +1 -1
- package/build/esm/cc/DoorLockCC.js +2 -0
- package/build/esm/cc/DoorLockCC.js.map +1 -1
- package/build/esm/cc/DoorLockLoggingCC.d.ts.map +1 -1
- package/build/esm/cc/DoorLockLoggingCC.js +1 -0
- package/build/esm/cc/DoorLockLoggingCC.js.map +1 -1
- package/build/esm/cc/EnergyProductionCC.d.ts.map +1 -1
- package/build/esm/cc/EnergyProductionCC.js +2 -0
- package/build/esm/cc/EnergyProductionCC.js.map +1 -1
- package/build/esm/cc/EntryControlCC.d.ts.map +1 -1
- package/build/esm/cc/EntryControlCC.js +1 -0
- package/build/esm/cc/EntryControlCC.js.map +1 -1
- package/build/esm/cc/FirmwareUpdateMetaDataCC.d.ts.map +1 -1
- package/build/esm/cc/FirmwareUpdateMetaDataCC.js +5 -0
- package/build/esm/cc/FirmwareUpdateMetaDataCC.js.map +1 -1
- package/build/esm/cc/HumidityControlModeCC.d.ts.map +1 -1
- package/build/esm/cc/HumidityControlModeCC.js +1 -0
- package/build/esm/cc/HumidityControlModeCC.js.map +1 -1
- package/build/esm/cc/HumidityControlSetpointCC.d.ts.map +1 -1
- package/build/esm/cc/HumidityControlSetpointCC.js +4 -0
- package/build/esm/cc/HumidityControlSetpointCC.js.map +1 -1
- package/build/esm/cc/InclusionControllerCC.d.ts.map +1 -1
- package/build/esm/cc/InclusionControllerCC.js +2 -0
- package/build/esm/cc/InclusionControllerCC.js.map +1 -1
- package/build/esm/cc/IndicatorCC.d.ts.map +1 -1
- package/build/esm/cc/IndicatorCC.js +7 -0
- package/build/esm/cc/IndicatorCC.js.map +1 -1
- package/build/esm/cc/IrrigationCC.d.ts.map +1 -1
- package/build/esm/cc/IrrigationCC.js +9 -0
- package/build/esm/cc/IrrigationCC.js.map +1 -1
- package/build/esm/cc/LanguageCC.d.ts.map +1 -1
- package/build/esm/cc/LanguageCC.js +1 -0
- package/build/esm/cc/LanguageCC.js.map +1 -1
- package/build/esm/cc/LockCC.d.ts.map +1 -1
- package/build/esm/cc/LockCC.js +1 -0
- package/build/esm/cc/LockCC.js.map +1 -1
- package/build/esm/cc/ManufacturerProprietaryCC.d.ts.map +1 -1
- package/build/esm/cc/ManufacturerProprietaryCC.js +2 -0
- package/build/esm/cc/ManufacturerProprietaryCC.js.map +1 -1
- package/build/esm/cc/ManufacturerSpecificCC.d.ts.map +1 -1
- package/build/esm/cc/ManufacturerSpecificCC.js +2 -0
- package/build/esm/cc/ManufacturerSpecificCC.js.map +1 -1
- package/build/esm/cc/MeterCC.d.ts.map +1 -1
- package/build/esm/cc/MeterCC.js +4 -0
- package/build/esm/cc/MeterCC.js.map +1 -1
- package/build/esm/cc/MultiChannelAssociationCC.d.ts +2 -0
- package/build/esm/cc/MultiChannelAssociationCC.d.ts.map +1 -1
- package/build/esm/cc/MultiChannelAssociationCC.js +17 -0
- package/build/esm/cc/MultiChannelAssociationCC.js.map +1 -1
- package/build/esm/cc/MultiChannelCC.d.ts +10 -0
- package/build/esm/cc/MultiChannelCC.d.ts.map +1 -1
- package/build/esm/cc/MultiChannelCC.js +94 -0
- package/build/esm/cc/MultiChannelCC.js.map +1 -1
- package/build/esm/cc/MultiCommandCC.d.ts +4 -0
- package/build/esm/cc/MultiCommandCC.d.ts.map +1 -1
- package/build/esm/cc/MultiCommandCC.js +35 -1
- package/build/esm/cc/MultiCommandCC.js.map +1 -1
- package/build/esm/cc/MultilevelSensorCC.d.ts.map +1 -1
- package/build/esm/cc/MultilevelSensorCC.js +5 -0
- package/build/esm/cc/MultilevelSensorCC.js.map +1 -1
- package/build/esm/cc/MultilevelSwitchCC.d.ts.map +1 -1
- package/build/esm/cc/MultilevelSwitchCC.js +4 -0
- package/build/esm/cc/MultilevelSwitchCC.js.map +1 -1
- package/build/esm/cc/NodeNamingCC.d.ts.map +1 -1
- package/build/esm/cc/NodeNamingCC.js +2 -0
- package/build/esm/cc/NodeNamingCC.js.map +1 -1
- package/build/esm/cc/NotificationCC.d.ts.map +1 -1
- package/build/esm/cc/NotificationCC.js +9 -0
- package/build/esm/cc/NotificationCC.js.map +1 -1
- package/build/esm/cc/PowerlevelCC.d.ts.map +1 -1
- package/build/esm/cc/PowerlevelCC.js +4 -0
- package/build/esm/cc/PowerlevelCC.js.map +1 -1
- package/build/esm/cc/ProtectionCC.d.ts.map +1 -1
- package/build/esm/cc/ProtectionCC.js +3 -0
- package/build/esm/cc/ProtectionCC.js.map +1 -1
- package/build/esm/cc/SceneActivationCC.d.ts.map +1 -1
- package/build/esm/cc/SceneActivationCC.js +1 -0
- package/build/esm/cc/SceneActivationCC.js.map +1 -1
- package/build/esm/cc/SceneActuatorConfigurationCC.d.ts.map +1 -1
- package/build/esm/cc/SceneActuatorConfigurationCC.js +2 -0
- package/build/esm/cc/SceneActuatorConfigurationCC.js.map +1 -1
- package/build/esm/cc/SceneControllerConfigurationCC.d.ts.map +1 -1
- package/build/esm/cc/SceneControllerConfigurationCC.js +2 -0
- package/build/esm/cc/SceneControllerConfigurationCC.js.map +1 -1
- package/build/esm/cc/ScheduleEntryLockCC.d.ts.map +1 -1
- package/build/esm/cc/ScheduleEntryLockCC.js +14 -0
- package/build/esm/cc/ScheduleEntryLockCC.js.map +1 -1
- package/build/esm/cc/Security2CC.d.ts +7 -1
- package/build/esm/cc/Security2CC.d.ts.map +1 -1
- package/build/esm/cc/Security2CC.js +534 -68
- package/build/esm/cc/Security2CC.js.map +1 -1
- package/build/esm/cc/SecurityCC.d.ts +7 -0
- package/build/esm/cc/SecurityCC.d.ts.map +1 -1
- package/build/esm/cc/SecurityCC.js +133 -7
- package/build/esm/cc/SecurityCC.js.map +1 -1
- package/build/esm/cc/SoundSwitchCC.d.ts.map +1 -1
- package/build/esm/cc/SoundSwitchCC.js +7 -0
- package/build/esm/cc/SoundSwitchCC.js.map +1 -1
- package/build/esm/cc/SupervisionCC.d.ts +4 -0
- package/build/esm/cc/SupervisionCC.d.ts.map +1 -1
- package/build/esm/cc/SupervisionCC.js +30 -0
- package/build/esm/cc/SupervisionCC.js.map +1 -1
- package/build/esm/cc/ThermostatFanModeCC.d.ts.map +1 -1
- package/build/esm/cc/ThermostatFanModeCC.js +1 -0
- package/build/esm/cc/ThermostatFanModeCC.js.map +1 -1
- package/build/esm/cc/ThermostatModeCC.d.ts.map +1 -1
- package/build/esm/cc/ThermostatModeCC.js +3 -0
- package/build/esm/cc/ThermostatModeCC.js.map +1 -1
- package/build/esm/cc/ThermostatSetbackCC.d.ts.map +1 -1
- package/build/esm/cc/ThermostatSetbackCC.js +2 -0
- package/build/esm/cc/ThermostatSetbackCC.js.map +1 -1
- package/build/esm/cc/ThermostatSetpointCC.d.ts.map +1 -1
- package/build/esm/cc/ThermostatSetpointCC.js +6 -0
- package/build/esm/cc/ThermostatSetpointCC.js.map +1 -1
- package/build/esm/cc/TimeCC.d.ts.map +1 -1
- package/build/esm/cc/TimeCC.js +4 -0
- package/build/esm/cc/TimeCC.js.map +1 -1
- package/build/esm/cc/TimeParametersCC.d.ts.map +1 -1
- package/build/esm/cc/TimeParametersCC.js +1 -0
- package/build/esm/cc/TimeParametersCC.js.map +1 -1
- package/build/esm/cc/TransportServiceCC.d.ts +5 -0
- package/build/esm/cc/TransportServiceCC.d.ts.map +1 -1
- package/build/esm/cc/TransportServiceCC.js +24 -0
- package/build/esm/cc/TransportServiceCC.js.map +1 -1
- package/build/esm/cc/UserCodeCC.d.ts.map +1 -1
- package/build/esm/cc/UserCodeCC.js +12 -0
- package/build/esm/cc/UserCodeCC.js.map +1 -1
- package/build/esm/cc/VersionCC.d.ts.map +1 -1
- package/build/esm/cc/VersionCC.js +4 -0
- package/build/esm/cc/VersionCC.js.map +1 -1
- package/build/esm/cc/WakeUpCC.d.ts.map +1 -1
- package/build/esm/cc/WakeUpCC.js +1 -0
- package/build/esm/cc/WakeUpCC.js.map +1 -1
- package/build/esm/cc/WindowCoveringCC.d.ts.map +1 -1
- package/build/esm/cc/WindowCoveringCC.js +5 -0
- package/build/esm/cc/WindowCoveringCC.js.map +1 -1
- package/build/esm/cc/ZWavePlusCC.d.ts.map +1 -1
- package/build/esm/cc/ZWavePlusCC.js +1 -0
- package/build/esm/cc/ZWavePlusCC.js.map +1 -1
- package/build/esm/cc/ZWaveProtocolCC.d.ts.map +1 -1
- package/build/esm/cc/ZWaveProtocolCC.js +27 -0
- package/build/esm/cc/ZWaveProtocolCC.js.map +1 -1
- package/build/esm/cc/manufacturerProprietary/Decorators.d.ts.map +1 -1
- package/build/esm/cc/manufacturerProprietary/Decorators.js +2 -1
- package/build/esm/cc/manufacturerProprietary/Decorators.js.map +1 -1
- package/build/esm/cc/manufacturerProprietary/FibaroCC.d.ts.map +1 -1
- package/build/esm/cc/manufacturerProprietary/FibaroCC.js +3 -0
- package/build/esm/cc/manufacturerProprietary/FibaroCC.js.map +1 -1
- package/build/esm/lib/CommandClass.d.ts +15 -1
- package/build/esm/lib/CommandClass.d.ts.map +1 -1
- package/build/esm/lib/CommandClass.js +94 -1
- package/build/esm/lib/CommandClass.js.map +1 -1
- package/build/esm/lib/CommandClassDecorators.d.ts.map +1 -1
- package/build/esm/lib/CommandClassDecorators.js +2 -1
- package/build/esm/lib/CommandClassDecorators.js.map +1 -1
- package/build/esm/lib/Security2/Extension.js +1 -1
- package/build/esm/lib/Security2/Extension.js.map +1 -1
- package/package.json +6 -6
|
@@ -32,7 +32,7 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
|
|
|
32
32
|
}
|
|
33
33
|
return useValue ? value : void 0;
|
|
34
34
|
};
|
|
35
|
-
import { CommandClasses, MPANState, MessagePriority,
|
|
35
|
+
import { CommandClasses, MPANState, MessagePriority, SPANState, SecurityClass, TransmitOptions, ZWaveError, ZWaveErrorCodes, decryptAES128CCMAsync, decryptAES128CCMSync, encodeBitMask, encryptAES128CCMAsync, encryptAES128CCMSync, getCCName, highResTimestamp, isLongRangeNodeId, isTransmissionError, isZWaveError, parseBitMask, parseCCList, securityClassIsS2, securityClassOrder, validatePayload, } from "@zwave-js/core";
|
|
36
36
|
import { EncapsulationFlags, NODE_ID_BROADCAST, NODE_ID_BROADCAST_LR, encodeCCList, } from "@zwave-js/core/safe";
|
|
37
37
|
import { Bytes } from "@zwave-js/shared/safe";
|
|
38
38
|
import { buffer2hex, getEnumMemberName, pick } from "@zwave-js/shared/safe";
|
|
@@ -56,6 +56,7 @@ function bitMaskToSecurityClass(buffer, offset) {
|
|
|
56
56
|
validatePayload(keys.length === 1);
|
|
57
57
|
return keys[0];
|
|
58
58
|
}
|
|
59
|
+
const SECURITY_S2_AUTH_TAG_LENGTH = 8;
|
|
59
60
|
function getAuthenticationData(sendingNodeId, destination, homeId, commandLength, unencryptedPayload) {
|
|
60
61
|
const nodeIdSize = isLongRangeNodeId(sendingNodeId) || isLongRangeNodeId(destination)
|
|
61
62
|
? 2
|
|
@@ -110,17 +111,20 @@ function assertSecurityTX(ctx, destination) {
|
|
|
110
111
|
}
|
|
111
112
|
return ret;
|
|
112
113
|
}
|
|
113
|
-
|
|
114
|
+
/** @deprecated Use {@link decryptSinglecastAsync} instead */
|
|
115
|
+
function decryptSinglecastSync(ctx, securityManager, sendingNodeId, curSequenceNumber, prevSequenceNumber, ciphertext, authData, authTag, spanState, extensions) {
|
|
114
116
|
const decryptWithNonce = (nonce) => {
|
|
115
117
|
const { keyCCM: key } = securityManager.getKeysForNode(sendingNodeId);
|
|
116
118
|
const iv = nonce;
|
|
117
119
|
return {
|
|
118
120
|
key,
|
|
119
121
|
iv,
|
|
120
|
-
|
|
122
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
123
|
+
...decryptAES128CCMSync(key, iv, ciphertext, authData, authTag),
|
|
121
124
|
};
|
|
122
125
|
};
|
|
123
126
|
const getNonceAndDecrypt = () => {
|
|
127
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
124
128
|
const iv = securityManager.nextNonce(sendingNodeId);
|
|
125
129
|
return decryptWithNonce(iv);
|
|
126
130
|
};
|
|
@@ -172,6 +176,7 @@ function decryptSinglecast(ctx, securityManager, sendingNodeId, curSequenceNumbe
|
|
|
172
176
|
const isBootstrappingNode = securityManager.tempKeys.has(sendingNodeId);
|
|
173
177
|
if (isBootstrappingNode) {
|
|
174
178
|
// We're currently bootstrapping the node, it might be using a temporary key
|
|
179
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
175
180
|
securityManager.initializeTempSPAN(sendingNodeId, senderEI, receiverEI);
|
|
176
181
|
const ret = getNonceAndDecrypt();
|
|
177
182
|
// Decryption with the temporary key worked
|
|
@@ -203,6 +208,7 @@ function decryptSinglecast(ctx, securityManager, sendingNodeId, curSequenceNumbe
|
|
|
203
208
|
continue;
|
|
204
209
|
}
|
|
205
210
|
// Initialize an SPAN with that security class
|
|
211
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
206
212
|
securityManager.initializeSPAN(sendingNodeId, secClass, senderEI, receiverEI);
|
|
207
213
|
const ret = getNonceAndDecrypt();
|
|
208
214
|
// It worked, return the result
|
|
@@ -230,17 +236,212 @@ function decryptSinglecast(ctx, securityManager, sendingNodeId, curSequenceNumbe
|
|
|
230
236
|
securityClass: undefined,
|
|
231
237
|
};
|
|
232
238
|
}
|
|
233
|
-
function
|
|
239
|
+
async function decryptSinglecastAsync(ctx, securityManager, sendingNodeId, curSequenceNumber, prevSequenceNumber, ciphertext, authData, authTag, spanState, extensions) {
|
|
240
|
+
const decryptWithNonce = async (nonce) => {
|
|
241
|
+
const { keyCCM: key } = securityManager.getKeysForNode(sendingNodeId);
|
|
242
|
+
const iv = nonce;
|
|
243
|
+
return {
|
|
244
|
+
key,
|
|
245
|
+
iv,
|
|
246
|
+
...(await decryptAES128CCMAsync(ciphertext, key, iv, authData, authTag)),
|
|
247
|
+
};
|
|
248
|
+
};
|
|
249
|
+
const getNonceAndDecrypt = async () => {
|
|
250
|
+
const iv = await securityManager.nextNonceAsync(sendingNodeId);
|
|
251
|
+
return decryptWithNonce(iv);
|
|
252
|
+
};
|
|
253
|
+
if (spanState.type === SPANState.SPAN) {
|
|
254
|
+
// There SHOULD be a shared SPAN between both parties. But experience has shown that both could have
|
|
255
|
+
// sent a command at roughly the same time, using the same SPAN for encryption.
|
|
256
|
+
// To avoid a nasty desync and both nodes trying to resync at the same time, causing message loss,
|
|
257
|
+
// we accept commands encrypted with the previous SPAN under very specific circumstances:
|
|
258
|
+
if (
|
|
259
|
+
// The previous SPAN is still known, i.e. the node didn't send another command that was successfully decrypted
|
|
260
|
+
!!spanState.currentSPAN
|
|
261
|
+
// it is still valid
|
|
262
|
+
&& spanState.currentSPAN.expires > highResTimestamp()
|
|
263
|
+
// The received command is exactly the next, expected one
|
|
264
|
+
&& prevSequenceNumber != undefined
|
|
265
|
+
&& curSequenceNumber === ((prevSequenceNumber + 1) & 0xff)
|
|
266
|
+
// And in case of a mock-based test, do this only on the controller
|
|
267
|
+
&& !ctx.__internalIsMockNode) {
|
|
268
|
+
const nonce = spanState.currentSPAN.nonce;
|
|
269
|
+
spanState.currentSPAN = undefined;
|
|
270
|
+
// If we could decrypt this way, we're done...
|
|
271
|
+
const result = await decryptWithNonce(nonce);
|
|
272
|
+
if (result.authOK) {
|
|
273
|
+
return {
|
|
274
|
+
...result,
|
|
275
|
+
securityClass: spanState.securityClass,
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
// ...otherwise, we need to try the normal way
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
// forgetting the current SPAN shouldn't be necessary but better be safe than sorry
|
|
282
|
+
spanState.currentSPAN = undefined;
|
|
283
|
+
}
|
|
284
|
+
// This can only happen if the security class is known
|
|
285
|
+
return {
|
|
286
|
+
...(await getNonceAndDecrypt()),
|
|
287
|
+
securityClass: spanState.securityClass,
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
else if (spanState.type === SPANState.LocalEI) {
|
|
291
|
+
// We've sent the other our receiver's EI and received its sender's EI,
|
|
292
|
+
// meaning we can now establish an SPAN
|
|
293
|
+
const senderEI = getSenderEI(extensions);
|
|
294
|
+
if (!senderEI)
|
|
295
|
+
failNoSPAN();
|
|
296
|
+
const receiverEI = spanState.receiverEI;
|
|
297
|
+
// How we do this depends on whether we know the security class of the other node
|
|
298
|
+
const isBootstrappingNode = securityManager.tempKeys.has(sendingNodeId);
|
|
299
|
+
if (isBootstrappingNode) {
|
|
300
|
+
// We're currently bootstrapping the node, it might be using a temporary key
|
|
301
|
+
await securityManager.initializeTempSPANAsync(sendingNodeId, senderEI, receiverEI);
|
|
302
|
+
const ret = await getNonceAndDecrypt();
|
|
303
|
+
// Decryption with the temporary key worked
|
|
304
|
+
if (ret.authOK) {
|
|
305
|
+
return {
|
|
306
|
+
...ret,
|
|
307
|
+
securityClass: SecurityClass.Temporary,
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
// Reset the SPAN state and try with the recently granted security class
|
|
311
|
+
securityManager.setSPANState(sendingNodeId, spanState);
|
|
312
|
+
}
|
|
313
|
+
// When ending up here, one of two situations has occured:
|
|
314
|
+
// a) We've taken over an existing network and do not know the node's security class
|
|
315
|
+
// b) We know the security class, but we're about to establish a new SPAN. This may happen at a lower
|
|
316
|
+
// security class than the one the node normally uses, e.g. when we're being queried for securely
|
|
317
|
+
// supported CCs.
|
|
318
|
+
// In both cases, we should simply try decoding with multiple security classes, starting from the highest one.
|
|
319
|
+
// If this fails, we restore the previous (partial) SPAN state.
|
|
320
|
+
// Try all security classes where we do not definitely know that it was not granted
|
|
321
|
+
// While bootstrapping a node, we consider the key that is being exchanged (including S0) to be the highest. No need to look at others
|
|
322
|
+
const possibleSecurityClasses = isBootstrappingNode
|
|
323
|
+
? [ctx.getHighestSecurityClass(sendingNodeId)]
|
|
324
|
+
: securityClassOrder.filter((s) => ctx.hasSecurityClass(sendingNodeId, s)
|
|
325
|
+
!== false);
|
|
326
|
+
for (const secClass of possibleSecurityClasses) {
|
|
327
|
+
// Skip security classes we don't have keys for
|
|
328
|
+
if (!securityManager.hasKeysForSecurityClass(secClass)) {
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
// Initialize an SPAN with that security class
|
|
332
|
+
await securityManager.initializeSPANAsync(sendingNodeId, secClass, senderEI, receiverEI);
|
|
333
|
+
const ret = await getNonceAndDecrypt();
|
|
334
|
+
// It worked, return the result
|
|
335
|
+
if (ret.authOK) {
|
|
336
|
+
// Also if we weren't sure before, we now know that the security class is granted
|
|
337
|
+
if (ctx.hasSecurityClass(sendingNodeId, secClass)
|
|
338
|
+
=== undefined) {
|
|
339
|
+
ctx.setSecurityClass(sendingNodeId, secClass, true);
|
|
340
|
+
}
|
|
341
|
+
return {
|
|
342
|
+
...ret,
|
|
343
|
+
securityClass: secClass,
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
// Reset the SPAN state and try with the next security class
|
|
348
|
+
securityManager.setSPANState(sendingNodeId, spanState);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
// Nothing worked, fail the decryption
|
|
353
|
+
return {
|
|
354
|
+
plaintext: new Uint8Array(),
|
|
355
|
+
authOK: false,
|
|
356
|
+
securityClass: undefined,
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
/** @deprecated Use {@link decryptMulticastAsync} instead */
|
|
360
|
+
function decryptMulticastSync(sendingNodeId, securityManager, groupId, ciphertext, authData, authTag) {
|
|
361
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
234
362
|
const iv = securityManager.nextPeerMPAN(sendingNodeId, groupId);
|
|
235
363
|
const { keyCCM: key } = securityManager.getKeysForNode(sendingNodeId);
|
|
236
364
|
return {
|
|
237
365
|
key,
|
|
238
366
|
iv,
|
|
239
|
-
|
|
367
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
368
|
+
...decryptAES128CCMSync(key, iv, ciphertext, authData, authTag),
|
|
240
369
|
// The security class is irrelevant when decrypting multicast commands
|
|
241
370
|
securityClass: undefined,
|
|
242
371
|
};
|
|
243
372
|
}
|
|
373
|
+
async function decryptMulticastAsync(sendingNodeId, securityManager, groupId, ciphertext, authData, authTag) {
|
|
374
|
+
const iv = await securityManager.nextPeerMPANAsync(sendingNodeId, groupId);
|
|
375
|
+
const { keyCCM: key } = securityManager.getKeysForNode(sendingNodeId);
|
|
376
|
+
return {
|
|
377
|
+
key,
|
|
378
|
+
iv,
|
|
379
|
+
...(await decryptAES128CCMAsync(ciphertext, key, iv, authData, authTag)),
|
|
380
|
+
// The security class is irrelevant when decrypting multicast commands
|
|
381
|
+
securityClass: undefined,
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
function parseExtensions(buffer, wasEncrypted) {
|
|
385
|
+
const extensions = [];
|
|
386
|
+
let mustDiscardCommand = false;
|
|
387
|
+
let offset = 0;
|
|
388
|
+
parsing: while (true) {
|
|
389
|
+
if (buffer.length < offset + 2) {
|
|
390
|
+
// An S2 extension was expected, but the buffer is too short
|
|
391
|
+
mustDiscardCommand = true;
|
|
392
|
+
break parsing;
|
|
393
|
+
}
|
|
394
|
+
// The length field could be too large, which would cause part of the actual ciphertext
|
|
395
|
+
// to be ignored. Try to avoid this for known extensions by checking the actual and expected length.
|
|
396
|
+
const { actual: actualLength, expected: expectedLength } = Security2Extension
|
|
397
|
+
.getExtensionLength(buffer.subarray(offset));
|
|
398
|
+
// Parse the extension using the expected length if possible
|
|
399
|
+
const extensionLength = expectedLength ?? actualLength;
|
|
400
|
+
if (extensionLength < 2) {
|
|
401
|
+
// An S2 extension was expected, but the length is too short
|
|
402
|
+
mustDiscardCommand = true;
|
|
403
|
+
break parsing;
|
|
404
|
+
}
|
|
405
|
+
else if (extensionLength
|
|
406
|
+
> buffer.length
|
|
407
|
+
- offset
|
|
408
|
+
- (wasEncrypted
|
|
409
|
+
? 0
|
|
410
|
+
: SECURITY_S2_AUTH_TAG_LENGTH)) {
|
|
411
|
+
// The supposed length is longer than the space the extensions may occupy
|
|
412
|
+
mustDiscardCommand = true;
|
|
413
|
+
break parsing;
|
|
414
|
+
}
|
|
415
|
+
const extensionData = buffer.subarray(offset, offset + extensionLength);
|
|
416
|
+
offset += extensionLength;
|
|
417
|
+
const ext = Security2Extension.parse(extensionData);
|
|
418
|
+
switch (validateS2Extension(ext, wasEncrypted)) {
|
|
419
|
+
case ValidateS2ExtensionResult.OK:
|
|
420
|
+
if (expectedLength != undefined
|
|
421
|
+
&& actualLength !== expectedLength) {
|
|
422
|
+
// The extension length field does not match, ignore the extension
|
|
423
|
+
}
|
|
424
|
+
else {
|
|
425
|
+
extensions.push(ext);
|
|
426
|
+
}
|
|
427
|
+
break;
|
|
428
|
+
case ValidateS2ExtensionResult.DiscardExtension:
|
|
429
|
+
// Do nothing
|
|
430
|
+
break;
|
|
431
|
+
case ValidateS2ExtensionResult.DiscardCommand:
|
|
432
|
+
mustDiscardCommand = true;
|
|
433
|
+
break;
|
|
434
|
+
}
|
|
435
|
+
// Check if that was the last extension
|
|
436
|
+
if (!ext.moreToFollow)
|
|
437
|
+
break parsing;
|
|
438
|
+
}
|
|
439
|
+
return {
|
|
440
|
+
extensions,
|
|
441
|
+
mustDiscardCommand,
|
|
442
|
+
bytesRead: offset,
|
|
443
|
+
};
|
|
444
|
+
}
|
|
244
445
|
function getDestinationIDTX() {
|
|
245
446
|
if (this.isSinglecast())
|
|
246
447
|
return this.nodeId;
|
|
@@ -302,7 +503,7 @@ let Security2CCAPI = (() => {
|
|
|
302
503
|
if (!securityManager) {
|
|
303
504
|
throw new ZWaveError(`Nonces can only be sent if secure communication is set up!`, ZWaveErrorCodes.Driver_NoSecurity);
|
|
304
505
|
}
|
|
305
|
-
const receiverEI = securityManager.
|
|
506
|
+
const receiverEI = await securityManager.generateNonceAsync(this.endpoint.nodeId);
|
|
306
507
|
const cc = new Security2CCNonceReport({
|
|
307
508
|
nodeId: this.endpoint.nodeId,
|
|
308
509
|
endpointIndex: this.endpoint.index,
|
|
@@ -922,6 +1123,7 @@ let Security2CCMessageEncapsulation = (() => {
|
|
|
922
1123
|
throw new ZWaveError("Multicast Security S2 encapsulation requires the MGRP extension", ZWaveErrorCodes.Security2CC_MissingExtension);
|
|
923
1124
|
}
|
|
924
1125
|
}
|
|
1126
|
+
/** @deprecated Use {@link fromAsync} instead */
|
|
925
1127
|
static from(raw, ctx) {
|
|
926
1128
|
const securityManager = assertSecurityRX(ctx);
|
|
927
1129
|
validatePayload(raw.payload.length >= 2);
|
|
@@ -934,61 +1136,12 @@ let Security2CCMessageEncapsulation = (() => {
|
|
|
934
1136
|
let offset = 2;
|
|
935
1137
|
const extensions = [];
|
|
936
1138
|
let mustDiscardCommand = false;
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
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;
|
|
988
|
-
}
|
|
989
|
-
};
|
|
990
|
-
if (hasExtensions)
|
|
991
|
-
parseExtensions(raw.payload, false);
|
|
1139
|
+
if (hasExtensions) {
|
|
1140
|
+
const parseResult = parseExtensions(raw.payload.subarray(offset), false);
|
|
1141
|
+
extensions.push(...parseResult.extensions);
|
|
1142
|
+
offset += parseResult.bytesRead;
|
|
1143
|
+
mustDiscardCommand = parseResult.mustDiscardCommand;
|
|
1144
|
+
}
|
|
992
1145
|
const mcctx = (() => {
|
|
993
1146
|
const multicastGroupId = getMulticastGroupId(extensions);
|
|
994
1147
|
if (ctx.frameType === "multicast" || ctx.frameType === "broadcast") {
|
|
@@ -1008,9 +1161,11 @@ let Security2CCMessageEncapsulation = (() => {
|
|
|
1008
1161
|
// we still need to increment the SPAN or MPAN state
|
|
1009
1162
|
if (mustDiscardCommand) {
|
|
1010
1163
|
if (mcctx.isMulticast) {
|
|
1164
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
1011
1165
|
securityManager.nextPeerMPAN(ctx.sourceNodeId, mcctx.groupId);
|
|
1012
1166
|
}
|
|
1013
1167
|
else {
|
|
1168
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
1014
1169
|
securityManager.nextNonce(ctx.sourceNodeId);
|
|
1015
1170
|
}
|
|
1016
1171
|
validatePayload.fail("Invalid S2 extension");
|
|
@@ -1043,7 +1198,9 @@ let Security2CCMessageEncapsulation = (() => {
|
|
|
1043
1198
|
securityManager.storePeerMPAN(ctx.sourceNodeId, mcctx.groupId, { type: MPANState.OutOfSync });
|
|
1044
1199
|
failNoMPAN();
|
|
1045
1200
|
}
|
|
1046
|
-
decrypt = () =>
|
|
1201
|
+
decrypt = () =>
|
|
1202
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
1203
|
+
decryptMulticastSync(ctx.sourceNodeId, securityManager, mcctx.groupId, ciphertext, authData, authTag);
|
|
1047
1204
|
}
|
|
1048
1205
|
else {
|
|
1049
1206
|
// Decrypt payload and verify integrity
|
|
@@ -1057,7 +1214,9 @@ let Security2CCMessageEncapsulation = (() => {
|
|
|
1057
1214
|
// For now, do the same as if we didn't have any EI
|
|
1058
1215
|
failNoSPAN();
|
|
1059
1216
|
}
|
|
1060
|
-
decrypt = () =>
|
|
1217
|
+
decrypt = () =>
|
|
1218
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
1219
|
+
decryptSinglecastSync(ctx, securityManager, ctx.sourceNodeId, sequenceNumber, prevSequenceNumber, ciphertext, authData, authTag, spanState, extensions);
|
|
1061
1220
|
}
|
|
1062
1221
|
let plaintext;
|
|
1063
1222
|
let authOK = false;
|
|
@@ -1108,8 +1267,12 @@ let Security2CCMessageEncapsulation = (() => {
|
|
|
1108
1267
|
// Remember which security class was used to decrypt this message, so we can discard it later
|
|
1109
1268
|
const securityClass = decryptionSecurityClass;
|
|
1110
1269
|
offset = 0;
|
|
1111
|
-
if (hasEncryptedExtensions)
|
|
1112
|
-
parseExtensions(plaintext, true);
|
|
1270
|
+
if (hasEncryptedExtensions) {
|
|
1271
|
+
const parseResult = parseExtensions(plaintext, true);
|
|
1272
|
+
extensions.push(...parseResult.extensions);
|
|
1273
|
+
offset += parseResult.bytesRead;
|
|
1274
|
+
mustDiscardCommand = parseResult.mustDiscardCommand;
|
|
1275
|
+
}
|
|
1113
1276
|
// Before we can continue, check if the command must be discarded
|
|
1114
1277
|
if (mustDiscardCommand) {
|
|
1115
1278
|
validatePayload.fail("Invalid extension");
|
|
@@ -1131,6 +1294,7 @@ let Security2CCMessageEncapsulation = (() => {
|
|
|
1131
1294
|
// make sure this contains a complete CC command that's worth splitting
|
|
1132
1295
|
validatePayload(decryptedCCBytes.length >= 2);
|
|
1133
1296
|
// and deserialize the CC
|
|
1297
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
1134
1298
|
encapsulated = CommandClass.parse(decryptedCCBytes, ctx);
|
|
1135
1299
|
}
|
|
1136
1300
|
const ret = new Security2CCMessageEncapsulation({
|
|
@@ -1148,6 +1312,187 @@ let Security2CCMessageEncapsulation = (() => {
|
|
|
1148
1312
|
ret.plaintext = decryptedCCBytes;
|
|
1149
1313
|
return ret;
|
|
1150
1314
|
}
|
|
1315
|
+
static async fromAsync(raw, ctx) {
|
|
1316
|
+
const securityManager = assertSecurityRX(ctx);
|
|
1317
|
+
validatePayload(raw.payload.length >= 2);
|
|
1318
|
+
// Check the sequence number to avoid duplicates
|
|
1319
|
+
const sequenceNumber = raw.payload[0];
|
|
1320
|
+
// Ensure the node has a security class
|
|
1321
|
+
validatePayload.withReason("No security class granted")(ctx.getHighestSecurityClass(ctx.sourceNodeId) !== SecurityClass.None);
|
|
1322
|
+
const hasExtensions = !!(raw.payload[1] & 0b1);
|
|
1323
|
+
const hasEncryptedExtensions = !!(raw.payload[1] & 0b10);
|
|
1324
|
+
let offset = 2;
|
|
1325
|
+
const extensions = [];
|
|
1326
|
+
let mustDiscardCommand = false;
|
|
1327
|
+
if (hasExtensions) {
|
|
1328
|
+
const parseResult = parseExtensions(raw.payload.subarray(offset), false);
|
|
1329
|
+
extensions.push(...parseResult.extensions);
|
|
1330
|
+
offset += parseResult.bytesRead;
|
|
1331
|
+
mustDiscardCommand = parseResult.mustDiscardCommand;
|
|
1332
|
+
}
|
|
1333
|
+
const mcctx = (() => {
|
|
1334
|
+
const multicastGroupId = getMulticastGroupId(extensions);
|
|
1335
|
+
if (ctx.frameType === "multicast" || ctx.frameType === "broadcast") {
|
|
1336
|
+
if (multicastGroupId == undefined) {
|
|
1337
|
+
validatePayload.fail("Multicast frames without MGRP extension");
|
|
1338
|
+
}
|
|
1339
|
+
return {
|
|
1340
|
+
isMulticast: true,
|
|
1341
|
+
groupId: multicastGroupId,
|
|
1342
|
+
};
|
|
1343
|
+
}
|
|
1344
|
+
else {
|
|
1345
|
+
return { isMulticast: false, groupId: multicastGroupId };
|
|
1346
|
+
}
|
|
1347
|
+
})();
|
|
1348
|
+
// If a command is to be discarded before decryption,
|
|
1349
|
+
// we still need to increment the SPAN or MPAN state
|
|
1350
|
+
if (mustDiscardCommand) {
|
|
1351
|
+
if (mcctx.isMulticast) {
|
|
1352
|
+
await securityManager.nextPeerMPANAsync(ctx.sourceNodeId, mcctx.groupId);
|
|
1353
|
+
}
|
|
1354
|
+
else {
|
|
1355
|
+
await securityManager.nextNonceAsync(ctx.sourceNodeId);
|
|
1356
|
+
}
|
|
1357
|
+
validatePayload.fail("Invalid S2 extension");
|
|
1358
|
+
}
|
|
1359
|
+
let prevSequenceNumber;
|
|
1360
|
+
let mpanState;
|
|
1361
|
+
if (mcctx.isMulticast) {
|
|
1362
|
+
mpanState = securityManager.getPeerMPAN(ctx.sourceNodeId, mcctx.groupId);
|
|
1363
|
+
}
|
|
1364
|
+
else {
|
|
1365
|
+
// Don't accept duplicate Singlecast commands
|
|
1366
|
+
prevSequenceNumber = validateSequenceNumber(securityManager, ctx.sourceNodeId, sequenceNumber);
|
|
1367
|
+
// When a node receives a singlecast message after a multicast group was marked out of sync,
|
|
1368
|
+
// it must forget about the group.
|
|
1369
|
+
if (mcctx.groupId == undefined) {
|
|
1370
|
+
securityManager.resetOutOfSyncMPANs(ctx.sourceNodeId);
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
const unencryptedPayload = raw.payload.subarray(0, offset);
|
|
1374
|
+
const ciphertext = raw.payload.subarray(offset, -SECURITY_S2_AUTH_TAG_LENGTH);
|
|
1375
|
+
const authTag = raw.payload.subarray(-SECURITY_S2_AUTH_TAG_LENGTH);
|
|
1376
|
+
const messageLength = 2 /* CommandClass.computeEncapsulationOverhead() */
|
|
1377
|
+
+ raw.payload.length;
|
|
1378
|
+
const authData = getAuthenticationData(ctx.sourceNodeId, getDestinationIDRX(ctx, extensions), ctx.homeId, messageLength, unencryptedPayload);
|
|
1379
|
+
let decrypt;
|
|
1380
|
+
if (mcctx.isMulticast) {
|
|
1381
|
+
// For incoming multicast commands, make sure we have an MPAN
|
|
1382
|
+
if (mpanState?.type !== MPANState.MPAN) {
|
|
1383
|
+
// If we don't, mark the MPAN as out of sync, so we can respond accordingly on the singlecast followup
|
|
1384
|
+
securityManager.storePeerMPAN(ctx.sourceNodeId, mcctx.groupId, { type: MPANState.OutOfSync });
|
|
1385
|
+
failNoMPAN();
|
|
1386
|
+
}
|
|
1387
|
+
decrypt = () => decryptMulticastAsync(ctx.sourceNodeId, securityManager, mcctx.groupId, ciphertext, authData, authTag);
|
|
1388
|
+
}
|
|
1389
|
+
else {
|
|
1390
|
+
// Decrypt payload and verify integrity
|
|
1391
|
+
const spanState = securityManager.getSPANState(ctx.sourceNodeId);
|
|
1392
|
+
// If we are not able to establish an SPAN yet, fail the decryption
|
|
1393
|
+
if (spanState.type === SPANState.None) {
|
|
1394
|
+
failNoSPAN();
|
|
1395
|
+
}
|
|
1396
|
+
else if (spanState.type === SPANState.RemoteEI) {
|
|
1397
|
+
// TODO: The specs are not clear how to handle this case
|
|
1398
|
+
// For now, do the same as if we didn't have any EI
|
|
1399
|
+
failNoSPAN();
|
|
1400
|
+
}
|
|
1401
|
+
decrypt = () => decryptSinglecastAsync(ctx, securityManager, ctx.sourceNodeId, sequenceNumber, prevSequenceNumber, ciphertext, authData, authTag, spanState, extensions);
|
|
1402
|
+
}
|
|
1403
|
+
let plaintext;
|
|
1404
|
+
let authOK = false;
|
|
1405
|
+
let key;
|
|
1406
|
+
let iv;
|
|
1407
|
+
let decryptionSecurityClass;
|
|
1408
|
+
// If the Receiver is unable to authenticate the singlecast message with the current SPAN,
|
|
1409
|
+
// the Receiver SHOULD try decrypting the message with one or more of the following SPAN values,
|
|
1410
|
+
// stopping when decryption is successful or the maximum number of iterations is reached.
|
|
1411
|
+
// If the Receiver is unable to decrypt the S2 MC frame with the current MPAN, the Receiver MAY try
|
|
1412
|
+
// decrypting the frame with one or more of the subsequent MPAN values, stopping when decryption is
|
|
1413
|
+
// successful or the maximum number of iterations is reached.
|
|
1414
|
+
const decryptAttempts = mcctx.isMulticast
|
|
1415
|
+
? MAX_DECRYPT_ATTEMPTS_MULTICAST
|
|
1416
|
+
: mcctx.groupId != undefined
|
|
1417
|
+
? MAX_DECRYPT_ATTEMPTS_SC_FOLLOWUP
|
|
1418
|
+
: MAX_DECRYPT_ATTEMPTS_SINGLECAST;
|
|
1419
|
+
for (let i = 0; i < decryptAttempts; i++) {
|
|
1420
|
+
({
|
|
1421
|
+
plaintext,
|
|
1422
|
+
authOK,
|
|
1423
|
+
key,
|
|
1424
|
+
iv,
|
|
1425
|
+
securityClass: decryptionSecurityClass,
|
|
1426
|
+
} = await decrypt());
|
|
1427
|
+
if (!!authOK && !!plaintext)
|
|
1428
|
+
break;
|
|
1429
|
+
// No need to try further SPANs if we just got the sender's EI
|
|
1430
|
+
if (!!getSenderEI(extensions))
|
|
1431
|
+
break;
|
|
1432
|
+
}
|
|
1433
|
+
// If authentication fails, do so with an error code that instructs the
|
|
1434
|
+
// applHost to tell the node we have no nonce
|
|
1435
|
+
if (!authOK || !plaintext) {
|
|
1436
|
+
if (mcctx.isMulticast) {
|
|
1437
|
+
// Mark the MPAN as out of sync
|
|
1438
|
+
securityManager.storePeerMPAN(ctx.sourceNodeId, mcctx.groupId, { type: MPANState.OutOfSync });
|
|
1439
|
+
validatePayload.fail(ZWaveErrorCodes.Security2CC_CannotDecodeMulticast);
|
|
1440
|
+
}
|
|
1441
|
+
else {
|
|
1442
|
+
validatePayload.fail(ZWaveErrorCodes.Security2CC_CannotDecode);
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
else if (!mcctx.isMulticast && mcctx.groupId != undefined) {
|
|
1446
|
+
// After reception of a singlecast followup, the MPAN state must be increased
|
|
1447
|
+
securityManager.tryIncrementPeerMPAN(ctx.sourceNodeId, mcctx.groupId);
|
|
1448
|
+
}
|
|
1449
|
+
// Remember which security class was used to decrypt this message, so we can discard it later
|
|
1450
|
+
const securityClass = decryptionSecurityClass;
|
|
1451
|
+
offset = 0;
|
|
1452
|
+
if (hasEncryptedExtensions) {
|
|
1453
|
+
const parseResult = parseExtensions(plaintext, true);
|
|
1454
|
+
extensions.push(...parseResult.extensions);
|
|
1455
|
+
offset += parseResult.bytesRead;
|
|
1456
|
+
mustDiscardCommand = parseResult.mustDiscardCommand;
|
|
1457
|
+
}
|
|
1458
|
+
// Before we can continue, check if the command must be discarded
|
|
1459
|
+
if (mustDiscardCommand) {
|
|
1460
|
+
validatePayload.fail("Invalid extension");
|
|
1461
|
+
}
|
|
1462
|
+
// If the MPAN extension was received, store the MPAN
|
|
1463
|
+
if (!mcctx.isMulticast) {
|
|
1464
|
+
const mpanExtension = extensions.find((e) => e instanceof MPANExtension);
|
|
1465
|
+
if (mpanExtension) {
|
|
1466
|
+
securityManager.storePeerMPAN(ctx.sourceNodeId, mpanExtension.groupId, {
|
|
1467
|
+
type: MPANState.MPAN,
|
|
1468
|
+
currentMPAN: mpanExtension.innerMPANState,
|
|
1469
|
+
});
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
// Not every S2 message includes an encapsulated CC
|
|
1473
|
+
const decryptedCCBytes = plaintext.subarray(offset);
|
|
1474
|
+
let encapsulated;
|
|
1475
|
+
if (decryptedCCBytes.length > 0) {
|
|
1476
|
+
// make sure this contains a complete CC command that's worth splitting
|
|
1477
|
+
validatePayload(decryptedCCBytes.length >= 2);
|
|
1478
|
+
// and deserialize the CC
|
|
1479
|
+
encapsulated = await CommandClass.parseAsync(decryptedCCBytes, ctx);
|
|
1480
|
+
}
|
|
1481
|
+
const ret = new Security2CCMessageEncapsulation({
|
|
1482
|
+
nodeId: ctx.sourceNodeId,
|
|
1483
|
+
sequenceNumber,
|
|
1484
|
+
securityClass,
|
|
1485
|
+
extensions,
|
|
1486
|
+
encapsulated,
|
|
1487
|
+
});
|
|
1488
|
+
// Remember for debugging purposes
|
|
1489
|
+
ret.key = key;
|
|
1490
|
+
ret.iv = iv;
|
|
1491
|
+
ret.authData = authData;
|
|
1492
|
+
ret.authTag = authTag;
|
|
1493
|
+
ret.plaintext = decryptedCCBytes;
|
|
1494
|
+
return ret;
|
|
1495
|
+
}
|
|
1151
1496
|
securityClass;
|
|
1152
1497
|
// Only used for testing/debugging purposes
|
|
1153
1498
|
key;
|
|
@@ -1187,7 +1532,8 @@ let Security2CCMessageEncapsulation = (() => {
|
|
|
1187
1532
|
getMulticastGroupId() {
|
|
1188
1533
|
return getMulticastGroupId(this.extensions);
|
|
1189
1534
|
}
|
|
1190
|
-
|
|
1535
|
+
/** @deprecated Use {@link maybeAddSPANExtensionAsync} instead */
|
|
1536
|
+
maybeAddSPANExtensionSync(ctx, securityManager) {
|
|
1191
1537
|
if (!this.isSinglecast())
|
|
1192
1538
|
return;
|
|
1193
1539
|
const receiverNodeId = this.nodeId;
|
|
@@ -1200,12 +1546,14 @@ let Security2CCMessageEncapsulation = (() => {
|
|
|
1200
1546
|
else if (spanState.type === SPANState.RemoteEI) {
|
|
1201
1547
|
// We have the receiver's EI, generate our input and send it over
|
|
1202
1548
|
// With both, we can create an SPAN
|
|
1549
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
1203
1550
|
const senderEI = securityManager.generateNonce(undefined);
|
|
1204
1551
|
const receiverEI = spanState.receiverEI;
|
|
1205
1552
|
// While bootstrapping a node, prefer the temporary key, unless the
|
|
1206
1553
|
// specific command specifies a security class
|
|
1207
1554
|
if (this.securityClass == undefined
|
|
1208
1555
|
&& securityManager.tempKeys.has(receiverNodeId)) {
|
|
1556
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
1209
1557
|
securityManager.initializeTempSPAN(receiverNodeId, senderEI, receiverEI);
|
|
1210
1558
|
}
|
|
1211
1559
|
else {
|
|
@@ -1214,6 +1562,7 @@ let Security2CCMessageEncapsulation = (() => {
|
|
|
1214
1562
|
if (securityClass == undefined) {
|
|
1215
1563
|
throw new ZWaveError("No security class defined for this command!", ZWaveErrorCodes.Security2CC_NoSPAN);
|
|
1216
1564
|
}
|
|
1565
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
1217
1566
|
securityManager.initializeSPAN(receiverNodeId, securityClass, senderEI, receiverEI);
|
|
1218
1567
|
}
|
|
1219
1568
|
// Add or update the SPAN extension
|
|
@@ -1227,11 +1576,53 @@ let Security2CCMessageEncapsulation = (() => {
|
|
|
1227
1576
|
}
|
|
1228
1577
|
}
|
|
1229
1578
|
}
|
|
1579
|
+
async maybeAddSPANExtensionAsync(ctx, securityManager) {
|
|
1580
|
+
if (!this.isSinglecast())
|
|
1581
|
+
return;
|
|
1582
|
+
const receiverNodeId = this.nodeId;
|
|
1583
|
+
const spanState = securityManager.getSPANState(receiverNodeId);
|
|
1584
|
+
if (spanState.type === SPANState.None
|
|
1585
|
+
|| spanState.type === SPANState.LocalEI) {
|
|
1586
|
+
// Can't do anything here if we don't have the receiver's EI
|
|
1587
|
+
throw new ZWaveError(`Security S2 CC requires the receiver's nonce to be sent!`, ZWaveErrorCodes.Security2CC_NoSPAN);
|
|
1588
|
+
}
|
|
1589
|
+
else if (spanState.type === SPANState.RemoteEI) {
|
|
1590
|
+
// We have the receiver's EI, generate our input and send it over
|
|
1591
|
+
// With both, we can create an SPAN
|
|
1592
|
+
const senderEI = await securityManager.generateNonceAsync(undefined);
|
|
1593
|
+
const receiverEI = spanState.receiverEI;
|
|
1594
|
+
// While bootstrapping a node, prefer the temporary key, unless the
|
|
1595
|
+
// specific command specifies a security class
|
|
1596
|
+
if (this.securityClass == undefined
|
|
1597
|
+
&& securityManager.tempKeys.has(receiverNodeId)) {
|
|
1598
|
+
await securityManager.initializeTempSPANAsync(receiverNodeId, senderEI, receiverEI);
|
|
1599
|
+
}
|
|
1600
|
+
else {
|
|
1601
|
+
const securityClass = this.securityClass
|
|
1602
|
+
?? ctx.getHighestSecurityClass(receiverNodeId);
|
|
1603
|
+
if (securityClass == undefined) {
|
|
1604
|
+
throw new ZWaveError("No security class defined for this command!", ZWaveErrorCodes.Security2CC_NoSPAN);
|
|
1605
|
+
}
|
|
1606
|
+
await securityManager.initializeSPANAsync(receiverNodeId, securityClass, senderEI, receiverEI);
|
|
1607
|
+
}
|
|
1608
|
+
// Add or update the SPAN extension
|
|
1609
|
+
let spanExtension = this.extensions.find((e) => e instanceof SPANExtension);
|
|
1610
|
+
if (spanExtension) {
|
|
1611
|
+
spanExtension.senderEI = senderEI;
|
|
1612
|
+
}
|
|
1613
|
+
else {
|
|
1614
|
+
spanExtension = new SPANExtension({ senderEI });
|
|
1615
|
+
this.extensions.push(spanExtension);
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
}
|
|
1619
|
+
/** @deprecated Use {@link serializeAsync} instead */
|
|
1230
1620
|
serialize(ctx) {
|
|
1231
1621
|
const securityManager = assertSecurityTX(ctx, this.nodeId);
|
|
1232
1622
|
this.ensureSequenceNumber(securityManager);
|
|
1233
1623
|
// Include Sender EI in the command if we only have the receiver's EI
|
|
1234
|
-
|
|
1624
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
1625
|
+
this.maybeAddSPANExtensionSync(ctx, securityManager);
|
|
1235
1626
|
const unencryptedExtensions = this.extensions.filter((e) => !e.isEncrypted());
|
|
1236
1627
|
const encryptedExtensions = this.extensions.filter((e) => e.isEncrypted());
|
|
1237
1628
|
const unencryptedPayload = Bytes.concat([
|
|
@@ -1242,6 +1633,7 @@ let Security2CCMessageEncapsulation = (() => {
|
|
|
1242
1633
|
]),
|
|
1243
1634
|
...unencryptedExtensions.map((e, index) => e.serialize(index < unencryptedExtensions.length - 1)),
|
|
1244
1635
|
]);
|
|
1636
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
1245
1637
|
const serializedCC = this.encapsulated?.serialize(ctx)
|
|
1246
1638
|
?? new Bytes();
|
|
1247
1639
|
const plaintextPayload = Bytes.concat([
|
|
@@ -1259,6 +1651,7 @@ let Security2CCMessageEncapsulation = (() => {
|
|
|
1259
1651
|
// Singlecast:
|
|
1260
1652
|
// Generate a nonce for encryption, and remember it to attempt decryption
|
|
1261
1653
|
// of potential in-flight messages from the target node.
|
|
1654
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
1262
1655
|
iv = securityManager.nextNonce(this.nodeId, true);
|
|
1263
1656
|
const { keyCCM } =
|
|
1264
1657
|
// Prefer the overridden security class if it was given
|
|
@@ -1269,11 +1662,13 @@ let Security2CCMessageEncapsulation = (() => {
|
|
|
1269
1662
|
}
|
|
1270
1663
|
else {
|
|
1271
1664
|
// Multicast:
|
|
1665
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
1272
1666
|
const keyAndIV = securityManager.getMulticastKeyAndIV(destinationTag);
|
|
1273
1667
|
key = keyAndIV.key;
|
|
1274
1668
|
iv = keyAndIV.iv;
|
|
1275
1669
|
}
|
|
1276
|
-
|
|
1670
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
1671
|
+
const { ciphertext: ciphertextPayload, authTag } = encryptAES128CCMSync(key, iv, plaintextPayload, authData, SECURITY_S2_AUTH_TAG_LENGTH);
|
|
1277
1672
|
// Remember key and IV for debugging purposes
|
|
1278
1673
|
this.key = key;
|
|
1279
1674
|
this.iv = iv;
|
|
@@ -1285,8 +1680,69 @@ let Security2CCMessageEncapsulation = (() => {
|
|
|
1285
1680
|
ciphertextPayload,
|
|
1286
1681
|
authTag,
|
|
1287
1682
|
]);
|
|
1683
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
1288
1684
|
return super.serialize(ctx);
|
|
1289
1685
|
}
|
|
1686
|
+
async serializeAsync(ctx) {
|
|
1687
|
+
const securityManager = assertSecurityTX(ctx, this.nodeId);
|
|
1688
|
+
this.ensureSequenceNumber(securityManager);
|
|
1689
|
+
// Include Sender EI in the command if we only have the receiver's EI
|
|
1690
|
+
await this.maybeAddSPANExtensionAsync(ctx, securityManager);
|
|
1691
|
+
const unencryptedExtensions = this.extensions.filter((e) => !e.isEncrypted());
|
|
1692
|
+
const encryptedExtensions = this.extensions.filter((e) => e.isEncrypted());
|
|
1693
|
+
const unencryptedPayload = Bytes.concat([
|
|
1694
|
+
Bytes.from([
|
|
1695
|
+
this.sequenceNumber,
|
|
1696
|
+
(encryptedExtensions.length > 0 ? 0b10 : 0)
|
|
1697
|
+
| (unencryptedExtensions.length > 0 ? 1 : 0),
|
|
1698
|
+
]),
|
|
1699
|
+
...unencryptedExtensions.map((e, index) => e.serialize(index < unencryptedExtensions.length - 1)),
|
|
1700
|
+
]);
|
|
1701
|
+
const serializedCC = (await this.encapsulated?.serializeAsync(ctx))
|
|
1702
|
+
?? new Bytes();
|
|
1703
|
+
const plaintextPayload = Bytes.concat([
|
|
1704
|
+
...encryptedExtensions.map((e, index) => e.serialize(index < encryptedExtensions.length - 1)),
|
|
1705
|
+
serializedCC,
|
|
1706
|
+
]);
|
|
1707
|
+
// Generate the authentication data for CCM encryption
|
|
1708
|
+
const destinationTag = getDestinationIDTX.call(this);
|
|
1709
|
+
const messageLength = this.computeEncapsulationOverhead()
|
|
1710
|
+
+ serializedCC.length;
|
|
1711
|
+
const authData = getAuthenticationData(ctx.ownNodeId, destinationTag, ctx.homeId, messageLength, unencryptedPayload);
|
|
1712
|
+
let key;
|
|
1713
|
+
let iv;
|
|
1714
|
+
if (this.isSinglecast()) {
|
|
1715
|
+
// Singlecast:
|
|
1716
|
+
// Generate a nonce for encryption, and remember it to attempt decryption
|
|
1717
|
+
// of potential in-flight messages from the target node.
|
|
1718
|
+
iv = await securityManager.nextNonceAsync(this.nodeId, true);
|
|
1719
|
+
const { keyCCM } =
|
|
1720
|
+
// Prefer the overridden security class if it was given
|
|
1721
|
+
this.securityClass != undefined
|
|
1722
|
+
? securityManager.getKeysForSecurityClass(this.securityClass)
|
|
1723
|
+
: securityManager.getKeysForNode(this.nodeId);
|
|
1724
|
+
key = keyCCM;
|
|
1725
|
+
}
|
|
1726
|
+
else {
|
|
1727
|
+
// Multicast:
|
|
1728
|
+
const keyAndIV = await securityManager.getMulticastKeyAndIVAsync(destinationTag);
|
|
1729
|
+
key = keyAndIV.key;
|
|
1730
|
+
iv = keyAndIV.iv;
|
|
1731
|
+
}
|
|
1732
|
+
const { ciphertext: ciphertextPayload, authTag } = await encryptAES128CCMAsync(plaintextPayload, key, iv, authData, SECURITY_S2_AUTH_TAG_LENGTH);
|
|
1733
|
+
// Remember key and IV for debugging purposes
|
|
1734
|
+
this.key = key;
|
|
1735
|
+
this.iv = iv;
|
|
1736
|
+
this.authData = authData;
|
|
1737
|
+
this.authTag = authTag;
|
|
1738
|
+
this.ciphertext = ciphertextPayload;
|
|
1739
|
+
this.payload = Bytes.concat([
|
|
1740
|
+
unencryptedPayload,
|
|
1741
|
+
ciphertextPayload,
|
|
1742
|
+
authTag,
|
|
1743
|
+
]);
|
|
1744
|
+
return super.serializeAsync(ctx);
|
|
1745
|
+
}
|
|
1290
1746
|
computeEncapsulationOverhead() {
|
|
1291
1747
|
// Security S2 adds:
|
|
1292
1748
|
// * 1 byte sequence number
|
|
@@ -1422,6 +1878,7 @@ let Security2CCNonceReport = (() => {
|
|
|
1422
1878
|
if (this.SOS) {
|
|
1423
1879
|
this.payload = Bytes.concat([this.payload, this.receiverEI]);
|
|
1424
1880
|
}
|
|
1881
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
1425
1882
|
return super.serialize(ctx);
|
|
1426
1883
|
}
|
|
1427
1884
|
toLogEntry(ctx) {
|
|
@@ -1484,6 +1941,7 @@ let Security2CCNonceGet = (() => {
|
|
|
1484
1941
|
const securityManager = assertSecurityTX(ctx, this.nodeId);
|
|
1485
1942
|
this.ensureSequenceNumber(securityManager);
|
|
1486
1943
|
this.payload = Bytes.from([this.sequenceNumber]);
|
|
1944
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
1487
1945
|
return super.serialize(ctx);
|
|
1488
1946
|
}
|
|
1489
1947
|
toLogEntry(ctx) {
|
|
@@ -1560,6 +2018,7 @@ let Security2CCKEXReport = (() => {
|
|
|
1560
2018
|
encodeBitMask(this.supportedECDHProfiles, 7, ECDHProfiles.Curve25519),
|
|
1561
2019
|
encodeBitMask(this.requestedKeys, SecurityClass.S0_Legacy, SecurityClass.S2_Unauthenticated),
|
|
1562
2020
|
]);
|
|
2021
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
1563
2022
|
return super.serialize(ctx);
|
|
1564
2023
|
}
|
|
1565
2024
|
toLogEntry(ctx) {
|
|
@@ -1687,6 +2146,7 @@ let Security2CCKEXSet = (() => {
|
|
|
1687
2146
|
encodeBitMask([this.selectedECDHProfile], 7, ECDHProfiles.Curve25519),
|
|
1688
2147
|
encodeBitMask(this.grantedKeys, SecurityClass.S0_Legacy, SecurityClass.S2_Unauthenticated),
|
|
1689
2148
|
]);
|
|
2149
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
1690
2150
|
return super.serialize(ctx);
|
|
1691
2151
|
}
|
|
1692
2152
|
toLogEntry(ctx) {
|
|
@@ -1737,6 +2197,7 @@ let Security2CCKEXFail = (() => {
|
|
|
1737
2197
|
failType;
|
|
1738
2198
|
serialize(ctx) {
|
|
1739
2199
|
this.payload = Bytes.from([this.failType]);
|
|
2200
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
1740
2201
|
return super.serialize(ctx);
|
|
1741
2202
|
}
|
|
1742
2203
|
toLogEntry(ctx) {
|
|
@@ -1786,6 +2247,7 @@ let Security2CCPublicKeyReport = (() => {
|
|
|
1786
2247
|
Bytes.from([this.includingNode ? 1 : 0]),
|
|
1787
2248
|
this.publicKey,
|
|
1788
2249
|
]);
|
|
2250
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
1789
2251
|
return super.serialize(ctx);
|
|
1790
2252
|
}
|
|
1791
2253
|
toLogEntry(ctx) {
|
|
@@ -1838,6 +2300,7 @@ let Security2CCNetworkKeyReport = (() => {
|
|
|
1838
2300
|
securityClassToBitMask(this.grantedKey),
|
|
1839
2301
|
this.networkKey,
|
|
1840
2302
|
]);
|
|
2303
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
1841
2304
|
return super.serialize(ctx);
|
|
1842
2305
|
}
|
|
1843
2306
|
toLogEntry(ctx) {
|
|
@@ -1884,6 +2347,7 @@ let Security2CCNetworkKeyGet = (() => {
|
|
|
1884
2347
|
requestedKey;
|
|
1885
2348
|
serialize(ctx) {
|
|
1886
2349
|
this.payload = securityClassToBitMask(this.requestedKey);
|
|
2350
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
1887
2351
|
return super.serialize(ctx);
|
|
1888
2352
|
}
|
|
1889
2353
|
toLogEntry(ctx) {
|
|
@@ -1953,6 +2417,7 @@ let Security2CCTransferEnd = (() => {
|
|
|
1953
2417
|
this.payload = Bytes.from([
|
|
1954
2418
|
(this.keyVerified ? 0b10 : 0) + (this.keyRequestComplete ? 0b1 : 0),
|
|
1955
2419
|
]);
|
|
2420
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
1956
2421
|
return super.serialize(ctx);
|
|
1957
2422
|
}
|
|
1958
2423
|
toLogEntry(ctx) {
|
|
@@ -2002,6 +2467,7 @@ let Security2CCCommandsSupportedReport = (() => {
|
|
|
2002
2467
|
supportedCCs;
|
|
2003
2468
|
serialize(ctx) {
|
|
2004
2469
|
this.payload = encodeCCList(this.supportedCCs, []);
|
|
2470
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
2005
2471
|
return super.serialize(ctx);
|
|
2006
2472
|
}
|
|
2007
2473
|
toLogEntry(ctx) {
|