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