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 }