• 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; // MERKLE_TREE_INCLUDE
66     uint32_t size;
67     uint64_t treeSize;
68     uint64_t treeOffset;
69     uint8_t  rootHash[64];
70 } MerkleTreeExtension;
71 
72 typedef struct {
73     uint32_t saltSize;
74     uint32_t signSize;
75     uint32_t flags;
76     uint64_t dataSize;
77     uint8_t  salt[32];
78     uint32_t extensionNum;
79     uint32_t extensionOffset;
80     uint8_t  signature[0];
81 } SignInfo;
82 
83 typedef struct {
84     uint32_t magic;
85     SignInfo signInfo;
86 } HapSignInfo;
87 
88 typedef struct {
89     uint32_t fileNameOffset;
90     uint32_t fileNameSize;
91     uint32_t signOffset;
92     uint32_t signSize;
93 } EntryInfo;
94 
95 typedef struct {
96     uint32_t  magic;
97     uint32_t  length;
98     uint32_t  sectionNum;
99     EntryInfo info[0];
100 } NativeLibSignInfo;
101 #pragma pack(pop)
102 
103 using SignMap = std::unordered_map<std::string, uintptr_t>;
104 using ReadBuffer = const char *;
105 #define CONST_STATIC_CAST(type, ptr) static_cast<const type *>(static_cast<const void *>(ptr))
106 
107 class CodeSignBlock {
108 public:
109     CodeSignBlock();
110     ~CodeSignBlock();
111 
112     static constexpr uint64_t CSB_BLOCK_HEADER_MAGIC = 0xE046C8C65389FCCD;
113     static constexpr uint32_t CSB_FSVERITY_MAGIC = 0x1E3831AB;
114     static constexpr uint32_t CSB_HAP_HEADER_MAGIC = 0xC1B5CC66;
115     static constexpr uint32_t CSB_SO_HEADER_MAGIC = 0xED2E720;
116     static constexpr uint32_t CSB_SIGN_INFO_MERKLE_TREE = 0x1;
117     static constexpr uint32_t CSB_EXTENSION_TYPE_MERKLE_TREE = 1;
118 
119     int32_t ParseCodeSignBlock(const std::string &realPath, const EntryMap &entryMap, FileType fileType);
120     int32_t GetOneFileAndCodeSignInfo(std::string &targetFile, struct code_sign_enable_arg &arg);
121 
122 private:
123     int32_t ParseNativeLibSignInfo(const EntryMap &entryMap);
124     int32_t ParseHapSignInfo(const std::string &path);
125     int32_t ParseCodeSignBlockBaseInfo(ReadBuffer codeSignBlock, uint32_t &blockSize);
126     int32_t GetCodeSignBlockBuffer(const std::string &path, ReadBuffer &signBuffer, uint32_t &size);
127 
128     static constexpr uint32_t CSB_HEADER_VERSION = 1;
129     static constexpr uint32_t CSB_HEADER_FLAG_MERKLE_TREE = 0x1;
130     static constexpr uint32_t CSB_HEADER_FLAG_SO = 0x2;
131     static constexpr uint32_t CSB_FSVERITY_INFO_SEG = 0x1;
132     static constexpr uint32_t CSB_HAP_META_SEG = 0x2;
133     static constexpr uint32_t CSB_NATIVE_LIB_INFO_SEG = 0x3;
134     static constexpr uint32_t CSB_SEGMENT_MAX = 3;
135     static constexpr uint32_t CSB_FSVERITY_BLOCK_SIZE = 12;
136 
GetCodeSignBlockHeader(void)137     const CodeSignBlockHeader *GetCodeSignBlockHeader(void)
138     {
139         return blockHeader_;
140     }
GetFsVerityInfo(void)141     const FsVerityInfo *GetFsVerityInfo(void)
142     {
143         return fsVerityInfo_;
144     }
GetHapSignInfo(void)145     const HapSignInfo *GetHapSignInfo(void)
146     {
147         return hapSignInfo_;
148     }
GetNativeLibSignInfo(void)149     const NativeLibSignInfo *GetNativeLibSignInfo(void)
150     {
151         return nativeLibSignInfo_;
152     }
153 
SetCodeSignBlockHeader(const CodeSignBlockHeader * header,uint32_t & blockSize)154     int32_t SetCodeSignBlockHeader(const CodeSignBlockHeader *header, uint32_t &blockSize)
155     {
156         if (header->magic != CSB_BLOCK_HEADER_MAGIC) {
157             return CS_ERR_BLOCK_MAGIC;
158         }
159         if (header->version != CSB_HEADER_VERSION) {
160             return CS_ERR_BLOCK_VERSION;
161         }
162         if ((header->segmentNum > CSB_SEGMENT_MAX) || (header->segmentNum == 0)) {
163             return CS_ERR_BLOCK_SEG_NUM;
164         }
165         if (header->blockSize != blockSize) {
166             return CS_ERR_BLOCK_SIZE;
167         }
168         blockHeader_ = header;
169         return CS_SUCCESS;
170     }
171 
SetFsVerityInfo(const FsVerityInfo * info)172     int32_t SetFsVerityInfo(const FsVerityInfo *info)
173     {
174         if (info->magic != CSB_FSVERITY_MAGIC) {
175             return CS_ERR_FSVERITY_MAGIC;
176         }
177         if (info->version != 1) {
178             return CS_ERR_FSVERITY_VERSION;
179         }
180         if (info->logBlockSize != CSB_FSVERITY_BLOCK_SIZE) {
181             return CS_ERR_FSVERITY_BLOCK_SIZE;
182         }
183         fsVerityInfo_ = info;
184         return CS_SUCCESS;
185     }
186 
SetHapSignInfo(const HapSignInfo * info)187     int32_t SetHapSignInfo(const HapSignInfo *info)
188     {
189         if (info->magic != CSB_HAP_HEADER_MAGIC) {
190             return CS_ERR_HAP_MAGIC;
191         }
192         const auto signInfo = &info->signInfo;
193         if (blockHeader_->flags & CSB_HEADER_FLAG_MERKLE_TREE) {
194             if (signInfo->extensionOffset >= blockHeader_->blockSize) {
195                 return CS_ERR_HAP_EXTERNSION;
196             }
197         }
198         hapSignInfo_ = info;
199         return CS_SUCCESS;
200     }
201 
SetNativeLibSignInfo(const NativeLibSignInfo * info)202     int32_t SetNativeLibSignInfo(const NativeLibSignInfo *info)
203     {
204         if (info->magic != CSB_SO_HEADER_MAGIC) {
205             return CS_ERR_SO_MAGIC;
206         }
207         if ((blockHeader_->flags & CSB_HEADER_FLAG_SO) && !info->sectionNum) {
208             return CS_ERR_SO_SECTION_NUM;
209         }
210         nativeLibSignInfo_ = info;
211         return CS_SUCCESS;
212     }
213 
GetOneMapNodeFromSignMap(std::string & fileName,uintptr_t & signInfo)214     int32_t GetOneMapNodeFromSignMap(std::string &fileName, uintptr_t &signInfo)
215     {
216         std::lock_guard<std::mutex> guard(signMapMutex_);
217         if (signMap_.empty()) {
218             return CS_SUCCESS_END;
219         }
220 
221         auto info = signMap_.begin();
222         fileName = info->first;
223         signInfo = info->second;
224         signMap_.erase(fileName);
225         return CS_SUCCESS;
226     }
227 
228     Verify::SignatureInfo signatureInfo_;
229     const CodeSignBlockHeader *blockHeader_ = nullptr;
230     const FsVerityInfo *fsVerityInfo_ = nullptr;
231     const HapSignInfo *hapSignInfo_ = nullptr;
232     const NativeLibSignInfo *nativeLibSignInfo_ = nullptr;
233     std::mutex signMapMutex_;
234     SignMap signMap_;
235 };
236 } // CodeSign namespace
237 } // Security namespace
238 } // OHOS namespace
239 #endif
240