1b1994897Sopenharmony_ci/** 2b1994897Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 3b1994897Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4b1994897Sopenharmony_ci * you may not use this file except in compliance with the License. 5b1994897Sopenharmony_ci * You may obtain a copy of the License at 6b1994897Sopenharmony_ci * 7b1994897Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8b1994897Sopenharmony_ci * 9b1994897Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10b1994897Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11b1994897Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12b1994897Sopenharmony_ci * See the License for the specific language governing permissions and 13b1994897Sopenharmony_ci * limitations under the License. 14b1994897Sopenharmony_ci */ 15b1994897Sopenharmony_ci 16b1994897Sopenharmony_ci#ifndef LIBPANDAFILE_DATA_PROTECT_H 17b1994897Sopenharmony_ci#define LIBPANDAFILE_DATA_PROTECT_H 18b1994897Sopenharmony_ci 19b1994897Sopenharmony_ci#include <cstdint> 20b1994897Sopenharmony_ci#include <string> 21b1994897Sopenharmony_ci#include <string_view> 22b1994897Sopenharmony_ci#include <vector> 23b1994897Sopenharmony_ci 24b1994897Sopenharmony_ci#if defined(PANDA_ENABLE_DATA_PROTECT) 25b1994897Sopenharmony_ci#include <sys/auxv.h> 26b1994897Sopenharmony_ci#include <asm/hwcap.h> 27b1994897Sopenharmony_ci#endif 28b1994897Sopenharmony_ci 29b1994897Sopenharmony_cinamespace panda::panda_file { 30b1994897Sopenharmony_ci 31b1994897Sopenharmony_ciclass DataProtect { 32b1994897Sopenharmony_cipublic: 33b1994897Sopenharmony_ci DataProtect() : protect_pointer_(0) {} 34b1994897Sopenharmony_ci explicit DataProtect(const uintptr_t pointer) 35b1994897Sopenharmony_ci { 36b1994897Sopenharmony_ci if (pointer == 0) { 37b1994897Sopenharmony_ci protect_pointer_ = 0; 38b1994897Sopenharmony_ci return; 39b1994897Sopenharmony_ci } 40b1994897Sopenharmony_ci protect_pointer_ = DataProtectPac(pointer, reinterpret_cast<uintptr_t>(&protect_pointer_)); 41b1994897Sopenharmony_ci } 42b1994897Sopenharmony_ci 43b1994897Sopenharmony_ci ~DataProtect() = default; 44b1994897Sopenharmony_ci 45b1994897Sopenharmony_ci static inline uintptr_t DataProtectAut(const uintptr_t pointer, [[maybe_unused]]const uintptr_t address) 46b1994897Sopenharmony_ci { 47b1994897Sopenharmony_ci#if defined(PANDA_ENABLE_DATA_PROTECT) 48b1994897Sopenharmony_ci uint64_t hwcaps = getauxval(AT_HWCAP); 49b1994897Sopenharmony_ci if (!(hwcaps & HWCAP_PACA) || !(hwcaps & HWCAP_PACG)) { 50b1994897Sopenharmony_ci return pointer; 51b1994897Sopenharmony_ci } 52b1994897Sopenharmony_ci void *t1 = reinterpret_cast<void*>(pointer); 53b1994897Sopenharmony_ci void *t2 = reinterpret_cast<void*>(address); 54b1994897Sopenharmony_ci#ifdef PAC_DFI_PTR_BKEY 55b1994897Sopenharmony_ci __asm__ __volatile__("autdb %0, %1":"+r"(t1):"r"(t2):); 56b1994897Sopenharmony_ci#else 57b1994897Sopenharmony_ci __asm__ __volatile__("autda %0, %1":"+r"(t1):"r"(t2):); 58b1994897Sopenharmony_ci#endif 59b1994897Sopenharmony_ci return reinterpret_cast<uintptr_t>(t1); 60b1994897Sopenharmony_ci#else 61b1994897Sopenharmony_ci return pointer; 62b1994897Sopenharmony_ci#endif 63b1994897Sopenharmony_ci } 64b1994897Sopenharmony_ci 65b1994897Sopenharmony_ci static inline uintptr_t DataProtectPac(const uintptr_t pointer, [[maybe_unused]]const uintptr_t address) 66b1994897Sopenharmony_ci { 67b1994897Sopenharmony_ci#if defined(PANDA_ENABLE_DATA_PROTECT) 68b1994897Sopenharmony_ci uint64_t hwcaps = getauxval(AT_HWCAP); 69b1994897Sopenharmony_ci if (!(hwcaps & HWCAP_PACA) || !(hwcaps & HWCAP_PACG)) { 70b1994897Sopenharmony_ci return pointer; 71b1994897Sopenharmony_ci } 72b1994897Sopenharmony_ci void *t1 = reinterpret_cast<void*>(pointer); 73b1994897Sopenharmony_ci void *t2 = reinterpret_cast<void*>(address); 74b1994897Sopenharmony_ci#ifdef PAC_DFI_PTR_BKEY 75b1994897Sopenharmony_ci __asm__ __volatile__("pacdb %0, %1":"+r"(t1):"r"(t2):); 76b1994897Sopenharmony_ci#else 77b1994897Sopenharmony_ci __asm__ __volatile__("pacda %0, %1":"+r"(t1):"r"(t2):); 78b1994897Sopenharmony_ci#endif 79b1994897Sopenharmony_ci return reinterpret_cast<uintptr_t>(t1); 80b1994897Sopenharmony_ci#else 81b1994897Sopenharmony_ci return pointer; 82b1994897Sopenharmony_ci#endif 83b1994897Sopenharmony_ci } 84b1994897Sopenharmony_ci 85b1994897Sopenharmony_ci void Update(const uintptr_t pointer) 86b1994897Sopenharmony_ci { 87b1994897Sopenharmony_ci if (pointer == 0) { 88b1994897Sopenharmony_ci protect_pointer_ = 0; 89b1994897Sopenharmony_ci return; 90b1994897Sopenharmony_ci } 91b1994897Sopenharmony_ci protect_pointer_ = DataProtectPac(pointer, reinterpret_cast<uintptr_t>(&protect_pointer_)); 92b1994897Sopenharmony_ci } 93b1994897Sopenharmony_ci 94b1994897Sopenharmony_ci uintptr_t GetOriginPointer() const 95b1994897Sopenharmony_ci { 96b1994897Sopenharmony_ci if (protect_pointer_ == 0) { 97b1994897Sopenharmony_ci return protect_pointer_; 98b1994897Sopenharmony_ci } 99b1994897Sopenharmony_ci return DataProtectAut(protect_pointer_, reinterpret_cast<uintptr_t>(&protect_pointer_)); 100b1994897Sopenharmony_ci } 101b1994897Sopenharmony_ci 102b1994897Sopenharmony_ciprivate: 103b1994897Sopenharmony_ci uintptr_t protect_pointer_; 104b1994897Sopenharmony_ci}; 105b1994897Sopenharmony_ci 106b1994897Sopenharmony_ciclass BoolPacProtect { 107b1994897Sopenharmony_cipublic: 108b1994897Sopenharmony_ci enum PacBoolean : uintptr_t { 109b1994897Sopenharmony_ci PAC_FALSE = 1, 110b1994897Sopenharmony_ci PAC_TRUE = 2, 111b1994897Sopenharmony_ci }; 112b1994897Sopenharmony_ci 113b1994897Sopenharmony_ci BoolPacProtect() 114b1994897Sopenharmony_ci { 115b1994897Sopenharmony_ci Update(false); 116b1994897Sopenharmony_ci } 117b1994897Sopenharmony_ci 118b1994897Sopenharmony_ci explicit BoolPacProtect(const bool flag) 119b1994897Sopenharmony_ci { 120b1994897Sopenharmony_ci Update(flag); 121b1994897Sopenharmony_ci } 122b1994897Sopenharmony_ci 123b1994897Sopenharmony_ci void Update(const bool flag) 124b1994897Sopenharmony_ci { 125b1994897Sopenharmony_ci protect_bool_ = DataProtect::DataProtectPac(flag ? PAC_TRUE : PAC_FALSE, 126b1994897Sopenharmony_ci reinterpret_cast<uintptr_t>(&protect_bool_)); 127b1994897Sopenharmony_ci } 128b1994897Sopenharmony_ci 129b1994897Sopenharmony_ci bool GetBool() const 130b1994897Sopenharmony_ci { 131b1994897Sopenharmony_ci auto value = DataProtect::DataProtectAut(protect_bool_, reinterpret_cast<uintptr_t>(&protect_bool_)); 132b1994897Sopenharmony_ci return value == PAC_TRUE ? true : false; 133b1994897Sopenharmony_ci } 134b1994897Sopenharmony_ci 135b1994897Sopenharmony_ciprivate: 136b1994897Sopenharmony_ci uintptr_t protect_bool_; 137b1994897Sopenharmony_ci}; 138b1994897Sopenharmony_ci 139b1994897Sopenharmony_ciclass StringPacProtect { 140b1994897Sopenharmony_cipublic: 141b1994897Sopenharmony_ci 142b1994897Sopenharmony_ci enum Shift : uint8_t { 143b1994897Sopenharmony_ci SHIFT8 = 8, 144b1994897Sopenharmony_ci SHIFT16 = 16, 145b1994897Sopenharmony_ci SHIFT24 = 24, 146b1994897Sopenharmony_ci SHIFT32 = 32 147b1994897Sopenharmony_ci }; 148b1994897Sopenharmony_ci 149b1994897Sopenharmony_ci StringPacProtect() : data_(std::vector<uintptr_t>()), origin_length_(0) {} 150b1994897Sopenharmony_ci 151b1994897Sopenharmony_ci explicit StringPacProtect(std::string_view str_data) 152b1994897Sopenharmony_ci { 153b1994897Sopenharmony_ci Update(str_data); 154b1994897Sopenharmony_ci } 155b1994897Sopenharmony_ci 156b1994897Sopenharmony_ci ~StringPacProtect() 157b1994897Sopenharmony_ci { 158b1994897Sopenharmony_ci Clear(); 159b1994897Sopenharmony_ci } 160b1994897Sopenharmony_ci 161b1994897Sopenharmony_ci // replace data with pac(str_data) 162b1994897Sopenharmony_ci void Update(std::string_view str_data) 163b1994897Sopenharmony_ci { 164b1994897Sopenharmony_ci Clear(); 165b1994897Sopenharmony_ci AppendWithoutCheckBack(str_data); 166b1994897Sopenharmony_ci } 167b1994897Sopenharmony_ci 168b1994897Sopenharmony_ci void Append(char ch) 169b1994897Sopenharmony_ci { 170b1994897Sopenharmony_ci constexpr uint32_t step = 4; 171b1994897Sopenharmony_ci if (origin_length_ % step > 0) { 172b1994897Sopenharmony_ci // Filling back empty 173b1994897Sopenharmony_ci uint32_t empty_count = step - (origin_length_ % step); 174b1994897Sopenharmony_ci auto last_data = DataProtect::DataProtectAut(data_.back(), reinterpret_cast<uintptr_t>(&data_)); 175b1994897Sopenharmony_ci data_.pop_back(); 176b1994897Sopenharmony_ci uint8_t shift = (SHIFT8 * (empty_count - 1)); 177b1994897Sopenharmony_ci last_data |= static_cast<uintptr_t>(ch) << shift; 178b1994897Sopenharmony_ci data_.push_back(DataProtect::DataProtectPac(last_data, reinterpret_cast<uintptr_t>(&data_))); 179b1994897Sopenharmony_ci } else { 180b1994897Sopenharmony_ci uintptr_t temp_data = uintptr_t(ch); 181b1994897Sopenharmony_ci temp_data <<= SHIFT24; 182b1994897Sopenharmony_ci data_.push_back(DataProtect::DataProtectPac(temp_data, reinterpret_cast<uintptr_t>(&data_))); 183b1994897Sopenharmony_ci } 184b1994897Sopenharmony_ci origin_length_++; 185b1994897Sopenharmony_ci } 186b1994897Sopenharmony_ci 187b1994897Sopenharmony_ci // data += pac(str_data) 188b1994897Sopenharmony_ci void Append(std::string_view str_data) 189b1994897Sopenharmony_ci { 190b1994897Sopenharmony_ci if (str_data.empty()) { 191b1994897Sopenharmony_ci return; 192b1994897Sopenharmony_ci } 193b1994897Sopenharmony_ci constexpr uint32_t step = 4; 194b1994897Sopenharmony_ci 195b1994897Sopenharmony_ci auto str = reinterpret_cast<const uint8_t *>(str_data.data()); 196b1994897Sopenharmony_ci auto len = str_data.length(); 197b1994897Sopenharmony_ci if (origin_length_ % step != 0) { 198b1994897Sopenharmony_ci // Filling back empty 199b1994897Sopenharmony_ci uint32_t iter = 0; 200b1994897Sopenharmony_ci uint32_t empty_count = step - (origin_length_ % step); 201b1994897Sopenharmony_ci auto last_data = DataProtect::DataProtectAut(data_.back(), reinterpret_cast<uintptr_t>(&data_)); 202b1994897Sopenharmony_ci data_.pop_back(); 203b1994897Sopenharmony_ci 204b1994897Sopenharmony_ci last_data >>= SHIFT8 * empty_count; 205b1994897Sopenharmony_ci while (iter < empty_count) { 206b1994897Sopenharmony_ci last_data <<= SHIFT8; 207b1994897Sopenharmony_ci last_data += (iter < len ? str[iter] : 0); 208b1994897Sopenharmony_ci iter++; 209b1994897Sopenharmony_ci } 210b1994897Sopenharmony_ci data_.push_back(DataProtect::DataProtectPac(last_data, reinterpret_cast<uintptr_t>(&data_))); 211b1994897Sopenharmony_ci origin_length_ += (empty_count < len ? empty_count : len); 212b1994897Sopenharmony_ci if (empty_count < len) { 213b1994897Sopenharmony_ci AppendWithoutCheckBack(str_data.substr(empty_count)); 214b1994897Sopenharmony_ci } 215b1994897Sopenharmony_ci } else { 216b1994897Sopenharmony_ci AppendWithoutCheckBack(str_data); 217b1994897Sopenharmony_ci } 218b1994897Sopenharmony_ci } 219b1994897Sopenharmony_ci 220b1994897Sopenharmony_ci // return string(aut(data)) 221b1994897Sopenharmony_ci std::string GetOriginString() const 222b1994897Sopenharmony_ci { 223b1994897Sopenharmony_ci if (data_.empty()) { 224b1994897Sopenharmony_ci return ""; 225b1994897Sopenharmony_ci } 226b1994897Sopenharmony_ci 227b1994897Sopenharmony_ci std::string res = ""; 228b1994897Sopenharmony_ci constexpr uintptr_t mask = 0xff000000; 229b1994897Sopenharmony_ci for (uint32_t iter = 0; iter < data_.size(); ++iter) { 230b1994897Sopenharmony_ci uintptr_t temp_data = DataProtect::DataProtectAut(data_[iter], reinterpret_cast<uintptr_t>(&data_)); 231b1994897Sopenharmony_ci res.push_back(char((temp_data & mask) >> SHIFT24)); 232b1994897Sopenharmony_ci temp_data <<= SHIFT8; 233b1994897Sopenharmony_ci res.push_back(char((temp_data & mask) >> SHIFT24)); 234b1994897Sopenharmony_ci temp_data <<= SHIFT8; 235b1994897Sopenharmony_ci res.push_back(char((temp_data & mask) >> SHIFT24)); 236b1994897Sopenharmony_ci temp_data <<= SHIFT8; 237b1994897Sopenharmony_ci res.push_back(char((temp_data & mask) >> SHIFT24)); 238b1994897Sopenharmony_ci } 239b1994897Sopenharmony_ci 240b1994897Sopenharmony_ci // delete back empty 241b1994897Sopenharmony_ci while (res.size() > origin_length_) { 242b1994897Sopenharmony_ci res.pop_back(); 243b1994897Sopenharmony_ci } 244b1994897Sopenharmony_ci 245b1994897Sopenharmony_ci return res; 246b1994897Sopenharmony_ci } 247b1994897Sopenharmony_ci 248b1994897Sopenharmony_ci bool CompareStringWithPacedString(std::string_view str_data) 249b1994897Sopenharmony_ci { 250b1994897Sopenharmony_ci uint32_t len = str_data.length(); 251b1994897Sopenharmony_ci constexpr uint32_t step = 4; 252b1994897Sopenharmony_ci if (len != origin_length_) { 253b1994897Sopenharmony_ci return false; 254b1994897Sopenharmony_ci } 255b1994897Sopenharmony_ci auto str = reinterpret_cast<const uint8_t *>(str_data.data()); 256b1994897Sopenharmony_ci 257b1994897Sopenharmony_ci auto data_ptr = data_.begin(); 258b1994897Sopenharmony_ci uint32_t left = 0; 259b1994897Sopenharmony_ci while (left < len) { 260b1994897Sopenharmony_ci uint32_t right = left + step; 261b1994897Sopenharmony_ci uintptr_t temp_data = 0; 262b1994897Sopenharmony_ci 263b1994897Sopenharmony_ci while (left < right) { 264b1994897Sopenharmony_ci temp_data <<= SHIFT8; 265b1994897Sopenharmony_ci temp_data += (left < len ? str[left] : 0); 266b1994897Sopenharmony_ci ++left; 267b1994897Sopenharmony_ci } 268b1994897Sopenharmony_ci auto res = DataProtect::DataProtectPac(temp_data, reinterpret_cast<uintptr_t>(&data_)); 269b1994897Sopenharmony_ci if (res != *data_ptr) { 270b1994897Sopenharmony_ci return false; 271b1994897Sopenharmony_ci } 272b1994897Sopenharmony_ci ++data_ptr; 273b1994897Sopenharmony_ci } 274b1994897Sopenharmony_ci return true; 275b1994897Sopenharmony_ci } 276b1994897Sopenharmony_ci 277b1994897Sopenharmony_ci void Clear() 278b1994897Sopenharmony_ci { 279b1994897Sopenharmony_ci std::vector<uintptr_t>().swap(data_); 280b1994897Sopenharmony_ci origin_length_ = 0; 281b1994897Sopenharmony_ci } 282b1994897Sopenharmony_ci 283b1994897Sopenharmony_ci // PacDataSize = ceil(StrLength / 4) 284b1994897Sopenharmony_ci uint32_t PacDataSize() 285b1994897Sopenharmony_ci { 286b1994897Sopenharmony_ci return data_.size(); 287b1994897Sopenharmony_ci } 288b1994897Sopenharmony_ci 289b1994897Sopenharmony_ci // Original String Length Before Pac 290b1994897Sopenharmony_ci uint32_t StrLength() 291b1994897Sopenharmony_ci { 292b1994897Sopenharmony_ci return origin_length_; 293b1994897Sopenharmony_ci } 294b1994897Sopenharmony_ci 295b1994897Sopenharmony_ciprivate: 296b1994897Sopenharmony_ci 297b1994897Sopenharmony_ci void AppendWithoutCheckBack(std::string_view str_data) 298b1994897Sopenharmony_ci { 299b1994897Sopenharmony_ci if (str_data.empty()) { 300b1994897Sopenharmony_ci return; 301b1994897Sopenharmony_ci } 302b1994897Sopenharmony_ci auto str = reinterpret_cast<const uint8_t *>(str_data.data()); 303b1994897Sopenharmony_ci uint32_t len = str_data.length(); 304b1994897Sopenharmony_ci 305b1994897Sopenharmony_ci constexpr uint32_t step = 4; 306b1994897Sopenharmony_ci uint32_t left = 0; 307b1994897Sopenharmony_ci // uint32 = char << 24 | char << 16 | char << 8 | char 308b1994897Sopenharmony_ci // compress 4 char => 1 uint32 => PAC(uint32) => uintptr_t 309b1994897Sopenharmony_ci while (left < len) { 310b1994897Sopenharmony_ci uint32_t right = left + step; 311b1994897Sopenharmony_ci uintptr_t temp_data = 0; 312b1994897Sopenharmony_ci 313b1994897Sopenharmony_ci while (left < right) { 314b1994897Sopenharmony_ci temp_data <<= SHIFT8; 315b1994897Sopenharmony_ci temp_data += (left < len ? str[left] : 0); 316b1994897Sopenharmony_ci ++left; 317b1994897Sopenharmony_ci } 318b1994897Sopenharmony_ci data_.push_back(DataProtect::DataProtectPac(temp_data, reinterpret_cast<uintptr_t>(&data_))); 319b1994897Sopenharmony_ci } 320b1994897Sopenharmony_ci origin_length_ += str_data.length(); 321b1994897Sopenharmony_ci } 322b1994897Sopenharmony_ci 323b1994897Sopenharmony_ci std::vector<uintptr_t>data_; 324b1994897Sopenharmony_ci uint32_t origin_length_; 325b1994897Sopenharmony_ci}; 326b1994897Sopenharmony_ci 327b1994897Sopenharmony_ci} 328b1994897Sopenharmony_ci#endif // LIBPANDAFILE_DATA_PROTECT_H 329