1/* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "patch/update_patch.h" 17#include <memory> 18#include <vector> 19#include "blocks_patch.h" 20#include "diffpatch.h" 21#include "image_patch.h" 22#include "openssl/sha.h" 23#include "securec.h" 24 25using namespace Hpackage; 26namespace UpdatePatch { 27int32_t UpdateApplyPatch::ApplyImagePatch(const PatchParam ¶m, const std::vector<uint8_t> &bonusData, 28 ImageProcessor writer, const std::string& expected) 29{ 30 if (writer == nullptr) { 31 PATCH_LOGE("ApplyImagePatch : processor is null"); 32 return -1; 33 } 34 std::unique_ptr<ImagePatchWriter> patchWriter = std::make_unique<ImagePatchWriter>(writer, expected, ""); 35 if (patchWriter == nullptr) { 36 PATCH_LOGE("ApplyImagePatch : Failed to create patch writer"); 37 return -1; 38 } 39 int32_t ret = patchWriter->Init(); 40 if (ret != 0) { 41 PATCH_LOGE("ApplyImagePatch : Failed to init patch writer"); 42 return -1; 43 } 44 ret = ApplyImagePatch(param, patchWriter.get(), bonusData); 45 if (ret != 0) { 46 PATCH_LOGE("ApplyImagePatch : Failed to apply image patch"); 47 return -1; 48 } 49 return patchWriter->Finish(); 50} 51 52bool UpdateApplyPatch::PreCheck(const PatchParam ¶m, const UpdatePatchWriterPtr writer) 53{ 54 if (writer == nullptr) { 55 PATCH_LOGE("check param fail "); 56 return false; 57 } 58 if (param.patchSize < (std::char_traits<char>::length(PKGDIFF_MAGIC) + sizeof(int32_t))) { 59 PATCH_LOGE("patch too short to contain header "); 60 return false; 61 } 62 if (memcmp(param.patch, PKGDIFF_MAGIC, std::char_traits<char>::length(PKGDIFF_MAGIC)) != 0) { 63 PATCH_LOGE("corrupt patch file header (magic number) "); 64 return false; 65 } 66 return true; 67} 68 69int32_t UpdateApplyPatch::ApplyImagePatch(const PatchParam ¶m, 70 UpdatePatchWriterPtr writer, const std::vector<uint8_t> &bonusData) 71{ 72 if (!PreCheck(param, writer)) { 73 return -1; 74 } 75 size_t offset = std::char_traits<char>::length(PKGDIFF_MAGIC); 76 int32_t numChunks = ImagePatch::ReadLE<int32_t>(param.patch + offset); 77 offset += sizeof(int32_t); 78 79 std::vector<uint8_t> empty; 80 for (int i = 0; i < numChunks; ++i) { 81 // each chunk's header record starts with 4 bytes. 82 if ((offset + sizeof(int32_t)) > param.patchSize) { 83 PATCH_LOGE("Failed to read chunk record "); 84 return -1; 85 } 86 int32_t type = ImagePatch::ReadLE<int32_t>(param.patch + offset); 87 PATCH_DEBUG("ApplyImagePatch numChunks[%d] type %d offset %d", i, type, offset); 88 offset += sizeof(int32_t); 89 std::unique_ptr<ImagePatch> imagePatch = nullptr; 90 switch (type) { 91 case BLOCK_NORMAL: 92 imagePatch = std::make_unique<NormalImagePatch>(writer); 93 break; 94 case BLOCK_RAW: 95 imagePatch = std::make_unique<RowImagePatch>(writer); 96 break; 97 case BLOCK_DEFLATE: 98 imagePatch = std::make_unique<ZipImagePatch>(writer, ((i == 1) ? bonusData : empty)); 99 break; 100 case BLOCK_LZ4: 101 imagePatch = std::make_unique<Lz4ImagePatch>(writer, ((i == 1) ? bonusData : empty)); 102 break; 103 default: 104 break; 105 } 106 if (imagePatch == nullptr) { 107 PATCH_LOGE("Failed to creareimg patch "); 108 return -1; 109 } 110 int32_t ret = imagePatch->ApplyImagePatch(param, offset); 111 if (ret != 0) { 112 PATCH_LOGE("Apply image patch fail "); 113 return -1; 114 } 115 } 116 return 0; 117} 118 119int32_t UpdateApplyPatch::ApplyBlockPatch(const PatchBuffer &patchInfo, 120 const BlockBuffer &oldInfo, std::vector<uint8_t> &newData) 121{ 122 std::unique_ptr<BlocksBufferPatch> patch = std::make_unique<BlocksBufferPatch>(patchInfo, oldInfo, newData); 123 if (patch == nullptr) { 124 PATCH_LOGE("Failed to creare patch "); 125 return -1; 126 } 127 return patch->ApplyPatch(); 128} 129 130int32_t UpdateApplyPatch::ApplyBlockPatch(const PatchBuffer &patchInfo, 131 const BlockBuffer &oldInfo, UpdatePatchWriterPtr writer) 132{ 133 PkgManager* pkgManager = Hpackage::PkgManager::CreatePackageInstance(); 134 if (pkgManager == nullptr) { 135 PATCH_LOGE("Failed to get pkg manager"); 136 return -1; 137 } 138 139 Hpackage::PkgManager::StreamPtr stream = nullptr; 140 int32_t ret = pkgManager->CreatePkgStream(stream, "", {oldInfo.buffer, oldInfo.length}); 141 if (stream == nullptr || ret != PKG_SUCCESS) { 142 PATCH_LOGE("Failed to create stream"); 143 pkgManager->ClosePkgStream(stream); 144 Hpackage::PkgManager::ReleasePackageInstance(pkgManager); 145 return -1; 146 } 147 148 std::unique_ptr<BlocksStreamPatch> patch = std::make_unique<BlocksStreamPatch>(patchInfo, stream, writer); 149 if (patch == nullptr) { 150 PATCH_LOGE("Failed to creare patch "); 151 pkgManager->ClosePkgStream(stream); 152 Hpackage::PkgManager::ReleasePackageInstance(pkgManager); 153 return -1; 154 } 155 ret = patch->ApplyPatch(); 156 pkgManager->ClosePkgStream(stream); 157 Hpackage::PkgManager::ReleasePackageInstance(pkgManager); 158 return ret; 159} 160 161int32_t UpdateApplyPatch::ApplyBlockPatch(const PatchBuffer &patchInfo, 162 const BlockBuffer &oldInfo, ImageProcessor writer, const std::string& expected) 163{ 164 if (writer == nullptr) { 165 PATCH_LOGE("ApplyBlockPatch : processor is null"); 166 return -1; 167 } 168 std::unique_ptr<ImagePatchWriter> patchWriter = std::make_unique<ImagePatchWriter>(writer, expected, ""); 169 if (patchWriter == nullptr) { 170 PATCH_LOGE("ApplyBlockPatch : Failed to create patch writer"); 171 return -1; 172 } 173 int32_t ret = patchWriter->Init(); 174 if (ret != 0) { 175 PATCH_LOGE("ApplyBlockPatch : Failed to init patch writer"); 176 return -1; 177 } 178 179 PkgManager* pkgManager = Hpackage::PkgManager::CreatePackageInstance(); 180 if (pkgManager == nullptr) { 181 PATCH_LOGE("ApplyBlockPatch ::Failed to get pkg manager"); 182 return -1; 183 } 184 185 Hpackage::PkgManager::StreamPtr stream = nullptr; 186 ret = pkgManager->CreatePkgStream(stream, "", {oldInfo.buffer, oldInfo.length}); 187 if (stream == nullptr) { 188 PATCH_LOGE("Failed to create stream"); 189 pkgManager->ClosePkgStream(stream); 190 Hpackage::PkgManager::ReleasePackageInstance(pkgManager); 191 return -1; 192 } 193 194 std::unique_ptr<BlocksStreamPatch> patch = std::make_unique<BlocksStreamPatch>(patchInfo, 195 stream, patchWriter.get()); 196 if (patch == nullptr) { 197 PATCH_LOGE("Failed to creare patch "); 198 pkgManager->ClosePkgStream(stream); 199 Hpackage::PkgManager::ReleasePackageInstance(pkgManager); 200 return -1; 201 } 202 ret = patch->ApplyPatch(); 203 pkgManager->ClosePkgStream(stream); 204 Hpackage::PkgManager::ReleasePackageInstance(pkgManager); 205 if (ret != 0) { 206 PATCH_LOGE("Failed to applay patch "); 207 return -1; 208 } 209 return patchWriter->Finish(); 210} 211 212int32_t UpdateApplyPatch::ApplyBlockPatch(const PatchBuffer &patchInfo, 213 Hpackage::PkgManager::StreamPtr stream, UpdatePatchWriterPtr writer) 214{ 215 std::unique_ptr<BlocksStreamPatch> patch = std::make_unique<BlocksStreamPatch>(patchInfo, stream, writer); 216 if (patch == nullptr) { 217 PATCH_LOGE("Failed to creare patch "); 218 return -1; 219 } 220 return patch->ApplyPatch(); 221} 222 223int32_t UpdateApplyPatch::ApplyPatch(const std::string &patchName, 224 const std::string &oldName, const std::string &newName) 225{ 226 PATCH_DEBUG("UpdatePatch::ApplyPatch : %s ", patchName.c_str()); 227 std::vector<uint8_t> empty; 228 MemMapInfo patchData {}; 229 MemMapInfo oldData {}; 230 if (PatchMapFile(patchName, patchData) != 0) { 231 PATCH_LOGE("ApplyPatch : Failed to read patch file"); 232 return -1; 233 } 234 if (PatchMapFile(oldName, oldData) != 0) { 235 PATCH_LOGE("ApplyPatch : Failed to read old file"); 236 return -1; 237 } 238 PATCH_LOGI("UpdatePatch::ApplyPatch patchData %zu oldData %zu ", patchData.length, oldData.length); 239 std::unique_ptr<FilePatchWriter> writer = std::make_unique<FilePatchWriter>(newName); 240 if (writer == nullptr) { 241 PATCH_LOGE("Failed to create writer"); 242 return -1; 243 } 244 writer->Init(); 245 246 // check if image patch 247 if (patchData.length < std::char_traits<char>::length(PKGDIFF_MAGIC)) { 248 PATCH_LOGE("length error"); 249 return -1; 250 } 251 if (memcmp(patchData.memory, PKGDIFF_MAGIC, std::char_traits<char>::length(PKGDIFF_MAGIC)) == 0) { 252 PatchParam param {}; 253 param.patch = patchData.memory; 254 param.patchSize = patchData.length; 255 param.oldBuff = oldData.memory; 256 param.oldSize = oldData.length; 257 if (UpdatePatch::UpdateApplyPatch::ApplyImagePatch(param, writer.get(), empty) != 0) { 258 PATCH_LOGE("Failed to apply image patch file"); 259 return -1; 260 } 261 } else if (memcmp(patchData.memory, BSDIFF_MAGIC, std::char_traits<char>::length(BSDIFF_MAGIC)) == 0) { // bsdiff 262 PatchBuffer patchInfo = {patchData.memory, 0, patchData.length}; 263 BlockBuffer oldInfo = {oldData.memory, oldData.length}; 264 if (ApplyBlockPatch(patchInfo, oldInfo, writer.get()) != 0) { 265 PATCH_LOGE("Failed to apply block patch"); 266 return -1; 267 } 268 } else { 269 PATCH_LOGE("Invalid patch file"); 270 return -1; 271 } 272 writer->Finish(); 273 return 0; 274} 275 276int32_t ImagePatchWriter::Init() 277{ 278 if (init_) { 279 PATCH_LOGE("Has beed init"); 280 return -1; 281 } 282 if (writer_ == nullptr) { 283 PATCH_LOGE("Writer is null"); 284 return -1; 285 } 286 SHA256_Init(&sha256Ctx_); 287 init_ = true; 288 return 0; 289} 290 291int32_t ImagePatchWriter::Write(size_t start, const BlockBuffer &buffer, size_t len) 292{ 293 if (!init_) { 294 PATCH_LOGE("Failed to check init"); 295 return -1; 296 } 297 if (len == 0) { 298 return 0; 299 } 300 SHA256_Update(&sha256Ctx_, buffer.buffer, len); 301 return writer_(start, buffer, len); 302} 303 304int32_t ImagePatchWriter::Finish() 305{ 306 if (!init_) { 307 PATCH_LOGE("Failed to check init"); 308 return -1; 309 } 310 std::vector<uint8_t> digest(SHA256_DIGEST_LENGTH); 311 SHA256_Final(digest.data(), &sha256Ctx_); 312 BlockBuffer data = { digest.data(), digest.size() }; 313 std::string hexDigest = ConvertSha256Hex(data); 314 init_ = false; 315 int32_t ret = hexDigest.compare(expected_); 316 if (ret != 0) { 317 PATCH_LOGE("VerifySha256 SHA256 : %s expected SHA256 : %s", hexDigest.c_str(), expected_.c_str()); 318 return ret; 319 } 320 return 0; 321} 322 323int32_t FilePatchWriter::Init() 324{ 325 if (init_) { 326 PATCH_LOGE("Has beed init"); 327 return -1; 328 } 329 if (!stream_.is_open()) { 330 stream_.open(newFileName_, std::ios::out | std::ios::binary); 331 if (stream_.fail()) { 332 PATCH_LOGE("Failed to open %s", newFileName_.c_str()); 333 return -1; 334 } 335 } 336 init_ = true; 337 return 0; 338} 339 340int32_t FilePatchWriter::Write(size_t start, const BlockBuffer &buffer, size_t len) 341{ 342 if (!init_) { 343 PATCH_LOGE("Failed to check init"); 344 return -1; 345 } 346 if (len == 0) { 347 return 0; 348 } 349 if (!stream_.is_open()) { 350 stream_.open(newFileName_, std::ios::out | std::ios::binary); 351 if (stream_.fail()) { 352 PATCH_LOGE("Failed to open %s", newFileName_.c_str()); 353 return -1; 354 } 355 } 356 stream_.write(reinterpret_cast<const char*>(buffer.buffer), len); 357 return 0; 358} 359 360int32_t FilePatchWriter::Finish() 361{ 362 if (!init_) { 363 PATCH_LOGE("Failed to check init"); 364 return -1; 365 } 366 PATCH_LOGI("FilePatchWriter %zu", static_cast<size_t>(stream_.tellp())); 367 stream_.close(); 368 init_ = false; 369 return 0; 370} 371} // namespace UpdatePatch