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 #include "package/package.h"
16 #include <cstdio>
17 #include <cstdlib>
18 #include <iostream>
19 #include <memory>
20 #include "log/log.h"
21 #include "package/pkg_manager.h"
22 #include "securec.h"
23 
24 using namespace Updater;
25 using namespace Hpackage;
26 constexpr uint32_t VERIFY_FINSH_PERCENT = 100;
27 
28 namespace {
GetUpgradePkgInfo(UpgradePkgInfo * upgradePackageInfo,std::vector<std::pair<std::string,ComponentInfo>> & files,const UpgradePkgInfoExt * pkgInfoExt,std::vector<ComponentInfoExt> & compInfo)29 int32_t GetUpgradePkgInfo(UpgradePkgInfo *upgradePackageInfo,
30     std::vector<std::pair<std::string, ComponentInfo>> &files,
31     const UpgradePkgInfoExt *pkgInfoExt,
32     std::vector<ComponentInfoExt> &compInfo)
33 {
34     upgradePackageInfo->updateFileVersion = pkgInfoExt->updateFileVersion;
35     if (pkgInfoExt->softwareVersion != nullptr) {
36         upgradePackageInfo->softwareVersion = pkgInfoExt->softwareVersion;
37     }
38     if (pkgInfoExt->productUpdateId != nullptr) {
39         upgradePackageInfo->productUpdateId = pkgInfoExt->productUpdateId;
40     }
41     if (pkgInfoExt->descriptPackageId != nullptr) {
42         upgradePackageInfo->descriptPackageId = pkgInfoExt->descriptPackageId;
43     }
44     if (pkgInfoExt->time != nullptr) {
45         upgradePackageInfo->time = pkgInfoExt->time;
46     }
47     if (pkgInfoExt->date != nullptr) {
48         upgradePackageInfo->date = pkgInfoExt->date;
49     }
50     upgradePackageInfo->pkgInfo.digestMethod = pkgInfoExt->digestMethod;
51     upgradePackageInfo->pkgInfo.signMethod = pkgInfoExt->signMethod;
52     upgradePackageInfo->pkgInfo.entryCount = pkgInfoExt->entryCount;
53     upgradePackageInfo->pkgInfo.pkgType = PKG_PACK_TYPE_UPGRADE;
54     files.resize(pkgInfoExt->entryCount);
55     for (uint32_t i = 0; i < pkgInfoExt->entryCount; i++) {
56         files[i].first.assign(compInfo[i].filePath);
57         ComponentInfo* info = &files[i].second;
58         if (memcpy_s(info->digest, sizeof(info->digest), compInfo[i].digest, sizeof(info->digest)) != EOK) {
59             LOG(ERROR) << "GetUpgradePkgInfo memcpy failed";
60             return PKG_NONE_MEMORY;
61         }
62         info->fileInfo.identity.assign(compInfo[i].componentAddr);
63         info->fileInfo.unpackedSize = compInfo[i].size;
64         info->fileInfo.packedSize = compInfo[i].size;
65         info->fileInfo.packMethod = PKG_COMPRESS_METHOD_NONE;
66         info->fileInfo.digestMethod = pkgInfoExt->digestMethod;
67         info->version.assign(compInfo[i].version);
68         info->id = compInfo[i].id;
69         info->resType = compInfo[i].resType;
70         info->type = compInfo[i].type;
71         info->originalSize = compInfo[i].originalSize;
72         info->compFlags = compInfo[i].flags;
73     }
74     return PKG_SUCCESS;
75 }
76 
GetZipPkgInfo(PkgManager::PkgInfoPtr pkgInfo,std::vector<std::pair<std::string,ZipFileInfo>> & files,const UpgradePkgInfoExt * pkgInfoExt,std::vector<ComponentInfoExt> & compInfo)77 int32_t GetZipPkgInfo(PkgManager::PkgInfoPtr pkgInfo,
78     std::vector<std::pair<std::string, ZipFileInfo>> &files,
79     const UpgradePkgInfoExt *pkgInfoExt,
80     std::vector<ComponentInfoExt> &compInfo)
81 {
82     pkgInfo->signMethod = pkgInfoExt->signMethod;
83     pkgInfo->digestMethod  = pkgInfoExt->digestMethod;
84     pkgInfo->entryCount = pkgInfoExt->entryCount;
85     pkgInfo->pkgType = pkgInfoExt->pkgType;
86     files.resize(pkgInfoExt->entryCount);
87     for (uint32_t i = 0; i < pkgInfo->entryCount; i++) {
88         files[i].first.assign(compInfo[i].filePath);
89         ZipFileInfo* info = &files[i].second;
90         info->fileInfo.identity.assign(compInfo[i].componentAddr);
91         info->fileInfo.packMethod = PKG_COMPRESS_METHOD_ZIP;
92         info->fileInfo.digestMethod = PKG_DIGEST_TYPE_CRC;
93     }
94     return PKG_SUCCESS;
95 }
96 
GetLz4PkgInfo(PkgManager::PkgInfoPtr pkgInfo,std::vector<std::pair<std::string,Lz4FileInfo>> & files,const UpgradePkgInfoExt * pkgInfoExt,std::vector<ComponentInfoExt> & compInfo)97 int32_t GetLz4PkgInfo(PkgManager::PkgInfoPtr pkgInfo,
98     std::vector<std::pair<std::string, Lz4FileInfo>> &files,
99     const UpgradePkgInfoExt *pkgInfoExt,
100     std::vector<ComponentInfoExt> &compInfo)
101 {
102     pkgInfo->signMethod = pkgInfoExt->signMethod;
103     pkgInfo->digestMethod  = pkgInfoExt->digestMethod;
104     pkgInfo->entryCount = pkgInfoExt->entryCount;
105     pkgInfo->pkgType = PKG_PACK_TYPE_LZ4;
106     files.resize(pkgInfoExt->entryCount);
107     for (uint32_t i = 0; i < pkgInfoExt->entryCount; i++) {
108         files[i].first.assign(compInfo[i].filePath);
109         Lz4FileInfo* info = &files[i].second;
110         info->fileInfo.identity.assign(compInfo[i].componentAddr);
111         info->fileInfo.packMethod = PKG_COMPRESS_METHOD_LZ4;
112         info->fileInfo.digestMethod = PKG_DIGEST_TYPE_CRC;
113         info->compressionLevel = MID_COMPRESS_LEVEL;
114         info->blockSizeID = 0;
115         info->contentChecksumFlag = 0;
116         info->blockIndependence = 0;
117     }
118     return PKG_SUCCESS;
119 }
120 }
121 
CreatePackage(const UpgradePkgInfoExt * pkgInfoExt,std::vector<ComponentInfoExt> & compInfo,const char * path,const char * keyPath)122 int32_t CreatePackage(const UpgradePkgInfoExt *pkgInfoExt,
123     std::vector<ComponentInfoExt> &compInfo,
124     const char *path,
125     const char *keyPath)
126 {
127     if (pkgInfoExt == nullptr || path == nullptr || keyPath == nullptr || pkgInfoExt->entryCount > compInfo.size()) {
128         LOG(ERROR) << "Check param fail ";
129         return PKG_INVALID_PARAM;
130     }
131     PkgManager::PkgManagerPtr manager = PkgManager::CreatePackageInstance();
132     if (manager == nullptr) {
133         LOG(ERROR) << "CreatePackageInstance fail ";
134         return PKG_INVALID_PARAM;
135     }
136 
137     int32_t ret = PKG_SUCCESS;
138     switch (pkgInfoExt->pkgType) {
139         case PKG_PACK_TYPE_UPGRADE: {
140             UpgradePkgInfo upgradePackageInfo;
141             std::vector<std::pair<std::string, ComponentInfo>> files;
142             ret = GetUpgradePkgInfo(&upgradePackageInfo, files, pkgInfoExt, compInfo);
143             if (ret == PKG_SUCCESS) {
144                 ret = manager->CreatePackage(path, keyPath, &upgradePackageInfo.pkgInfo, files);
145             }
146             break;
147         }
148         case PKG_PACK_TYPE_ZIP:
149         case PKG_PACK_TYPE_GZIP: {
150             PkgInfo info;
151             std::vector<std::pair<std::string, ZipFileInfo>> files;
152             ret = GetZipPkgInfo(&info, files, pkgInfoExt, compInfo);
153             if (ret == PKG_SUCCESS) {
154                 ret = manager->CreatePackage(path, keyPath, &info, files);
155             }
156             break;
157         }
158         case PKG_PACK_TYPE_LZ4: {
159             PkgInfo info;
160             std::vector<std::pair<std::string, Lz4FileInfo>> files;
161             ret = GetLz4PkgInfo(&info, files, pkgInfoExt, compInfo);
162             if (ret == PKG_SUCCESS) {
163                 ret = manager->CreatePackage(path, keyPath, &info, files);
164             }
165             break;
166         }
167         default:
168             ret = PKG_INVALID_PARAM;
169             break;
170     }
171     PkgManager::ReleasePackageInstance(manager);
172     return ret;
173 }
174 
VerifyPackage(const char * packagePath,const char * keyPath,const char * version,const uint8_t * digest,size_t size)175 int32_t VerifyPackage(const char *packagePath,
176     const char *keyPath,
177     const char *version,
178     const uint8_t *digest,
179     size_t size)
180 {
181     if (packagePath == nullptr || keyPath == nullptr || version == nullptr) {
182         LOG(ERROR) << "Check param fail";
183         return PKG_INVALID_PARAM;
184     }
185     PkgManager::PkgManagerPtr manager = PkgManager::CreatePackageInstance();
186     if (manager == nullptr) {
187         LOG(ERROR) << "CreatePackageInstance fail";
188         return PKG_INVALID_PARAM;
189     }
190 
191     PkgBuffer digestBuffer(const_cast<uint8_t*>(digest), size);
192     int32_t ret = manager->VerifyPackage(packagePath, keyPath, version, digestBuffer,
193         [](int32_t result, uint32_t percent) {});
194     PkgManager::ReleasePackageInstance(manager);
195     return ret;
196 }
197 
VerifyPackageWithCallback(const std::string & packagePath,const std::string & keyPath,std::function<void (int32_t result,uint32_t percent)> cb)198 int32_t VerifyPackageWithCallback(const std::string &packagePath,
199     const std::string &keyPath, std::function<void(int32_t result, uint32_t percent)> cb)
200 {
201     if (packagePath.empty() || keyPath.empty() || cb == nullptr) {
202         return PKG_INVALID_PARAM;
203     }
204 
205     PkgManager *manager = PkgManager::CreatePackageInstance();
206     if (manager == nullptr) {
207         LOG(ERROR) << "CreatePackageInstance fail";
208         return PKG_INVALID_PARAM;
209     }
210     PkgBuffer digestBuffer {};
211     std::string version {};
212     int32_t ret = manager->VerifyPackage(packagePath, keyPath, version, digestBuffer, cb);
213     if (ret != 0) {
214         cb(ret, VERIFY_FINSH_PERCENT);
215     }
216     PkgManager::ReleasePackageInstance(manager);
217     return ret;
218 }
219 
220 int32_t ExtraPackageDir(const char *packagePath, [[maybe_unused]] const char *keyPath, const char *dir,
221     const char *outPath)
222 {
223     if (packagePath == nullptr || outPath == nullptr) {
224         LOG(ERROR) << "Check param fail ";
225         return PKG_INVALID_PARAM;
226     }
227     PkgManager::PkgManagerPtr manager = PkgManager::CreatePackageInstance();
228     if (manager == nullptr) {
229         LOG(ERROR) << "CreatePackageInstance fail ";
230         return PKG_INVALID_PARAM;
231     }
232 
233     std::vector<std::string> components;
234     int32_t ret = manager->LoadPackageWithoutUnPack(std::string(packagePath), components);
235     if (ret != PKG_SUCCESS) {
236         LOG(ERROR) << "LoadPackageWithoutUnPack fail";
237         PkgManager::ReleasePackageInstance(manager);
238         return ret;
239     }
240 
241     for (size_t i = 0; i < components.size(); i++) {
242         if (dir != nullptr && components[i].compare(0, strlen(dir), dir) != 0) {
243             continue;
244         }
245         PkgManager::StreamPtr outStream = nullptr;
246         manager->CreatePkgStream(outStream, std::string(outPath) + components[i], 0, PkgStream::PkgStreamType_Write);
247         if (outStream == nullptr) {
248             LOG(ERROR) << "CreatePkgStream fail";
249             PkgManager::ReleasePackageInstance(manager);
250             return PKG_INVALID_STREAM;
251         }
252         manager->ExtractFile(components[i], outStream);
253         manager->ClosePkgStream(outStream);
254     }
255     PkgManager::ReleasePackageInstance(manager);
256     return PKG_SUCCESS;
257 }
258 
259 int32_t ExtraPackageFile(const char *packagePath, [[maybe_unused]] const char *keyPath, const char *file,
260     const char *outPath)
261 {
262     if (packagePath == nullptr || outPath == nullptr || file == nullptr) {
263         LOG(ERROR) << "Check param fail ";
264         return PKG_INVALID_PARAM;
265     }
266 
267     PkgManager::PkgManagerPtr manager = PkgManager::CreatePackageInstance();
268     if (manager == nullptr) {
269         LOG(ERROR) << "Check param fail ";
270         return PKG_INVALID_PARAM;
271     }
272 
273     std::vector<std::string> components;
274     int32_t ret = manager->LoadPackageWithoutUnPack(std::string(packagePath), components);
275     if (ret != PKG_SUCCESS) {
276         LOG(ERROR) << "LoadPackageWithoutUnPack fail";
277         PkgManager::ReleasePackageInstance(manager);
278         return ret;
279     }
280 
281     PkgManager::StreamPtr outStream = nullptr;
282     manager->CreatePkgStream(outStream, std::string(outPath) + file, 0, PkgStream::PkgStreamType_Write);
283     if (outStream == nullptr) {
284         LOG(ERROR) << "CreatePkgStream fail";
285         PkgManager::ReleasePackageInstance(manager);
286         return PKG_INVALID_STREAM;
287     }
288     manager->ExtractFile(file, outStream);
289 
290     manager->ClosePkgStream(outStream);
291     PkgManager::ReleasePackageInstance(manager);
292     return PKG_SUCCESS;
293 }
294