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 30namespace OHOS { 31namespace Security { 32namespace CodeSign { 33 34#pragma pack(push, 1) 35typedef struct { 36 uint32_t type; 37 uint32_t size; 38 uint32_t offset; 39} PropertyBlobHeader; 40 41typedef 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 50typedef struct { 51 uint32_t type; 52 uint32_t offset; 53 uint32_t size; 54} SegmentHeader; 55 56typedef 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 64typedef struct { 65 uint32_t type; 66 uint32_t size; 67} ExtensionHeader; 68 69typedef struct { 70 uint64_t treeSize; 71 uint64_t treeOffset; 72 uint8_t rootHash[64]; 73} MerkleTreeExtension; 74 75typedef 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 84typedef 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 95typedef struct { 96 uint32_t magic; 97 SignInfo signInfo; 98} HapSignInfo; 99 100typedef struct { 101 uint32_t fileNameOffset; 102 uint32_t fileNameSize; 103 uint32_t signOffset; 104 uint32_t signSize; 105} EntryInfo; 106 107typedef struct { 108 uint32_t magic; 109 uint32_t length; 110 uint32_t sectionNum; 111 EntryInfo info[0]; 112} NativeLibSignInfo; 113#pragma pack(pop) 114 115using SignMap = std::unordered_map<std::string, uintptr_t>; 116using ReadBuffer = const char *; 117#define CONST_STATIC_CAST(type, ptr) static_cast<const type *>(static_cast<const void *>(ptr)) 118 119class CodeSignBlock { 120public: 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); 137 int32_t ProcessExtension(uintptr_t &extensionAddr, const uintptr_t blockAddrEnd, struct code_sign_enable_arg &arg); 138 139private: 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 154 const CodeSignBlockHeader *GetCodeSignBlockHeader(void) 155 { 156 return blockHeader_; 157 } 158 const FsVerityInfo *GetFsVerityInfo(void) 159 { 160 return fsVerityInfo_; 161 } 162 const HapSignInfo *GetHapSignInfo(void) 163 { 164 return hapSignInfo_; 165 } 166 const NativeLibSignInfo *GetNativeLibSignInfo(void) 167 { 168 return nativeLibSignInfo_; 169 } 170 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 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 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 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 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