• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef CODE_SIGN_BLOCK_H
17 #define CODE_SIGN_BLOCK_H
18 
19 #include <cstdint>
20 #include <cstdlib>
21 #include <string>
22 #include <vector>
23 #include <unordered_map>
24 #include <mutex>
25 #include <linux/fsverity.h>
26 #include "code_sign_utils.h"
27 #include "interfaces/hap_verify.h"
28 #include "interfaces/hap_verify_result.h"
29 
30 namespace OHOS {
31 namespace Security {
32 namespace CodeSign {
33 
34 #pragma pack(push, 1)
35 typedef struct {
36     uint32_t type;
37     uint32_t size;
38     uint32_t offset;
39 } PropertyBlobHeader;
40 
41 typedef struct {
42     uint64_t magic;
43     uint32_t version;
44     uint32_t blockSize;
45     uint32_t segmentNum;
46     uint32_t flags;
47     uint8_t  reserved[8];
48 } CodeSignBlockHeader;
49 
50 typedef struct {
51     uint32_t type;
52     uint32_t offset;
53     uint32_t size;
54 } SegmentHeader;
55 
56 typedef struct {
57     uint32_t magic;
58     uint8_t  version;
59     uint8_t  hashAlgorithm;
60     uint8_t  logBlockSize;
61     uint8_t  reserved[1];
62 } FsVerityInfo;
63 
64 typedef struct {
65     uint32_t type;
66     uint32_t size;
67 } ExtensionHeader;
68 
69 typedef struct {
70     uint64_t treeSize;
71     uint64_t treeOffset;
72     uint8_t  rootHash[64];
73 } MerkleTreeExtension;
74 
75 typedef struct {
76     uint64_t mapOffset;
77     uint64_t mapSize;
78     uint8_t  unitSize;
79     uint8_t  reversed[3];
80     uint32_t sign_size;
81     uint8_t  signature[0];
82 } PageInfoExtension;
83 
84 typedef struct {
85     uint32_t saltSize;
86     uint32_t signSize;
87     uint32_t flags;
88     uint64_t dataSize;
89     uint8_t  salt[32];
90     uint32_t extensionNum;
91     uint32_t extensionOffset;
92     uint8_t  signature[0];
93 } SignInfo;
94 
95 typedef struct {
96     uint32_t magic;
97     SignInfo signInfo;
98 } HapSignInfo;
99 
100 typedef struct {
101     uint32_t fileNameOffset;
102     uint32_t fileNameSize;
103     uint32_t signOffset;
104     uint32_t signSize;
105 } EntryInfo;
106 
107 typedef struct {
108     uint32_t  magic;
109     uint32_t  length;
110     uint32_t  sectionNum;
111     EntryInfo info[0];
112 } NativeLibSignInfo;
113 #pragma pack(pop)
114 
115 using SignMap = std::unordered_map<std::string, uintptr_t>;
116 using ReadBuffer = const char *;
117 #define CONST_STATIC_CAST(type, ptr) static_cast<const type *>(static_cast<const void *>(ptr))
118 
119 class CodeSignBlock {
120 public:
121     CodeSignBlock();
122     ~CodeSignBlock();
123 
124     static constexpr uint64_t CSB_BLOCK_HEADER_MAGIC = 0xE046C8C65389FCCD;
125     static constexpr uint32_t CSB_FSVERITY_MAGIC = 0x1E3831AB;
126     static constexpr uint32_t CSB_HAP_HEADER_MAGIC = 0xC1B5CC66;
127     static constexpr uint32_t CSB_SO_HEADER_MAGIC = 0xED2E720;
128     static constexpr uint32_t CSB_SIGN_INFO_MERKLE_TREE = 0x1;
129     static constexpr uint32_t CSB_SIGN_INFO_RUNTIME_PAGE = 0x2;
130     static constexpr uint32_t CSB_EXTENSION_TYPE_MERKLE_TREE = 1;
131     static constexpr uint32_t CSB_EXTENSION_TYPE_PAGE_INFO = 2;
132     static constexpr uint32_t CSB_SIGN_INFO_MAX_PAGEINFO_UNITSIZE = 7;
133     static constexpr uint32_t CSB_EXTENSION_TYPE_PAGE_INFO_VERSION = 2;
134 
135     int32_t ParseCodeSignBlock(const std::string &realPath, const EntryMap &entryMap, FileType fileType);
136     int32_t GetOneFileAndCodeSignInfo(std::string &targetFile, struct code_sign_enable_arg &arg, uint32_t flag);
137     int32_t ProcessExtension(uintptr_t &extensionAddr, const uintptr_t blockAddrEnd, struct code_sign_enable_arg &arg);
138 
139 private:
140     int32_t ParseNativeLibSignInfo(const EntryMap &entryMap);
141     int32_t ParseHapSignInfo(const std::string &path);
142     int32_t ParseCodeSignBlockBaseInfo(ReadBuffer codeSignBlock, uint32_t &blockSize);
143     int32_t GetCodeSignBlockBuffer(const std::string &path, ReadBuffer &signBuffer, uint32_t &size);
144 
145     static constexpr uint32_t CSB_HEADER_VERSION = 1;
146     static constexpr uint32_t CSB_HEADER_FLAG_MERKLE_TREE = 0x1;
147     static constexpr uint32_t CSB_HEADER_FLAG_SO = 0x2;
148     static constexpr uint32_t CSB_FSVERITY_INFO_SEG = 0x1;
149     static constexpr uint32_t CSB_HAP_META_SEG = 0x2;
150     static constexpr uint32_t CSB_NATIVE_LIB_INFO_SEG = 0x3;
151     static constexpr uint32_t CSB_SEGMENT_MAX = 3;
152     static constexpr uint32_t CSB_FSVERITY_BLOCK_SIZE = 12;
153 
GetCodeSignBlockHeader(void)154     const CodeSignBlockHeader *GetCodeSignBlockHeader(void)
155     {
156         return blockHeader_;
157     }
GetFsVerityInfo(void)158     const FsVerityInfo *GetFsVerityInfo(void)
159     {
160         return fsVerityInfo_;
161     }
GetHapSignInfo(void)162     const HapSignInfo *GetHapSignInfo(void)
163     {
164         return hapSignInfo_;
165     }
GetNativeLibSignInfo(void)166     const NativeLibSignInfo *GetNativeLibSignInfo(void)
167     {
168         return nativeLibSignInfo_;
169     }
170 
SetCodeSignBlockHeader(const CodeSignBlockHeader * header,uint32_t & blockSize)171     int32_t SetCodeSignBlockHeader(const CodeSignBlockHeader *header, uint32_t &blockSize)
172     {
173         if (header->magic != CSB_BLOCK_HEADER_MAGIC) {
174             return CS_ERR_BLOCK_MAGIC;
175         }
176         if (header->version != CSB_HEADER_VERSION) {
177             return CS_ERR_BLOCK_VERSION;
178         }
179         if ((header->segmentNum > CSB_SEGMENT_MAX) || (header->segmentNum == 0)) {
180             return CS_ERR_BLOCK_SEG_NUM;
181         }
182         if (header->blockSize != blockSize) {
183             return CS_ERR_BLOCK_SIZE;
184         }
185         blockHeader_ = header;
186         return CS_SUCCESS;
187     }
188 
SetFsVerityInfo(const FsVerityInfo * info)189     int32_t SetFsVerityInfo(const FsVerityInfo *info)
190     {
191         if (info->magic != CSB_FSVERITY_MAGIC) {
192             return CS_ERR_FSVERITY_MAGIC;
193         }
194         if (info->version != 1) {
195             return CS_ERR_FSVERITY_VERSION;
196         }
197         if (info->logBlockSize != CSB_FSVERITY_BLOCK_SIZE) {
198             return CS_ERR_FSVERITY_BLOCK_SIZE;
199         }
200         fsVerityInfo_ = info;
201         return CS_SUCCESS;
202     }
203 
SetHapSignInfo(const HapSignInfo * info)204     int32_t SetHapSignInfo(const HapSignInfo *info)
205     {
206         if (info->magic != CSB_HAP_HEADER_MAGIC) {
207             return CS_ERR_HAP_MAGIC;
208         }
209         const auto signInfo = &info->signInfo;
210         if (blockHeader_->flags & CSB_HEADER_FLAG_MERKLE_TREE) {
211             if (signInfo->extensionOffset >= blockHeader_->blockSize) {
212                 return CS_ERR_HAP_EXTERNSION;
213             }
214         }
215         hapSignInfo_ = info;
216         return CS_SUCCESS;
217     }
218 
SetNativeLibSignInfo(const NativeLibSignInfo * info)219     int32_t SetNativeLibSignInfo(const NativeLibSignInfo *info)
220     {
221         if (info->magic != CSB_SO_HEADER_MAGIC) {
222             return CS_ERR_SO_MAGIC;
223         }
224         if ((blockHeader_->flags & CSB_HEADER_FLAG_SO) && !info->sectionNum) {
225             return CS_ERR_SO_SECTION_NUM;
226         }
227         nativeLibSignInfo_ = info;
228         return CS_SUCCESS;
229     }
230 
GetOneMapNodeFromSignMap(std::string & fileName,uintptr_t & signInfo)231     int32_t GetOneMapNodeFromSignMap(std::string &fileName, uintptr_t &signInfo)
232     {
233         std::lock_guard<std::mutex> guard(signMapMutex_);
234         if (signMap_.empty()) {
235             return CS_SUCCESS_END;
236         }
237 
238         auto info = signMap_.begin();
239         fileName = info->first;
240         signInfo = info->second;
241         signMap_.erase(fileName);
242         return CS_SUCCESS;
243     }
244 
245     Verify::SignatureInfo signatureInfo_;
246     const CodeSignBlockHeader *blockHeader_ = nullptr;
247     const FsVerityInfo *fsVerityInfo_ = nullptr;
248     const HapSignInfo *hapSignInfo_ = nullptr;
249     const NativeLibSignInfo *nativeLibSignInfo_ = nullptr;
250     std::mutex signMapMutex_;
251     SignMap signMap_;
252 };
253 } // CodeSign namespace
254 } // Security namespace
255 } // OHOS namespace
256 #endif
257