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