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 24using namespace Updater; 25using namespace Hpackage; 26constexpr uint32_t VERIFY_FINSH_PERCENT = 100; 27constexpr uint32_t MAX_ENTRY_COUNT = 4096; 28 29namespace { 30int32_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 83int32_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 108int32_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 138int32_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 191int32_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 214int32_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 236int32_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 275int32_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