ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
noise.h
Go to the documentation of this file.
1#pragma once
3#ifdef USE_NOISE
4#include <array>
5#include <cstddef>
6#include <cstdint>
7#include "esphome/core/log.h"
8
9// Forward decl from <noise/protocol.h>
10using NoiseHandshakeState = struct NoiseHandshakeState_s;
11
12namespace esphome::noise {
13
14using psk_t = std::array<uint8_t, 32>;
15
17 public:
18 // The all-zeros PSK is reserved: it marks the device as unprovisioned and
19 // doubles as the well-known provisioning PSK that unprovisioned devices
20 // accept for Noise handshakes (passive-sniffing protection only, no
21 // authentication). It is never a valid real key.
22 static bool is_all_zeros(const psk_t &psk) {
23 uint8_t acc = 0;
24 for (uint8_t b : psk) {
25 acc |= b;
26 }
27 return acc == 0;
28 }
32 void set_psk(const uint8_t *psk) { this->psk_ = psk; }
34 void load_psk(psk_t &out) const;
35 bool has_psk() const { return this->psk_ != nullptr; }
36
37 protected:
38 const uint8_t *psk_{nullptr};
39};
40
42const LogString *noise_err_to_logstr(int err);
43
44#ifdef USE_NOISE_SPARE_EPHEMERAL
45// One responder ephemeral key pair made ahead of time (about 60 ms on ESP8266), refilled by the api server
46// while idle and consumed by the next noise handshake of any transport; empty means the handshake generates
47// its own. Private key then public key; the private key stays in RAM until consumed.
48static constexpr size_t SPARE_EPHEMERAL_KEY_SIZE = 32;
49static constexpr size_t SPARE_EPHEMERAL_SIZE = 2 * SPARE_EPHEMERAL_KEY_SIZE;
50extern uint8_t spare_ephemeral[SPARE_EPHEMERAL_SIZE]; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
51// The clamp always sets bit 254, so it doubles as the ready flag
52inline bool has_spare_ephemeral() { return (spare_ephemeral[SPARE_EPHEMERAL_KEY_SIZE - 1] & 0x40) != 0; }
57#endif
58
59// Shared wire format for the noise transports (api and ota): every frame is
60// FRAME_INDICATOR, a 16-bit big-endian payload length, then the payload.
61// Handshake payloads start with a status byte; transport payloads end with
62// the ChaCha20-Poly1305 MAC.
63static constexpr uint8_t FRAME_INDICATOR = 0x01;
64static constexpr size_t FRAME_HEADER_SIZE = 3;
65static constexpr size_t MAC_SIZE = 16;
66static constexpr size_t MAX_HANDSHAKE_SIZE = 128;
67static constexpr uint8_t HANDSHAKE_STATUS_OK = 0x00;
68static constexpr uint8_t HANDSHAKE_STATUS_REJECT = 0x01;
69
70inline void write_frame_header(uint8_t *buf, uint16_t payload_len) {
71 buf[0] = FRAME_INDICATOR;
72 buf[1] = (uint8_t) (payload_len >> 8);
73 buf[2] = (uint8_t) payload_len;
74}
75
79size_t format_reject_payload(uint8_t *buf, size_t capacity, const LogString *reason);
80
83const LogString *reject_reason_for(int err);
84
89static constexpr size_t MAC_FAILURE_PAYLOAD_SIZE = sizeof("Handshake MAC failure");
90
91} // namespace esphome::noise
92#endif // USE_NOISE
void set_psk(const uint8_t *psk)
psk points at 32 bytes that outlive the context (PROGMEM or caller owned RAM); nullptr means no key.
Definition noise.h:32
static bool is_all_zeros(const psk_t &psk)
Definition noise.h:22
void load_psk(psk_t &out) const
Copy the key out (flash-aware on ESP8266); all zeros when none is set.
Definition noise.cpp:18
const uint8_t * psk_
Definition noise.h:38
bool state
Definition fan.h:2
std::vector< uint8_t > & out
Definition gif.cpp:49
void write_frame_header(uint8_t *buf, uint16_t payload_len)
Definition noise.h:70
std::array< uint8_t, 32 > psk_t
Definition noise.h:14
uint8_t spare_ephemeral[SPARE_EPHEMERAL_SIZE]
Definition noise.cpp:29
const LogString * noise_err_to_logstr(int err)
Convert a noise error code to a readable error.
Definition noise.cpp:58
size_t format_reject_payload(uint8_t *buf, size_t capacity, const LogString *reason)
Fill buf with a handshake reject payload (status byte plus the reason text, PROGMEM aware); returns t...
Definition noise.cpp:100
int consume_spare_ephemeral(NoiseHandshakeState *state)
Move the key pair into a handshake that has not started and wipe the slot; 0 unless noise-c rejects i...
Definition noise.cpp:46
bool has_spare_ephemeral()
Definition noise.h:52
const LogString * reject_reason_for(int err)
Reject reason for a failed handshake read.
Definition noise.cpp:96
void prepare_spare_ephemeral()
Fill the slot; blocks for the base point multiply.
Definition noise.cpp:31
uint16_t uint16_t & capacity
Definition helpers.cpp:34
struct NoiseHandshakeState_s NoiseHandshakeState
Definition noise.h:10