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
ApplyImagePatch(const PatchParam & param,UpdatePatchWriterPtr writer,const std::vector<uint8_t> & bonusData)52 int32_t UpdateApplyPatch::ApplyImagePatch(const PatchParam ¶m,
53 UpdatePatchWriterPtr writer, const std::vector<uint8_t> &bonusData)
54 {
55 PATCH_CHECK(writer != nullptr, return -1, "check param fail ");
56 PATCH_CHECK(param.patchSize >= (std::char_traits<char>::length(PKGDIFF_MAGIC) + sizeof(int32_t)),
57 return -1, "patch too short to contain header ");
58 PATCH_CHECK(memcmp(param.patch, PKGDIFF_MAGIC, std::char_traits<char>::length(PKGDIFF_MAGIC)) == 0,
59 return -1, "corrupt patch file header (magic number) ");
60 size_t offset = std::char_traits<char>::length(PKGDIFF_MAGIC);
61 int32_t numChunks = ImagePatch::ReadLE<int32_t>(param.patch + offset);
62 offset += sizeof(int32_t);
63
64 std::vector<uint8_t> empty;
65 for (int i = 0; i < numChunks; ++i) {
66 // each chunk's header record starts with 4 bytes.
67 PATCH_CHECK((offset + sizeof(int32_t)) <= param.patchSize, return -1, "Failed to read chunk record ");
68 int32_t type = ImagePatch::ReadLE<int32_t>(param.patch + offset);
69 PATCH_LOGI("ApplyImagePatch numChunks[%d] type %d offset %d", i, type, offset);
70 offset += sizeof(int32_t);
71 std::unique_ptr<ImagePatch> imagePatch = nullptr;
72 switch (type) {
73 case BLOCK_NORMAL:
74 imagePatch = std::make_unique<NormalImagePatch>(writer);
75 break;
76 case BLOCK_RAW:
77 imagePatch = std::make_unique<RowImagePatch>(writer);
78 break;
79 case BLOCK_DEFLATE:
80 imagePatch = std::make_unique<ZipImagePatch>(writer, ((i == 1) ? bonusData : empty));
81 break;
82 case BLOCK_LZ4:
83 imagePatch = std::make_unique<Lz4ImagePatch>(writer, ((i == 1) ? bonusData : empty));
84 break;
85 default:
86 break;
87 }
88 PATCH_CHECK(imagePatch != nullptr, return -1, "Failed to creareimg patch ");
89 int32_t ret = imagePatch->ApplyImagePatch(param, offset);
90 PATCH_CHECK(ret == 0, return -1, "Apply image patch fail ");
91 }
92 return 0;
93 }
94
ApplyBlockPatch(const PatchBuffer & patchInfo,const BlockBuffer & oldInfo,std::vector<uint8_t> & newData)95 int32_t UpdateApplyPatch::ApplyBlockPatch(const PatchBuffer &patchInfo,
96 const BlockBuffer &oldInfo, std::vector<uint8_t> &newData)
97 {
98 std::unique_ptr<BlocksBufferPatch> patch = std::make_unique<BlocksBufferPatch>(patchInfo, oldInfo, newData);
99 if (patch == nullptr) {
100 PATCH_LOGE("Failed to creare patch ");
101 return -1;
102 }
103 return patch->ApplyPatch();
104 }
105
ApplyBlockPatch(const PatchBuffer & patchInfo,const BlockBuffer & oldInfo,UpdatePatchWriterPtr writer)106 int32_t UpdateApplyPatch::ApplyBlockPatch(const PatchBuffer &patchInfo,
107 const BlockBuffer &oldInfo, UpdatePatchWriterPtr writer)
108 {
109 PkgManager* pkgManager = Hpackage::PkgManager::GetPackageInstance();
110 if (pkgManager == nullptr) {
111 PATCH_LOGE("Failed to get pkg manager");
112 return -1;
113 }
114
115 Hpackage::PkgManager::StreamPtr stream = nullptr;
116 int32_t ret = pkgManager->CreatePkgStream(stream, "", {oldInfo.buffer, oldInfo.length});
117 if (stream == nullptr || ret != PKG_SUCCESS) {
118 PATCH_LOGE("Failed to create stream");
119 pkgManager->ClosePkgStream(stream);
120 return -1;
121 }
122
123 std::unique_ptr<BlocksStreamPatch> patch = std::make_unique<BlocksStreamPatch>(patchInfo, stream, writer);
124 if (patch == nullptr) {
125 PATCH_LOGE("Failed to creare patch ");
126 pkgManager->ClosePkgStream(stream);
127 return -1;
128 }
129 ret = patch->ApplyPatch();
130 pkgManager->ClosePkgStream(stream);
131 return ret;
132 }
133
ApplyBlockPatch(const PatchBuffer & patchInfo,const BlockBuffer & oldInfo,ImageProcessor writer,const std::string & expected)134 int32_t UpdateApplyPatch::ApplyBlockPatch(const PatchBuffer &patchInfo,
135 const BlockBuffer &oldInfo, ImageProcessor writer, const std::string& expected)
136 {
137 if (writer == nullptr) {
138 PATCH_LOGE("ApplyBlockPatch : processor is null");
139 return -1;
140 }
141 std::unique_ptr<ImagePatchWriter> patchWriter = std::make_unique<ImagePatchWriter>(writer, expected, "");
142 if (patchWriter == nullptr) {
143 PATCH_LOGE("ApplyBlockPatch : Failed to create patch writer");
144 return -1;
145 }
146 int32_t ret = patchWriter->Init();
147 if (ret != 0) {
148 PATCH_LOGE("ApplyBlockPatch : Failed to init patch writer");
149 return -1;
150 }
151
152 PkgManager* pkgManager = Hpackage::PkgManager::GetPackageInstance();
153 if (pkgManager == nullptr) {
154 PATCH_LOGE("ApplyBlockPatch ::Failed to get pkg manager");
155 return -1;
156 }
157
158 Hpackage::PkgManager::StreamPtr stream = nullptr;
159 ret = pkgManager->CreatePkgStream(stream, "", {oldInfo.buffer, oldInfo.length});
160 if (stream == nullptr) {
161 PATCH_LOGE("Failed to create stream");
162 pkgManager->ClosePkgStream(stream);
163 return -1;
164 }
165
166 std::unique_ptr<BlocksStreamPatch> patch = std::make_unique<BlocksStreamPatch>(patchInfo,
167 stream, patchWriter.get());
168 if (patch == nullptr) {
169 PATCH_LOGE("Failed to creare patch ");
170 pkgManager->ClosePkgStream(stream);
171 return -1;
172 }
173 ret = patch->ApplyPatch();
174 pkgManager->ClosePkgStream(stream);
175 if (ret != 0) {
176 PATCH_LOGE("Failed to applay patch ");
177 return -1;
178 }
179 return patchWriter->Finish();
180 }
181
ApplyBlockPatch(const PatchBuffer & patchInfo,Hpackage::PkgManager::StreamPtr stream,UpdatePatchWriterPtr writer)182 int32_t UpdateApplyPatch::ApplyBlockPatch(const PatchBuffer &patchInfo,
183 Hpackage::PkgManager::StreamPtr stream, UpdatePatchWriterPtr writer)
184 {
185 std::unique_ptr<BlocksStreamPatch> patch = std::make_unique<BlocksStreamPatch>(patchInfo, stream, writer);
186 if (patch == nullptr) {
187 PATCH_LOGE("Failed to creare patch ");
188 return -1;
189 }
190 return patch->ApplyPatch();
191 }
192
ApplyPatch(const std::string & patchName,const std::string & oldName,const std::string & newName)193 int32_t UpdateApplyPatch::ApplyPatch(const std::string &patchName,
194 const std::string &oldName, const std::string &newName)
195 {
196 PATCH_DEBUG("UpdatePatch::ApplyPatch : %s ", patchName.c_str());
197 std::vector<uint8_t> empty;
198 MemMapInfo patchData {};
199 MemMapInfo oldData {};
200 int32_t ret = PatchMapFile(patchName, patchData);
201 if (ret != 0) {
202 PATCH_LOGE("ApplyPatch : Failed to read patch file");
203 return -1;
204 }
205 ret = PatchMapFile(oldName, oldData);
206 if (ret != 0) {
207 PATCH_LOGE("ApplyPatch : Failed to read old file");
208 return -1;
209 }
210 PATCH_LOGI("UpdatePatch::ApplyPatch patchData %zu oldData %zu ", patchData.length, oldData.length);
211 std::unique_ptr<FilePatchWriter> writer = std::make_unique<FilePatchWriter>(newName);
212 if (writer == nullptr) {
213 PATCH_LOGE("Failed to create writer");
214 return -1;
215 }
216 writer->Init();
217
218 // check if image patch
219 if (memcmp(patchData.memory, PKGDIFF_MAGIC, std::char_traits<char>::length(PKGDIFF_MAGIC)) == 0) {
220 PatchParam param {};
221 param.patch = patchData.memory;
222 param.patchSize = patchData.length;
223 param.oldBuff = oldData.memory;
224 param.oldSize = oldData.length;
225 ret = UpdatePatch::UpdateApplyPatch::ApplyImagePatch(param, writer.get(), empty);
226 if (ret != 0) {
227 PATCH_LOGE("Failed to apply image patch file");
228 return -1;
229 }
230 } else if (memcmp(patchData.memory, BSDIFF_MAGIC, std::char_traits<char>::length(BSDIFF_MAGIC)) == 0) { // bsdiff
231 PatchBuffer patchInfo = {patchData.memory, 0, patchData.length};
232 BlockBuffer oldInfo = {oldData.memory, oldData.length};
233 ret = ApplyBlockPatch(patchInfo, oldInfo, writer.get());
234 if (ret != 0) {
235 PATCH_LOGE("Failed to apply block patch");
236 return -1;
237 }
238 } else {
239 PATCH_LOGE("Invalid patch file");
240 return -1;
241 }
242 writer->Finish();
243 return 0;
244 }
245
Init()246 int32_t ImagePatchWriter::Init()
247 {
248 if (init_) {
249 PATCH_LOGE("Has beed init");
250 return -1;
251 }
252 if (writer_ == nullptr) {
253 PATCH_LOGE("Writer is null");
254 return -1;
255 }
256 SHA256_Init(&sha256Ctx_);
257 init_ = true;
258 return 0;
259 }
260
Write(size_t start,const BlockBuffer & buffer,size_t len)261 int32_t ImagePatchWriter::Write(size_t start, const BlockBuffer &buffer, size_t len)
262 {
263 if (!init_) {
264 PATCH_LOGE("Failed to check init");
265 return -1;
266 }
267 if (len == 0) {
268 return 0;
269 }
270 SHA256_Update(&sha256Ctx_, buffer.buffer, len);
271 return writer_(start, buffer, len);
272 }
273
Finish()274 int32_t ImagePatchWriter::Finish()
275 {
276 if (!init_) {
277 PATCH_LOGE("Failed to check init");
278 return -1;
279 }
280 std::vector<uint8_t> digest(SHA256_DIGEST_LENGTH);
281 SHA256_Final(digest.data(), &sha256Ctx_);
282 BlockBuffer data = { digest.data(), digest.size() };
283 std::string hexDigest = ConvertSha256Hex(data);
284 PATCH_LOGI("VerifySha256 SHA256 : %s expected SHA256 : %s", hexDigest.c_str(), expected_.c_str());
285 init_ = false;
286 return hexDigest.compare(expected_);
287 }
288
Init()289 int32_t FilePatchWriter::Init()
290 {
291 if (init_) {
292 PATCH_LOGE("Has beed init");
293 return -1;
294 }
295 if (!stream_.is_open()) {
296 stream_.open(newFileName_, std::ios::out | std::ios::binary);
297 if (stream_.fail()) {
298 PATCH_LOGE("Failed to open %s", newFileName_.c_str());
299 return -1;
300 }
301 }
302 init_ = true;
303 return 0;
304 }
305
Write(size_t start,const BlockBuffer & buffer,size_t len)306 int32_t FilePatchWriter::Write(size_t start, const BlockBuffer &buffer, size_t len)
307 {
308 if (!init_) {
309 PATCH_LOGE("Failed to check init");
310 return -1;
311 }
312 if (len == 0) {
313 return 0;
314 }
315 if (!stream_.is_open()) {
316 stream_.open(newFileName_, std::ios::out | std::ios::binary);
317 if (stream_.fail()) {
318 PATCH_LOGE("Failed to open %s", newFileName_.c_str());
319 return -1;
320 }
321 }
322 stream_.write(reinterpret_cast<const char*>(buffer.buffer), len);
323 return 0;
324 }
325
Finish()326 int32_t FilePatchWriter::Finish()
327 {
328 if (!init_) {
329 PATCH_LOGE("Failed to check init");
330 return -1;
331 }
332 PATCH_LOGI("FilePatchWriter %zu", static_cast<size_t>(stream_.tellp()));
333 stream_.close();
334 init_ = false;
335 return 0;
336 }
337 } // namespace UpdatePatch