UNPKG

zigbee-on-host

Version:

Zigbee stack designed to run on a host and communicate with a radio co-processor (RCP)

238 lines (237 loc) 10 kB
/** * const enum with sole purpose of avoiding "magic numbers" in code for well-known values */ export declare const enum ZigbeeConsts { COORDINATOR_ADDRESS = 0, /** min reserved address for broacasts */ BCAST_MIN = 65528, /** Low power routers only */ BCAST_LOW_POWER_ROUTERS = 65531, /** All routers and coordinator */ BCAST_DEFAULT = 65532, /** macRxOnWhenIdle = TRUE (all non-sleepy devices) */ BCAST_RX_ON_WHEN_IDLE = 65533, /** All devices in PAN (including sleepy end devices) */ BCAST_SLEEPY = 65535, /** The amount of time after which a broadcast is considered propagated throughout the network */ BCAST_TIME_WINDOW = 9000, /** The maximum amount of time that the MAC will hold a message for indirect transmission to a child. (7.68sec for Zigbee Pro) */ MAC_INDIRECT_TRANSMISSION_TIMEOUT = 7680, HA_ENDPOINT = 1, HA_PROFILE_ID = 260, ZDO_ENDPOINT = 0, ZDO_PROFILE_ID = 0, NETWORK_ADDRESS_REQUEST = 0, IEEE_ADDRESS_REQUEST = 1, NODE_DESCRIPTOR_REQUEST = 2, POWER_DESCRIPTOR_REQUEST = 3, SIMPLE_DESCRIPTOR_REQUEST = 4, ACTIVE_ENDPOINTS_REQUEST = 5, END_DEVICE_ANNOUNCE = 19, LQI_TABLE_REQUEST = 49, ROUTING_TABLE_REQUEST = 50, NWK_UPDATE_REQUEST = 56, GP_ENDPOINT = 242, GP_PROFILE_ID = 41440, GP_GROUP_ID = 2948, GP_CLUSTER_ID = 33, TOUCHLINK_PROFILE_ID = 49246, SEC_L = 2, SEC_BLOCKSIZE = 16, SEC_NONCE_LEN = 13, SEC_KEYSIZE = 16, /** 3-bit encoding of (L-1) */ SEC_CCM_FLAG_L = 1, SEC_IPAD = 54, SEC_OPAD = 92, SEC_CONTROL_LEVEL = 7, SEC_CONTROL_KEY = 24, SEC_CONTROL_NONCE = 32, SEC_CONTROL_REQ_VERIFIED_FC = 64 } export declare const enum ZigbeeSecurityLevel { NONE = 0, MIC32 = 1, MIC64 = 2, MIC128 = 3, ENC = 4, /** Zigbee 3.0 */ ENC_MIC32 = 5, ENC_MIC64 = 6, ENC_MIC128 = 7 } export declare const enum ZigbeeKeyType { LINK = 0, NWK = 1, TRANSPORT = 2, LOAD = 3 } export type ZigbeeSecurityControl = { level: ZigbeeSecurityLevel; keyId: ZigbeeKeyType; nonce: boolean; /** * TODO: currently always false, see R23.1 4.6.3.8 * R23: * This bit indicates to the receiver that it SHALL only accept the message if the receiver has verified * the frame counter of the corresponding apsDeviceKeyPairSet. * When the bit is set, and the receiver has an unverified frame counter it SHALL drop the current received message * and initiate a challenge via the ZDO Security_Challenge_req. See section 4.6.3.8 for more details. */ reqVerifiedFc: boolean; }; export type ZigbeeSecurityHeader = { /** uint8_t (same as above) */ control: ZigbeeSecurityControl; /** uint32_t */ frameCounter: number; /** uint64_t */ source64?: bigint; /** uint8_t */ keySeqNum?: number; /** (utility, not part of the spec) */ micLen?: 0 | 4 | 8 | 16; }; /** Valid install code lengths excluding CRC (bytes) */ export declare const INSTALL_CODE_VALID_SIZES: readonly [6, 8, 12, 16]; /** * 16-02828-012 (Base Device Behavior) §10.1.1.1 (Install code CRC) * * SPEC COMPLIANCE NOTES: * - ✅ Implements CRC-16/X25 parameters defined for install code validation * - ✅ Accepts byte arrays or buffers to match commissioning tooling interfaces * - ⚠️ Caller must remove trailing CRC bytes before invoking per spec guidance * DEVICE SCOPE: Trust Center and joining devices */ export declare function computeInstallCodeCRC(data: number[] | Uint8Array | Buffer): number; /** * 13-0402-13 (Zigbee Key Establishment) §10.1 & B.1.3 (Cryptographic hash) * * SPEC COMPLIANCE NOTES: * - ✅ Applies AES-128-MMO padding with 0x80 bit and bit-length trailer as mandated * - ✅ Processes full blocks iteratively to support arbitrary-length install codes * - ⚠️ Relies on caller to provide raw install code without CRC * DEVICE SCOPE: Trust Center and install-code provisioning devices */ export declare function aes128MmoHash(data: Buffer): Buffer; /** * 05-3474-23 R23.1, Annex B/A (CCM* mode of operation) * * SPEC COMPLIANCE NOTES: * - ✅ Implements CCM* counter generation with L=2 for Zigbee network/APS security * - ✅ Returns authentication tag and ciphertext slices matching Zigbee frame layout * - ⚠️ Assumes caller has already constructed nonce and formatted data per CCM* expectations * DEVICE SCOPE: All logical devices */ export declare function aes128CcmStar(M: 0 | 2 | 4 | 8 | 16, key: Buffer, nonce: Buffer, data: Buffer): [authTag: Buffer, ciphertext: Buffer]; /** * 05-3474-23 R23.1, Annex B (CCM* authentication primitive) * * SPEC COMPLIANCE NOTES: * - ✅ Builds B0 and authentication blocks per Zigbee CCM* definition using zero IV * - ✅ Pads associated data and payload to AES block size exactly per spec * - ⚠️ Caller must supply AAD in correct order (NWK header + security header) * DEVICE SCOPE: All logical devices */ export declare function computeAuthTag(authData: Buffer, M: number, key: Buffer, nonce: Buffer, data: Buffer): Buffer; /** * 05-3474-23 R23.1, Figure 4-25 (Security control field) * * SPEC COMPLIANCE NOTES: * - ✅ Packs security level, key identifier, and nonce flag per Zigbee bit layout * - ✅ Supports temporary level override for CCM* calculations * - ⚠️ Caller responsible for ensuring override matches actual MIC length in use * DEVICE SCOPE: All logical devices */ export declare function combineSecurityControl(control: ZigbeeSecurityControl, levelOverride?: number): number; /** * 05-3474-23 R23.1, Annex B (Nonce construction) * * SPEC COMPLIANCE NOTES: * - ✅ Orders IEEE source, frame counter, and security control bytes per Zigbee CCM* requirements * - ✅ Allows level override to align with temporary security level adjustments * - ⚠️ Expects caller to provide IEEE source (Trust Center or extended address) * DEVICE SCOPE: All logical devices */ export declare function makeNonce(header: ZigbeeSecurityHeader, source64: bigint, levelOverride?: number): Buffer; /** * Pre-hashing default keys makes decryptions ~5x faster * * SPEC COMPLIANCE NOTES: * - ✅ Stores hashed defaults for NWK/LINK/TRANSPORT/LOAD keys per Zigbee security model * - ⚠️ Caller must refresh hashes when Trust Center rotates keys * DEVICE SCOPE: Trust Center primarily */ export declare function registerDefaultHashedKeys(link: Buffer, nwk: Buffer, transport: Buffer, load: Buffer): void; /** * 05-3474-23 R23.1, Annex B.1.4 (Keyed hash for message authentication) * * SPEC COMPLIANCE NOTES: * - ✅ Implements HMAC-like construction using AES-128-MMO with specified ipad/opad constants * - ✅ Supports arbitrary input byte per Trust Center transport/load key derivation rules * - ⚠️ Requires 16-byte key input; caller must validate length upstream * DEVICE SCOPE: Trust Center and devices deriving transport/load keys */ export declare function makeKeyedHash(key: Buffer, inputByte: number): Buffer; /** * 05-3474-23 R23.1, Annex B.1.5 (Key usage definitions) * * SPEC COMPLIANCE NOTES: * - ✅ Returns unhashed NWK/LINK keys and hashed transport/load keys as mandated * - ✅ Throws on unsupported key identifiers to avoid silent misuse * - ⚠️ Caller must provide correct key material (hashed vs raw) for custom key types * DEVICE SCOPE: Trust Center and any device handling Zigbee key transports */ export declare function makeKeyedHashByType(keyId: ZigbeeKeyType, key: Buffer): Buffer; /** * 05-3474-23 R23.1, Table B-6 (Auxiliary security header) * * SPEC COMPLIANCE NOTES: * - ✅ Parses frame counter, optional extended source, and key sequence per Zigbee security spec * - ✅ Forces Zigbee 3.0 security level (ENC-MIC-32) consistent with stack policy * - ⚠️ Does not yet evaluate legacy MIC length options (fixed to 4 bytes) * DEVICE SCOPE: All logical devices */ export declare function decodeZigbeeSecurityHeader(data: Buffer, offset: number, source64?: bigint): [ZigbeeSecurityHeader, offset: number]; /** * 05-3474-23 R23.1, Table B-6 (Auxiliary security header) * * SPEC COMPLIANCE NOTES: * - ✅ Serialises security control, frame counter, optional IEEE source, and key sequence * - ✅ Aligns with Zigbee requirement to include KeySeqNum when using NWK keys * - ⚠️ Caller must ensure header.control.nonce implies presence of source64 * DEVICE SCOPE: All logical devices */ export declare function encodeZigbeeSecurityHeader(data: Buffer, offset: number, header: ZigbeeSecurityHeader): number; /** * 05-3474-23 R23.1, Annex B (Inbound security processing) * * SPEC COMPLIANCE NOTES: * - ✅ Applies CCM* decryption using hashed keys derived per key type definition * - ✅ Validates MIC before returning payload, preserving stack integrity * - ⚠️ Currently assumes Zigbee 3.0 ENC-MIC-32; legacy level support TODO * DEVICE SCOPE: All logical devices */ export declare function decryptZigbeePayload(data: Buffer, offset: number, key?: Buffer, source64?: bigint): [Buffer, header: ZigbeeSecurityHeader, offset: number]; /** * 05-3474-23 R23.1, Annex B (Outbound security processing) * * SPEC COMPLIANCE NOTES: * - ✅ Computes MIC over NWK/APS header and encrypts payload per CCM* specification * - ✅ Utilises hashed key cache for performance while maintaining spec compliance * - ⚠️ Requires caller to set header.micLen consistent with selected security level * DEVICE SCOPE: All logical devices */ export declare function encryptZigbeePayload(data: Buffer, offset: number, payload: Buffer, header: ZigbeeSecurityHeader, key?: Buffer): [Buffer, authTag: Buffer, offset: number]; /** * Converts a channels array to a uint32 channel mask. * @param channels * @returns */ export declare const convertChannelsToMask: (channels: number[]) => number; /** * Converts a uint32 channel mask to a channels array. * @param mask * @returns */ export declare const convertMaskToChannels: (mask: number) => number[];