• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &param, 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 &param,
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