19static const char *
const TAG =
"api.noise";
21static const char PROLOGUE_INIT[] PROGMEM =
"NoiseAPIInit";
23static const char *
const PROLOGUE_INIT =
"NoiseAPIInit";
25static constexpr size_t PROLOGUE_INIT_LEN = 12;
27#define HELPER_LOG(msg, ...) ESP_LOGVV(TAG, "%s: " msg, this->client_info_->get_combined_info().c_str(), ##__VA_ARGS__)
29#ifdef HELPER_LOG_PACKETS
30#define LOG_PACKET_RECEIVED(buffer) ESP_LOGVV(TAG, "Received frame: %s", format_hex_pretty(buffer).c_str())
31#define LOG_PACKET_SENDING(data, len) ESP_LOGVV(TAG, "Sending raw: %s", format_hex_pretty(data, len).c_str())
33#define LOG_PACKET_RECEIVED(buffer) ((void) 0)
34#define LOG_PACKET_SENDING(data, len) ((void) 0)
39 if (err == NOISE_ERROR_NO_MEMORY)
40 return LOG_STR(
"NO_MEMORY");
41 if (err == NOISE_ERROR_UNKNOWN_ID)
42 return LOG_STR(
"UNKNOWN_ID");
43 if (err == NOISE_ERROR_UNKNOWN_NAME)
44 return LOG_STR(
"UNKNOWN_NAME");
45 if (err == NOISE_ERROR_MAC_FAILURE)
46 return LOG_STR(
"MAC_FAILURE");
47 if (err == NOISE_ERROR_NOT_APPLICABLE)
48 return LOG_STR(
"NOT_APPLICABLE");
49 if (err == NOISE_ERROR_SYSTEM)
50 return LOG_STR(
"SYSTEM");
51 if (err == NOISE_ERROR_REMOTE_KEY_REQUIRED)
52 return LOG_STR(
"REMOTE_KEY_REQUIRED");
53 if (err == NOISE_ERROR_LOCAL_KEY_REQUIRED)
54 return LOG_STR(
"LOCAL_KEY_REQUIRED");
55 if (err == NOISE_ERROR_PSK_REQUIRED)
56 return LOG_STR(
"PSK_REQUIRED");
57 if (err == NOISE_ERROR_INVALID_LENGTH)
58 return LOG_STR(
"INVALID_LENGTH");
59 if (err == NOISE_ERROR_INVALID_PARAM)
60 return LOG_STR(
"INVALID_PARAM");
61 if (err == NOISE_ERROR_INVALID_STATE)
62 return LOG_STR(
"INVALID_STATE");
63 if (err == NOISE_ERROR_INVALID_NONCE)
64 return LOG_STR(
"INVALID_NONCE");
65 if (err == NOISE_ERROR_INVALID_PRIVATE_KEY)
66 return LOG_STR(
"INVALID_PRIVATE_KEY");
67 if (err == NOISE_ERROR_INVALID_PUBLIC_KEY)
68 return LOG_STR(
"INVALID_PUBLIC_KEY");
69 if (err == NOISE_ERROR_INVALID_FORMAT)
70 return LOG_STR(
"INVALID_FORMAT");
71 if (err == NOISE_ERROR_INVALID_SIGNATURE)
72 return LOG_STR(
"INVALID_SIGNATURE");
73 return LOG_STR(
"UNKNOWN");
85 prologue_.resize(old_size + PROLOGUE_INIT_LEN);
87 memcpy_P(
prologue_.data() + old_size, PROLOGUE_INIT, PROLOGUE_INIT_LEN);
89 std::memcpy(
prologue_.data() + old_size, PROLOGUE_INIT, PROLOGUE_INIT_LEN);
109 HELPER_LOG(
"%s failed: %s", LOG_STR_ARG(func_name), LOG_STR_ARG(
noise_err_to_logstr(err)));
149 if (frame ==
nullptr) {
150 HELPER_LOG(
"Bad argument for try_read_frame_");
164 if (
static_cast<uint8_t
>(received) != to_read) {
183 HELPER_LOG(
"Bad packet len for handshake: %d", msg_size);
188 if (
rx_buf_.size() != msg_size) {
201 if (
static_cast<uint16_t
>(received) != to_read) {
229 HELPER_LOG(
"Bad state for method: %d", (
int)
state_);
234 std::vector<uint8_t> frame;
242 prologue_.resize(old_size + 2 + frame.size());
243 prologue_[old_size] = (uint8_t) (frame.size() >> 8);
244 prologue_[old_size + 1] = (uint8_t) frame.size();
245 std::memcpy(
prologue_.data() + old_size + 2, frame.data(), frame.size());
254 std::vector<uint8_t> msg;
256 size_t name_len = name.size() + 1;
257 size_t mac_len = mac.size() + 1;
258 size_t name_offset = 1;
259 size_t mac_offset = name_offset + name_len;
260 size_t total_size = 1 + name_len + mac_len;
262 msg.resize(total_size);
268 std::memcpy(msg.data() + name_offset, name.c_str(), name_len);
270 std::memcpy(msg.data() + mac_offset, mac.c_str(), mac_len);
284 int action = noise_handshakestate_get_action(
handshake_);
285 if (action == NOISE_ACTION_READ_MESSAGE) {
287 std::vector<uint8_t> frame;
296 }
else if (frame[0] != 0x00) {
297 HELPER_LOG(
"Bad handshake error byte: %u", frame[0]);
303 noise_buffer_init(mbuf);
304 noise_buffer_set_input(mbuf, frame.data() + 1, frame.size() - 1);
305 err = noise_handshakestate_read_message(
handshake_, &mbuf,
nullptr);
309 : LOG_STR(
"Handshake error"));
317 }
else if (action == NOISE_ACTION_WRITE_MESSAGE) {
320 noise_buffer_init(mbuf);
321 noise_buffer_set_output(mbuf, buffer + 1,
sizeof(buffer) - 1);
323 err = noise_handshakestate_write_message(
handshake_, &mbuf,
nullptr);
339 HELPER_LOG(
"Bad action for handshake: %d", action);
349#ifdef USE_STORE_LOG_STR_IN_FLASH
351 size_t reason_len = strlen_P(
reinterpret_cast<PGM_P
>(reason));
352 std::vector<uint8_t> data;
353 data.resize(reason_len + 1);
357 if (reason_len > 0) {
358 memcpy_P(data.data() + 1,
reinterpret_cast<PGM_P
>(reason), reason_len);
362 const char *reason_str = LOG_STR_ARG(reason);
363 size_t reason_len = strlen(reason_str);
364 std::vector<uint8_t> data;
365 data.resize(reason_len + 1);
369 if (reason_len > 0) {
370 std::memcpy(data.data() + 1, reason_str, reason_len);
392 std::vector<uint8_t> frame;
398 noise_buffer_init(mbuf);
399 noise_buffer_set_inout(mbuf, frame.data(), frame.size(), frame.size());
406 uint16_t msg_size = mbuf.size;
407 uint8_t *msg_data = frame.data();
410 HELPER_LOG(
"Bad data packet: size %d too short", msg_size);
414 uint16_t
type = (((uint16_t) msg_data[0]) << 8) | msg_data[1];
415 uint16_t data_len = (((uint16_t) msg_data[2]) << 8) | msg_data[3];
416 if (data_len > msg_size - 4) {
418 HELPER_LOG(
"Bad data packet: data_len %u greater than msg_size %u", data_len, msg_size);
446 if (packets.empty()) {
450 std::vector<uint8_t> *raw_buffer = buffer.
get_buffer();
451 uint8_t *buffer_data = raw_buffer->data();
455 uint16_t total_write_len = 0;
458 for (
const auto &packet : packets) {
460 uint8_t *buf_start = buffer_data + packet.offset;
467 const uint8_t msg_offset = 3;
468 buf_start[msg_offset] =
static_cast<uint8_t
>(packet.message_type >> 8);
469 buf_start[msg_offset + 1] =
static_cast<uint8_t
>(packet.message_type);
470 buf_start[msg_offset + 2] =
static_cast<uint8_t
>(packet.payload_size >> 8);
471 buf_start[msg_offset + 3] =
static_cast<uint8_t
>(packet.payload_size);
479 noise_buffer_init(mbuf);
480 noise_buffer_set_inout(mbuf, buf_start + msg_offset, 4 + packet.payload_size,
483 int err = noise_cipherstate_encrypt(
send_cipher_, &mbuf);
490 buf_start[1] =
static_cast<uint8_t
>(mbuf.size >> 8);
491 buf_start[2] =
static_cast<uint8_t
>(mbuf.size);
494 size_t packet_len =
static_cast<size_t>(3 + mbuf.size);
496 total_write_len += packet_len;
506 header[1] = (uint8_t) (
len >> 8);
507 header[2] = (uint8_t)
len;
515 iov[1].
iov_base =
const_cast<uint8_t *
>(data);
530 nid_.pattern_id = NOISE_PATTERN_NN;
531 nid_.cipher_id = NOISE_CIPHER_CHACHAPOLY;
532 nid_.dh_id = NOISE_DH_CURVE25519;
533 nid_.prefix_id = NOISE_PREFIX_STANDARD;
534 nid_.hybrid_id = NOISE_DH_NONE;
535 nid_.hash_id = NOISE_HASH_SHA256;
536 nid_.modifier_ids[0] = NOISE_MODIFIER_PSK0;
538 err = noise_handshakestate_new_by_id(&
handshake_, &
nid_, NOISE_ROLE_RESPONDER);
544 const auto &psk =
ctx_->get_psk();
545 err = noise_handshakestate_set_pre_shared_key(
handshake_, psk.data(), psk.size());
568 int action = noise_handshakestate_get_action(
handshake_);
569 if (action == NOISE_ACTION_READ_MESSAGE || action == NOISE_ACTION_WRITE_MESSAGE)
571 if (action != NOISE_ACTION_SPLIT) {
573 HELPER_LOG(
"Bad action for handshake: %d", action);
584 HELPER_LOG(
"Handshake complete!");
610 ESP_LOGE(TAG,
"Acquiring random bytes failed; rebooting");
const std::string & get_name() const
Get the name of this Application set by pre_setup().
APIError handle_socket_read_result_(ssize_t received)
std::vector< uint8_t > rx_buf_
std::vector< struct iovec > reusable_iovs_
uint8_t frame_header_padding_
uint8_t frame_footer_size_
APIError write_raw_(const struct iovec *iov, int iovcnt, uint16_t total_write_len)
APIError write_protobuf_packet(uint8_t type, ProtoWriteBuffer buffer) override
uint8_t rx_header_buf_len_
NoiseCipherState * send_cipher_
APIError read_packet(ReadPacketBuffer *buffer) override
APIError write_protobuf_packets(ProtoWriteBuffer buffer, std::span< const PacketInfo > packets) override
NoiseCipherState * recv_cipher_
~APINoiseFrameHelper() override
std::vector< uint8_t > prologue_
APIError try_read_frame_(std::vector< uint8_t > *frame)
Read a packet into the rx_buf_.
APIError handle_noise_error_(int err, const LogString *func_name, APIError api_err)
APIError state_action_()
To be called from read/write methods.
APIError loop() override
Run through handshake messages (if in that phase)
NoiseHandshakeState * handshake_
uint8_t rx_header_buf_[3]
APIError handle_handshake_frame_error_(APIError aerr)
void send_explicit_handshake_reject_(const LogString *reason)
APIError write_frame_(const uint8_t *data, uint16_t len)
std::shared_ptr< APINoiseContext > ctx_
APIError init() override
Initialize the frame helper, returns OK if successful.
APIError check_handshake_finished_()
APIError init_handshake_()
Initiate the data structures for the handshake.
std::vector< uint8_t > * get_buffer() const
bool ready() const
Check if socket has data ready to read For loop-monitored sockets, checks with the Application's sele...
virtual ssize_t read(void *buf, size_t len)=0
void noise_rand_bytes(void *output, size_t len)
@ HANDSHAKESTATE_READ_FAILED
@ HANDSHAKESTATE_BAD_STATE
@ HANDSHAKESTATE_SPLIT_FAILED
@ BAD_HANDSHAKE_PACKET_LEN
@ BAD_HANDSHAKE_ERROR_BYTE
@ HANDSHAKESTATE_SETUP_FAILED
@ CIPHERSTATE_ENCRYPT_FAILED
@ CIPHERSTATE_DECRYPT_FAILED
@ HANDSHAKESTATE_WRITE_FAILED
const LogString * noise_err_to_logstr(int err)
Convert a noise error code to a readable error.
bool random_bytes(uint8_t *data, size_t len)
Generate len number of random bytes.
std::string get_mac_address()
Get the device MAC address as a string, in lowercase hex notation.
Application App
Global storage of Application pointer - only one Application can exist.
std::vector< uint8_t > container