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
37 using namespace Updater;
38 using namespace Hpackage;
39 namespace OHOS {
40 class FuzzPackageUnitTest : public FuzzPkgTest {
41 public:
FuzzPackageUnitTest()42 FuzzPackageUnitTest() {}
~FuzzPackageUnitTest()43 ~FuzzPackageUnitTest() override {}
44 public:
TestInvalidCreatePackage()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
TestPackagePack(int type=PKG_DIGEST_TYPE_SHA256)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
TestZipPkgCompress(int digestMethod)129 int TestZipPkgCompress(int digestMethod)
130 {
131 return CreateZipPackage(testFileNames_, TEST_PATH_TO + testZipPackageName, TEST_PATH_FROM, digestMethod);
132 }
133
TestPackageUnpack(int type)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
TestZipPkgDecompress(int digestMethod)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
TestGZipPkgCompress()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
TestVerifyUpgradePackage()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
TestVerifyPackageWithCallback()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
TestLz4PkgCompress()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
FUZZPackageUnitTest(const uint8_t * data,size_t size)237 void 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
FuzzVerifyPackage(const uint8_t * data,size_t size)251 void 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 */
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)282 extern "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