1 /*
2 * Copyright (c) 2022 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 "device_security_level_callback_helper.h"
17
18 #include <cstdint>
19 #include <functional>
20 #include <map>
21 #include <new>
22 #include <utility>
23
24 #include "hilog/log_cpp.h"
25 #include "idevice_security_level.h"
26 #include "timer.h"
27
28 #include "device_security_info.h"
29 #include "device_security_level_callback_stub.h"
30 #include "device_security_level_defines.h"
31
32 namespace OHOS {
33 namespace Security {
34 namespace DeviceSecurityLevel {
35 using namespace OHOS::HiviewDFX;
36
37 constexpr char TIMER_NAME[] = "DSLM_CALL_TIMER";
38 constexpr uint32_t KEEP_COMPENSATION_LEN = 5;
39 constexpr uint32_t MAX_CALLBACKS_NUM = 128;
40
DeviceSecurityLevelCallbackHelper()41 DeviceSecurityLevelCallbackHelper::DeviceSecurityLevelCallbackHelper()
42 {
43 auto request = [this](uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) {
44 return this->OnRemoteRequest(code, data, reply, option);
45 };
46 stub_ = new (std::nothrow) DeviceSecurityLevelCallbackStub(request);
47 }
48
~DeviceSecurityLevelCallbackHelper()49 DeviceSecurityLevelCallbackHelper::~DeviceSecurityLevelCallbackHelper()
50 {
51 stub_ = nullptr;
52 }
53
Publish(const DeviceIdentify & identity,const ResultCallback & callback,uint32_t keep,sptr<DeviceSecurityLevelCallbackStub> & stub,uint32_t & cookie)54 bool DeviceSecurityLevelCallbackHelper::Publish(const DeviceIdentify &identity, const ResultCallback &callback,
55 uint32_t keep, sptr<DeviceSecurityLevelCallbackStub> &stub, uint32_t &cookie)
56 {
57 if (stub_ == nullptr) {
58 return false;
59 }
60
61 auto result = holder_.PushCallback(identity, callback, keep, cookie);
62 if (!result) {
63 HILOG_ERROR(LOG_CORE, "DeviceSecurityLevelCallbackHelper::PushCallback failed");
64 return false;
65 }
66
67 stub = stub_;
68 return true;
69 }
70
Withdraw(uint32_t cookie)71 bool DeviceSecurityLevelCallbackHelper::Withdraw(uint32_t cookie)
72 {
73 if (cookie == 0) {
74 return false;
75 }
76
77 auto result = holder_.PopCallback(cookie);
78 if (!result) {
79 HILOG_ERROR(LOG_CORE, "DeviceSecurityLevelCallbackHelper::withdraw failed");
80 return false;
81 }
82 return true;
83 }
84
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)85 int32_t DeviceSecurityLevelCallbackHelper::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply,
86 MessageOption &option)
87 {
88 if (code == DeviceSecurityLevelCallbackStub::CMD_SET_DEVICE_SECURITY_LEVEL) {
89 auto cookie = data.ReadUint32();
90 auto result = data.ReadUint32();
91 auto level = data.ReadUint32();
92 HILOG_INFO(LOG_CORE, "callback cookie %{public}u, result %{public}u, level %{public}u", cookie, result, level);
93 holder_.PopCallback(cookie, result, level);
94 }
95
96 return SUCCESS;
97 }
98
CallbackInfoHolder()99 DeviceSecurityLevelCallbackHelper::CallbackInfoHolder::CallbackInfoHolder() : timer_(TIMER_NAME)
100 {
101 timer_.Setup();
102 }
103
~CallbackInfoHolder()104 DeviceSecurityLevelCallbackHelper::CallbackInfoHolder::~CallbackInfoHolder()
105 {
106 timer_.Shutdown();
107 }
108
PushCallback(const DeviceIdentify & identity,const ResultCallback & callback,uint32_t keep,uint32_t & cookie)109 bool DeviceSecurityLevelCallbackHelper::CallbackInfoHolder::PushCallback(const DeviceIdentify &identity,
110 const ResultCallback &callback, uint32_t keep, uint32_t &cookie)
111 {
112 std::lock_guard<std::mutex> lock(mutex_);
113 if (map_.size() > MAX_CALLBACKS_NUM) {
114 HILOG_ERROR(LOG_CORE, "DeviceSecurityLevelCallbackHelper::PushCallback reached max");
115 return false;
116 }
117
118 cookie = ++generate_;
119 CallbackInfo info = {.identity = identity, .callback = callback, .cookie = cookie};
120 auto result = map_.emplace(generate_, info);
121 if (result.second) {
122 auto deleter = [cookie, this]() { PopCallback(cookie, ERR_TIMEOUT, 0); };
123 keep += KEEP_COMPENSATION_LEN;
124 timer_.Register(deleter, keep * 1000, true); // 1000 millisec
125 }
126 return result.second;
127 }
128
PopCallback(uint32_t cookie,uint32_t result,uint32_t level)129 bool DeviceSecurityLevelCallbackHelper::CallbackInfoHolder::PopCallback(uint32_t cookie, uint32_t result,
130 uint32_t level)
131 {
132 DeviceIdentify identity;
133 ResultCallback callback;
134 {
135 std::lock_guard<std::mutex> lock(mutex_);
136 auto iter = map_.find(cookie);
137 if (iter == map_.end()) {
138 return false;
139 }
140 identity = iter->second.identity;
141 callback = iter->second.callback;
142 map_.erase(iter);
143 }
144
145 if (callback != nullptr) {
146 DeviceSecurityInfo *info = new (std::nothrow) DeviceSecurityInfo();
147 if (info != nullptr) {
148 info->magicNum = SECURITY_MAGIC;
149 info->result = result;
150 info->level = level;
151 }
152 callback(&identity, info);
153 }
154
155 return true;
156 }
PopCallback(uint32_t cookie)157 bool DeviceSecurityLevelCallbackHelper::CallbackInfoHolder::PopCallback(uint32_t cookie)
158 {
159 std::lock_guard<std::mutex> lock(mutex_);
160 auto iter = map_.find(cookie);
161 if (iter == map_.end()) {
162 return false;
163 }
164 map_.erase(iter);
165 return true;
166 }
167 } // namespace DeviceSecurityLevel
168 } // namespace Security
169 } // namespace OHOS
170