15static const char *
const TAG =
"api.socket";
24 return "BAD_HANDSHAKE_PACKET_LEN";
26 return "BAD_INDICATOR";
28 return "BAD_DATA_PACKET";
30 return "TCP_NODELAY_FAILED";
32 return "TCP_NONBLOCKING_FAILED";
34 return "CLOSE_FAILED";
36 return "SHUTDOWN_FAILED";
42 return "SOCKET_READ_FAILED";
44 return "SOCKET_WRITE_FAILED";
46 return "HANDSHAKESTATE_READ_FAILED";
48 return "HANDSHAKESTATE_WRITE_FAILED";
50 return "HANDSHAKESTATE_BAD_STATE";
52 return "CIPHERSTATE_DECRYPT_FAILED";
54 return "CIPHERSTATE_ENCRYPT_FAILED";
56 return "OUT_OF_MEMORY";
58 return "HANDSHAKESTATE_SETUP_FAILED";
60 return "HANDSHAKESTATE_SPLIT_FAILED";
62 return "BAD_HANDSHAKE_ERROR_BYTE";
64 return "CONNECTION_CLOSED";
72 buffer.
data.reserve(total_write_len);
73 for (
int i = 0; i < iovcnt; i++) {
74 const uint8_t *data =
reinterpret_cast<uint8_t *
>(iov[i].
iov_base);
77 this->
tx_buf_.push_back(std::move(buffer));
88 uint16_t total_write_len = 0;
89 for (
int i = 0; i < iovcnt; i++) {
90#ifdef HELPER_LOG_PACKETS
91 ESP_LOGVV(TAG,
"Sending raw: %s",
92 format_hex_pretty(
reinterpret_cast<uint8_t *
>(iov[i].iov_base), iov[i].iov_len).c_str());
94 total_write_len +=
static_cast<uint16_t
>(iov[i].
iov_len);
117 if (errno == EWOULDBLOCK || errno == EAGAIN) {
123 ESP_LOGVV(TAG,
"%s: Socket write failed with errno %d", this->
info_.c_str(), errno);
126 }
else if (
static_cast<uint16_t
>(sent) < total_write_len) {
129 uint16_t to_consume =
static_cast<uint16_t
>(sent);
130 uint16_t remaining = total_write_len -
static_cast<uint16_t
>(sent);
132 buffer.
data.reserve(remaining);
134 for (
int i = 0; i < iovcnt; i++) {
135 if (to_consume >= iov[i].iov_len) {
137 to_consume -=
static_cast<uint16_t
>(iov[i].
iov_len);
140 const uint8_t *data =
reinterpret_cast<uint8_t *
>(iov[i].
iov_base) + to_consume;
141 uint16_t
len =
static_cast<uint16_t
>(iov[i].
iov_len) - to_consume;
142 buffer.
data.insert(buffer.
data.end(), data, data +
len);
147 this->
tx_buf_.push_back(std::move(buffer));
157 bool tx_buf_empty =
false;
158 while (!tx_buf_empty) {
166 if (errno != EWOULDBLOCK && errno != EAGAIN) {
168 ESP_LOGVV(TAG,
"%s: Socket write failed with errno %d", this->
info_.c_str(), errno);
174 }
else if (sent == 0) {
177 }
else if (
static_cast<uint16_t
>(sent) < front_buffer.
remaining()) {
180 front_buffer.
offset +=
static_cast<uint16_t
>(sent);
186 tx_buf_empty = this->
tx_buf_.empty();
196 ESP_LOGVV(TAG,
"%s: Bad state for init %d", this->
info_.c_str(), (
int)
state_);
202 ESP_LOGVV(TAG,
"%s: Setting nonblocking failed with errno %d", this->
info_.c_str(), errno);
210 ESP_LOGVV(TAG,
"%s: Setting nodelay failed with errno %d", this->
info_.c_str(), errno);
216#define HELPER_LOG(msg, ...) ESP_LOGVV(TAG, "%s: " msg, this->info_.c_str(), ##__VA_ARGS__)
221static const char *
const PROLOGUE_INIT =
"NoiseAPIInit";
225 if (err == NOISE_ERROR_NO_MEMORY)
227 if (err == NOISE_ERROR_UNKNOWN_ID)
229 if (err == NOISE_ERROR_UNKNOWN_NAME)
230 return "UNKNOWN_NAME";
231 if (err == NOISE_ERROR_MAC_FAILURE)
232 return "MAC_FAILURE";
233 if (err == NOISE_ERROR_NOT_APPLICABLE)
234 return "NOT_APPLICABLE";
235 if (err == NOISE_ERROR_SYSTEM)
237 if (err == NOISE_ERROR_REMOTE_KEY_REQUIRED)
238 return "REMOTE_KEY_REQUIRED";
239 if (err == NOISE_ERROR_LOCAL_KEY_REQUIRED)
240 return "LOCAL_KEY_REQUIRED";
241 if (err == NOISE_ERROR_PSK_REQUIRED)
242 return "PSK_REQUIRED";
243 if (err == NOISE_ERROR_INVALID_LENGTH)
244 return "INVALID_LENGTH";
245 if (err == NOISE_ERROR_INVALID_PARAM)
246 return "INVALID_PARAM";
247 if (err == NOISE_ERROR_INVALID_STATE)
248 return "INVALID_STATE";
249 if (err == NOISE_ERROR_INVALID_NONCE)
250 return "INVALID_NONCE";
251 if (err == NOISE_ERROR_INVALID_PRIVATE_KEY)
252 return "INVALID_PRIVATE_KEY";
253 if (err == NOISE_ERROR_INVALID_PUBLIC_KEY)
254 return "INVALID_PUBLIC_KEY";
255 if (err == NOISE_ERROR_INVALID_FORMAT)
256 return "INVALID_FORMAT";
257 if (err == NOISE_ERROR_INVALID_SIGNATURE)
258 return "INVALID_SIGNATURE";
270 prologue_.insert(
prologue_.end(), PROLOGUE_INIT, PROLOGUE_INIT + strlen(PROLOGUE_INIT));
305 if (frame ==
nullptr) {
306 HELPER_LOG(
"Bad argument for try_read_frame_");
315 if (received == -1) {
316 if (errno == EWOULDBLOCK || errno == EAGAIN) {
320 HELPER_LOG(
"Socket read failed with errno %d", errno);
322 }
else if (received == 0) {
324 HELPER_LOG(
"Connection closed");
328 if (
static_cast<uint8_t
>(received) != to_read) {
338 if (indicator != 0x01) {
340 HELPER_LOG(
"Bad indicator byte %u", indicator);
349 HELPER_LOG(
"Bad packet len for handshake: %d", msg_size);
354 if (
rx_buf_.size() != msg_size) {
362 if (received == -1) {
363 if (errno == EWOULDBLOCK || errno == EAGAIN) {
367 HELPER_LOG(
"Socket read failed with errno %d", errno);
369 }
else if (received == 0) {
371 HELPER_LOG(
"Connection closed");
375 if (
static_cast<uint16_t
>(received) != to_read) {
382#ifdef HELPER_LOG_PACKETS
406 HELPER_LOG(
"Bad state for method: %d", (
int)
state_);
437 std::vector<uint8_t> msg;
439 msg.reserve(1 + name.size() + 1 + mac.size() + 1);
445 const uint8_t *name_ptr =
reinterpret_cast<const uint8_t *
>(name.c_str());
446 msg.insert(msg.end(), name_ptr, name_ptr + name.size() + 1);
448 const uint8_t *mac_ptr =
reinterpret_cast<const uint8_t *
>(mac.c_str());
449 msg.insert(msg.end(), mac_ptr, mac_ptr + mac.size() + 1);
463 int action = noise_handshakestate_get_action(
handshake_);
464 if (action == NOISE_ACTION_READ_MESSAGE) {
479 if (frame.
msg.empty()) {
482 }
else if (frame.
msg[0] != 0x00) {
483 HELPER_LOG(
"Bad handshake error byte: %u", frame.
msg[0]);
489 noise_buffer_init(mbuf);
490 noise_buffer_set_input(mbuf, frame.
msg.data() + 1, frame.
msg.size() - 1);
491 err = noise_handshakestate_read_message(
handshake_, &mbuf,
nullptr);
494 HELPER_LOG(
"noise_handshakestate_read_message failed: %s",
noise_err_to_str(err).c_str());
495 if (err == NOISE_ERROR_MAC_FAILURE) {
506 }
else if (action == NOISE_ACTION_WRITE_MESSAGE) {
509 noise_buffer_init(mbuf);
510 noise_buffer_set_output(mbuf, buffer + 1,
sizeof(buffer) - 1);
512 err = noise_handshakestate_write_message(
handshake_, &mbuf,
nullptr);
515 HELPER_LOG(
"noise_handshakestate_write_message failed: %s",
noise_err_to_str(err).c_str());
529 HELPER_LOG(
"Bad action for handshake: %d", action);
539 std::vector<uint8_t> data;
540 data.resize(reason.length() + 1);
544 if (!reason.empty()) {
545 std::memcpy(data.data() + 1, reason.c_str(), reason.length());
572 noise_buffer_init(mbuf);
573 noise_buffer_set_inout(mbuf, frame.
msg.data(), frame.
msg.size(), frame.
msg.size());
577 HELPER_LOG(
"noise_cipherstate_decrypt failed: %s",
noise_err_to_str(err).c_str());
581 uint16_t msg_size = mbuf.size;
582 uint8_t *msg_data = frame.
msg.data();
585 HELPER_LOG(
"Bad data packet: size %d too short", msg_size);
593 uint16_t
type = (((uint16_t) msg_data[0]) << 8) | msg_data[1];
594 uint16_t data_len = (((uint16_t) msg_data[2]) << 8) | msg_data[3];
595 if (data_len > msg_size - 4) {
597 HELPER_LOG(
"Bad data packet: data_len %u greater than msg_size %u", data_len, msg_size);
608 std::vector<uint8_t> *raw_buffer = buffer.
get_buffer();
615 std::vector<PacketInfo> packets;
616 packets.emplace_back(
type, 0, payload_len);
631 if (packets.empty()) {
635 std::vector<uint8_t> *raw_buffer = buffer.
get_buffer();
640 for (
const auto &packet : packets) {
641 uint16_t
type = packet.message_type;
642 uint16_t offset = packet.offset;
643 uint16_t payload_len = packet.payload_size;
644 uint16_t msg_len = 4 + payload_len;
647 uint8_t *buf_start = raw_buffer->data() + offset;
654 const uint8_t msg_offset = 3;
655 buf_start[msg_offset + 0] = (uint8_t) (
type >> 8);
656 buf_start[msg_offset + 1] = (uint8_t)
type;
657 buf_start[msg_offset + 2] = (uint8_t) (payload_len >> 8);
658 buf_start[msg_offset + 3] = (uint8_t) payload_len;
666 noise_buffer_init(mbuf);
667 noise_buffer_set_inout(mbuf, buf_start + msg_offset, msg_len, msg_len +
frame_footer_size_);
669 int err = noise_cipherstate_encrypt(
send_cipher_, &mbuf);
672 HELPER_LOG(
"noise_cipherstate_encrypt failed: %s",
noise_err_to_str(err).c_str());
677 buf_start[1] = (uint8_t) (mbuf.size >> 8);
678 buf_start[2] = (uint8_t) mbuf.size;
694 header[1] = (uint8_t) (
len >> 8);
695 header[2] = (uint8_t)
len;
703 iov[1].
iov_base =
const_cast<uint8_t *
>(data);
718 nid_.pattern_id = NOISE_PATTERN_NN;
719 nid_.cipher_id = NOISE_CIPHER_CHACHAPOLY;
720 nid_.dh_id = NOISE_DH_CURVE25519;
721 nid_.prefix_id = NOISE_PREFIX_STANDARD;
722 nid_.hybrid_id = NOISE_DH_NONE;
723 nid_.hash_id = NOISE_HASH_SHA256;
724 nid_.modifier_ids[0] = NOISE_MODIFIER_PSK0;
726 err = noise_handshakestate_new_by_id(&
handshake_, &
nid_, NOISE_ROLE_RESPONDER);
729 HELPER_LOG(
"noise_handshakestate_new_by_id failed: %s",
noise_err_to_str(err).c_str());
733 const auto &psk =
ctx_->get_psk();
734 err = noise_handshakestate_set_pre_shared_key(
handshake_, psk.data(), psk.size());
737 HELPER_LOG(
"noise_handshakestate_set_pre_shared_key failed: %s",
noise_err_to_str(err).c_str());
744 HELPER_LOG(
"noise_handshakestate_set_prologue failed: %s",
noise_err_to_str(err).c_str());
753 HELPER_LOG(
"noise_handshakestate_start failed: %s",
noise_err_to_str(err).c_str());
762 int action = noise_handshakestate_get_action(
handshake_);
763 if (action == NOISE_ACTION_READ_MESSAGE || action == NOISE_ACTION_WRITE_MESSAGE)
765 if (action != NOISE_ACTION_SPLIT) {
767 HELPER_LOG(
"Bad action for handshake: %d", action);
773 HELPER_LOG(
"noise_handshakestate_split failed: %s",
noise_err_to_str(err).c_str());
779 HELPER_LOG(
"Handshake complete!");
805 ESP_LOGE(TAG,
"Acquiring random bytes failed; rebooting");
813#ifdef USE_API_PLAINTEXT
849 if (frame ==
nullptr) {
850 HELPER_LOG(
"Bad argument for try_read_frame_");
865 if (received == -1) {
866 if (errno == EWOULDBLOCK || errno == EAGAIN) {
870 HELPER_LOG(
"Socket read failed with errno %d", errno);
872 }
else if (received == 0) {
874 HELPER_LOG(
"Connection closed");
892 HELPER_LOG(
"Header buffer overflow");
914 uint8_t varint_pos = 1;
915 uint32_t consumed = 0;
918 if (!msg_size_varint.has_value()) {
923 if (msg_size_varint->as_uint32() > std::numeric_limits<uint16_t>::max()) {
925 HELPER_LOG(
"Bad packet: message size %" PRIu32
" exceeds maximum %u", msg_size_varint->as_uint32(),
926 std::numeric_limits<uint16_t>::max());
932 varint_pos += consumed;
935 if (!msg_type_varint.has_value()) {
939 if (msg_type_varint->as_uint32() > std::numeric_limits<uint16_t>::max()) {
941 HELPER_LOG(
"Bad packet: message type %" PRIu32
" exceeds maximum %u", msg_type_varint->as_uint32(),
942 std::numeric_limits<uint16_t>::max());
959 if (received == -1) {
960 if (errno == EWOULDBLOCK || errno == EAGAIN) {
964 HELPER_LOG(
"Socket read failed with errno %d", errno);
966 }
else if (received == 0) {
968 HELPER_LOG(
"Connection closed");
972 if (
static_cast<uint16_t
>(received) != to_read) {
979#ifdef HELPER_LOG_PACKETS
1004 struct iovec iov[1];
1013 const char msg[] =
"\x00"
1014 "Bad indicator byte";
1029 std::vector<uint8_t> *raw_buffer = buffer.
get_buffer();
1033 std::vector<PacketInfo> packets;
1034 packets.emplace_back(
type, 0, payload_len);
1040 const std::vector<PacketInfo> &packets) {
1045 if (packets.empty()) {
1049 std::vector<uint8_t> *raw_buffer = buffer.
get_buffer();
1053 for (
const auto &packet : packets) {
1054 uint16_t
type = packet.message_type;
1055 uint16_t offset = packet.offset;
1056 uint16_t payload_len = packet.payload_size;
1061 uint8_t total_header_len = 1 + size_varint_len + type_varint_len;
1088 uint8_t *buf_start = raw_buffer->data() + offset;
1092 buf_start[header_offset] = 0x00;
1102 iov.
iov_base = buf_start + header_offset;
1103 iov.
iov_len = total_header_len + payload_len;
const std::string & get_name() const
Get the name of this Application set by pre_setup().
std::vector< uint8_t > rx_buf_
std::vector< struct iovec > reusable_iovs_
uint8_t frame_header_padding_
void buffer_data_from_iov_(const struct iovec *iov, int iovcnt, uint16_t total_write_len)
APIError try_send_tx_buf_()
uint8_t frame_footer_size_
APIError write_raw_(const struct iovec *iov, int iovcnt)
std::deque< SendBuffer > tx_buf_
uint8_t rx_header_buf_len_
APIError write_protobuf_packet(uint16_t type, ProtoWriteBuffer buffer) override
NoiseCipherState * send_cipher_
APIError read_packet(ReadPacketBuffer *buffer) override
NoiseCipherState * recv_cipher_
APIError try_read_frame_(ParsedFrame *frame)
Read a packet into the rx_buf_.
~APINoiseFrameHelper() override
std::vector< uint8_t > prologue_
APIError write_protobuf_packets(ProtoWriteBuffer buffer, const std::vector< PacketInfo > &packets) override
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 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_()
void send_explicit_handshake_reject_(const std::string &reason)
APIError init_handshake_()
Initiate the data structures for the handshake.
uint8_t rx_header_buf_[6]
uint16_t rx_header_parsed_type_
APIError write_protobuf_packets(ProtoWriteBuffer buffer, const std::vector< PacketInfo > &packets) override
APIError init() override
Initialize the frame helper, returns OK if successful.
uint16_t rx_header_parsed_len_
APIError loop() override
Not used for plaintext.
APIError read_packet(ReadPacketBuffer *buffer) override
APIError write_protobuf_packet(uint16_t type, ProtoWriteBuffer buffer) override
uint8_t rx_header_buf_pos_
APIError try_read_frame_(ParsedFrame *frame)
Read a packet into the rx_buf_.
static uint32_t varint(uint32_t value)
ProtoSize class for Protocol Buffer serialization size calculation.
Representation of a VarInt - in ProtoBuf should be 64bit but we only use 32bit.
void encode_to_buffer_unchecked(uint8_t *buffer, size_t len)
Encode the varint value to a pre-allocated buffer without bounds checking.
static optional< ProtoVarInt > parse(const uint8_t *buffer, uint32_t len, uint32_t *consumed)
std::vector< uint8_t > * get_buffer() const
virtual ssize_t write(const void *buf, size_t len)=0
virtual int setblocking(bool blocking)=0
virtual ssize_t writev(const struct iovec *iov, int iovcnt)=0
virtual ssize_t read(void *buf, size_t len)=0
virtual int setsockopt(int level, int optname, const void *optval, socklen_t optlen)=0
@ 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
void noise_rand_bytes(void *output, size_t len)
std::string noise_err_to_str(int err)
Convert a noise error code to a readable error.
const char * api_error_to_str(APIError err)
Providing packet encoding functions for exchanging data with a remote host.
bool random_bytes(uint8_t *data, size_t len)
Generate len number of random bytes.
std::string to_string(int value)
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::string format_hex_pretty(const uint8_t *data, size_t length)
Format the byte array data of length len in pretty-printed, human-readable hex.
std::vector< uint8_t > msg
uint16_t remaining() const
std::vector< uint8_t > data
const uint8_t * current_data() const
std::vector< uint8_t > container