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_single.h"
17
18 #include <sstream>
19 #include "errcode.h"
20 #include "log.h"
21
22 namespace OHOS {
23 namespace Security {
24 namespace CodeSign {
25
JitCodeSignerSingle()26 JitCodeSignerSingle::JitCodeSignerSingle()
27 {
28 Reset();
29 }
30
Reset()31 void JitCodeSignerSingle::Reset()
32 {
33 tmpBuffer_ = nullptr;
34 ctx_.InitSalt();
35 ctx_.Init(0);
36 signTable_.clear();
37 offset_ = 0;
38 }
39
SignInstruction(Instr insn)40 void JitCodeSignerSingle::SignInstruction(Instr insn)
41 {
42 int index = GetIndexFromOffset(offset_);
43 #ifdef JIT_CODE_SIGN_DEBUGGABLE
44 LOG_INFO("Offset = %{public}x, insn = %{public}x", offset_, insn);
45 if (static_cast<size_t>(index) != signTable_.size()) {
46 LOG_ERROR("Index = %{public}d not equal signtable size = %{public}zu.",
47 GetIndexFromOffset(offset_), signTable_.size());
48 }
49 #endif
50 signTable_.push_back(ctx_.SignSingle(insn, index));
51 offset_ += INSTRUCTION_SIZE;
52 }
53
SkipNext(uint32_t n)54 void JitCodeSignerSingle::SkipNext(uint32_t n) {}
55
PatchInstruction(int offset,Instr insn)56 int32_t JitCodeSignerSingle::PatchInstruction(int offset, Instr insn)
57 {
58 #ifdef JIT_CODE_SIGN_DEBUGGABLE
59 LOG_INFO("offset = %{public}x, insn = %{public}x", offset, insn);
60 #endif
61 int curIndex = 0;
62 if (!ConvertPatchOffsetToIndex(offset, curIndex)) {
63 LOG_ERROR("Offset invalid");
64 return CS_ERR_PATCH_INVALID;
65 }
66 uint32_t signature = ctx_.SignSingle(insn, curIndex);
67 signTable_[curIndex] = signature;
68 return CS_SUCCESS;
69 }
70
ValidateCodeCopy(Instr * jitMemory,Byte * tmpBuffer,int size)71 int32_t JitCodeSignerSingle::ValidateCodeCopy(Instr *jitMemory,
72 Byte *tmpBuffer, int size)
73 {
74 int32_t ret = CheckDataCopy(jitMemory, tmpBuffer, size);
75 if (ret != CS_SUCCESS) {
76 return ret;
77 }
78
79 PACSignCtx verifyCtx(CTXPurpose::VERIFY, ctx_.GetSalt());
80 int offset = 0;
81 while (offset < size) {
82 int index = GetIndexFromOffset(offset);
83 Instr insn = *reinterpret_cast<const Instr *>(tmpBuffer_ + offset);
84 uint32_t signature = verifyCtx.SignSingle(insn, index);
85 if (signature != signTable_[index]) {
86 #ifdef JIT_FORT_DISABLE
87 LOG_ERROR("validate insn(%{public}x) without context failed at index = " \
88 "%{public}x, signature(%{public}x) != wanted(%{public}x)",
89 insn, index * INSTRUCTION_SIZE, signature, signTable_[index]);
90 #endif
91 #ifndef JIT_CODE_SIGN_PERMISSIVE
92 return CS_ERR_VALIDATE_CODE;
93 #endif
94 }
95 *(jitMemory + index) = insn;
96 offset += INSTRUCTION_SIZE;
97 }
98 return CS_SUCCESS;
99 }
100 }
101 }
102 }