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 "jit_code_signer_base.h"
17
18 #include <sstream>
19 #include "errcode.h"
20 #include "log.h"
21
22 namespace OHOS {
23 namespace Security {
24 namespace CodeSign {
25
26 constexpr int32_t BYTE_BIT_SIZE = 8;
27 constexpr uint32_t UNALIGNMENT_MASK = 0x3;
28
GetOneInstrForQueue(std::queue<Byte> & queue)29 inline static Instr GetOneInstrForQueue(std::queue<Byte> &queue)
30 {
31 Instr insn = 0;
32 int i = 0;
33 while ((i < INSTRUCTION_SIZE) && !queue.empty()) {
34 insn |= (queue.front() << (BYTE_BIT_SIZE * i));
35 queue.pop();
36 i++;
37 }
38 return insn;
39 }
40
RegisterTmpBuffer(Byte * tmpBuffer)41 void JitCodeSignerBase::RegisterTmpBuffer(Byte *tmpBuffer)
42 {
43 tmpBuffer_ = tmpBuffer;
44 }
45
SignData(const Byte * const data,uint32_t size)46 int32_t JitCodeSignerBase::SignData(const Byte *const data, uint32_t size)
47 {
48 if (data == nullptr) {
49 return CS_ERR_INVALID_DATA;
50 }
51 uint32_t cur = 0;
52 size_t unsignedSize = willSign_.size();
53 if ((unsignedSize == 0) && (size >= INSTRUCTION_SIZE)) {
54 auto insnPtr = reinterpret_cast<const Instr *const>(data);
55 while (cur + INSTRUCTION_SIZE <= size) {
56 SignInstruction(*insnPtr);
57 insnPtr++;
58 cur += INSTRUCTION_SIZE;
59 }
60 }
61
62 if (cur == size) {
63 return CS_SUCCESS;
64 }
65 unsignedSize += size - cur;
66 while (cur < size) {
67 willSign_.push(*(data + cur));
68 cur++;
69 }
70
71 while (unsignedSize >= INSTRUCTION_SIZE) {
72 Instr insn = GetOneInstrForQueue(willSign_);
73 SignInstruction(insn);
74 unsignedSize -= INSTRUCTION_SIZE;
75 }
76 return CS_SUCCESS;
77 }
78
PatchInstruction(Byte * buffer,Instr insn)79 int32_t JitCodeSignerBase::PatchInstruction(Byte *buffer, Instr insn)
80 {
81 if ((buffer == nullptr) || (tmpBuffer_ == nullptr)) {
82 return CS_ERR_PATCH_INVALID;
83 }
84 return PatchInstruction(static_cast<int>(buffer - tmpBuffer_), insn);
85 }
86
PatchData(int offset,const Byte * const data,uint32_t size)87 int32_t JitCodeSignerBase::PatchData(int offset, const Byte *const data, uint32_t size)
88 {
89 if (size & UNALIGNMENT_MASK) {
90 return CS_ERR_JIT_SIGN_SIZE;
91 }
92 if (data == nullptr) {
93 return CS_ERR_INVALID_DATA;
94 }
95 auto insnPtr = reinterpret_cast<const Instr *const>(data);
96 for (uint32_t i = 0; i < size; i += INSTRUCTION_SIZE) {
97 int ret = PatchInstruction(offset + i, *insnPtr);
98 if (ret != CS_SUCCESS) {
99 return ret;
100 }
101 insnPtr += 1;
102 }
103 return CS_SUCCESS;
104 }
105
PatchData(Byte * buffer,const Byte * const data,uint32_t size)106 int32_t JitCodeSignerBase::PatchData(Byte *buffer, const Byte *const data, uint32_t size)
107 {
108 if ((buffer == nullptr) || (tmpBuffer_ == nullptr)) {
109 return CS_ERR_PATCH_INVALID;
110 }
111 return PatchData(static_cast<int>(buffer - tmpBuffer_), data, size);
112 }
113
ConvertPatchOffsetToIndex(const int offset,int & curIndex)114 bool JitCodeSignerBase::ConvertPatchOffsetToIndex(const int offset, int &curIndex)
115 {
116 if ((offset < 0) || ((static_cast<uint32_t>(offset) & UNALIGNMENT_MASK) != 0)) {
117 return false;
118 }
119 curIndex = GetIndexFromOffset(offset);
120 if (static_cast<size_t>(curIndex) >= signTable_.size()) {
121 LOG_ERROR("Offset is out of range, index = %{public}d, signTable size = %{public}zu",
122 curIndex, signTable_.size());
123 return false;
124 }
125 return true;
126 }
127
CheckDataCopy(Instr * jitMemory,Byte * tmpBuffer,int size)128 int32_t JitCodeSignerBase::CheckDataCopy(Instr *jitMemory, Byte *tmpBuffer, int size)
129 {
130 if (jitMemory == nullptr) {
131 return CS_ERR_JIT_MEMORY;
132 }
133 if (tmpBuffer == nullptr) {
134 return CS_ERR_TMP_BUFFER;
135 }
136
137 // update tmp buffer
138 tmpBuffer_ = tmpBuffer;
139
140 if (((static_cast<uint32_t>(size) & UNALIGNMENT_MASK) != 0) ||
141 (static_cast<uint32_t>(size) > signTable_.size() * INSTRUCTION_SIZE)) {
142 #ifdef JIT_FORT_DISABLE
143 LOG_ERROR("Range invalid, size = %{public}d, table size = %{public}zu",
144 size, signTable_.size());
145 #endif
146 return CS_ERR_JIT_SIGN_SIZE;
147 }
148 return CS_SUCCESS;
149 }
150 }
151 }
152 }