1 /*
2 * Copyright (c) 2025-2025 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 "hks_ha_plugin.h"
17
18 #include <cstring>
19
20 #include "securec.h"
21 #include "hks_ha_event_queue.h"
22 #include "hks_mem.h"
23 #include "hks_log.h"
24 #include "hks_plugin_adapter.h"
25 #include "hks_plugin_def.h"
26 #include "hks_template.h"
27 #include "hks_report_generate_key.h"
28 #include "hks_report_import_key.h"
29 #include "hks_report_delete_key.h"
30 #include "hks_report_check_key_exited.h"
31 #include "hks_report_rename_key.h"
32 #include "hks_report_three_stage.h"
33 #include "hks_report_list_aliases.h"
34 #include "hks_report_data_size.h"
35 #include "hks_report_three_stage_build.h"
36 #include "hks_param.h"
37
38 static HksEventProcMap g_eventProcMap[] = {
39 {
40 HKS_EVENT_CRYPTO,
41 HksParamSetToEventInfoCrypto,
42 HksEventInfoNeedReportCrypto,
43 HksEventInfoIsEqualCrypto,
44 HksEventInfoAddCrypto,
45 HksEventInfoToMapCrypto,
46 },
47 {
48 HKS_EVENT_SIGN_VERIFY,
49 HksParamSetToEventInfoCrypto,
50 HksEventInfoNeedReportCrypto,
51 HksEventInfoIsEqualCrypto,
52 HksEventInfoAddCrypto,
53 HksEventInfoToMapCrypto,
54 },
55 {
56 HKS_EVENT_DERIVE,
57 HksParamSetToEventInfoAgreeDerive,
58 HksEventInfoNeedReportAgreeDerive,
59 HksEventInfoIsEqualAgreeDerive,
60 HksEventInfoAddAgreeDerive,
61 HksEventInfoToMapAgreeDerive,
62 },
63 {
64 HKS_EVENT_AGREE,
65 HksParamSetToEventInfoAgreeDerive,
66 HksEventInfoNeedReportAgreeDerive,
67 HksEventInfoIsEqualAgreeDerive,
68 HksEventInfoAddAgreeDerive,
69 HksEventInfoToMapAgreeDerive,
70 },
71 {
72 HKS_EVENT_MAC,
73 HksParamSetToEventInfoMac,
74 HksEventInfoNeedReportMac,
75 HksEventInfoIsEqualMac,
76 HksEventInfoAddMac,
77 HksEventInfoToMapMac,
78 },
79 {
80 HKS_EVENT_ATTEST,
81 HksParamSetToEventInfoAttest,
82 HksEventInfoNeedReportAttest,
83 HksEventInfoIsEqualAttest,
84 HksEventInfoAddAttest,
85 HksEventInfoToMapAttest,
86 },
87 {
88 HKS_EVENT_GENERATE_KEY,
89 HksParamSetToEventInfoForKeyGen,
90 HksEventInfoIsNeedReportForKeyGen,
91 HksEventInfoIsEqualForKeyGen,
92 HksEventInfoAddForKeyGen,
93 HksEventInfoToMapForKeyGen
94 },
95 {
96 HKS_EVENT_IMPORT_KEY,
97 HksParamSetToEventInfoForImport,
98 HksEventInfoIsNeedReportForImport,
99 HksEventInfoIsEqualForImport,
100 HksEventInfoAddForImport,
101 HksEventInfoToMapForImport,
102 },
103 {
104 HKS_EVENT_DELETE_KEY,
105 HksParamSetToEventInfoForDelete,
106 HksEventInfoIsNeedReportForDelete,
107 HksEventInfoIsEqualForDelete,
108 HksEventInfoAddForDelete,
109 HksEventInfoToMapForDelete
110 },
111 {
112 HKS_EVENT_CHECK_KEY_EXISTED,
113 HksParamSetToEventInfoForCheckKeyExited,
114 HksEventInfoIsNeedReportForCheckKeyExited,
115 HksEventInfoIsEqualForCheckKeyExited,
116 HksEventInfoAddForCheckKeyExited,
117 HksEventInfoToMapForCheckKeyExited
118 },
119 {
120 HKS_EVENT_RENAME_KEY,
121 HksParamSetToEventInfoForRename,
122 HksEventInfoIsNeedReportForRename,
123 HksEventInfoIsEqualForRename,
124 HksEventInfoAddForRename,
125 HksEventInfoToMapForRename
126 },
127 {
128 HKS_EVENT_LIST_ALIASES,
129 HksParamSetToEventInfoForListAliases,
130 HksEventInfoIsNeedReportForListAliases,
131 HksEventInfoIsEqualForListAliases,
132 HksEventInfoAddForListAliases,
133 HksEventInfoToMapForListAliases
134 },
135 {
136 HKS_EVENT_DATA_SIZE_STATISTICS,
137 HksParamSetToEventInfoForDataSize,
138 HksEventInfoIsNeedReportForDataSize,
139 HksEventInfoIsEqualForDataSize,
140 HksEventInfoAddForDataSize,
141 HksEventInfoToMapForDataSize
142 }
143 };
144
HksHaPlugin()145 HksHaPlugin::HksHaPlugin() : queue(), stopFlag(false)
146 {}
147
~HksHaPlugin()148 HksHaPlugin::~HksHaPlugin()
149 {
150 Destroy();
151 }
152
Destroy()153 void HksHaPlugin::Destroy()
154 {
155 queue.Stop();
156
157 StopWorkerThread();
158
159 eventCacheList.RemoveFront(eventCacheList.GetSize());
160 }
161
StartWorkerThread()162 void HksHaPlugin::StartWorkerThread()
163 {
164 workerThread = std::thread(&HksHaPlugin::WorkerThread, this);
165 }
166
StopWorkerThread()167 void HksHaPlugin::StopWorkerThread()
168 {
169 stopFlag = true;
170 }
171
Enqueue(uint32_t eventId,struct HksParamSet * paramSet)172 bool HksHaPlugin::Enqueue(uint32_t eventId, struct HksParamSet *paramSet)
173 {
174 return queue.Enqueue(eventId, paramSet);
175 }
176
HksEventProcFind(uint32_t eventId)177 HksEventProcMap *HksHaPlugin::HksEventProcFind(uint32_t eventId)
178 {
179 for (uint32_t i = 0; i < HKS_ARRAY_SIZE(g_eventProcMap); ++i) {
180 HKS_IF_TRUE_RETURN(g_eventProcMap[i].eventId == eventId, &g_eventProcMap[i])
181 }
182 return nullptr;
183 }
184
HandlerReport(HksEventQueueItem & item)185 void HksHaPlugin::HandlerReport(HksEventQueueItem &item)
186 {
187 HKS_IF_NULL_LOGE_RETURN_VOID(item.paramSet, "HandlerReport: paramSet is"
188 "null for eventId %" LOG_PUBLIC "u", item.eventId);
189
190 uint32_t eventId = item.eventId;
191 auto procMap = HksEventProcFind(eventId);
192 HKS_IF_NULL_LOGE_RETURN_VOID(procMap, "HandlerReport: Event ID %" LOG_PUBLIC "u not found in"
193 "the eventProcMap", eventId);
194
195 struct HksEventInfo *eventInfo = (struct HksEventInfo *)HksMalloc(sizeof(struct HksEventInfo));
196 HKS_IF_NULL_LOGE_RETURN_VOID(eventInfo, "Failed to allocate HksEventInfo");
197
198 int32_t ret = procMap->eventInfoCreate(item.paramSet, eventInfo);
199 if (ret != HKS_SUCCESS) {
200 HKS_LOG_E("Failed to create HksEventInfo for eventId %" LOG_PUBLIC "u", eventId);
201 HKS_FREE(eventInfo);
202 return;
203 }
204
205 bool needReport = procMap->needReport(eventInfo);
206 HKS_IF_NOT_TRUE_RETURN(needReport, HandleStatisticEvent(eventInfo, eventId, procMap))
207
208 std::unordered_map<std::string, std::string> eventMap;
209 ret = procMap->eventInfoToMap(eventInfo, eventMap);
210 HKS_IF_NOT_SUCC_LOGE(ret, "Failed to convert HksEventInfo to map"
211 "for eventId %" LOG_PUBLIC "u", eventId);
212 HandleFaultEvent(&eventInfo->common, eventMap);
213
214 HksFreeEventInfo(&eventInfo);
215 HKS_FREE(eventInfo);
216 }
217
WorkerThread()218 void HksHaPlugin::WorkerThread()
219 {
220 while (!stopFlag) {
221 HksEventQueueItem item;
222 bool success = queue.Dequeue(item);
223 if (!success) {
224 continue;
225 }
226
227 HandlerReport(item);
228 HksFreeParamSet(&item.paramSet);
229 }
230 }
231
HandleFaultEvent(HksEventCommonInfo * commonInfo,std::unordered_map<std::string,std::string> & eventMap)232 void HksHaPlugin::HandleFaultEvent(
233 HksEventCommonInfo *commonInfo, std::unordered_map<std::string, std::string> &eventMap)
234 {
235 int32_t ret = HksPluginOnLocalRequest(CODE_FAULT_METRICS, commonInfo, &eventMap);
236 HKS_IF_NOT_SUCC_LOGE_RETURN_VOID(ret, "Failed to call OnSingleEventRequest: error code %" LOG_PUBLIC "d", ret);
237 }
238
GetCurrentTimestamp()239 static uint32_t GetCurrentTimestamp()
240 {
241 return static_cast<uint32_t>(time(nullptr));
242 }
243
HandleStatisticEvent(struct HksEventInfo * eventInfo,uint32_t eventId,HksEventProcMap * procMap)244 void HksHaPlugin::HandleStatisticEvent(struct HksEventInfo *eventInfo, uint32_t eventId, HksEventProcMap *procMap)
245 {
246 HKS_IF_NULL_LOGE_RETURN_VOID(eventInfo, "HandleStatisticEvent: Invalid eventInfo parameters");
247 HKS_IF_NULL_LOGE_RETURN_VOID(procMap, "HandleStatisticEvent: Invalid procMap parameters");
248
249 bool found = eventCacheList.FindAndUpdate(eventInfo, procMap);
250 if (!found) {
251 AddEventCache(eventId, eventInfo);
252 } else {
253 HksFreeEventInfo(&eventInfo);
254 HKS_FREE(eventInfo);
255 }
256
257 uint32_t currentSize = eventCacheList.GetSize();
258 HKS_IF_TRUE_RETURN_VOID(currentSize <= 0)
259
260 HKS_IF_TRUE_RETURN_VOID(eventCacheList.cacheList.empty())
261 const HksEventCacheNode &firstNode = eventCacheList.cacheList.front();
262 uint32_t reportCount = 0;
263 time_t currentTime = GetCurrentTimestamp();
264
265 HKS_IF_TRUE_RETURN_VOID((currentTime - firstNode.timestamp) <= MAX_CACHE_DURATION && currentSize < MAX_CACHE_SIZE)
266 reportCount = currentSize;
267 HKS_LOG_I("HksHaPlugin::HandleStatisticEvent:reportCount is %" LOG_PUBLIC "u", reportCount);
268 BatchReportEvents(reportCount);
269 }
270
AddEventCache(uint32_t eventId,struct HksEventInfo * eventInfo)271 void HksHaPlugin::AddEventCache(uint32_t eventId, struct HksEventInfo *eventInfo)
272 {
273 HksEventCacheNode newNode{eventId, GetCurrentTimestamp(), eventInfo};
274 eventCacheList.Add(newNode);
275 }
276
FillEventInfos(uint32_t reportCount,HksEventWithMap * eventsWithMap)277 int32_t HksHaPlugin::FillEventInfos(uint32_t reportCount, HksEventWithMap *eventsWithMap)
278 {
279 uint32_t count = 0;
280
281 for (auto it = eventCacheList.cacheList.begin(); it != eventCacheList.cacheList.end() && count < reportCount;
282 ++it) {
283 if (it->data) {
284 struct HksEventInfo *eventInfo = it->data;
285 eventsWithMap[count].common = eventInfo->common;
286
287 HksEventProcMap *procMap = HksEventProcFind(eventsWithMap[count].common.eventId);
288 HKS_IF_NULL_LOGI_RETURN(procMap, HKS_ERROR_NULL_POINTER, "procMap is null");
289
290 int32_t ret = procMap->eventInfoToMap(eventInfo, eventsWithMap[count].eventMap);
291 if (ret != HKS_SUCCESS) {
292 HKS_LOG_E("FillEventInfos: Failed to convert HksEventInfo to map for eventId %" LOG_PUBLIC "u",
293 eventsWithMap[count].common.eventId);
294 continue;
295 }
296 }
297 ++count;
298 }
299
300 return HKS_SUCCESS;
301 }
302
CallBatchReport(uint32_t reportCount,HksEventWithMap * eventsWithMap)303 int32_t HksHaPlugin::CallBatchReport(uint32_t reportCount, HksEventWithMap *eventsWithMap)
304 {
305 int32_t ret = HksPluginOnLocalRequest(CODE_STATISTICS_METRICS, (const void *)eventsWithMap, (void *)&reportCount);
306 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, HKS_ERROR_BAD_STATE, "CallBatchReport: HksHaPlugin_OnBatchEventRequest failed,"
307 "error code: %" LOG_PUBLIC "d", ret);
308
309 return HKS_SUCCESS;
310 }
311
RemoveReportedEvents(uint32_t reportCount)312 void HksHaPlugin::RemoveReportedEvents(uint32_t reportCount)
313 {
314 eventCacheList.RemoveFront(reportCount);
315 }
316
BatchReportEvents(uint32_t reportCount)317 int32_t HksHaPlugin::BatchReportEvents(uint32_t reportCount)
318 {
319 HKS_IF_TRUE_LOGI_RETURN(reportCount > eventCacheList.GetSize(), HKS_ERROR_INVALID_ARGUMENT,
320 "HksHaPlugin::BatchReportEvents:reportCount > queueSize")
321 HksEventWithMap *eventsWithMap = new (std::nothrow) HksEventWithMap[reportCount];
322 HKS_IF_NULL_LOGI_RETURN(eventsWithMap, HKS_ERROR_NULL_POINTER, "eventsWithMap is null");
323
324 int32_t ret = HKS_SUCCESS;
325 do {
326 ret = FillEventInfos(reportCount, eventsWithMap);
327 HKS_IF_NOT_SUCC_LOGI_BREAK(ret, "HksHaPlugin::BatchReportEvents:FillEventInfos fail");
328 ret = CallBatchReport(reportCount, eventsWithMap);
329 HKS_IF_NOT_SUCC_LOGI_BREAK(ret, "HksHaPlugin::BatchReportEvents:CallBatchReport fail");
330 } while (0);
331
332 RemoveReportedEvents(reportCount);
333 delete[] eventsWithMap;
334
335 return HKS_SUCCESS;
336 }
337
HksHaPluginInit(void)338 int32_t HksHaPluginInit(void)
339 {
340 HksHaPlugin::GetInstance().StartWorkerThread();
341 return HKS_SUCCESS;
342 }
343
HksHaPluginDestroy()344 void HksHaPluginDestroy()
345 {
346 HksHaPlugin::GetInstance().Destroy();
347 }