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 }