• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "coauth.h"
17 
18 #include "securec.h"
19 
20 #include "adaptor_algorithm.h"
21 #include "adaptor_log.h"
22 #include "adaptor_memory.h"
23 #include "pool.h"
24 
25 // Used to cache the ongoing coAuth scheduling.
26 static LinkedList *g_scheduleList = NULL;
27 
IsCoAuthInit()28 static bool IsCoAuthInit()
29 {
30     return g_scheduleList != NULL;
31 }
32 
DestroyScheduleNode(void * data)33 void DestroyScheduleNode(void *data)
34 {
35     if (data == NULL) {
36         LOG_ERROR("get null data");
37         return;
38     }
39     CoAuthSchedule *schedule = (CoAuthSchedule *)data;
40     if (schedule->templateIds.value != NULL) {
41         Free(schedule->templateIds.value);
42         schedule->templateIds.value = NULL;
43     }
44     Free(schedule);
45 }
46 
CopyCoAuthSchedule(const CoAuthSchedule * coAuthSchedule)47 CoAuthSchedule *CopyCoAuthSchedule(const CoAuthSchedule *coAuthSchedule)
48 {
49     if (coAuthSchedule == NULL || !IsTemplateArraysValid(&(coAuthSchedule->templateIds))) {
50         LOG_ERROR("coAuthSchedule is invalid");
51         return NULL;
52     }
53     CoAuthSchedule *schedule = (CoAuthSchedule *)Malloc(sizeof(CoAuthSchedule));
54     if (schedule == NULL) {
55         LOG_ERROR("schedule is null");
56         return NULL;
57     }
58     if (memcpy_s(schedule, sizeof(CoAuthSchedule), coAuthSchedule, sizeof(CoAuthSchedule)) != EOK) {
59         LOG_ERROR("copy schedule failed");
60         Free(schedule);
61         return NULL;
62     }
63     schedule->templateIds.value = NULL;
64     schedule->templateIds.num = 0;
65     ResultCode ret = CopyTemplateArrays(&(coAuthSchedule->templateIds), &(schedule->templateIds));
66     if (ret != RESULT_SUCCESS) {
67         LOG_ERROR("copy templateIds failed");
68         Free(schedule);
69         return NULL;
70     }
71     return schedule;
72 }
73 
DestroyCoAuthSchedule(CoAuthSchedule * coAuthSchedule)74 void DestroyCoAuthSchedule(CoAuthSchedule *coAuthSchedule)
75 {
76     if (coAuthSchedule == NULL) {
77         return;
78     }
79     DestroyScheduleNode(coAuthSchedule);
80 }
81 
InitCoAuth(void)82 ResultCode InitCoAuth(void)
83 {
84     if (!IsCoAuthInit()) {
85         g_scheduleList = CreateLinkedList(DestroyScheduleNode);
86     }
87     if (g_scheduleList == NULL) {
88         return RESULT_GENERAL_ERROR;
89     }
90     return RESULT_SUCCESS;
91 }
92 
DestoryCoAuth(void)93 void DestoryCoAuth(void)
94 {
95     DestroyLinkedList(g_scheduleList);
96     g_scheduleList = NULL;
97 }
98 
AddCoAuthSchedule(const CoAuthSchedule * coAuthSchedule)99 ResultCode AddCoAuthSchedule(const CoAuthSchedule *coAuthSchedule)
100 {
101     if (!IsCoAuthInit()) {
102         LOG_ERROR("pool not init");
103         return RESULT_NEED_INIT;
104     }
105     if (coAuthSchedule == NULL) {
106         LOG_ERROR("get null schedule");
107         return RESULT_BAD_PARAM;
108     }
109     CoAuthSchedule *schedule = CopyCoAuthSchedule(coAuthSchedule);
110     if (schedule == NULL) {
111         LOG_ERROR("no memory");
112         return RESULT_NO_MEMORY;
113     }
114     ResultCode result = g_scheduleList->insert(g_scheduleList, schedule);
115     if (result != RESULT_SUCCESS) {
116         LOG_ERROR("insert failed");
117         DestroyCoAuthSchedule(schedule);
118     }
119     return result;
120 }
121 
IsScheduleMatch(const void * data,const void * condition)122 static bool IsScheduleMatch(const void *data, const void *condition)
123 {
124     if ((condition == NULL) || (data == NULL)) {
125         LOG_ERROR("get null data");
126         return false;
127     }
128     uint64_t scheduleId = *(uint64_t *)condition;
129     CoAuthSchedule *coAuthSchedule = (CoAuthSchedule *)data;
130     return (coAuthSchedule->scheduleId == scheduleId);
131 }
132 
RemoveCoAuthSchedule(uint64_t scheduleId)133 ResultCode RemoveCoAuthSchedule(uint64_t scheduleId)
134 {
135     if (!IsCoAuthInit()) {
136         LOG_ERROR("pool not init");
137         return RESULT_NEED_INIT;
138     }
139     return g_scheduleList->remove(g_scheduleList, (void *)&scheduleId, IsScheduleMatch, true);
140 }
141 
GetCoAuthSchedule(uint64_t scheduleId)142 const CoAuthSchedule *GetCoAuthSchedule(uint64_t scheduleId)
143 {
144     if (!IsCoAuthInit()) {
145         LOG_ERROR("pool not init");
146         return NULL;
147     }
148     LinkedListIterator *iterator = g_scheduleList->createIterator(g_scheduleList);
149     if (iterator == NULL) {
150         LOG_ERROR("create iterator failed");
151         return NULL;
152     }
153     CoAuthSchedule *schedule = NULL;
154     while (iterator->hasNext(iterator)) {
155         schedule = (CoAuthSchedule *)iterator->next(iterator);
156         if (schedule == NULL) {
157             LOG_ERROR("list node is null, please check");
158             continue;
159         }
160         if (schedule->scheduleId != scheduleId) {
161             continue;
162         }
163         g_scheduleList->destroyIterator(iterator);
164         return schedule;
165     }
166     g_scheduleList->destroyIterator(iterator);
167     LOG_ERROR("can't find this schedule");
168     return NULL;
169 }
170 
IsScheduleIdDuplicate(uint64_t scheduleId)171 static bool IsScheduleIdDuplicate(uint64_t scheduleId)
172 {
173     LinkedListNode *temp = g_scheduleList->head;
174     CoAuthSchedule *schedule = NULL;
175     while (temp != NULL) {
176         schedule = (CoAuthSchedule *)temp->data;
177         if (schedule != NULL && schedule->scheduleId == scheduleId) {
178             return true;
179         }
180         temp = temp->next;
181     }
182 
183     return false;
184 }
185 
GenerateValidScheduleId(uint64_t * scheduleId)186 static ResultCode GenerateValidScheduleId(uint64_t *scheduleId)
187 {
188     if (g_scheduleList == NULL) {
189         LOG_ERROR("g_poolList is null");
190         return RESULT_BAD_PARAM;
191     }
192 
193     for (uint32_t i = 0; i < MAX_DUPLICATE_CHECK; ++i) {
194         uint64_t tempRandom;
195         if (SecureRandom((uint8_t *)&tempRandom, sizeof(uint64_t)) != RESULT_SUCCESS) {
196             LOG_ERROR("get random failed");
197             return RESULT_GENERAL_ERROR;
198         }
199         if (!IsScheduleIdDuplicate(tempRandom)) {
200             *scheduleId = tempRandom;
201             return RESULT_SUCCESS;
202         }
203     }
204 
205     LOG_ERROR("a rare failure");
206     return RESULT_GENERAL_ERROR;
207 }
208 
MountExecutorOnce(const LinkedList * executors,CoAuthSchedule * coAuthSchedule,uint32_t sensorHint,uint32_t executorRole)209 static ResultCode MountExecutorOnce(const LinkedList *executors, CoAuthSchedule *coAuthSchedule, uint32_t sensorHint,
210     uint32_t executorRole)
211 {
212     LinkedListNode *tempNode = executors->head;
213     while (tempNode != NULL) {
214         if (tempNode->data == NULL) {
215             LOG_ERROR("data is null");
216             return RESULT_UNKNOWN;
217         }
218         ExecutorInfoHal *executor = (ExecutorInfoHal *)tempNode->data;
219         if (executor->executorRole != executorRole) {
220             tempNode = tempNode->next;
221             continue;
222         }
223         if (sensorHint != INVALID_SENSOR_HINT && sensorHint != executor->executorSensorHint) {
224             tempNode = tempNode->next;
225             continue;
226         }
227         coAuthSchedule->executors[coAuthSchedule->executorSize] = *executor;
228         ++(coAuthSchedule->executorSize);
229         return RESULT_SUCCESS;
230     }
231     LOG_ERROR("mount executor failed");
232     return RESULT_NOT_FOUND;
233 }
234 
MountExecutor(const ScheduleParam * param,CoAuthSchedule * coAuthSchedule)235 static ResultCode MountExecutor(const ScheduleParam *param, CoAuthSchedule *coAuthSchedule)
236 {
237     ExecutorCondition condition = {};
238     SetExecutorConditionAuthType(&condition, param->authType);
239     if (param->collectorSensorHint != INVALID_SENSOR_HINT || param->verifierSensorHint != INVALID_SENSOR_HINT) {
240         SetExecutorConditionExecutorMatcher(&condition, param->executorMatcher);
241     }
242     LinkedList *executors = QueryExecutor(&condition);
243     if (executors == NULL) {
244         LOG_ERROR("query executor failed");
245         return RESULT_UNKNOWN;
246     }
247     ResultCode ret;
248     if (param->collectorSensorHint == INVALID_SENSOR_HINT || param->verifierSensorHint == INVALID_SENSOR_HINT ||
249         param->collectorSensorHint == param->verifierSensorHint) {
250         uint32_t allInOneSensorHint = param->verifierSensorHint | param->collectorSensorHint;
251         ret = MountExecutorOnce(executors, coAuthSchedule, allInOneSensorHint, ALL_IN_ONE);
252         if (ret == RESULT_SUCCESS) {
253             goto EXIT;
254         }
255     }
256     if (param->scheduleMode == SCHEDULE_MODE_IDENTIFY) {
257         LOG_ERROR("identification only supports all in one");
258         ret = RESULT_GENERAL_ERROR;
259         goto EXIT;
260     }
261     ret = MountExecutorOnce(executors, coAuthSchedule, param->verifierSensorHint, VERIFIER);
262     if (ret != RESULT_SUCCESS) {
263         LOG_ERROR("verifier is not found");
264         goto EXIT;
265     }
266     ret = MountExecutorOnce(executors, coAuthSchedule, param->collectorSensorHint, COLLECTOR);
267     if (ret != RESULT_SUCCESS) {
268         LOG_ERROR("collector is not found");
269     }
270 
271 EXIT:
272     DestroyLinkedList(executors);
273     return ret;
274 }
275 
GetScheduleVeriferSensorHint(const CoAuthSchedule * coAuthSchedule)276 uint32_t GetScheduleVeriferSensorHint(const CoAuthSchedule *coAuthSchedule)
277 {
278     if (coAuthSchedule == NULL) {
279         LOG_ERROR("coAuthSchedule is null");
280         return INVALID_SENSOR_HINT;
281     }
282     for (uint32_t i = 0; i < coAuthSchedule->executorSize; ++i) {
283         const ExecutorInfoHal *executor = coAuthSchedule->executors + i;
284         if (executor->executorRole == VERIFIER || executor->executorRole == ALL_IN_ONE) {
285             return executor->executorSensorHint;
286         }
287     }
288     LOG_ERROR("not found");
289     return INVALID_SENSOR_HINT;
290 }
291 
GenerateSchedule(const ScheduleParam * param)292 CoAuthSchedule *GenerateSchedule(const ScheduleParam *param)
293 {
294     if (param == NULL) {
295         LOG_ERROR("param is invalid");
296         return NULL;
297     }
298     CoAuthSchedule *coAuthSchedule = Malloc(sizeof(CoAuthSchedule));
299     if (coAuthSchedule == NULL) {
300         LOG_ERROR("coAuthSchedule is null");
301         return NULL;
302     }
303     if (memset_s(coAuthSchedule, sizeof(CoAuthSchedule), 0, sizeof(CoAuthSchedule)) != EOK) {
304         LOG_ERROR("reset coAuthSchedule failed");
305         Free(coAuthSchedule);
306         return NULL;
307     }
308     ResultCode ret = GenerateValidScheduleId(&coAuthSchedule->scheduleId);
309     if (ret != RESULT_SUCCESS) {
310         LOG_ERROR("get scheduleId failed");
311         goto FAIL;
312     }
313     coAuthSchedule->associateId = param->associateId;
314     coAuthSchedule->scheduleMode = param->scheduleMode;
315     coAuthSchedule->authType = param->authType;
316     if (param->templateIds != NULL) {
317         ret = CopyTemplateArrays(param->templateIds, &(coAuthSchedule->templateIds));
318         if (ret != RESULT_SUCCESS) {
319             LOG_ERROR("copy template failed");
320             goto FAIL;
321         }
322     }
323 
324     ret = MountExecutor(param, coAuthSchedule);
325     if (ret != RESULT_SUCCESS) {
326         LOG_ERROR("mount failed");
327         goto FAIL;
328     }
329     return coAuthSchedule;
330 FAIL:
331     DestroyCoAuthSchedule(coAuthSchedule);
332     return NULL;
333 }
334 
IsTemplateArraysValid(const TemplateIdArrays * templateIds)335 bool IsTemplateArraysValid(const TemplateIdArrays *templateIds)
336 {
337     if (templateIds == NULL) {
338         LOG_ERROR("templateIds is null");
339         return false;
340     }
341     if (templateIds->num > MAX_TEMPLATE_OF_SCHEDULE || (templateIds->num != 0 && templateIds->value == NULL)) {
342         LOG_ERROR("templateIds's content is invalid");
343         return false;
344     }
345     return true;
346 }
347 
CopyTemplateArrays(const TemplateIdArrays * in,TemplateIdArrays * out)348 ResultCode CopyTemplateArrays(const TemplateIdArrays *in, TemplateIdArrays *out)
349 {
350     if (!IsTemplateArraysValid(in) || out == NULL || out->value != NULL) {
351         LOG_ERROR("param is invalid");
352         return RESULT_BAD_PARAM;
353     }
354     if (in->num == 0) {
355         out->num = 0;
356         return RESULT_SUCCESS;
357     }
358     out->num = in->num;
359     out->value = (uint64_t *)Malloc(sizeof(uint64_t) * out->num);
360     if (out->value == NULL) {
361         LOG_ERROR("out value is null");
362         out->num = 0;
363         return RESULT_NO_MEMORY;
364     }
365     if (memcpy_s(out->value, (sizeof(uint64_t) * out->num), in->value, (sizeof(uint64_t) * in->num)) != EOK) {
366         LOG_ERROR("copy failed");
367         Free(out->value);
368         out->value = NULL;
369         out->num = 0;
370         return RESULT_BAD_COPY;
371     }
372     return RESULT_SUCCESS;
373 }