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