1 /*
2 * Copyright (c) 2024 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 #include "pac_sign_ctx.h"
17
18 #include <memory>
19 #include "errcode.h"
20 #include "log.h"
21 #include "random_helper.h"
22
23 namespace OHOS {
24 namespace Security {
25 namespace CodeSign {
26
27 constexpr uint64_t SIGN_WITH_CONTEXT_PREFIX = 0x2LL << 60;
28 constexpr uint64_t SIGN_WITHOUT_CONTEXT_PREFIX = 0x3LL << 60;
29 constexpr uint64_t AUTH_CONTEXT_PREFIX = 0x1LL << 60;
30 constexpr uint32_t HIGH_BITS_RIGHT_SHIFT = 32;
31
PACDB(uint64_t value,uint64_t modifier)32 static inline uint64_t PACDB(uint64_t value, uint64_t modifier)
33 {
34 #ifdef ARCH_PAC_SUPPORT
35 asm volatile("pacdb %0, %1" : "+r"(value) : "r"(modifier) :);
36 #endif
37 return value;
38 }
39
AUTDB(uint64_t value,uint64_t modifier)40 static inline uint64_t AUTDB(uint64_t value, uint64_t modifier)
41 {
42 #ifdef ARCH_PAC_SUPPORT
43 asm volatile("autdb %0, %1" : "+r"(value) : "r"(modifier) :);
44 #endif
45 return value;
46 }
47
PACGA(uint64_t value,uint64_t modifier)48 static inline uint32_t PACGA(uint64_t value, uint64_t modifier)
49 {
50 #ifdef ARCH_PAC_SUPPORT
51 uint64_t ret = 0;
52 asm volatile("pacga %0, %1, %2" : "=r"(ret) : "r"(value), "r"(modifier) :);
53 #else
54 uint64_t ret = value;
55 #endif
56 return static_cast<uint32_t>(ret >> HIGH_BITS_RIGHT_SHIFT);
57 }
58
PACSignCtx(CTXPurpose purpose,uint32_t salt)59 PACSignCtx::PACSignCtx(CTXPurpose purpose, uint32_t salt)
60 : context_(0), salt_(salt), index_(0), purpose_(purpose) {}
61
~PACSignCtx()62 PACSignCtx::~PACSignCtx() {}
63
InitSalt()64 void PACSignCtx::InitSalt()
65 {
66 static RandomHelper randomHelper;
67 uint32_t random = 0;
68 if (randomHelper.GetUint32(random) != CS_SUCCESS) {
69 LOG_ERROR("Init salt failed.");
70 int tmpAddr = 0;
71 // use random address as salt
72 random = static_cast<uint32_t>(
73 reinterpret_cast<uintptr_t>(&tmpAddr));
74 }
75 salt_ = random;
76 }
77
Init(int index)78 void PACSignCtx::Init(int index)
79 {
80 index_ = index;
81 SetContext(GetSalt());
82 }
83
PaddingContext(ContextType type,int index)84 uint64_t PACSignCtx::PaddingContext(ContextType type, int index)
85 {
86 uint32_t context;
87 uint64_t prefix;
88 switch (type) {
89 case SIGN_WITH_CONTEXT:
90 context = context_;
91 prefix = SIGN_WITH_CONTEXT_PREFIX;
92 index = index_;
93 break;
94 case SIGN_WITHOUT_CONTEXT:
95 context = GetSalt();
96 prefix = SIGN_WITHOUT_CONTEXT_PREFIX;
97 break;
98 case AUTH_CONTEXT:
99 context = GetSalt();
100 index = index_;
101 prefix = AUTH_CONTEXT_PREFIX;
102 break;
103 default:
104 return CS_ERR_UNSUPPORT;
105 }
106 #if defined(JIT_CODE_SIGN_DEBUGGABLE) && defined(JIT_FORT_DISABLE)
107 LOG_INFO("Padding prefix = %{public}lx, index = %{public}x, context = %{public}x",
108 prefix, index_, context);
109 #endif
110 uint64_t ret = prefix | ((static_cast<uint64_t>(index) & 0xfffffff) << 32) | context;
111 return ret;
112 }
113
SetContext(uint32_t context)114 void PACSignCtx::SetContext(uint32_t context)
115 {
116 if (purpose_ == CTXPurpose::VERIFY) {
117 context_ = context;
118 return;
119 }
120 uint64_t paddingContext = PaddingContext(AUTH_CONTEXT);
121 context_ = PACDB(context, paddingContext);
122 }
123
GetRealContext()124 uint64_t PACSignCtx::GetRealContext()
125 {
126 uint64_t paddingContext = PaddingContext(AUTH_CONTEXT);
127 return AUTDB(context_, paddingContext);
128 }
129
SignWithContext(uint32_t value)130 uint32_t PACSignCtx::SignWithContext(uint32_t value)
131 {
132 uint64_t paddingContext = PaddingContext(SIGN_WITH_CONTEXT);
133 return PACGA(value, paddingContext);
134 }
135
Update(uint32_t value)136 uint32_t PACSignCtx::Update(uint32_t value)
137 {
138 #if defined(JIT_CODE_SIGN_DEBUGGABLE) && defined(JIT_FORT_DISABLE)
139 LOG_INFO("Before update context = %{public}lx", context_);
140 #endif
141 if (purpose_ == CTXPurpose::SIGN) {
142 context_ = GetRealContext();
143 }
144 index_ += 1;
145 uint32_t signature = SignWithContext(value);
146 SetContext(signature);
147 #if defined(JIT_CODE_SIGN_DEBUGGABLE) && defined(JIT_FORT_DISABLE)
148 LOG_INFO("After update context = %{public}lx, signature = %{public}x",
149 context_, signature);
150 #endif
151 return signature;
152 }
153
SignSingle(uint32_t value,uint32_t index)154 uint32_t PACSignCtx::SignSingle(uint32_t value, uint32_t index)
155 {
156 uint64_t paddingContext = PaddingContext(SIGN_WITHOUT_CONTEXT, index);
157 uint32_t signature = PACGA(value, paddingContext);
158 #if defined(JIT_CODE_SIGN_DEBUGGABLE) && defined(JIT_FORT_DISABLE)
159 LOG_INFO("Get signature = %{public}x", signature);
160 #endif
161 return signature;
162 }
163
GetSalt()164 uint32_t PACSignCtx::GetSalt()
165 {
166 return salt_;
167 }
168 }
169 }
170 }