[api] Add zero-copy support for noise encryption key requests

This commit is contained in:
J. Nick Koston
2025-12-10 12:48:04 +01:00
parent fdd560b165
commit 2d3ccab0b3
7 changed files with 21 additions and 12 deletions
+1 -1
View File
@@ -747,7 +747,7 @@ message NoiseEncryptionSetKeyRequest {
option (source) = SOURCE_CLIENT; option (source) = SOURCE_CLIENT;
option (ifdef) = "USE_API_NOISE"; option (ifdef) = "USE_API_NOISE";
bytes key = 1; bytes key = 1 [(pointer_to_buffer) = true];
} }
message NoiseEncryptionSetKeyResponse { message NoiseEncryptionSetKeyResponse {
+2 -2
View File
@@ -1663,13 +1663,13 @@ bool APIConnection::send_noise_encryption_set_key_response(const NoiseEncryption
resp.success = false; resp.success = false;
psk_t psk{}; psk_t psk{};
if (msg.key.empty()) { if (msg.key_len == 0) {
if (this->parent_->clear_noise_psk(true)) { if (this->parent_->clear_noise_psk(true)) {
resp.success = true; resp.success = true;
} else { } else {
ESP_LOGW(TAG, "Failed to clear encryption key"); ESP_LOGW(TAG, "Failed to clear encryption key");
} }
} else if (base64_decode(msg.key, psk.data(), psk.size()) != psk.size()) { } else if (base64_decode(msg.key, msg.key_len, psk.data(), psk.size()) != psk.size()) {
ESP_LOGW(TAG, "Invalid encryption key length"); ESP_LOGW(TAG, "Invalid encryption key length");
} else if (!this->parent_->save_noise_psk(psk, true)) { } else if (!this->parent_->save_noise_psk(psk, true)) {
ESP_LOGW(TAG, "Failed to save encryption key"); ESP_LOGW(TAG, "Failed to save encryption key");
+5 -2
View File
@@ -858,9 +858,12 @@ void SubscribeLogsResponse::calculate_size(ProtoSize &size) const {
#ifdef USE_API_NOISE #ifdef USE_API_NOISE
bool NoiseEncryptionSetKeyRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) { bool NoiseEncryptionSetKeyRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) {
switch (field_id) { switch (field_id) {
case 1: case 1: {
this->key = value.as_string(); // Use raw data directly to avoid allocation
this->key = value.data();
this->key_len = value.size();
break; break;
}
default: default:
return false; return false;
} }
+3 -2
View File
@@ -1054,11 +1054,12 @@ class SubscribeLogsResponse final : public ProtoMessage {
class NoiseEncryptionSetKeyRequest final : public ProtoDecodableMessage { class NoiseEncryptionSetKeyRequest final : public ProtoDecodableMessage {
public: public:
static constexpr uint8_t MESSAGE_TYPE = 124; static constexpr uint8_t MESSAGE_TYPE = 124;
static constexpr uint8_t ESTIMATED_SIZE = 9; static constexpr uint8_t ESTIMATED_SIZE = 19;
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *message_name() const override { return "noise_encryption_set_key_request"; } const char *message_name() const override { return "noise_encryption_set_key_request"; }
#endif #endif
std::string key{}; const uint8_t *key{nullptr};
uint16_t key_len{0};
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
void dump_to(std::string &out) const override; void dump_to(std::string &out) const override;
#endif #endif
+1 -1
View File
@@ -1115,7 +1115,7 @@ void SubscribeLogsResponse::dump_to(std::string &out) const {
void NoiseEncryptionSetKeyRequest::dump_to(std::string &out) const { void NoiseEncryptionSetKeyRequest::dump_to(std::string &out) const {
MessageDumpHelper helper(out, "NoiseEncryptionSetKeyRequest"); MessageDumpHelper helper(out, "NoiseEncryptionSetKeyRequest");
out.append(" key: "); out.append(" key: ");
out.append(format_hex_pretty(reinterpret_cast<const uint8_t *>(this->key.data()), this->key.size())); out.append(format_hex_pretty(this->key, this->key_len));
out.append("\n"); out.append("\n");
} }
void NoiseEncryptionSetKeyResponse::dump_to(std::string &out) const { dump_field(out, "success", this->success); } void NoiseEncryptionSetKeyResponse::dump_to(std::string &out) const { dump_field(out, "success", this->success); }
+8 -4
View File
@@ -473,10 +473,14 @@ std::string base64_encode(const uint8_t *buf, size_t buf_len) {
} }
size_t base64_decode(const std::string &encoded_string, uint8_t *buf, size_t buf_len) { size_t base64_decode(const std::string &encoded_string, uint8_t *buf, size_t buf_len) {
int in_len = encoded_string.size(); return base64_decode(reinterpret_cast<const uint8_t *>(encoded_string.data()), encoded_string.size(), buf, buf_len);
}
size_t base64_decode(const uint8_t *encoded_data, size_t encoded_len, uint8_t *buf, size_t buf_len) {
size_t in_len = encoded_len;
int i = 0; int i = 0;
int j = 0; int j = 0;
int in = 0; size_t in = 0;
size_t out = 0; size_t out = 0;
uint8_t char_array_4[4], char_array_3[3]; uint8_t char_array_4[4], char_array_3[3];
bool truncated = false; bool truncated = false;
@@ -484,8 +488,8 @@ size_t base64_decode(const std::string &encoded_string, uint8_t *buf, size_t buf
// SAFETY: The loop condition checks is_base64() before processing each character. // SAFETY: The loop condition checks is_base64() before processing each character.
// This ensures base64_find_char() is only called on valid base64 characters, // This ensures base64_find_char() is only called on valid base64 characters,
// preventing the edge case where invalid chars would return 0 (same as 'A'). // preventing the edge case where invalid chars would return 0 (same as 'A').
while (in_len-- && (encoded_string[in] != '=') && is_base64(encoded_string[in])) { while (in_len-- && (encoded_data[in] != '=') && is_base64(encoded_data[in])) {
char_array_4[i++] = encoded_string[in]; char_array_4[i++] = encoded_data[in];
in++; in++;
if (i == 4) { if (i == 4) {
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
+1
View File
@@ -855,6 +855,7 @@ std::string base64_encode(const std::vector<uint8_t> &buf);
std::vector<uint8_t> base64_decode(const std::string &encoded_string); std::vector<uint8_t> base64_decode(const std::string &encoded_string);
size_t base64_decode(std::string const &encoded_string, uint8_t *buf, size_t buf_len); size_t base64_decode(std::string const &encoded_string, uint8_t *buf, size_t buf_len);
size_t base64_decode(const uint8_t *encoded_data, size_t encoded_len, uint8_t *buf, size_t buf_len);
///@} ///@}