1 /*
2  * Copyright (c) 2023 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 "code_signature_analysis_kit.h"
17 #include <pthread.h>
18 #include <stdint.h>
19 #include <securec.h>
20 
21 ModelManagerApi *g_securityGuardFunc = NULL;
22 ModelApi *g_modelFunc = NULL;
23 RetListener g_retListener = NULL;
24 AppRiskInfo *g_modelDataHead = NULL;
25 uint32_t g_riskAppCount = 0;
26 pthread_mutex_t g_modelVisitLock;
27 #define MAX_RISK_APP_COUNT (1024 * 100)
28 
FindExistingNode(uint32_t tokenId)29 static AppRiskInfo *FindExistingNode(uint32_t tokenId)
30 {
31     AppRiskInfo *node = g_modelDataHead->next;
32     while (node != NULL) {
33         if (node->tokenId == tokenId) {
34             break;
35         } else {
36             node = node->next;
37         }
38     }
39     return node;
40 }
41 
IsRiskStatusChanged(AppRiskInfo * node)42 static int32_t IsRiskStatusChanged(AppRiskInfo *node)
43 {
44     int64_t totalCount = 0;
45     int32_t eventCount = 0;
46     RiskPolicyType policy = node->status.policy;
47 
48     for (int32_t i = 0; i < CODE_SIGNATURE_ERROR_TYPE_SIZE; i++) {
49         TimeStampNode *tmp = ((node->errInfoList)[i]).timeStampChain;
50         totalCount += tmp->timeStamp.timeStampCount;
51         eventCount += (tmp->timeStamp.timeStampCount != 0) ? 1 : 0;
52     }
53     node->status.eventCount = eventCount;
54     node->status.totalCount = totalCount;
55     if ((totalCount > MAX_CODE_SIGNATURE_ERROR_NUM) || (eventCount == CODE_SIGNATURE_ERROR_TYPE_SIZE)) {
56         node->status.policy = LOG_REPORT;
57     } else {
58         node->status.policy = NO_SECURITY_RISK;
59     }
60 
61     int32_t isChanged = (node->status.policy != policy) ? STATUS_CHANGED : STATUS_NOT_CHANGED;
62     if ((node->status.policy == NO_SECURITY_RISK) && (policy != NO_SECURITY_RISK)) {
63         if (g_riskAppCount > 0) {
64             g_riskAppCount--;
65         }
66         MODEL_LOG_INFO("[%s]:g_riskAppCount reduced.", __func__);
67     } else if ((node->status.policy != NO_SECURITY_RISK) && (policy == NO_SECURITY_RISK)) {
68         if (g_riskAppCount < MAX_RISK_APP_COUNT) {
69             g_riskAppCount++;
70         }
71         MODEL_LOG_INFO("[%s]:g_riskAppCount added.", __func__);
72     }
73     return isChanged;
74 }
75 
DataPreProcess(const CodeSignatureReportedInfo * report,AppRiskInfo * node,uint32_t optType)76 static int32_t DataPreProcess(const CodeSignatureReportedInfo *report,
77                               AppRiskInfo *node,
78                               uint32_t optType)
79 {
80     TimeStampNode *head = ((node->errInfoList)[report->errorType]).timeStampChain;
81     if (optType == OUT_OF_STORAGE_LIFE) {
82         TimeStampNode *tmpNode = head->next;
83         TimeStampNode *tmpNodePrev = head;
84         while ((tmpNode != NULL) && (tmpNode->timeStamp.timeStampMs > report->timeStampMs)) {
85             tmpNode = tmpNode->next;
86             tmpNodePrev = tmpNodePrev->next;
87         }
88         tmpNodePrev->next = NULL;
89         // Delete all the event timestamps which are out of storage life.
90         while (tmpNode != NULL) {
91             TimeStampNode *deleted = tmpNode;
92             tmpNode = tmpNode->next;
93             free(deleted);
94             deleted = NULL;
95             head->timeStamp.timeStampCount--;
96         }
97         return OPER_SUCCESS;
98     }
99 
100     // Insert the newest report timestamp in the chain head.
101     if (optType == EVENT_REPORTED) {
102         TimeStampNode *tmp = NULL;
103         tmp = (TimeStampNode *)malloc(sizeof(TimeStampNode));
104         if (tmp == NULL) {
105             MODEL_LOG_ERROR("[%s]:malloc failed.", __func__);
106             return MEMORY_OPER_FAILED;
107         }
108         (void)memset_s(tmp, sizeof(TimeStampNode), 0, sizeof(TimeStampNode));
109         tmp->timeStamp.timeStampMs = report->timeStampMs;
110         tmp->next = head->next;
111         head->next = tmp;
112         head->timeStamp.timeStampCount++;
113     }
114     return OPER_SUCCESS;
115 }
116 
AppRiskInfoNodeInit(void)117 static AppRiskInfo *AppRiskInfoNodeInit(void)
118 {
119     AppRiskInfo *node = (AppRiskInfo *)malloc(sizeof(AppRiskInfo));
120     if (node == NULL) {
121         MODEL_LOG_ERROR("[%s]:malloc failed.", __func__);
122         return NULL;
123     }
124     (void)memset_s(node, sizeof(AppRiskInfo), 0, sizeof(AppRiskInfo));
125 
126     TimeStampNode *tmp = NULL;
127     tmp = (TimeStampNode *)malloc(sizeof(TimeStampNode) * CODE_SIGNATURE_ERROR_TYPE_SIZE);
128     if (tmp == NULL) {
129         MODEL_LOG_ERROR("[%s]:malloc failed.", __func__);
130         free(node);
131         return NULL;
132     }
133     (void)memset_s(tmp, sizeof(TimeStampNode) * CODE_SIGNATURE_ERROR_TYPE_SIZE,
134                    0, sizeof(TimeStampNode) * CODE_SIGNATURE_ERROR_TYPE_SIZE);
135 
136     for (int32_t i = 0; i < CODE_SIGNATURE_ERROR_TYPE_SIZE; i++) {
137         tmp[i].next = NULL;
138         tmp[i].timeStamp.timeStampCount = 0;
139         (node->errInfoList[i]).timeStampChain = &(tmp[i]);
140     }
141     node->status.eventCount = 0;
142     node->status.totalCount = 0;
143     node->status.policy = NO_SECURITY_RISK;
144     node->next = g_modelDataHead->next;
145     g_modelDataHead->next = node;
146     return node;
147 }
148 
ReleaseTimeStampChain(AppRiskInfo * node)149 static void ReleaseTimeStampChain(AppRiskInfo *node)
150 {
151     for (int32_t i = 0; i < CODE_SIGNATURE_ERROR_TYPE_SIZE; i++) {
152         TimeStampNode *head = (node->errInfoList[i]).timeStampChain->next;
153         while (head != NULL) {
154             TimeStampNode *tmp = head->next;
155             free(head);
156             head = tmp;
157         }
158     }
159     // Free timeStampChain head for each error type. They was allocated together.
160     free(node->errInfoList[0].timeStampChain);
161     return;
162 }
163 
SetResultInfoAccordingToNode(NotifyRiskResultInfo * result,AppRiskInfo * node)164 static void SetResultInfoAccordingToNode(NotifyRiskResultInfo *result, AppRiskInfo *node)
165 {
166     result->eventId = APPLICATION_RISK_EVENT_ID;
167     result->tokenId = node->tokenId;
168     result->policy = node->status.policy;
169 }
170 
UpdateInfoInCurrNode(const CodeSignatureReportedInfo * report,AppRiskInfo * node,uint32_t optType)171 static int32_t UpdateInfoInCurrNode(const CodeSignatureReportedInfo *report, AppRiskInfo *node, uint32_t optType)
172 {
173     int32_t res = DataPreProcess(report, node, optType);
174     if (res != OPER_SUCCESS) {
175         return res;
176     }
177     res = IsRiskStatusChanged(node);
178     if (g_riskAppCount >= MAX_RISK_APP_COUNT) {
179         return RISK_APP_NUM_EXCEEDED;
180     }
181     if (res == STATUS_NOT_CHANGED) {
182         return OPER_SUCCESS;
183     }
184     if (g_retListener == NULL) {
185         return OPER_SUCCESS;
186     }
187     /* Notify the SG db about APPLICATION_RISK_EVENT_ID change */
188     NotifyRiskResultInfo *result = (NotifyRiskResultInfo *)malloc(sizeof(NotifyRiskResultInfo));
189     if (result == NULL) {
190         MODEL_LOG_ERROR("[%s]:malloc failed.", __func__);
191         return MEMORY_OPER_FAILED;
192     }
193     (void)memset_s(result, sizeof(NotifyRiskResultInfo), 0, sizeof(NotifyRiskResultInfo));
194     SetResultInfoAccordingToNode(result, node);
195 
196     // Notify the change.
197     g_retListener((uint8_t *)result, sizeof(NotifyRiskResultInfo));
198     free(result);
199     return OPER_SUCCESS;
200 }
201 
AddNewAppInfoNode(const CodeSignatureReportedInfo * report,uint32_t optType)202 static int32_t AddNewAppInfoNode(const CodeSignatureReportedInfo *report, uint32_t optType)
203 {
204     AppRiskInfo *node = AppRiskInfoNodeInit();
205     if (node == NULL) {
206         return MEMORY_OPER_FAILED;
207     }
208 
209     node->tokenId = report->tokenId;
210     int32_t res = strcpy_s(node->bundleName, MAX_BUNDLE_NAME_LENGTH - 1, report->bundleName);
211     if (res != OPER_SUCCESS) {
212         MODEL_LOG_ERROR("[%s]:strcpy_s failed errno %d.", __func__, errno);
213         ReleaseTimeStampChain(node);
214         free(node);
215         return res;
216     }
217 
218     res = DataPreProcess(report, node, optType);
219     if (res != OPER_SUCCESS) {
220         ReleaseTimeStampChain(node);
221         free(node);
222         return res;
223     }
224 
225     (void)IsRiskStatusChanged(node);
226     return OPER_SUCCESS;
227 }
228 
DataProcess(const CodeSignatureReportedInfo * report,uint32_t optType)229 static int32_t DataProcess(const CodeSignatureReportedInfo *report, uint32_t optType)
230 {
231     if (report->tokenId == INVALID_TOKEN_ID) {
232         MODEL_LOG_ERROR("[%s]:tokenId is invalid.", __func__);
233         return INPUT_TOKEN_ID_INVALID;
234     }
235     if (report->errorType >= CODE_SIGNATURE_ERROR_TYPE_BUFF) {
236         MODEL_LOG_ERROR("[%s]:errorType %d is invalid.", __func__, report->errorType);
237         return INPUT_EVENT_TYPE_INVALID;
238     }
239     if (optType >= DATA_CHANGE_TYPE_BUFF) {
240         MODEL_LOG_ERROR("[%s]:optType %u is invalid.", __func__, optType);
241         return INPUT_OPER_TYPE_INVALID;
242     }
243 
244     (void)pthread_mutex_lock(&g_modelVisitLock);
245     if (g_modelDataHead == NULL) {
246         MODEL_LOG_ERROR("[%s]:model is released.", __func__);
247         (void)pthread_mutex_unlock(&g_modelVisitLock);
248         return MODEL_INIT_NOT_COMPLETED;
249     }
250     AppRiskInfo *node = FindExistingNode(report->tokenId);
251     if (node != NULL) {
252         int32_t res = UpdateInfoInCurrNode(report, node, optType);
253         (void)pthread_mutex_unlock(&g_modelVisitLock);
254         return res;
255     }
256 
257     // The deleted data is not in model cache already.
258     if (optType == OUT_OF_STORAGE_LIFE) {
259         (void)pthread_mutex_unlock(&g_modelVisitLock);
260         return OPER_SUCCESS;
261     }
262 
263     int32_t res = AddNewAppInfoNode(report, optType);
264     (void)pthread_mutex_unlock(&g_modelVisitLock);
265 
266     return res;
267 }
268 
DatabaseListener(uint32_t optType,uint8_t * result,uint32_t resultLen)269 static void DatabaseListener(uint32_t optType, uint8_t *result, uint32_t resultLen)
270 {
271     if ((result == NULL) || (resultLen != sizeof(CodeSignatureReportedInfo))) {
272         MODEL_LOG_ERROR("[%s]:ResultLen %u.", __func__, resultLen);
273         return;
274     }
275 
276     CodeSignatureReportedInfo *report = (CodeSignatureReportedInfo *)result;
277     int32_t res = DataProcess(report, optType);
278     if (res != OPER_SUCCESS) {
279         MODEL_LOG_ERROR("[%s]:DataProcess failed. Res %d.", __func__, res);
280     }
281     return;
282 }
283 
Init(ModelManagerApi * api)284 int32_t Init(ModelManagerApi *api)
285 {
286     if (api == NULL) {
287         MODEL_LOG_ERROR("[%s]:Input api func is null.", __func__);
288         return INPUT_POINT_NULL;
289     }
290 
291     (void)pthread_mutex_lock(&g_modelVisitLock);
292     if (g_modelDataHead != NULL) {
293         MODEL_LOG_ERROR("[%s]:Init has been completed already.", __func__);
294         (void)pthread_mutex_unlock(&g_modelVisitLock);
295         return INIT_OPER_REPEAT;
296     }
297     g_securityGuardFunc = api;
298 
299     g_modelDataHead = (AppRiskInfo *)malloc(sizeof(AppRiskInfo));
300     if (g_modelDataHead == NULL) {
301         MODEL_LOG_ERROR("[%s]:malloc failed.", __func__);
302         (void)pthread_mutex_unlock(&g_modelVisitLock);
303         return MEMORY_OPER_FAILED;
304     }
305     (void)memset_s(g_modelDataHead, sizeof(AppRiskInfo), 0, sizeof(AppRiskInfo));
306     g_modelDataHead->next = NULL;
307 
308     // Set the func where to subscribe the db change.
309     int64_t csErrEventId = CODE_SIGNATURE_ERROR_EVENT_ID;
310     uint32_t eventIdLen = 1;
311     g_securityGuardFunc->subscribeDb(&csErrEventId, eventIdLen, DatabaseListener);
312 
313     (void)pthread_mutex_unlock(&g_modelVisitLock);
314     return OPER_SUCCESS;
315 }
316 
Release(void)317 void Release(void)
318 {
319     (void)pthread_mutex_lock(&g_modelVisitLock);
320     if (g_modelDataHead == NULL) {
321         MODEL_LOG_ERROR("[%s]:Model has been release already.", __func__);
322         (void)pthread_mutex_unlock(&g_modelVisitLock);
323         return;
324     }
325 
326     while (g_modelDataHead->next != NULL) {
327         AppRiskInfo *node = g_modelDataHead->next;
328         g_modelDataHead->next = node->next;
329         ReleaseTimeStampChain(node);
330         free(node);
331     }
332     free(g_modelDataHead);
333     g_modelDataHead = NULL;
334     g_retListener = NULL;
335     g_securityGuardFunc = NULL;
336     g_riskAppCount = 0;
337 
338     (void)pthread_mutex_unlock(&g_modelVisitLock);
339     return;
340 }
341 
GetResult(uint8_t * result,uint32_t * resultLen)342 int32_t GetResult(uint8_t *result, uint32_t *resultLen)
343 {
344     if (result == NULL) {
345         return INPUT_POINT_NULL;
346     }
347 
348     (void)pthread_mutex_lock(&g_modelVisitLock);
349     if (g_modelDataHead == NULL) {
350         (void)pthread_mutex_unlock(&g_modelVisitLock);
351         return MODEL_INIT_NOT_COMPLETED;
352     }
353 
354     unsigned long long neededLen = g_riskAppCount * sizeof(NotifyRiskResultInfo);
355     if (*resultLen < neededLen) {
356         MODEL_LOG_ERROR("[%s]:ResultLen %u is smaller than needed %llu", __func__, *resultLen, neededLen);
357         (void)pthread_mutex_unlock(&g_modelVisitLock);
358         return SHORT_OF_MEMORY;
359     }
360     if (neededLen == 0) {
361         *resultLen = 0;
362         (void)pthread_mutex_unlock(&g_modelVisitLock);
363         return OPER_SUCCESS;
364     }
365 
366     NotifyRiskResultInfo *data = (NotifyRiskResultInfo *)malloc(neededLen);
367     if (data == NULL) {
368         (void)pthread_mutex_unlock(&g_modelVisitLock);
369         return SHORT_OF_MEMORY;
370     }
371     AppRiskInfo *node = g_modelDataHead->next;
372     uint32_t index = 0;
373     while (node != NULL) {
374         if (index == g_riskAppCount) {
375             break;
376         }
377         if (node->status.policy > NO_SECURITY_RISK) {
378             SetResultInfoAccordingToNode(&(data[index]), node);
379             index++;
380         }
381         node = node->next;
382     }
383     int32_t ret = memcpy_s(result, *resultLen, data, sizeof(NotifyRiskResultInfo) * index);
384     if (ret != OPER_SUCCESS) {
385         MODEL_LOG_ERROR("[%s]:memcpy_s failed", __func__);
386         *resultLen = 0;
387     } else {
388         *resultLen = sizeof(NotifyRiskResultInfo) * index;
389     }
390     free(data);
391     data = NULL;
392     (void)pthread_mutex_unlock(&g_modelVisitLock);
393     return ret;
394 }
395 
SubscribeResult(RetListener listener)396 int32_t SubscribeResult(RetListener listener)
397 {
398     if (listener == NULL) {
399         MODEL_LOG_ERROR("[%s]:Listener is null", __func__);
400         return INPUT_POINT_NULL;
401     }
402 
403     (void)pthread_mutex_lock(&g_modelVisitLock);
404     if (g_modelDataHead == NULL) {
405         MODEL_LOG_ERROR("[%s]:Init is not completed yet", __func__);
406         (void)pthread_mutex_unlock(&g_modelVisitLock);
407         return MODEL_INIT_NOT_COMPLETED;
408     }
409     g_retListener = listener;
410     (void)pthread_mutex_unlock(&g_modelVisitLock);
411     return OPER_SUCCESS;
412 }
413 
GetModelApi(void)414 ModelApi *GetModelApi(void)
415 {
416     int32_t res = pthread_mutex_init(&g_modelVisitLock, NULL);
417     if (res != OPER_SUCCESS) {
418         MODEL_LOG_ERROR("[%s]:pthread_mutex_init failed, res %d.", __func__, res);
419         return NULL;
420     }
421 
422     if (g_modelFunc != NULL) {
423         return g_modelFunc;
424     }
425     g_modelFunc = (ModelApi *)malloc(sizeof(ModelApi));
426     if (g_modelFunc == NULL) {
427         MODEL_LOG_ERROR("[%s]: malloc failed", __func__);
428         (void)pthread_mutex_destroy(&g_modelVisitLock);
429         return g_modelFunc;
430     }
431     (void)memset_s(g_modelFunc, sizeof(ModelApi), 0, sizeof(ModelApi));
432     g_modelFunc->init = Init;
433     g_modelFunc->release = Release;
434     g_modelFunc->getResult = GetResult;
435     g_modelFunc->subscribeResult = SubscribeResult;
436 
437     return g_modelFunc;
438 }
439