diff --git a/app.yaml b/app.yaml index 705f9a6..cddfd66 100644 --- a/app.yaml +++ b/app.yaml @@ -1,11 +1,12 @@ id: t11 name: t11 -version: 1.2.11 +version: 1.2.13.1 author: t11 icon: '' desc: t11 files: - 4g_download_manager.py + - 4g_upload_manager.py - app.yaml - archery_netcore.cpython-311-riscv64-linux-gnu.so - at_client.py @@ -18,8 +19,6 @@ files: - main.py - model_270139.cvimodel - model_270139.mud - - model_270820.cvimodel - - model_270820.mud - network.py - ota_manager.py - power.py @@ -34,3 +33,4 @@ files: - vision.py - wifi_config_httpd.py - wifi.py + - wpa_supplicant_conf.py diff --git a/cpp_ext/decrypt_ota_file.cpp b/cpp_ext/decrypt_ota_file.cpp index 02d7d6b..1b52e51 100644 --- a/cpp_ext/decrypt_ota_file.cpp +++ b/cpp_ext/decrypt_ota_file.cpp @@ -1,14 +1,11 @@ -#include -#include // 支持 std::vector, std::map 等 -#include #include #include #include #include #include #include -#include #include +#include #include "native_logger.hpp" namespace netcore{ @@ -18,11 +15,11 @@ namespace netcore{ constexpr size_t kOtaMagicLen = 7; constexpr size_t kGcmNonceLen = 12; constexpr size_t kGcmTagLen = 16; + constexpr size_t kHeaderLen = kOtaMagicLen + kGcmNonceLen; + // 分块解密,避免整包读入导致 RAM 峰值约为「文件大小×2」(小内存设备易 OOM) + constexpr size_t kDecryptChunk = 65536; - // 固定 32-byte AES-256-GCM key(提高被直接查看的成本;不是绝对安全) - // 注意:需要与打包端传入的 --aead-key-hex 保持一致。 static std::array ota_key_bytes() { - // 简单拆分混淆:key = a XOR b static const std::array a = { 0x92,0x99,0x4d,0x06,0x6f,0xb6,0xa6,0x3d,0x85,0x08,0xbe,0x73,0x5e,0x73,0x4d,0x8a, 0x53,0x88,0xe6,0x99,0xfc,0x10,0x29,0xb9,0x16,0x9b,0xe7,0x0c,0x65,0x21,0x1c,0xce @@ -36,56 +33,45 @@ namespace netcore{ return k; } - static bool read_file_all(const std::string& path, std::vector& out) { - std::ifstream ifs(path, std::ios::binary); - if (!ifs) return false; - ifs.seekg(0, std::ios::end); - std::streampos size = ifs.tellg(); - if (size <= 0) return false; - ifs.seekg(0, std::ios::beg); - out.resize(static_cast(size)); - if (!ifs.read(reinterpret_cast(out.data()), size)) return false; - return true; - } - - static bool write_file_all(const std::string& path, const uint8_t* data, size_t len) { - std::ofstream ofs(path, std::ios::binary | std::ios::trunc); - if (!ofs) return false; - ofs.write(reinterpret_cast(data), static_cast(len)); - return static_cast(ofs); - } - bool decrypt_ota_file_impl(const std::string& input_path, const std::string& output_zip_path) { - std::vector in; - if (!netcore::read_file_all(input_path, in)) { - netcore::log_error(std::string("decrypt_ota_file: read failed: ") + input_path); + std::ifstream ifs(input_path, std::ios::binary); + if (!ifs) { + netcore::log_error(std::string("decrypt_ota_file: open in failed: ") + input_path); return false; } - - const size_t min_len = kOtaMagicLen + kGcmNonceLen + kGcmTagLen + 1; - if (in.size() < min_len) { + ifs.seekg(0, std::ios::end); + const std::streampos szp = ifs.tellg(); + if (szp <= 0) { + netcore::log_error("decrypt_ota_file: empty input"); + return false; + } + const uint64_t file_size = static_cast(szp); + const size_t min_len = kHeaderLen + kGcmTagLen + 1; + if (file_size < min_len) { netcore::log_error("decrypt_ota_file: too short"); return false; } - if (!std::equal(in.begin(), in.begin() + kOtaMagicLen, reinterpret_cast(kOtaMagic))) { + const uint64_t ciphertext_len = file_size - kHeaderLen - kGcmTagLen; + + ifs.seekg(0, std::ios::beg); + std::array header{}; + ifs.read(reinterpret_cast(header.data()), static_cast(kHeaderLen)); + if (ifs.gcount() != static_cast(kHeaderLen)) { + netcore::log_error("decrypt_ota_file: read header failed"); + return false; + } + if (!std::equal(header.begin(), header.begin() + kOtaMagicLen, + reinterpret_cast(kOtaMagic))) { netcore::log_error("decrypt_ota_file: bad magic"); return false; } + const uint8_t* nonce = header.data() + kOtaMagicLen; - const uint8_t* nonce = in.data() + kOtaMagicLen; - const uint8_t* ct_and_tag = in.data() + kOtaMagicLen + kGcmNonceLen; - const size_t ct_and_tag_len = in.size() - (kOtaMagicLen + kGcmNonceLen); - if (ct_and_tag_len <= kGcmTagLen) { - netcore::log_error("decrypt_ota_file: no ciphertext"); + std::ofstream ofs(output_zip_path, std::ios::binary | std::ios::trunc); + if (!ofs) { + netcore::log_error(std::string("decrypt_ota_file: open out failed: ") + output_zip_path); return false; } - const size_t ciphertext_len = ct_and_tag_len - kGcmTagLen; - const uint8_t* ciphertext = ct_and_tag; - const uint8_t* tag = ct_and_tag + ciphertext_len; - - std::vector plain(ciphertext_len); - int out_len1 = 0; - int out_len2 = 0; EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new(); if (!ctx) { @@ -95,6 +81,8 @@ namespace netcore{ bool ok = false; auto key = ota_key_bytes(); + std::vector chunk_in(kDecryptChunk); + std::vector chunk_out(kDecryptChunk + EVP_MAX_BLOCK_LENGTH); do { if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), nullptr, nullptr, nullptr)) { @@ -109,27 +97,59 @@ namespace netcore{ netcore::log_error("decrypt_ota_file: set key/iv failed"); break; } - if (1 != EVP_DecryptUpdate(ctx, plain.data(), &out_len1, ciphertext, static_cast(ciphertext_len))) { - netcore::log_error("decrypt_ota_file: update failed"); + + uint64_t remaining = ciphertext_len; + while (remaining > 0) { + const size_t n = static_cast(std::min(remaining, kDecryptChunk)); + ifs.read(reinterpret_cast(chunk_in.data()), static_cast(n)); + if (ifs.gcount() != static_cast(n)) { + netcore::log_error("decrypt_ota_file: read ciphertext chunk failed"); + goto cleanup_ctx; + } + int outl = 0; + if (1 != EVP_DecryptUpdate(ctx, chunk_out.data(), &outl, + chunk_in.data(), static_cast(n))) { + netcore::log_error("decrypt_ota_file: update failed"); + goto cleanup_ctx; + } + if (outl > 0) { + ofs.write(reinterpret_cast(chunk_out.data()), outl); + if (!ofs) { + netcore::log_error("decrypt_ota_file: write plaintext failed"); + goto cleanup_ctx; + } + } + remaining -= n; + } + + std::array tag{}; + ifs.read(reinterpret_cast(tag.data()), static_cast(kGcmTagLen)); + if (ifs.gcount() != static_cast(kGcmTagLen)) { + netcore::log_error("decrypt_ota_file: read tag failed"); break; } - if (1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, static_cast(kGcmTagLen), const_cast(tag))) { + if (1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, static_cast(kGcmTagLen), tag.data())) { netcore::log_error("decrypt_ota_file: set tag failed"); break; } - if (1 != EVP_DecryptFinal_ex(ctx, plain.data() + out_len1, &out_len2)) { + + int outl2 = 0; + if (1 != EVP_DecryptFinal_ex(ctx, chunk_out.data(), &outl2)) { netcore::log_error("decrypt_ota_file: final failed (auth tag mismatch?)"); break; } - const size_t plain_len = static_cast(out_len1 + out_len2); - if (!netcore::write_file_all(output_zip_path, plain.data(), plain_len)) { - netcore::log_error(std::string("decrypt_ota_file: write failed: ") + output_zip_path); - break; + if (outl2 > 0) { + ofs.write(reinterpret_cast(chunk_out.data()), outl2); + if (!ofs) { + netcore::log_error("decrypt_ota_file: write final failed"); + break; + } } ok = true; } while (false); +cleanup_ctx: EVP_CIPHER_CTX_free(ctx); return ok; } -} \ No newline at end of file +} // namespace netcore diff --git a/ota_manager.py b/ota_manager.py index 06342d4..1421c5e 100644 --- a/ota_manager.py +++ b/ota_manager.py @@ -770,12 +770,12 @@ class OTAManager: # 很多 ML307R 的 MHTTP 对 https 不稳定;对已知域名做降级 if isinstance(url, str) and url.startswith("https://static.shelingxingqiu.com/"): - base_url = "https://static.shelingxingqiu.com" - # TODO:使用https,看看是否能成功 - self._is_https = True + base_url = "http://static.shelingxingqiu.com" + self._is_https = False else: base_url = f"http://{host}" self._is_https = False + self.logger.info(f"base_url: {base_url}, self._is_https: {self._is_https}") # logger removed - use self.logger instead def _log(*a): @@ -1160,8 +1160,8 @@ class OTAManager: self.logger.error(f"[OTA-4G][PWR] before_urc read_failed: {e}") t_dl0 = time.ticks_ms() - success, msg = self.download_file_via_4g(ota_url, downloaded_filename, debug=False) - t_dl_cost = time.ticks_diff(t_dl0, time.ticks_ms()) + success, msg = self.download_file_via_4g(ota_url, downloaded_filename, debug=True) + t_dl_cost = time.ticks_diff(time.ticks_ms(), t_dl0) self.logger.info(f"[OTA-4G] {msg}") self.logger.info(f"[OTA-4G] download_cost_ms={t_dl_cost}") diff --git a/version.py b/version.py index eaaa749..18e6df2 100644 --- a/version.py +++ b/version.py @@ -4,7 +4,8 @@ 应用版本号 每次 OTA 更新时,只需要更新这个文件中的版本号 """ -VERSION = '1.2.12' +VERSION = '1.2.14.1' + # 1.2.0 开始使用C++编译成.so,替换部分代码 # 1.2.1 ota使用加密包 @@ -19,8 +20,8 @@ VERSION = '1.2.12' # 1.2.10 config formal # 1.2.11 增加三角形的单应性算法,适配对应的靶纸 # 1.2.110 关掉了黑色三角形算法,只用于测试 - - +# 1.2.13 修改wifi连接 +# 1.2.14 修改了icc登录部分