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
16#ifndef PKG_FUZZ_TEST
17#define PKG_FUZZ_TEST
18
19#include <cstring>
20#include <fcntl.h>
21#include <iostream>
22#include <sys/mman.h>
23#include <sys/stat.h>
24#include <unistd.h>
25#include "pkg_algorithm.h"
26#include "pkg_manager.h"
27#include "pkg_manager_impl.h"
28#include "pkg_utils.h"
29#include "log.h"
30#include "utils.h"
31
32using Updater::InitUpdaterLogger;
33using Hpackage::PkgManager;
34using Hpackage::PkgManagerImpl;
35using Hpackage::PkgStream;
36using Hpackage::PkgAlgorithmFactory;
37using Hpackage::DigestAlgorithm;
38using Hpackage::ComponentInfo;
39using Hpackage::FileInfo;
40using Hpackage::ZipFileInfo;
41using Hpackage::PkgInfo;
42
43namespace OHOS {
44const std::string TEST_PATH_FROM = "/data/updater/src/";
45const std::string TEST_PATH_TO = "/data/updater/dst/";
46
47inline std::string GetFuzzPrivateKeyName(int type = 0)
48{
49    std::string name = TEST_PATH_FROM;
50    if (type == PKG_DIGEST_TYPE_SHA384) {
51        name += "rsa_private_key384.pem";
52    } else {
53        name += "rsa_private_key2048.pem";
54    }
55    return name;
56}
57
58inline std::string GetFuzzCertName(int type = 0)
59{
60    std::string name = TEST_PATH_FROM;
61    if (type == PKG_DIGEST_TYPE_SHA384) {
62        name += "signing_cert384.crt";
63    } else {
64        name += "signing_cert.crt";
65    }
66    return name;
67}
68
69class FuzzPkgTest {
70public:
71    FuzzPkgTest()
72    {
73        pkgManager_ = static_cast<PkgManagerImpl*>(PkgManager::CreatePackageInstance());
74    }
75    virtual ~FuzzPkgTest()
76    {
77        PkgManager::ReleasePackageInstance(pkgManager_);
78        pkgManager_ = nullptr;
79    }
80
81protected:
82    void SetUp()
83    {
84        InitUpdaterLogger("UPDATER ", "updater_log.log", "updater_status.log", "error_code.log");
85        // 先创建目标目录
86        if (access(TEST_PATH_TO.c_str(), R_OK | W_OK) == -1) {
87            mkdir(TEST_PATH_TO.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
88        }
89    }
90    void TestBody() {}
91    void TearDown() {}
92
93    int32_t BuildFileDigest(uint8_t &digest, size_t size, const std::string &pkgPath)
94    {
95        PkgManager::StreamPtr stream = nullptr;
96        int32_t ret = pkgManager_->CreatePkgStream(stream, pkgPath, 0, PkgStream::PkgStreamType_Read);
97        if (ret != 0) {
98            PKG_LOGE("Create input stream fail %s", pkgPath.c_str());
99            return ret;
100        }
101        size_t fileLength = stream->GetFileLength();
102        if (fileLength <= 0 || fileLength > SIZE_MAX) {
103            PKG_LOGE("Invalid file len %zu to load %s", fileLength, stream->GetFileName().c_str());
104            pkgManager_->ClosePkgStream(stream);
105            return -1;
106        }
107
108        size_t bufSize = 4096;
109        Hpackage::PkgBuffer buff(bufSize);
110        // 整包检查
111        DigestAlgorithm::DigestAlgorithmPtr alg =
112            PkgAlgorithmFactory::GetDigestAlgorithm(PKG_DIGEST_TYPE_SHA256);
113        if (alg == nullptr) {
114            PKG_LOGE("Invalid file %s", stream->GetFileName().c_str());
115            pkgManager_->ClosePkgStream(stream);
116            return -1;
117        }
118        alg->Init();
119
120        size_t offset = 0;
121        size_t readLen = 0;
122        while (offset < fileLength) {
123            ret = stream->Read(buff, offset, bufSize, readLen);
124            if (ret != 0) {
125                PKG_LOGE("read buffer fail %s", stream->GetFileName().c_str());
126                pkgManager_->ClosePkgStream(stream);
127                return ret;
128            }
129            alg->Update(buff, readLen);
130
131            offset += readLen;
132            readLen = 0;
133        }
134        Hpackage::PkgBuffer buffer(&digest, size);
135        alg->Final(buffer);
136        pkgManager_->ClosePkgStream(stream);
137        return 0;
138    }
139
140    void ExtractFile(PkgManager::PkgManagerPtr manager, std::vector<std::string> components, size_t num)
141    {
142        PkgManager::StreamPtr outStream = nullptr;
143        PKG_LOGI("comp [%zu] file name: %s \r\n", num, (TEST_PATH_TO + components[num]).c_str());
144        manager->CreatePkgStream(outStream, TEST_PATH_TO + components[num], 0, PkgStream::PkgStreamType_Write);
145        if (outStream == nullptr) {
146            return;
147        }
148        (void)manager->ExtractFile(components[num], outStream);
149        manager->ClosePkgStream(outStream);
150        const FileInfo *info = manager->GetFileInfo(components[num]);
151        if (info->packMethod == PKG_COMPRESS_METHOD_NONE) {
152            const ComponentInfo* compInfo = (const ComponentInfo*)manager->GetFileInfo(components[num]);
153            if (compInfo != nullptr) {
154                PKG_LOGI("comp [%zu] componentAddr: %s \n", num, (*compInfo).fileInfo.identity.c_str());
155                PKG_LOGI("comp [%zu] version: %s \n", num, (*compInfo).version.c_str());
156                PKG_LOGI("comp [%zu] originalSize: %zu \n", num, (*compInfo).originalSize);
157                PKG_LOGI("comp [%zu] size: %zu \n", num, (*compInfo).fileInfo.unpackedSize);
158                PKG_LOGI("comp [%zu] id: %d \n", num, (*compInfo).id);
159                PKG_LOGI("comp [%zu] resType: %d \n", num, (*compInfo).resType);
160                PKG_LOGI("comp [%zu] flags: %d \n", num, (*compInfo).compFlags);
161                PKG_LOGI("comp [%zu] type: %d \n", num, (*compInfo).type);
162            }
163        } else {
164            PKG_LOGI("FileInfo [%zu] id: %s \n", num, info->identity.c_str());
165            PKG_LOGI("FileInfo [%zu] unpackedSize: %zu \n", num, info->unpackedSize);
166            PKG_LOGI("FileInfo [%zu] packedSize: %zu \n", num, info->packedSize);
167            PKG_LOGI("FileInfo [%zu] packMethod: %d \n", num, info->packMethod);
168            PKG_LOGI("FileInfo [%zu] digestMethod: %d \n", num, info->digestMethod);
169            PKG_LOGI("FileInfo [%zu] flags: %d \n", num, info->flags);
170        }
171    }
172
173    int CreateZipPackage(const std::vector<std::string> &testNames,
174        const std::string pkgName, const std::string &base, int digestMethod)
175    {
176        PkgManager::PkgManagerPtr pkgManager = PkgManager::CreatePackageInstance();
177        std::vector<std::pair<std::string, ZipFileInfo>> files;
178        // 构建要打包的zip文件
179        for (auto name : testNames) {
180            ZipFileInfo zipFile;
181            zipFile.fileInfo.identity = name;
182            zipFile.fileInfo.packMethod = PKG_COMPRESS_METHOD_ZIP;
183            zipFile.fileInfo.digestMethod = PKG_DIGEST_TYPE_CRC;
184            std::string fileName = base + name;
185            files.push_back(std::pair<std::string, ZipFileInfo>(fileName, zipFile));
186        }
187
188        PkgInfo pkgInfo;
189        pkgInfo.signMethod = PKG_SIGN_METHOD_RSA;
190        pkgInfo.digestMethod = digestMethod;
191        pkgInfo.pkgType = PKG_PACK_TYPE_ZIP;
192        int32_t ret = pkgManager->CreatePackage(pkgName, GetFuzzPrivateKeyName(digestMethod), &pkgInfo, files);
193        PkgManager::ReleasePackageInstance(pkgManager);
194        return ret;
195    }
196    std::vector<std::string> testFileNames_ = {
197        "test_math.us",
198        "test_native.us",
199        "testscript.us",
200        "Verse-script.us",
201        "libcrypto.a",
202        "ggg.zip",
203        "loadScript.us",
204        "registerCmd.us",
205        "test_function.us",
206        "test_if.us",
207        "test_logic.us",
208    };
209    PkgManagerImpl* pkgManager_ = nullptr;
210    std::string testCombinePkgName = "test_CombinePackage.zip";
211    std::string testPackagePath = "/data/updater/package/";
212    std::string testPackageName = "test_package.bin";
213    std::string testZipPackageName = "test_package.zip";
214    std::string testLz4PackageName = "test_package.lz4";
215    std::string testGZipPackageName = "test_package.gz";
216};
217}
218#endif // PKG_FUZZ_TEST
219