Home IO Control
ESPHome add-on for IO-Homecontrol devices
Loading...
Searching...
No Matches
key_extraction_responder.cpp File Reference

"Recover System Key" (key extraction) — device-role responder collaborator. More...

#include "key_extraction_responder.h"
#include "hub_internal.h"
#include "device_registry.h"
#include "pairing_responder.h"
#include "proto_commands.h"
#include "proto_crypto.h"
#include "radio_interface.h"
#include "tuning_config.h"
#include <esp_random.h>
#include <cinttypes>
#include <cstdio>
#include <cstring>
Include dependency graph for key_extraction_responder.cpp:

Go to the source code of this file.

Namespaces

namespace  esphome
namespace  esphome::home_io_control

Detailed Description

"Recover System Key" (key extraction) — device-role responder collaborator.

Owns the impure side of the key-extraction feature: arming/disarming, throwaway node-ID generation, the 10-minute auto-off timer, the post-extraction grace window, transmitting device-role replies, and the security-sensitive result log block. The pure state-transition decisions live in pairing_responder.h/.cpp; the six RX branches (0x28/0x2C/0x31/0x32/0x36/0x3C) dispatch through try_handle_frame(), called from process_received_packet_() (hub_status.cpp).

Note
Hardware-confirmed 2026-08-02: a full extraction (0x28 through 0x33) between two real boards — SX1276 running this responder, SX1262 running this project's own PairingEngine as the "hub" — recovered the hub's node_id/system_key byte-for-byte. That validates the crypto, the state machine, and the radio wiring end-to-end on real RF hardware.
Warning
What that test does NOT validate: compatibility with a genuine third-party hub (Somfy TaHoma/Smoove, Velux KLF200, etc.). The device-role frames built here (create_discover_resp(), create_challenge_req(), create_key_confirm()) were reverse-engineered from this project's own encoder and a small number of captures. The self-test above necessarily agrees with those conventions (it's the same codebase on both ends); a real hub's exact requirements (discovery-response field completeness, retry cadence) may still differ. It is blind to two things in particular: a device-role frame that is self-consistent but wrong on air, and a protocol step a real hub requires that this project's own controller role never sends. Both are real failure modes against real hubs; see tests/corpus/captures/pairing/velux_kig300_pairing_key_extraction_stall.yaml and tests/corpus/captures/pairing/somfy_connectivity_kit_pairing_key_extraction_stall.yaml.

The device-role builders (create_discover_resp(), create_challenge_req_device_role(), create_key_confirm(), create_discover_confirm_ack()) are each pinned against a real device's captured framing by tests/corpus_device_role_builder_test.cpp, including create_discover_resp()'s flags/timestamp bytes, which mirror a real Somfy Izymo dimmer's captured values (see KEY_EXTRACTION_DISCOVER_RESP_FLAGS/_TIMESTAMP in proto_commands.cpp for the derivation) but remain unconfirmed against a real hub like every device-role field here.

recover_system_key_from_transfer()'s IV-derivation formula itself is independently pinned against two externally-captured known-answer key transfers (ProtoCrypto.CryptKeyMatchesDocumented*Capture in proto_crypto_test.cpp), so that formula does not rest on this codebase's own conventions — though both captures are short requests and don't exercise construct_iv()'s 8-byte truncation window, so a real hub sending a longer request is an open question. Treat a recovered key as unconfirmed until it has been verified against a real hub, or by successfully controlling a device with it.

Definition in file key_extraction_responder.cpp.