13 static const char *
const TAG =
"api.socket";
18 return errno == EWOULDBLOCK || errno == EAGAIN;
30 return "BAD_HANDSHAKE_PACKET_LEN";
32 return "BAD_INDICATOR";
34 return "BAD_DATA_PACKET";
36 return "TCP_NODELAY_FAILED";
38 return "TCP_NONBLOCKING_FAILED";
40 return "CLOSE_FAILED";
42 return "SHUTDOWN_FAILED";
48 return "SOCKET_READ_FAILED";
50 return "SOCKET_WRITE_FAILED";
52 return "HANDSHAKESTATE_READ_FAILED";
54 return "HANDSHAKESTATE_WRITE_FAILED";
56 return "HANDSHAKESTATE_BAD_STATE";
58 return "CIPHERSTATE_DECRYPT_FAILED";
60 return "CIPHERSTATE_ENCRYPT_FAILED";
62 return "OUT_OF_MEMORY";
64 return "HANDSHAKESTATE_SETUP_FAILED";
66 return "HANDSHAKESTATE_SPLIT_FAILED";
68 return "BAD_HANDSHAKE_ERROR_BYTE";
70 return "CONNECTION_CLOSED";
75 #define HELPER_LOG(msg, ...) ESP_LOGVV(TAG, "%s: " msg, info_.c_str(), ##__VA_ARGS__) 80 static const char *
const PROLOGUE_INIT =
"NoiseAPIInit";
84 if (err == NOISE_ERROR_NO_MEMORY)
86 if (err == NOISE_ERROR_UNKNOWN_ID)
88 if (err == NOISE_ERROR_UNKNOWN_NAME)
89 return "UNKNOWN_NAME";
90 if (err == NOISE_ERROR_MAC_FAILURE)
92 if (err == NOISE_ERROR_NOT_APPLICABLE)
93 return "NOT_APPLICABLE";
94 if (err == NOISE_ERROR_SYSTEM)
96 if (err == NOISE_ERROR_REMOTE_KEY_REQUIRED)
97 return "REMOTE_KEY_REQUIRED";
98 if (err == NOISE_ERROR_LOCAL_KEY_REQUIRED)
99 return "LOCAL_KEY_REQUIRED";
100 if (err == NOISE_ERROR_PSK_REQUIRED)
101 return "PSK_REQUIRED";
102 if (err == NOISE_ERROR_INVALID_LENGTH)
103 return "INVALID_LENGTH";
104 if (err == NOISE_ERROR_INVALID_PARAM)
105 return "INVALID_PARAM";
106 if (err == NOISE_ERROR_INVALID_STATE)
107 return "INVALID_STATE";
108 if (err == NOISE_ERROR_INVALID_NONCE)
109 return "INVALID_NONCE";
110 if (err == NOISE_ERROR_INVALID_PRIVATE_KEY)
111 return "INVALID_PRIVATE_KEY";
112 if (err == NOISE_ERROR_INVALID_PUBLIC_KEY)
113 return "INVALID_PUBLIC_KEY";
114 if (err == NOISE_ERROR_INVALID_FORMAT)
115 return "INVALID_FORMAT";
116 if (err == NOISE_ERROR_INVALID_SIGNATURE)
117 return "INVALID_SIGNATURE";
124 HELPER_LOG(
"Bad state for init %d", (
int)
state_);
127 int err =
socket_->setblocking(
false);
130 HELPER_LOG(
"Setting nonblocking failed with errno %d", errno);
135 err =
socket_->setsockopt(IPPROTO_TCP, TCP_NODELAY, &enable,
sizeof(
int));
138 HELPER_LOG(
"Setting nodelay failed with errno %d", errno);
143 prologue_.insert(
prologue_.end(), PROLOGUE_INIT, PROLOGUE_INIT + strlen(PROLOGUE_INIT));
179 if (frame ==
nullptr) {
180 HELPER_LOG(
"Bad argument for try_read_frame_");
189 if (received == -1) {
190 if (errno == EWOULDBLOCK || errno == EAGAIN) {
194 HELPER_LOG(
"Socket read failed with errno %d", errno);
196 }
else if (received == 0) {
198 HELPER_LOG(
"Connection closed");
201 rx_header_buf_len_ += received;
202 if ((
size_t) received != to_read) {
212 if (indicator != 0x01) {
214 HELPER_LOG(
"Bad indicator byte %u", indicator);
223 HELPER_LOG(
"Bad packet len for handshake: %d", msg_size);
228 if (
rx_buf_.size() != msg_size) {
236 if (received == -1) {
237 if (errno == EWOULDBLOCK || errno == EAGAIN) {
241 HELPER_LOG(
"Socket read failed with errno %d", errno);
243 }
else if (received == 0) {
245 HELPER_LOG(
"Connection closed");
248 rx_buf_len_ += received;
249 if ((
size_t) received != to_read) {
256 #ifdef HELPER_LOG_PACKETS 280 HELPER_LOG(
"Bad state for method: %d", (
int)
state_);
306 std::vector<uint8_t> msg;
312 const uint8_t *name_ptr =
reinterpret_cast<const uint8_t *
>(name.c_str());
313 msg.insert(msg.end(), name_ptr, name_ptr + name.size() + 1);
316 const uint8_t *mac_ptr =
reinterpret_cast<const uint8_t *
>(mac.c_str());
317 msg.insert(msg.end(), mac_ptr, mac_ptr + mac.size() + 1);
331 int action = noise_handshakestate_get_action(
handshake_);
332 if (action == NOISE_ACTION_READ_MESSAGE) {
347 if (frame.
msg.empty()) {
350 }
else if (frame.
msg[0] != 0x00) {
351 HELPER_LOG(
"Bad handshake error byte: %u", frame.
msg[0]);
357 noise_buffer_init(mbuf);
358 noise_buffer_set_input(mbuf, frame.
msg.data() + 1, frame.
msg.size() - 1);
359 err = noise_handshakestate_read_message(
handshake_, &mbuf,
nullptr);
362 HELPER_LOG(
"noise_handshakestate_read_message failed: %s",
noise_err_to_str(err).c_str());
363 if (err == NOISE_ERROR_MAC_FAILURE) {
374 }
else if (action == NOISE_ACTION_WRITE_MESSAGE) {
377 noise_buffer_init(mbuf);
378 noise_buffer_set_output(mbuf, buffer + 1,
sizeof(buffer) - 1);
380 err = noise_handshakestate_write_message(
handshake_, &mbuf,
nullptr);
383 HELPER_LOG(
"noise_handshakestate_write_message failed: %s",
noise_err_to_str(err).c_str());
397 HELPER_LOG(
"Bad action for handshake: %d", action);
407 std::vector<uint8_t> data;
408 data.resize(reason.length() + 1);
410 for (
size_t i = 0; i < reason.length(); i++) {
411 data[i + 1] = (uint8_t) reason[i];
438 noise_buffer_init(mbuf);
439 noise_buffer_set_inout(mbuf, frame.
msg.data(), frame.
msg.size(), frame.
msg.size());
443 HELPER_LOG(
"noise_cipherstate_decrypt failed: %s",
noise_err_to_str(err).c_str());
447 size_t msg_size = mbuf.size;
448 uint8_t *msg_data = frame.
msg.data();
451 HELPER_LOG(
"Bad data packet: size %d too short", msg_size);
459 uint16_t
type = (((uint16_t) msg_data[0]) << 8) | msg_data[1];
460 uint16_t data_len = (((uint16_t) msg_data[2]) << 8) | msg_data[3];
461 if (data_len > msg_size - 4) {
463 HELPER_LOG(
"Bad data packet: data_len %u greater than msg_size %u", data_len, msg_size);
487 size_t msg_len = 4 + payload_len + padding;
488 size_t frame_len = 3 + msg_len + noise_cipherstate_get_mac_length(
send_cipher_);
489 auto tmpbuf = std::unique_ptr<uint8_t[]>{
new (std::nothrow) uint8_t[frame_len]};
490 if (tmpbuf ==
nullptr) {
491 HELPER_LOG(
"Could not allocate for writing packet");
497 const uint8_t msg_offset = 3;
498 const uint8_t payload_offset = msg_offset + 4;
499 tmpbuf[msg_offset + 0] = (uint8_t) (type >> 8);
500 tmpbuf[msg_offset + 1] = (uint8_t) type;
501 tmpbuf[msg_offset + 2] = (uint8_t) (payload_len >> 8);
502 tmpbuf[msg_offset + 3] = (uint8_t) payload_len;
504 std::copy(payload, payload + payload_len, &tmpbuf[payload_offset]);
506 std::fill(&tmpbuf[payload_offset + payload_len], &tmpbuf[frame_len], 0);
509 noise_buffer_init(mbuf);
510 noise_buffer_set_inout(mbuf, &tmpbuf[msg_offset], msg_len, frame_len - msg_offset);
514 HELPER_LOG(
"noise_cipherstate_encrypt failed: %s",
noise_err_to_str(err).c_str());
518 size_t total_len = 3 + mbuf.size;
519 tmpbuf[1] = (uint8_t) (mbuf.size >> 8);
520 tmpbuf[2] = (uint8_t) mbuf.size;
524 iov.iov_len = total_len;
534 if (errno == EWOULDBLOCK || errno == EAGAIN)
537 HELPER_LOG(
"Socket write failed with errno %d", errno);
539 }
else if (sent == 0) {
559 size_t total_write_len = 0;
560 for (
int i = 0; i < iovcnt; i++) {
561 #ifdef HELPER_LOG_PACKETS 562 ESP_LOGVV(TAG,
"Sending raw: %s",
563 format_hex_pretty(reinterpret_cast<uint8_t *>(iov[i].iov_base), iov[i].iov_len).c_str());
565 total_write_len += iov[i].
iov_len;
577 for (
int i = 0; i < iovcnt; i++) {
579 reinterpret_cast<uint8_t *>(iov[i].iov_base) + iov[i].
iov_len);
584 ssize_t sent =
socket_->writev(iov, iovcnt);
587 for (
int i = 0; i < iovcnt; i++) {
589 reinterpret_cast<uint8_t *>(iov[i].iov_base) + iov[i].
iov_len);
592 }
else if (sent == -1) {
595 HELPER_LOG(
"Socket write failed with errno %d", errno);
597 }
else if ((
size_t) sent != total_write_len) {
599 size_t to_consume = sent;
600 for (
int i = 0; i < iovcnt; i++) {
601 if (to_consume >= iov[i].iov_len) {
605 reinterpret_cast<uint8_t *>(iov[i].iov_base) + iov[i].
iov_len);
617 header[1] = (uint8_t) (len >> 8);
618 header[2] = (uint8_t) len;
626 iov[1].
iov_base =
const_cast<uint8_t *
>(data);
641 nid_.pattern_id = NOISE_PATTERN_NN;
642 nid_.cipher_id = NOISE_CIPHER_CHACHAPOLY;
643 nid_.dh_id = NOISE_DH_CURVE25519;
644 nid_.prefix_id = NOISE_PREFIX_STANDARD;
645 nid_.hybrid_id = NOISE_DH_NONE;
646 nid_.hash_id = NOISE_HASH_SHA256;
647 nid_.modifier_ids[0] = NOISE_MODIFIER_PSK0;
649 err = noise_handshakestate_new_by_id(&
handshake_, &
nid_, NOISE_ROLE_RESPONDER);
652 HELPER_LOG(
"noise_handshakestate_new_by_id failed: %s",
noise_err_to_str(err).c_str());
656 const auto &psk =
ctx_->get_psk();
657 err = noise_handshakestate_set_pre_shared_key(
handshake_, psk.data(), psk.size());
660 HELPER_LOG(
"noise_handshakestate_set_pre_shared_key failed: %s",
noise_err_to_str(err).c_str());
667 HELPER_LOG(
"noise_handshakestate_set_prologue failed: %s",
noise_err_to_str(err).c_str());
676 HELPER_LOG(
"noise_handshakestate_start failed: %s",
noise_err_to_str(err).c_str());
685 int action = noise_handshakestate_get_action(
handshake_);
686 if (action == NOISE_ACTION_READ_MESSAGE || action == NOISE_ACTION_WRITE_MESSAGE)
688 if (action != NOISE_ACTION_SPLIT) {
690 HELPER_LOG(
"Bad action for handshake: %d", action);
696 HELPER_LOG(
"noise_handshakestate_split failed: %s",
noise_err_to_str(err).c_str());
700 HELPER_LOG(
"Handshake complete!");
730 int err =
socket_->shutdown(how);
733 if (how == SHUT_RDWR) {
742 ESP_LOGE(TAG,
"Failed to acquire random bytes, rebooting!");
747 #endif // USE_API_NOISE 749 #ifdef USE_API_PLAINTEXT 754 HELPER_LOG(
"Bad state for init %d", (
int)
state_);
757 int err =
socket_->setblocking(
false);
760 HELPER_LOG(
"Setting nonblocking failed with errno %d", errno);
764 err =
socket_->setsockopt(IPPROTO_TCP, TCP_NODELAY, &enable,
sizeof(
int));
767 HELPER_LOG(
"Setting nodelay failed with errno %d", errno);
799 if (frame ==
nullptr) {
800 HELPER_LOG(
"Bad argument for try_read_frame_");
805 while (!rx_header_parsed_) {
807 ssize_t received =
socket_->read(&data, 1);
808 if (received == -1) {
809 if (errno == EWOULDBLOCK || errno == EAGAIN) {
813 HELPER_LOG(
"Socket read failed with errno %d", errno);
815 }
else if (received == 0) {
817 HELPER_LOG(
"Connection closed");
830 uint32_t consumed = 0;
832 if (!msg_size_varint.has_value()) {
838 rx_header_parsed_len_ = msg_size_varint->as_uint32();
841 if (!msg_type_varint.has_value()) {
845 rx_header_parsed_type_ = msg_type_varint->as_uint32();
846 rx_header_parsed_ =
true;
851 if (
rx_buf_.size() != rx_header_parsed_len_) {
852 rx_buf_.resize(rx_header_parsed_len_);
857 size_t to_read = rx_header_parsed_len_ -
rx_buf_len_;
859 if (received == -1) {
860 if (errno == EWOULDBLOCK || errno == EAGAIN) {
864 HELPER_LOG(
"Socket read failed with errno %d", errno);
866 }
else if (received == 0) {
868 HELPER_LOG(
"Connection closed");
871 rx_buf_len_ += received;
872 if ((
size_t) received != to_read) {
879 #ifdef HELPER_LOG_PACKETS 887 rx_header_parsed_ =
false;
914 const char msg[] =
"\x00" 915 "Bad indicator byte";
925 buffer->
data_len = rx_header_parsed_len_;
926 buffer->
type = rx_header_parsed_type_;
935 std::vector<uint8_t> header;
936 header.push_back(0x00);
942 iov[0].
iov_len = header.size();
943 if (payload_len == 0) {
946 iov[1].
iov_base =
const_cast<uint8_t *
>(payload);
957 }
else if (sent == -1) {
959 HELPER_LOG(
"Socket write failed with errno %d", errno);
979 size_t total_write_len = 0;
980 for (
int i = 0; i < iovcnt; i++) {
981 #ifdef HELPER_LOG_PACKETS 982 ESP_LOGVV(TAG,
"Sending raw: %s",
985 total_write_len += iov[i].
iov_len;
997 for (
int i = 0; i < iovcnt; i++) {
1004 ssize_t sent =
socket_->writev(iov, iovcnt);
1007 for (
int i = 0; i < iovcnt; i++) {
1012 }
else if (sent == -1) {
1015 HELPER_LOG(
"Socket write failed with errno %d", errno);
1017 }
else if ((
size_t) sent != total_write_len) {
1019 size_t to_consume = sent;
1020 for (
int i = 0; i < iovcnt; i++) {
1021 if (to_consume >= iov[i].
iov_len) {
1043 int err =
socket_->shutdown(how);
1046 if (how == SHUT_RDWR) {
1051 #endif // USE_API_PLAINTEXT
~APINoiseFrameHelper() override
APIError write_frame_(const uint8_t *data, size_t len)
std::shared_ptr< APINoiseContext > ctx_
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
APIError close() override
Representation of a VarInt - in ProtoBuf should be 64bit but we only use 32bit.
const char * api_error_to_str(APIError err)
APIError write_packet(uint16_t type, const uint8_t *payload, size_t len) override
static optional< ProtoVarInt > parse(const uint8_t *buffer, uint32_t len, uint32_t *consumed)
NoiseCipherState * recv_cipher_
APIError init() override
Initialize the frame helper, returns OK if successful.
APIError write_raw_(const struct iovec *iov, int iovcnt)
Write the data to the socket, or buffer it a write would block.
std::vector< uint8_t > tx_buf_
bool random_bytes(uint8_t *data, size_t len)
Generate len number of random bytes.
std::unique_ptr< socket::Socket > socket_
APIError loop() override
Run through handshake messages (if in that phase)
APIError try_read_frame_(ParsedFrame *frame)
Read a packet into the rx_buf_.
NoiseHandshakeState * handshake_
bool is_would_block(ssize_t ret)
Is the given return value (from write syscalls) a wouldblock error?
std::vector< uint8_t > prologue_
void encode(std::vector< uint8_t > &out)
std::string get_mac_address()
Get the device MAC address as a string, in lowercase hex notation.
APIError loop() override
Not used for plaintext.
APIError try_read_frame_(ParsedFrame *frame)
Read a packet into the rx_buf_.
APIError shutdown(int how) override
std::string noise_err_to_str(int err)
Convert a noise error code to a readable error.
Application App
Global storage of Application pointer - only one Application can exist.
APIError shutdown(int how) override
uint8_t rx_header_buf_[3]
APIError read_packet(ReadPacketBuffer *buffer) override
const std::string & get_name() const
Get the name of this Application set by pre_setup().
void send_explicit_handshake_reject_(const std::string &reason)
APIError read_packet(ReadPacketBuffer *buffer) override
enum esphome::api::APINoiseFrameHelper::State state_
std::vector< uint8_t > msg
APIError init() override
Initialize the frame helper, returns OK if successful.
size_t rx_header_buf_len_
std::string to_string(int value)
APIError state_action_()
To be called from read/write methods.
APIError write_raw_(const struct iovec *iov, int iovcnt)
Write the data to the socket, or buffer it a write would block.
APIError init_handshake_()
Initiate the data structures for the handshake.
std::vector< uint8_t > rx_buf_
APIError write_packet(uint16_t type, const uint8_t *payload, size_t len) override
Implementation of SPI Controller mode.
APIError close() override
APIError try_send_tx_buf_()
void noise_rand_bytes(void *output, size_t len)
APIError try_send_tx_buf_()
std::vector< uint8_t > container
bool can_write_without_blocking() override
bool can_write_without_blocking() override
NoiseCipherState * send_cipher_
APIError check_handshake_finished_()