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,ComponentInfoExt compInfo[])29 int32_t GetUpgradePkgInfo(UpgradePkgInfo *upgradePackageInfo,
30 std::vector<std::pair<std::string, ComponentInfo>> &files,
31 const UpgradePkgInfoExt *pkgInfoExt,
32 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,ComponentInfoExt compInfo[])77 int32_t GetZipPkgInfo(PkgManager::PkgInfoPtr pkgInfo,
78 std::vector<std::pair<std::string, ZipFileInfo>> &files,
79 const UpgradePkgInfoExt *pkgInfoExt,
80 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,ComponentInfoExt compInfo[])97 int32_t GetLz4PkgInfo(PkgManager::PkgInfoPtr pkgInfo,
98 std::vector<std::pair<std::string, Lz4FileInfo>> &files,
99 const UpgradePkgInfoExt *pkgInfoExt,
100 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,ComponentInfoExt compInfo[],const char * path,const char * keyPath)122 int32_t CreatePackage(const UpgradePkgInfoExt *pkgInfoExt,
123 ComponentInfoExt compInfo[],
124 const char *path,
125 const char *keyPath)
126 {
127 PkgManager::PkgManagerPtr manager = PkgManager::GetPackageInstance();
128 if (pkgInfoExt == nullptr || path == nullptr || keyPath == nullptr || manager == nullptr) {
129 LOG(ERROR) << "Check param fail ";
130 return PKG_INVALID_PARAM;
131 }
132
133 int32_t ret = PKG_SUCCESS;
134 switch (pkgInfoExt->pkgType) {
135 case PKG_PACK_TYPE_UPGRADE: {
136 UpgradePkgInfo upgradePackageInfo;
137 std::vector<std::pair<std::string, ComponentInfo>> files;
138 ret = GetUpgradePkgInfo(&upgradePackageInfo, files, pkgInfoExt, compInfo);
139 if (ret == PKG_SUCCESS) {
140 ret = manager->CreatePackage(path, keyPath, &upgradePackageInfo.pkgInfo, files);
141 }
142 break;
143 }
144 case PKG_PACK_TYPE_ZIP:
145 case PKG_PACK_TYPE_GZIP: {
146 PkgInfo info;
147 std::vector<std::pair<std::string, ZipFileInfo>> files;
148 ret = GetZipPkgInfo(&info, files, pkgInfoExt, compInfo);
149 if (ret == PKG_SUCCESS) {
150 ret = manager->CreatePackage(path, keyPath, &info, files);
151 }
152 break;
153 }
154 case PKG_PACK_TYPE_LZ4: {
155 PkgInfo info;
156 std::vector<std::pair<std::string, Lz4FileInfo>> files;
157 ret = GetLz4PkgInfo(&info, files, pkgInfoExt, compInfo);
158 if (ret == PKG_SUCCESS) {
159 ret = manager->CreatePackage(path, keyPath, &info, files);
160 }
161 break;
162 }
163 default:
164 ret = PKG_INVALID_PARAM;
165 break;
166 }
167 PkgManager::ReleasePackageInstance(manager);
168 return ret;
169 }
170
VerifyPackage(const char * packagePath,const char * keyPath,const char * version,const uint8_t * digest,size_t size)171 int32_t VerifyPackage(const char *packagePath,
172 const char *keyPath,
173 const char *version,
174 const uint8_t *digest,
175 size_t size)
176 {
177 PkgManager::PkgManagerPtr manager = PkgManager::GetPackageInstance();
178 if (packagePath == nullptr || keyPath == nullptr || version == nullptr || manager == nullptr) {
179 return PKG_INVALID_PARAM;
180 }
181
182 PkgBuffer digestBuffer(const_cast<uint8_t*>(digest), size);
183 int32_t ret = manager->VerifyPackage(packagePath, keyPath, version, digestBuffer,
184 [](int32_t result, uint32_t percent) {});
185 PkgManager::ReleasePackageInstance(manager);
186 return ret;
187 }
188
VerifyPackageWithCallback(const std::string & packagePath,const std::string & keyPath,std::function<void (int32_t result,uint32_t percent)> cb)189 int32_t VerifyPackageWithCallback(const std::string &packagePath,
190 const std::string &keyPath, std::function<void(int32_t result, uint32_t percent)> cb)
191 {
192 if (packagePath.empty() || keyPath.empty() || cb == nullptr) {
193 return PKG_INVALID_PARAM;
194 }
195
196 PkgManager *manager = PkgManager::GetPackageInstance();
197 PkgBuffer digestBuffer {};
198 std::string version {};
199 int32_t ret = manager->VerifyPackage(packagePath, keyPath, version, digestBuffer, cb);
200 if (ret != 0) {
201 cb(ret, VERIFY_FINSH_PERCENT);
202 }
203 PkgManager::ReleasePackageInstance(manager);
204 return ret;
205 }
206
ExtraPackageDir(const char * packagePath,const char * keyPath,const char * dir,const char * outPath)207 int32_t ExtraPackageDir(const char *packagePath, [[maybe_unused]] const char *keyPath, const char *dir,
208 const char *outPath)
209 {
210 PkgManager::PkgManagerPtr manager = PkgManager::GetPackageInstance();
211 if (packagePath == nullptr || outPath == nullptr || manager == nullptr) {
212 LOG(ERROR) << "Check param fail ";
213 return PKG_INVALID_PARAM;
214 }
215
216 std::vector<std::string> components;
217 int32_t ret = manager->LoadPackageWithoutUnPack(std::string(packagePath), components);
218 if (ret != PKG_SUCCESS) {
219 LOG(ERROR) << "LoadPackageWithoutUnPack fail";
220 PkgManager::ReleasePackageInstance(manager);
221 return ret;
222 }
223
224 for (size_t i = 0; i < components.size(); i++) {
225 if (dir != nullptr && components[i].compare(0, strlen(dir), dir) != 0) {
226 continue;
227 }
228 PkgManager::StreamPtr outStream = nullptr;
229 manager->CreatePkgStream(outStream, std::string(outPath) + components[i], 0, PkgStream::PkgStreamType_Write);
230 if (outStream == nullptr) {
231 LOG(ERROR) << "CreatePkgStream fail";
232 PkgManager::ReleasePackageInstance(manager);
233 return PKG_INVALID_STREAM;
234 }
235 manager->ExtractFile(components[i], outStream);
236 manager->ClosePkgStream(outStream);
237 }
238 PkgManager::ReleasePackageInstance(manager);
239 return PKG_SUCCESS;
240 }
241
ExtraPackageFile(const char * packagePath,const char * keyPath,const char * file,const char * outPath)242 int32_t ExtraPackageFile(const char *packagePath, [[maybe_unused]] const char *keyPath, const char *file,
243 const char *outPath)
244 {
245 PkgManager::PkgManagerPtr manager = PkgManager::GetPackageInstance();
246 if (packagePath == nullptr || outPath == nullptr || file == nullptr || manager == nullptr) {
247 LOG(ERROR) << "Check param fail ";
248 return PKG_INVALID_PARAM;
249 }
250
251 std::vector<std::string> components;
252 int32_t ret = manager->LoadPackageWithoutUnPack(std::string(packagePath), components);
253 if (ret != PKG_SUCCESS) {
254 LOG(ERROR) << "LoadPackageWithoutUnPack fail";
255 PkgManager::ReleasePackageInstance(manager);
256 return ret;
257 }
258
259 PkgManager::StreamPtr outStream = nullptr;
260 manager->CreatePkgStream(outStream, std::string(outPath) + file, 0, PkgStream::PkgStreamType_Write);
261 if (outStream == nullptr) {
262 LOG(ERROR) << "CreatePkgStream fail";
263 PkgManager::ReleasePackageInstance(manager);
264 return PKG_INVALID_STREAM;
265 }
266 manager->ExtractFile(file, outStream);
267
268 manager->ClosePkgStream(outStream);
269 PkgManager::ReleasePackageInstance(manager);
270 return PKG_SUCCESS;
271 }