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