18e920a95Sopenharmony_ci/*
28e920a95Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
38e920a95Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
48e920a95Sopenharmony_ci * you may not use this file except in compliance with the License.
58e920a95Sopenharmony_ci * You may obtain a copy of the License at
68e920a95Sopenharmony_ci *
78e920a95Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
88e920a95Sopenharmony_ci *
98e920a95Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
108e920a95Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
118e920a95Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128e920a95Sopenharmony_ci * See the License for the specific language governing permissions and
138e920a95Sopenharmony_ci * limitations under the License.
148e920a95Sopenharmony_ci */
158e920a95Sopenharmony_ci
168e920a95Sopenharmony_ci#ifndef CODE_SIGN_BLOCK_H
178e920a95Sopenharmony_ci#define CODE_SIGN_BLOCK_H
188e920a95Sopenharmony_ci
198e920a95Sopenharmony_ci#include <cstdint>
208e920a95Sopenharmony_ci#include <cstdlib>
218e920a95Sopenharmony_ci#include <string>
228e920a95Sopenharmony_ci#include <vector>
238e920a95Sopenharmony_ci#include <unordered_map>
248e920a95Sopenharmony_ci#include <mutex>
258e920a95Sopenharmony_ci#include <linux/fsverity.h>
268e920a95Sopenharmony_ci#include "code_sign_utils.h"
278e920a95Sopenharmony_ci#include "interfaces/hap_verify.h"
288e920a95Sopenharmony_ci#include "interfaces/hap_verify_result.h"
298e920a95Sopenharmony_ci
308e920a95Sopenharmony_cinamespace OHOS {
318e920a95Sopenharmony_cinamespace Security {
328e920a95Sopenharmony_cinamespace CodeSign {
338e920a95Sopenharmony_ci
348e920a95Sopenharmony_ci#pragma pack(push, 1)
358e920a95Sopenharmony_citypedef struct {
368e920a95Sopenharmony_ci    uint32_t type;
378e920a95Sopenharmony_ci    uint32_t size;
388e920a95Sopenharmony_ci    uint32_t offset;
398e920a95Sopenharmony_ci} PropertyBlobHeader;
408e920a95Sopenharmony_ci
418e920a95Sopenharmony_citypedef struct {
428e920a95Sopenharmony_ci    uint64_t magic;
438e920a95Sopenharmony_ci    uint32_t version;
448e920a95Sopenharmony_ci    uint32_t blockSize;
458e920a95Sopenharmony_ci    uint32_t segmentNum;
468e920a95Sopenharmony_ci    uint32_t flags;
478e920a95Sopenharmony_ci    uint8_t  reserved[8];
488e920a95Sopenharmony_ci} CodeSignBlockHeader;
498e920a95Sopenharmony_ci
508e920a95Sopenharmony_citypedef struct {
518e920a95Sopenharmony_ci    uint32_t type;
528e920a95Sopenharmony_ci    uint32_t offset;
538e920a95Sopenharmony_ci    uint32_t size;
548e920a95Sopenharmony_ci} SegmentHeader;
558e920a95Sopenharmony_ci
568e920a95Sopenharmony_citypedef struct {
578e920a95Sopenharmony_ci    uint32_t magic;
588e920a95Sopenharmony_ci    uint8_t  version;
598e920a95Sopenharmony_ci    uint8_t  hashAlgorithm;
608e920a95Sopenharmony_ci    uint8_t  logBlockSize;
618e920a95Sopenharmony_ci    uint8_t  reserved[1];
628e920a95Sopenharmony_ci} FsVerityInfo;
638e920a95Sopenharmony_ci
648e920a95Sopenharmony_citypedef struct {
658e920a95Sopenharmony_ci    uint32_t type;
668e920a95Sopenharmony_ci    uint32_t size;
678e920a95Sopenharmony_ci} ExtensionHeader;
688e920a95Sopenharmony_ci
698e920a95Sopenharmony_citypedef struct {
708e920a95Sopenharmony_ci    uint64_t treeSize;
718e920a95Sopenharmony_ci    uint64_t treeOffset;
728e920a95Sopenharmony_ci    uint8_t  rootHash[64];
738e920a95Sopenharmony_ci} MerkleTreeExtension;
748e920a95Sopenharmony_ci
758e920a95Sopenharmony_citypedef struct {
768e920a95Sopenharmony_ci    uint64_t mapOffset;
778e920a95Sopenharmony_ci    uint64_t mapSize;
788e920a95Sopenharmony_ci    uint8_t  unitSize;
798e920a95Sopenharmony_ci    uint8_t  reversed[3];
808e920a95Sopenharmony_ci    uint32_t sign_size;
818e920a95Sopenharmony_ci    uint8_t  signature[0];
828e920a95Sopenharmony_ci} PageInfoExtension;
838e920a95Sopenharmony_ci
848e920a95Sopenharmony_citypedef struct {
858e920a95Sopenharmony_ci    uint32_t saltSize;
868e920a95Sopenharmony_ci    uint32_t signSize;
878e920a95Sopenharmony_ci    uint32_t flags;
888e920a95Sopenharmony_ci    uint64_t dataSize;
898e920a95Sopenharmony_ci    uint8_t  salt[32];
908e920a95Sopenharmony_ci    uint32_t extensionNum;
918e920a95Sopenharmony_ci    uint32_t extensionOffset;
928e920a95Sopenharmony_ci    uint8_t  signature[0];
938e920a95Sopenharmony_ci} SignInfo;
948e920a95Sopenharmony_ci
958e920a95Sopenharmony_citypedef struct {
968e920a95Sopenharmony_ci    uint32_t magic;
978e920a95Sopenharmony_ci    SignInfo signInfo;
988e920a95Sopenharmony_ci} HapSignInfo;
998e920a95Sopenharmony_ci
1008e920a95Sopenharmony_citypedef struct {
1018e920a95Sopenharmony_ci    uint32_t fileNameOffset;
1028e920a95Sopenharmony_ci    uint32_t fileNameSize;
1038e920a95Sopenharmony_ci    uint32_t signOffset;
1048e920a95Sopenharmony_ci    uint32_t signSize;
1058e920a95Sopenharmony_ci} EntryInfo;
1068e920a95Sopenharmony_ci
1078e920a95Sopenharmony_citypedef struct {
1088e920a95Sopenharmony_ci    uint32_t  magic;
1098e920a95Sopenharmony_ci    uint32_t  length;
1108e920a95Sopenharmony_ci    uint32_t  sectionNum;
1118e920a95Sopenharmony_ci    EntryInfo info[0];
1128e920a95Sopenharmony_ci} NativeLibSignInfo;
1138e920a95Sopenharmony_ci#pragma pack(pop)
1148e920a95Sopenharmony_ci
1158e920a95Sopenharmony_ciusing SignMap = std::unordered_map<std::string, uintptr_t>;
1168e920a95Sopenharmony_ciusing ReadBuffer = const char *;
1178e920a95Sopenharmony_ci#define CONST_STATIC_CAST(type, ptr) static_cast<const type *>(static_cast<const void *>(ptr))
1188e920a95Sopenharmony_ci
1198e920a95Sopenharmony_ciclass CodeSignBlock {
1208e920a95Sopenharmony_cipublic:
1218e920a95Sopenharmony_ci    CodeSignBlock();
1228e920a95Sopenharmony_ci    ~CodeSignBlock();
1238e920a95Sopenharmony_ci
1248e920a95Sopenharmony_ci    static constexpr uint64_t CSB_BLOCK_HEADER_MAGIC = 0xE046C8C65389FCCD;
1258e920a95Sopenharmony_ci    static constexpr uint32_t CSB_FSVERITY_MAGIC = 0x1E3831AB;
1268e920a95Sopenharmony_ci    static constexpr uint32_t CSB_HAP_HEADER_MAGIC = 0xC1B5CC66;
1278e920a95Sopenharmony_ci    static constexpr uint32_t CSB_SO_HEADER_MAGIC = 0xED2E720;
1288e920a95Sopenharmony_ci    static constexpr uint32_t CSB_SIGN_INFO_MERKLE_TREE = 0x1;
1298e920a95Sopenharmony_ci    static constexpr uint32_t CSB_SIGN_INFO_RUNTIME_PAGE = 0x2;
1308e920a95Sopenharmony_ci    static constexpr uint32_t CSB_EXTENSION_TYPE_MERKLE_TREE = 1;
1318e920a95Sopenharmony_ci    static constexpr uint32_t CSB_EXTENSION_TYPE_PAGE_INFO = 2;
1328e920a95Sopenharmony_ci    static constexpr uint32_t CSB_SIGN_INFO_MAX_PAGEINFO_UNITSIZE = 7;
1338e920a95Sopenharmony_ci    static constexpr uint32_t CSB_EXTENSION_TYPE_PAGE_INFO_VERSION = 2;
1348e920a95Sopenharmony_ci
1358e920a95Sopenharmony_ci    int32_t ParseCodeSignBlock(const std::string &realPath, const EntryMap &entryMap, FileType fileType);
1368e920a95Sopenharmony_ci    int32_t GetOneFileAndCodeSignInfo(std::string &targetFile, struct code_sign_enable_arg &arg);
1378e920a95Sopenharmony_ci    int32_t ProcessExtension(uintptr_t &extensionAddr, const uintptr_t blockAddrEnd, struct code_sign_enable_arg &arg);
1388e920a95Sopenharmony_ci
1398e920a95Sopenharmony_ciprivate:
1408e920a95Sopenharmony_ci    int32_t ParseNativeLibSignInfo(const EntryMap &entryMap);
1418e920a95Sopenharmony_ci    int32_t ParseHapSignInfo(const std::string &path);
1428e920a95Sopenharmony_ci    int32_t ParseCodeSignBlockBaseInfo(ReadBuffer codeSignBlock, uint32_t &blockSize);
1438e920a95Sopenharmony_ci    int32_t GetCodeSignBlockBuffer(const std::string &path, ReadBuffer &signBuffer, uint32_t &size);
1448e920a95Sopenharmony_ci
1458e920a95Sopenharmony_ci    static constexpr uint32_t CSB_HEADER_VERSION = 1;
1468e920a95Sopenharmony_ci    static constexpr uint32_t CSB_HEADER_FLAG_MERKLE_TREE = 0x1;
1478e920a95Sopenharmony_ci    static constexpr uint32_t CSB_HEADER_FLAG_SO = 0x2;
1488e920a95Sopenharmony_ci    static constexpr uint32_t CSB_FSVERITY_INFO_SEG = 0x1;
1498e920a95Sopenharmony_ci    static constexpr uint32_t CSB_HAP_META_SEG = 0x2;
1508e920a95Sopenharmony_ci    static constexpr uint32_t CSB_NATIVE_LIB_INFO_SEG = 0x3;
1518e920a95Sopenharmony_ci    static constexpr uint32_t CSB_SEGMENT_MAX = 3;
1528e920a95Sopenharmony_ci    static constexpr uint32_t CSB_FSVERITY_BLOCK_SIZE = 12;
1538e920a95Sopenharmony_ci
1548e920a95Sopenharmony_ci    const CodeSignBlockHeader *GetCodeSignBlockHeader(void)
1558e920a95Sopenharmony_ci    {
1568e920a95Sopenharmony_ci        return blockHeader_;
1578e920a95Sopenharmony_ci    }
1588e920a95Sopenharmony_ci    const FsVerityInfo *GetFsVerityInfo(void)
1598e920a95Sopenharmony_ci    {
1608e920a95Sopenharmony_ci        return fsVerityInfo_;
1618e920a95Sopenharmony_ci    }
1628e920a95Sopenharmony_ci    const HapSignInfo *GetHapSignInfo(void)
1638e920a95Sopenharmony_ci    {
1648e920a95Sopenharmony_ci        return hapSignInfo_;
1658e920a95Sopenharmony_ci    }
1668e920a95Sopenharmony_ci    const NativeLibSignInfo *GetNativeLibSignInfo(void)
1678e920a95Sopenharmony_ci    {
1688e920a95Sopenharmony_ci        return nativeLibSignInfo_;
1698e920a95Sopenharmony_ci    }
1708e920a95Sopenharmony_ci
1718e920a95Sopenharmony_ci    int32_t SetCodeSignBlockHeader(const CodeSignBlockHeader *header, uint32_t &blockSize)
1728e920a95Sopenharmony_ci    {
1738e920a95Sopenharmony_ci        if (header->magic != CSB_BLOCK_HEADER_MAGIC) {
1748e920a95Sopenharmony_ci            return CS_ERR_BLOCK_MAGIC;
1758e920a95Sopenharmony_ci        }
1768e920a95Sopenharmony_ci        if (header->version != CSB_HEADER_VERSION) {
1778e920a95Sopenharmony_ci            return CS_ERR_BLOCK_VERSION;
1788e920a95Sopenharmony_ci        }
1798e920a95Sopenharmony_ci        if ((header->segmentNum > CSB_SEGMENT_MAX) || (header->segmentNum == 0)) {
1808e920a95Sopenharmony_ci            return CS_ERR_BLOCK_SEG_NUM;
1818e920a95Sopenharmony_ci        }
1828e920a95Sopenharmony_ci        if (header->blockSize != blockSize) {
1838e920a95Sopenharmony_ci            return CS_ERR_BLOCK_SIZE;
1848e920a95Sopenharmony_ci        }
1858e920a95Sopenharmony_ci        blockHeader_ = header;
1868e920a95Sopenharmony_ci        return CS_SUCCESS;
1878e920a95Sopenharmony_ci    }
1888e920a95Sopenharmony_ci
1898e920a95Sopenharmony_ci    int32_t SetFsVerityInfo(const FsVerityInfo *info)
1908e920a95Sopenharmony_ci    {
1918e920a95Sopenharmony_ci        if (info->magic != CSB_FSVERITY_MAGIC) {
1928e920a95Sopenharmony_ci            return CS_ERR_FSVERITY_MAGIC;
1938e920a95Sopenharmony_ci        }
1948e920a95Sopenharmony_ci        if (info->version != 1) {
1958e920a95Sopenharmony_ci            return CS_ERR_FSVERITY_VERSION;
1968e920a95Sopenharmony_ci        }
1978e920a95Sopenharmony_ci        if (info->logBlockSize != CSB_FSVERITY_BLOCK_SIZE) {
1988e920a95Sopenharmony_ci            return CS_ERR_FSVERITY_BLOCK_SIZE;
1998e920a95Sopenharmony_ci        }
2008e920a95Sopenharmony_ci        fsVerityInfo_ = info;
2018e920a95Sopenharmony_ci        return CS_SUCCESS;
2028e920a95Sopenharmony_ci    }
2038e920a95Sopenharmony_ci
2048e920a95Sopenharmony_ci    int32_t SetHapSignInfo(const HapSignInfo *info)
2058e920a95Sopenharmony_ci    {
2068e920a95Sopenharmony_ci        if (info->magic != CSB_HAP_HEADER_MAGIC) {
2078e920a95Sopenharmony_ci            return CS_ERR_HAP_MAGIC;
2088e920a95Sopenharmony_ci        }
2098e920a95Sopenharmony_ci        const auto signInfo = &info->signInfo;
2108e920a95Sopenharmony_ci        if (blockHeader_->flags & CSB_HEADER_FLAG_MERKLE_TREE) {
2118e920a95Sopenharmony_ci            if (signInfo->extensionOffset >= blockHeader_->blockSize) {
2128e920a95Sopenharmony_ci                return CS_ERR_HAP_EXTERNSION;
2138e920a95Sopenharmony_ci            }
2148e920a95Sopenharmony_ci        }
2158e920a95Sopenharmony_ci        hapSignInfo_ = info;
2168e920a95Sopenharmony_ci        return CS_SUCCESS;
2178e920a95Sopenharmony_ci    }
2188e920a95Sopenharmony_ci
2198e920a95Sopenharmony_ci    int32_t SetNativeLibSignInfo(const NativeLibSignInfo *info)
2208e920a95Sopenharmony_ci    {
2218e920a95Sopenharmony_ci        if (info->magic != CSB_SO_HEADER_MAGIC) {
2228e920a95Sopenharmony_ci            return CS_ERR_SO_MAGIC;
2238e920a95Sopenharmony_ci        }
2248e920a95Sopenharmony_ci        if ((blockHeader_->flags & CSB_HEADER_FLAG_SO) && !info->sectionNum) {
2258e920a95Sopenharmony_ci            return CS_ERR_SO_SECTION_NUM;
2268e920a95Sopenharmony_ci        }
2278e920a95Sopenharmony_ci        nativeLibSignInfo_ = info;
2288e920a95Sopenharmony_ci        return CS_SUCCESS;
2298e920a95Sopenharmony_ci    }
2308e920a95Sopenharmony_ci
2318e920a95Sopenharmony_ci    int32_t GetOneMapNodeFromSignMap(std::string &fileName, uintptr_t &signInfo)
2328e920a95Sopenharmony_ci    {
2338e920a95Sopenharmony_ci        std::lock_guard<std::mutex> guard(signMapMutex_);
2348e920a95Sopenharmony_ci        if (signMap_.empty()) {
2358e920a95Sopenharmony_ci            return CS_SUCCESS_END;
2368e920a95Sopenharmony_ci        }
2378e920a95Sopenharmony_ci
2388e920a95Sopenharmony_ci        auto info = signMap_.begin();
2398e920a95Sopenharmony_ci        fileName = info->first;
2408e920a95Sopenharmony_ci        signInfo = info->second;
2418e920a95Sopenharmony_ci        signMap_.erase(fileName);
2428e920a95Sopenharmony_ci        return CS_SUCCESS;
2438e920a95Sopenharmony_ci    }
2448e920a95Sopenharmony_ci
2458e920a95Sopenharmony_ci    Verify::SignatureInfo signatureInfo_;
2468e920a95Sopenharmony_ci    const CodeSignBlockHeader *blockHeader_ = nullptr;
2478e920a95Sopenharmony_ci    const FsVerityInfo *fsVerityInfo_ = nullptr;
2488e920a95Sopenharmony_ci    const HapSignInfo *hapSignInfo_ = nullptr;
2498e920a95Sopenharmony_ci    const NativeLibSignInfo *nativeLibSignInfo_ = nullptr;
2508e920a95Sopenharmony_ci    std::mutex signMapMutex_;
2518e920a95Sopenharmony_ci    SignMap signMap_;
2528e920a95Sopenharmony_ci};
2538e920a95Sopenharmony_ci} // CodeSign namespace
2548e920a95Sopenharmony_ci} // Security namespace
2558e920a95Sopenharmony_ci} // OHOS namespace
2568e920a95Sopenharmony_ci#endif
257