1/* 2 * Copyright (c) 2023 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 "package_fuzzer.h" 17 18#include <array> 19#include <cstddef> 20#include <cstdint> 21#include <cstring> 22#include <fcntl.h> 23#include <iostream> 24#include <string> 25#include <sys/mman.h> 26#include <sys/stat.h> 27#include <unistd.h> 28#include <vector> 29#include "log/log.h" 30#include "package.h" 31#include "pkg_algorithm.h" 32#include "pkg_manager.h" 33#include "pkg_manager_impl.h" 34#include "pkg_fuzz_test.h" 35#include "pkg_utils.h" 36 37using namespace Updater; 38using namespace Hpackage; 39namespace OHOS { 40class FuzzPackageUnitTest : public FuzzPkgTest { 41public: 42 FuzzPackageUnitTest() {} 43 ~FuzzPackageUnitTest() override {} 44public: 45 int TestInvalidCreatePackage() 46 { 47 std::vector<ComponentInfoExt> info; 48 uint8_t pkgType = PkgPackType::PKG_PACK_TYPE_UPGRADE; 49 int ret = CreatePackage(nullptr, info, nullptr, GetFuzzPrivateKeyName(0).c_str()); 50 51 UpgradePkgInfoExt pkgInfoExt {}; 52 pkgInfoExt.pkgType = pkgType; 53 ret = CreatePackage(&pkgInfoExt, info, nullptr, GetFuzzPrivateKeyName(0).c_str()); 54 55 constexpr uint32_t digestLen = 32; 56 ret = VerifyPackage(nullptr, GetFuzzCertName(0).c_str(), nullptr, nullptr, digestLen); 57 58 std::string packagePath = TEST_PATH_TO + testPackageName; 59 pkgInfoExt.pkgType = pkgType; 60 ret = CreatePackage(&pkgInfoExt, info, packagePath.c_str(), GetFuzzPrivateKeyName(0).c_str()); 61 62 pkgType = PkgPackType::PKG_PACK_TYPE_ZIP; 63 pkgInfoExt.pkgType = pkgType; 64 ret = CreatePackage(&pkgInfoExt, info, packagePath.c_str(), GetFuzzPrivateKeyName(0).c_str()); 65 66 pkgType = PkgPackType::PKG_PACK_TYPE_LZ4; 67 pkgInfoExt.pkgType = pkgType; 68 ret = CreatePackage(&pkgInfoExt, info, packagePath.c_str(), GetFuzzPrivateKeyName(0).c_str()); 69 70 pkgType = PkgPackType::PKG_PACK_TYPE_GZIP; 71 pkgInfoExt.pkgType = pkgType; 72 ret = CreatePackage(&pkgInfoExt, info, packagePath.c_str(), GetFuzzPrivateKeyName(0).c_str()); 73 74 pkgType = PkgPackType::PKG_PACK_TYPE_NONE; 75 pkgInfoExt.pkgType = pkgType; 76 ret = CreatePackage(&pkgInfoExt, info, packagePath.c_str(), GetFuzzPrivateKeyName(0).c_str()); 77 return ret; 78 } 79 80 int TestPackagePack(int type = PKG_DIGEST_TYPE_SHA256) 81 { 82 int32_t ret; 83 uint32_t updateFileVersion = 1000; 84 UpgradePkgInfoExt pkgInfo; 85 pkgInfo.productUpdateId = strdup("555.555.100.555"); 86 pkgInfo.softwareVersion = strdup("100.100.100.100"); 87 pkgInfo.date = strdup("2021-02-02"); 88 pkgInfo.time = strdup("21:23:49"); 89 pkgInfo.entryCount = testFileNames_.size(); 90 pkgInfo.updateFileVersion = updateFileVersion; 91 pkgInfo.digestMethod = type; 92 pkgInfo.signMethod = PKG_SIGN_METHOD_RSA; 93 pkgInfo.pkgType = PKG_PACK_TYPE_UPGRADE; 94 std::string filePath; 95 uint32_t componentIdBase = 100; 96 uint8_t componentFlags = 22; 97 std::vector<ComponentInfoExt> comp(testFileNames_.size()); 98 for (size_t n = 0; n < testFileNames_.size(); n++) { 99 comp[n].componentAddr = strdup(testFileNames_[n].c_str()); 100 filePath = TEST_PATH_FROM; 101 filePath += testFileNames_[n].c_str(); 102 comp[n].filePath = strdup(filePath.c_str()); 103 comp[n].version = strdup("55555555"); 104 ret = BuildFileDigest(*comp[n].digest, sizeof(comp[n].digest), filePath); 105 comp[n].size = GetFileSize(filePath); 106 comp[n].originalSize = comp[n].size; 107 comp[n].id = n + componentIdBase; 108 comp[n].resType = 1; 109 comp[n].type = 1; 110 comp[n].flags = componentFlags; 111 filePath.clear(); 112 } 113 std::string packagePath = TEST_PATH_TO; 114 packagePath += testPackageName; 115 ret = CreatePackage(&pkgInfo, comp, packagePath.c_str(), 116 GetFuzzPrivateKeyName(pkgInfo.digestMethod).c_str()); 117 for (size_t n = 0; n < testFileNames_.size(); n++) { 118 free(comp[n].componentAddr); 119 free(comp[n].filePath); 120 free(comp[n].version); 121 } 122 free(pkgInfo.productUpdateId); 123 free(pkgInfo.softwareVersion); 124 free(pkgInfo.date); 125 free(pkgInfo.time); 126 return ret; 127 } 128 129 int TestZipPkgCompress(int digestMethod) 130 { 131 return CreateZipPackage(testFileNames_, TEST_PATH_TO + testZipPackageName, TEST_PATH_FROM, digestMethod); 132 } 133 134 int TestPackageUnpack(int type) 135 { 136 std::vector<std::string> componentsList; 137 // 使用上面打包的包进行解析 138 int32_t ret = pkgManager_->LoadPackage( 139 testPackagePath + "test_package.zip", GetFuzzCertName(type), componentsList); 140 141 for (size_t n = 0; n < componentsList.size(); n++) { 142 PKG_LOGI("comp [%zu] file name: %s \r\n", n, (TEST_PATH_TO + componentsList[n]).c_str()); 143 ExtractFile(pkgManager_, componentsList, n); 144 } 145 return ret; 146 } 147 148 int TestZipPkgDecompress(int digestMethod) 149 { 150 std::vector<std::string> componentsList; 151 int32_t ret = pkgManager_->LoadPackage(TEST_PATH_TO + testZipPackageName, 152 GetFuzzCertName(digestMethod), componentsList); 153 154 for (size_t n = 0; n < componentsList.size(); n++) { 155 PKG_LOGI("file name: %s \r\n", (TEST_PATH_TO + componentsList[n]).c_str()); 156 ExtractFile(pkgManager_, componentsList, n); 157 } 158 return ret; 159 } 160 161 int TestGZipPkgCompress() 162 { 163 int ret = TestPackagePack(); 164 std::vector<std::pair<std::string, ZipFileInfo>> files; 165 ZipFileInfo zipFile; 166 zipFile.fileInfo.identity = testPackageName; 167 zipFile.fileInfo.packMethod = PKG_COMPRESS_METHOD_GZIP; 168 zipFile.fileInfo.digestMethod = PKG_DIGEST_TYPE_CRC; 169 std::string fileName = TEST_PATH_TO + testPackageName; 170 files.push_back(std::pair<std::string, ZipFileInfo>(fileName, zipFile)); 171 172 PkgInfo info; 173 info.signMethod = PKG_SIGN_METHOD_RSA; 174 info.digestMethod = PKG_DIGEST_TYPE_SHA256; 175 info.pkgType = PKG_PACK_TYPE_GZIP; 176 ret = pkgManager_->CreatePackage(TEST_PATH_TO + testGZipPackageName, 177 GetFuzzPrivateKeyName(info.digestMethod), &info, files); 178 return ret; 179 } 180 181 int TestVerifyUpgradePackage() 182 { 183 constexpr size_t digestSize = 32; 184 std::vector<uint8_t> digest(digestSize); 185 std::string path = testPackagePath + "test_package.zip"; 186 BuildFileDigest(*digest.data(), digest.capacity(), path.c_str()); 187 int ret = VerifyPackage(path.c_str(), GetFuzzCertName(0).c_str(), "", digest.data(), digest.capacity()); 188 ret = VerifyPackage(nullptr, nullptr, nullptr, nullptr, digest.capacity()); 189 return ret; 190 } 191 192 int TestVerifyPackageWithCallback() 193 { 194 std::string path = testPackagePath + "test_package.zip"; 195 int ret = VerifyPackageWithCallback(path.c_str(), GetFuzzCertName(0).c_str(), 196 [](int32_t result, uint32_t percent) { PKG_LOGI("progress: %u\n", percent); }); 197 198 std::string keyPath = ""; 199 ret = VerifyPackageWithCallback(path.c_str(), keyPath.c_str(), 200 [](int32_t result, uint32_t percent) { PKG_LOGI("progress: %u\n", percent); }); 201 202 std::function<void(int32_t result, uint32_t percent)> cb = nullptr; 203 ret = VerifyPackageWithCallback(path.c_str(), GetFuzzCertName(0).c_str(), cb); 204 205 path = ""; 206 ret = VerifyPackageWithCallback(path.c_str(), GetFuzzCertName(0).c_str(), 207 [](int32_t result, uint32_t percent) { PKG_LOGI("progress: %u\n", percent); }); 208 return ret; 209 } 210 211 int TestLz4PkgCompress() 212 { 213 int ret = TestPackagePack(); 214 std::vector<std::pair<std::string, Lz4FileInfo>> files; 215 Lz4FileInfo zipFile; 216 int8_t compressionLevel = 14; 217 zipFile.fileInfo.identity = testPackageName; 218 zipFile.fileInfo.packMethod = PKG_COMPRESS_METHOD_LZ4; 219 zipFile.fileInfo.digestMethod = PKG_DIGEST_TYPE_CRC; 220 zipFile.compressionLevel = compressionLevel; 221 zipFile.blockSizeID = 0; 222 zipFile.contentChecksumFlag = 0; 223 zipFile.blockIndependence = 0; 224 std::string fileName = TEST_PATH_TO + testPackageName; 225 files.push_back(std::pair<std::string, Lz4FileInfo>(fileName, zipFile)); 226 227 PkgInfo info; 228 info.pkgType = PKG_PACK_TYPE_LZ4; 229 info.signMethod = PKG_SIGN_METHOD_RSA; 230 info.digestMethod = PKG_DIGEST_TYPE_SHA256; 231 ret = pkgManager_->CreatePackage(TEST_PATH_TO + testLz4PackageName, 232 GetFuzzPrivateKeyName(info.digestMethod), &info, files); 233 return ret; 234 } 235}; 236 237void FUZZPackageUnitTest(const uint8_t* data, size_t size) 238{ 239 FuzzPackageUnitTest test; 240 (void)test.TestLz4PkgCompress(); 241 (void)test.TestInvalidCreatePackage(); 242 (void)test.TestVerifyUpgradePackage(); 243 (void)test.TestVerifyPackageWithCallback(); 244 (void)test.TestPackagePack(PKG_DIGEST_TYPE_SHA256); 245 (void)test.TestPackageUnpack(PKG_DIGEST_TYPE_SHA256); 246 (void)test.TestZipPkgCompress(PKG_DIGEST_TYPE_SHA256); 247 (void)test.TestZipPkgDecompress(PKG_DIGEST_TYPE_SHA256); 248 (void)test.TestGZipPkgCompress(); 249} 250 251void FuzzVerifyPackage(const uint8_t* data, size_t size) 252{ 253 constexpr size_t digestSize = 32; 254 std::vector<uint8_t> digest(digestSize); 255 const std::string keyPath = "/data/fuzz/test/signing_cert.crt"; 256 const std::string pkgPath = "/data/fuzz/test/updater.zip"; 257 const std::string pkgDir = "/data/fuzz/test"; 258 const std::string dataInfo = std::string(reinterpret_cast<const char*>(data), size); 259 VerifyPackage(dataInfo.c_str(), keyPath.c_str(), "", digest.data(), digest.capacity()); 260 VerifyPackage(pkgPath.c_str(), dataInfo.c_str(), "", digest.data(), digest.capacity()); 261 VerifyPackage(pkgPath.c_str(), keyPath.c_str(), dataInfo.c_str(), digest.data(), digest.capacity()); 262 VerifyPackage(pkgPath.c_str(), keyPath.c_str(), "", data, size); 263 264 VerifyPackageWithCallback(dataInfo.c_str(), keyPath.c_str(), 265 [](int32_t result, uint32_t percent) {}); 266 VerifyPackageWithCallback(pkgPath, dataInfo.c_str(), [](int32_t result, uint32_t percent) {}); 267 268 ExtraPackageDir(dataInfo.c_str(), keyPath.c_str(), nullptr, pkgDir.c_str()); 269 ExtraPackageDir(pkgPath.c_str(), dataInfo.c_str(), nullptr, pkgDir.c_str()); 270 ExtraPackageDir(pkgPath.c_str(), keyPath.c_str(), dataInfo.c_str(), pkgDir.c_str()); 271 ExtraPackageDir(pkgPath.c_str(), keyPath.c_str(), nullptr, dataInfo.c_str()); 272 273 const std::string file = "updater.bin"; 274 ExtraPackageFile(dataInfo.c_str(), keyPath.c_str(), file.c_str(), pkgDir.c_str()); 275 ExtraPackageFile(pkgPath.c_str(), dataInfo.c_str(), file.c_str(), pkgDir.c_str()); 276 ExtraPackageFile(pkgPath.c_str(), keyPath.c_str(), dataInfo.c_str(), pkgDir.c_str()); 277 ExtraPackageFile(pkgPath.c_str(), keyPath.c_str(), file.c_str(), dataInfo.c_str()); 278} 279} 280 281/* Fuzzer entry point */ 282extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) 283{ 284 /* Run your code on data */ 285 OHOS::FuzzVerifyPackage(data, size); 286 return 0; 287} 288 289