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 
PreCheck(const PatchParam & param,const UpdatePatchWriterPtr writer)52 bool UpdateApplyPatch::PreCheck(const PatchParam &param, 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 &param,
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