[api] Fix potential buffer overflow in noise PSK base64 decode (#12395)

This commit is contained in:
J. Nick Koston
2025-12-10 04:20:23 +01:00
committed by Jonathan Swoboda
parent 1d13d18a16
commit 78b76045ce
2 changed files with 30 additions and 16 deletions

View File

@@ -1669,7 +1669,7 @@ bool APIConnection::send_noise_encryption_set_key_response(const NoiseEncryption
} else {
ESP_LOGW(TAG, "Failed to clear encryption key");
}
} else if (base64_decode(msg.key, psk.data(), msg.key.size()) != psk.size()) {
} else if (base64_decode(msg.key, psk.data(), psk.size()) != psk.size()) {
ESP_LOGW(TAG, "Invalid encryption key length");
} else if (!this->parent_->save_noise_psk(psk, true)) {
ESP_LOGW(TAG, "Failed to save encryption key");

View File

@@ -480,22 +480,13 @@ 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) {
std::vector<uint8_t> decoded = base64_decode(encoded_string);
if (decoded.size() > buf_len) {
ESP_LOGW(TAG, "Base64 decode: buffer too small, truncating");
decoded.resize(buf_len);
}
memcpy(buf, decoded.data(), decoded.size());
return decoded.size();
}
std::vector<uint8_t> base64_decode(const std::string &encoded_string) {
int in_len = encoded_string.size();
int i = 0;
int j = 0;
int in = 0;
size_t out = 0;
uint8_t char_array_4[4], char_array_3[3];
std::vector<uint8_t> ret;
bool truncated = false;
// SAFETY: The loop condition checks is_base64() before processing each character.
// This ensures base64_find_char() is only called on valid base64 characters,
@@ -511,8 +502,13 @@ std::vector<uint8_t> base64_decode(const std::string &encoded_string) {
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (i = 0; (i < 3); i++)
ret.push_back(char_array_3[i]);
for (i = 0; i < 3; i++) {
if (out < buf_len) {
buf[out++] = char_array_3[i];
} else {
truncated = true;
}
}
i = 0;
}
}
@@ -528,10 +524,28 @@ std::vector<uint8_t> base64_decode(const std::string &encoded_string) {
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (j = 0; (j < i - 1); j++)
ret.push_back(char_array_3[j]);
for (j = 0; j < i - 1; j++) {
if (out < buf_len) {
buf[out++] = char_array_3[j];
} else {
truncated = true;
}
}
}
if (truncated) {
ESP_LOGW(TAG, "Base64 decode: buffer too small, truncating");
}
return out;
}
std::vector<uint8_t> base64_decode(const std::string &encoded_string) {
// Calculate maximum decoded size: every 4 base64 chars = 3 bytes
size_t max_len = ((encoded_string.size() + 3) / 4) * 3;
std::vector<uint8_t> ret(max_len);
size_t actual_len = base64_decode(encoded_string, ret.data(), max_len);
ret.resize(actual_len);
return ret;
}