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
25 using namespace Hpackage;
26 namespace UpdatePatch {
ApplyImagePatch(const PatchParam & param,const std::vector<uint8_t> & bonusData,ImageProcessor writer,const std::string & expected)27 int32_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
PreCheck(const PatchParam & param,const UpdatePatchWriterPtr writer)52 bool 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
ApplyImagePatch(const PatchParam & param,UpdatePatchWriterPtr writer,const std::vector<uint8_t> & bonusData)69 int32_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
ApplyBlockPatch(const PatchBuffer & patchInfo,const BlockBuffer & oldInfo,std::vector<uint8_t> & newData)119 int32_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
ApplyBlockPatch(const PatchBuffer & patchInfo,const BlockBuffer & oldInfo,UpdatePatchWriterPtr writer)130 int32_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
ApplyBlockPatch(const PatchBuffer & patchInfo,const BlockBuffer & oldInfo,ImageProcessor writer,const std::string & expected)161 int32_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
ApplyBlockPatch(const PatchBuffer & patchInfo,Hpackage::PkgManager::StreamPtr stream,UpdatePatchWriterPtr writer)212 int32_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
ApplyPatch(const std::string & patchName,const std::string & oldName,const std::string & newName)223 int32_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
Init()276 int32_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
Write(size_t start,const BlockBuffer & buffer,size_t len)291 int32_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
Finish()304 int32_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
Init()323 int32_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
Write(size_t start,const BlockBuffer & buffer,size_t len)340 int32_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
Finish()360 int32_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