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