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 "context_manager.h"
17
18 #include "securec.h"
19
20 #include "adaptor_log.h"
21 #include "auth_level.h"
22 #include "coauth.h"
23 #include "idm_database.h"
24
25 #ifdef IAM_TEST_ENABLE
26 #define IAM_STATIC
27 #else
28 #define IAM_STATIC static
29 #endif
30
31 IAM_STATIC bool IsContextDuplicate(uint64_t contextId);
32 IAM_STATIC ResultCode CreateAndInsertSchedules(UserAuthContext *context, uint32_t authMode);
33 IAM_STATIC ResultCode CreateAuthSchedule(UserAuthContext *context, CoAuthSchedule **schedule);
34 IAM_STATIC ResultCode CreateIdentifySchedule(const UserAuthContext *context, CoAuthSchedule **schedule);
35 IAM_STATIC void DestroyContextNode(void *data);
36 IAM_STATIC ResultCode InsertScheduleToContext(CoAuthSchedule *schedule, UserAuthContext *context);
37
38 // Stores information about the current user authentication schedule.
39 IAM_STATIC LinkedList *g_contextList = NULL;
40
InitUserAuthContextList(void)41 ResultCode InitUserAuthContextList(void)
42 {
43 if (g_contextList != NULL) {
44 return RESULT_SUCCESS;
45 }
46 g_contextList = CreateLinkedList(DestroyContextNode);
47 if (g_contextList == NULL) {
48 return RESULT_GENERAL_ERROR;
49 }
50 return RESULT_SUCCESS;
51 }
52
DestoryUserAuthContextList(void)53 void DestoryUserAuthContextList(void)
54 {
55 DestroyLinkedList(g_contextList);
56 g_contextList = NULL;
57 }
58
InitAuthContext(AuthSolutionHal params)59 IAM_STATIC UserAuthContext *InitAuthContext(AuthSolutionHal params)
60 {
61 UserAuthContext *context = (UserAuthContext *)Malloc(sizeof(UserAuthContext));
62 if (context == NULL) {
63 LOG_ERROR("context malloc failed");
64 return NULL;
65 }
66 (void)memset_s(context, sizeof(UserAuthContext), 0, sizeof(UserAuthContext));
67 if (memcpy_s(context->challenge, CHALLENGE_LEN, params.challenge, CHALLENGE_LEN) != EOK) {
68 LOG_ERROR("failed to copy challenge");
69 Free(context);
70 return NULL;
71 }
72 context->contextId = params.contextId;
73 context->userId = params.userId;
74 context->authType = params.authType;
75 context->authTrustLevel = params.authTrustLevel;
76 context->collectorSensorHint = params.executorSensorHint;
77 context->scheduleList = CreateLinkedList(DestroyScheduleNode);
78 if (context->scheduleList == NULL) {
79 LOG_ERROR("schedule list create failed");
80 Free(context);
81 return NULL;
82 }
83 return context;
84 }
85
GenerateAuthContext(AuthSolutionHal params,UserAuthContext ** context)86 ResultCode GenerateAuthContext(AuthSolutionHal params, UserAuthContext **context)
87 {
88 LOG_INFO("start");
89 if (context == NULL) {
90 LOG_ERROR("context is null");
91 return RESULT_BAD_PARAM;
92 }
93 if (g_contextList == NULL) {
94 LOG_ERROR("need init");
95 return RESULT_NEED_INIT;
96 }
97 if (IsContextDuplicate(params.contextId)) {
98 LOG_ERROR("contextId is duplicate");
99 return RESULT_DUPLICATE_CHECK_FAILED;
100 }
101 *context = InitAuthContext(params);
102 if (*context == NULL) {
103 LOG_ERROR("init context failed");
104 return RESULT_GENERAL_ERROR;
105 }
106 ResultCode ret = CreateAndInsertSchedules(*context, SCHEDULE_MODE_AUTH);
107 if (ret != RESULT_SUCCESS) {
108 LOG_ERROR("create schedule failed %{public}d", ret);
109 DestroyContextNode(*context);
110 *context = NULL;
111 return ret;
112 }
113 ret = g_contextList->insert(g_contextList, *context);
114 if (ret != RESULT_SUCCESS) {
115 LOG_ERROR("create schedule failed");
116 DestroyContextNode(*context);
117 *context = NULL;
118 return RESULT_GENERAL_ERROR;
119 }
120 return RESULT_SUCCESS;
121 }
122
CreateIdentifySchedule(const UserAuthContext * context,CoAuthSchedule ** schedule)123 IAM_STATIC ResultCode CreateIdentifySchedule(const UserAuthContext *context, CoAuthSchedule **schedule)
124 {
125 ScheduleParam scheduleParam = {};
126 scheduleParam.associateId.contextId = context->contextId;
127 scheduleParam.authType = context->authType;
128 scheduleParam.collectorSensorHint = context->collectorSensorHint;
129 scheduleParam.verifierSensorHint = context->collectorSensorHint;
130 scheduleParam.scheduleMode = SCHEDULE_MODE_IDENTIFY;
131 *schedule = GenerateSchedule(&scheduleParam);
132 if (*schedule == NULL) {
133 LOG_ERROR("GenerateSchedule failed");
134 return RESULT_GENERAL_ERROR;
135 }
136 return RESULT_SUCCESS;
137 }
138
InitIdentifyContext(const IdentifyParam * params)139 IAM_STATIC UserAuthContext *InitIdentifyContext(const IdentifyParam *params)
140 {
141 UserAuthContext *context = (UserAuthContext *)Malloc(sizeof(UserAuthContext));
142 if (context == NULL) {
143 LOG_ERROR("context malloc failed");
144 return NULL;
145 }
146 (void)memset_s(context, sizeof(UserAuthContext), 0, sizeof(UserAuthContext));
147 if (memcpy_s(context->challenge, CHALLENGE_LEN, params->challenge, CHALLENGE_LEN) != EOK) {
148 LOG_ERROR("failed to copy challenge");
149 Free(context);
150 return NULL;
151 }
152 context->contextId = params->contextId;
153 context->authType = params->authType;
154 context->collectorSensorHint = params->executorSensorHint;
155 context->scheduleList = CreateLinkedList(DestroyScheduleNode);
156 if (context->scheduleList == NULL) {
157 LOG_ERROR("schedule list create failed");
158 Free(context);
159 return NULL;
160 }
161 return context;
162 }
163
GenerateIdentifyContext(IdentifyParam params)164 UserAuthContext *GenerateIdentifyContext(IdentifyParam params)
165 {
166 LOG_INFO("start");
167 if (g_contextList == NULL) {
168 LOG_ERROR("need init");
169 return NULL;
170 }
171 if (IsContextDuplicate(params.contextId)) {
172 LOG_ERROR("contextId is duplicate");
173 return NULL;
174 }
175
176 UserAuthContext *context = InitIdentifyContext(¶ms);
177 if (context == NULL) {
178 LOG_ERROR("init context failed");
179 return NULL;
180 }
181 ResultCode ret = CreateAndInsertSchedules(context, SCHEDULE_MODE_IDENTIFY);
182 if (ret != RESULT_SUCCESS) {
183 LOG_ERROR("create schedule failed");
184 DestroyContextNode(context);
185 return NULL;
186 }
187 ret = g_contextList->insert(g_contextList, context);
188 if (ret != RESULT_SUCCESS) {
189 LOG_ERROR("create schedule failed");
190 DestroyContextNode(context);
191 return NULL;
192 }
193 return context;
194 }
195
GetContext(uint64_t contextId)196 UserAuthContext *GetContext(uint64_t contextId)
197 {
198 if (g_contextList == NULL) {
199 LOG_ERROR("context list is null");
200 return NULL;
201 }
202 uint32_t num = g_contextList->getSize(g_contextList);
203 LinkedListNode *tempNode = g_contextList->head;
204 UserAuthContext *contextRet = NULL;
205 for (uint32_t index = 0; index < num; index++) {
206 if (tempNode == NULL) {
207 LOG_ERROR("node is null");
208 return NULL;
209 }
210 contextRet = (UserAuthContext *)tempNode->data;
211 if (contextRet != NULL && contextRet->contextId == contextId) {
212 return contextRet;
213 }
214 tempNode = tempNode->next;
215 }
216 return NULL;
217 }
218
InsertScheduleToContext(CoAuthSchedule * schedule,UserAuthContext * context)219 IAM_STATIC ResultCode InsertScheduleToContext(CoAuthSchedule *schedule, UserAuthContext *context)
220 {
221 LinkedList *scheduleList = context->scheduleList;
222 return scheduleList->insert(scheduleList, schedule);
223 }
224
CreateAndInsertSchedules(UserAuthContext * context,uint32_t authMode)225 IAM_STATIC ResultCode CreateAndInsertSchedules(UserAuthContext *context, uint32_t authMode)
226 {
227 LOG_INFO("start");
228 CoAuthSchedule *schedule = NULL;
229 ResultCode result = RESULT_BAD_PARAM;
230 if (authMode == SCHEDULE_MODE_AUTH) {
231 result = CreateAuthSchedule(context, &schedule);
232 } else if (authMode == SCHEDULE_MODE_IDENTIFY) {
233 result = CreateIdentifySchedule(context, &schedule);
234 } else {
235 LOG_ERROR("authMode is invalid");
236 return result;
237 }
238 if (result != RESULT_SUCCESS) {
239 LOG_INFO("create schedule fail %{public}d", result);
240 return result;
241 }
242 if (AddCoAuthSchedule(schedule) != RESULT_SUCCESS) {
243 LOG_ERROR("AddCoAuthSchedule failed");
244 DestroyCoAuthSchedule(schedule);
245 return RESULT_UNKNOWN;
246 }
247 if (InsertScheduleToContext(schedule, context) != RESULT_SUCCESS) {
248 RemoveCoAuthSchedule(schedule->scheduleId);
249 DestroyCoAuthSchedule(schedule);
250 LOG_ERROR("insert failed");
251 return RESULT_UNKNOWN;
252 }
253 return RESULT_SUCCESS;
254 }
255
GetAuthCredentialList(const UserAuthContext * context)256 IAM_STATIC LinkedList *GetAuthCredentialList(const UserAuthContext *context)
257 {
258 CredentialCondition condition = {};
259 SetCredentialConditionAuthType(&condition, context->authType);
260 SetCredentialConditionUserId(&condition, context->userId);
261 if (context->collectorSensorHint != INVALID_SENSOR_HINT) {
262 uint32_t executorMatcher;
263 ResultCode ret = QueryCollecterMatcher(context->authType, context->collectorSensorHint, &executorMatcher);
264 if (ret != RESULT_SUCCESS) {
265 LOG_ERROR("query collect matcher failed");
266 return NULL;
267 }
268 SetCredentialConditionExecutorMatcher(&condition, executorMatcher);
269 }
270 return QueryCredentialLimit(&condition);
271 }
272
CheckCredentialSize(LinkedList * credList)273 IAM_STATIC ResultCode CheckCredentialSize(LinkedList *credList)
274 {
275 uint32_t credNum = credList->getSize(credList);
276 if (credNum == 0) {
277 LOG_ERROR("credNum is 0");
278 return RESULT_NOT_ENROLLED;
279 }
280 if (credNum > MAX_CREDENTIAL) {
281 LOG_ERROR("credNum exceed limit");
282 return RESULT_EXCEED_LIMIT;
283 }
284 return RESULT_SUCCESS;
285 }
286
QueryAuthTempletaInfo(UserAuthContext * context,Uint64Array * templateIds,uint32_t * sensorHint,uint32_t * matcher,uint32_t * acl)287 IAM_STATIC ResultCode QueryAuthTempletaInfo(UserAuthContext *context, Uint64Array *templateIds,
288 uint32_t *sensorHint, uint32_t *matcher, uint32_t *acl)
289 {
290 LinkedList *credList = GetAuthCredentialList(context);
291 if (credList == NULL) {
292 LOG_ERROR("query credential failed");
293 return RESULT_UNKNOWN;
294 }
295 ResultCode checkResult = CheckCredentialSize(credList);
296 if (checkResult != RESULT_SUCCESS) {
297 LOG_ERROR("CheckCredentialSize failed %{public}d", checkResult);
298 DestroyLinkedList(credList);
299 return checkResult;
300 }
301 templateIds->data = (uint64_t *)Malloc(sizeof(uint64_t) * credList->getSize(credList));
302 if (templateIds->data == NULL) {
303 LOG_ERROR("value malloc failed");
304 DestroyLinkedList(credList);
305 return RESULT_NO_MEMORY;
306 }
307 templateIds->len = 0;
308 LinkedListNode *temp = credList->head;
309 if (temp == NULL || temp->data == NULL) {
310 LOG_ERROR("link node is invalid");
311 goto FAIL;
312 }
313 CredentialInfoHal *credentialHal = (CredentialInfoHal *)temp->data;
314 *sensorHint = credentialHal->executorSensorHint;
315 *matcher = credentialHal->executorMatcher;
316 *acl = credentialHal->capabilityLevel;
317 while (temp != NULL) {
318 if (temp->data == NULL) {
319 LOG_ERROR("link node is invalid");
320 goto FAIL;
321 }
322 credentialHal = (CredentialInfoHal *)temp->data;
323 if (credentialHal->executorSensorHint == *sensorHint) {
324 templateIds->data[templateIds->len] = credentialHal->templateId;
325 ++(templateIds->len);
326 }
327 temp = temp->next;
328 }
329 DestroyLinkedList(credList);
330 return RESULT_SUCCESS;
331
332 FAIL:
333 Free(templateIds->data);
334 templateIds->data = NULL;
335 DestroyLinkedList(credList);
336 return RESULT_UNKNOWN;
337 }
338
CreateAuthSchedule(UserAuthContext * context,CoAuthSchedule ** schedule)339 IAM_STATIC ResultCode CreateAuthSchedule(UserAuthContext *context, CoAuthSchedule **schedule)
340 {
341 Uint64Array templateIds = {};
342 uint32_t verifierSensorHint;
343 uint32_t executorMatcher;
344 uint32_t acl;
345 ResultCode ret = QueryAuthTempletaInfo(context, &templateIds, &verifierSensorHint, &executorMatcher, &acl);
346 if (ret != RESULT_SUCCESS) {
347 LOG_ERROR("QueryAuthTempletaInfo failed %{public}d", ret);
348 return ret;
349 }
350 ScheduleParam scheduleParam = {};
351 scheduleParam.associateId.contextId = context->contextId;
352 scheduleParam.authType = context->authType;
353 scheduleParam.collectorSensorHint = context->collectorSensorHint;
354 scheduleParam.verifierSensorHint = verifierSensorHint;
355 scheduleParam.templateIds = &templateIds;
356 scheduleParam.executorMatcher = executorMatcher;
357 scheduleParam.scheduleMode = SCHEDULE_MODE_AUTH;
358 *schedule = GenerateSchedule(&scheduleParam);
359 if (*schedule == NULL) {
360 LOG_ERROR("schedule is null");
361 Free(templateIds.data);
362 return RESULT_GENERAL_ERROR;
363 }
364 uint32_t scheduleAtl;
365 ret = QueryScheduleAtl(*schedule, acl, &scheduleAtl);
366 if (ret != RESULT_SUCCESS || context->authTrustLevel > scheduleAtl) {
367 Free(templateIds.data);
368 DestroyCoAuthSchedule(*schedule);
369 *schedule = NULL;
370 return ret;
371 }
372 Free(templateIds.data);
373 return RESULT_SUCCESS;
374 }
375
IsContextDuplicate(uint64_t contextId)376 IAM_STATIC bool IsContextDuplicate(uint64_t contextId)
377 {
378 if (g_contextList == NULL) {
379 LOG_ERROR("context list is null");
380 return false;
381 }
382 LinkedListNode *tempNode = g_contextList->head;
383 while (tempNode != NULL) {
384 UserAuthContext *context = (UserAuthContext *)tempNode->data;
385 if (context == NULL) {
386 LOG_ERROR("context is null, please check");
387 tempNode = tempNode->next;
388 continue;
389 }
390 if (context->contextId == contextId) {
391 return true;
392 }
393 tempNode = tempNode->next;
394 }
395 return false;
396 }
397
CopySchedules(UserAuthContext * context,LinkedList ** schedules)398 ResultCode CopySchedules(UserAuthContext *context, LinkedList **schedules)
399 {
400 if (context == NULL || context->scheduleList == NULL || schedules == NULL) {
401 LOG_ERROR("param is null");
402 return RESULT_BAD_PARAM;
403 }
404 LinkedList *scheduleList = context->scheduleList;
405 uint32_t scheduleNum = scheduleList->getSize(scheduleList);
406 if (scheduleNum > AUTH_MAX_SCHEDULING_NUM) {
407 LOG_ERROR("scheduleNum is invalid, scheduleNum is %{public}u", scheduleNum);
408 return RESULT_UNKNOWN;
409 }
410 *schedules = CreateLinkedList(DestroyScheduleNode);
411 if (*schedules == NULL) {
412 LOG_ERROR("schedules malloc failed");
413 return RESULT_NO_MEMORY;
414 }
415 if (scheduleNum == 0) {
416 LOG_INFO("scheduleNum is zero");
417 return RESULT_SUCCESS;
418 }
419
420 LinkedListNode *temp = scheduleList->head;
421 while (temp != NULL) {
422 if (temp->data == NULL) {
423 LOG_ERROR("node data is wrong, please check");
424 goto ERROR;
425 }
426 CoAuthSchedule *schedule = CopyCoAuthSchedule((CoAuthSchedule *)temp->data);
427 if (schedule == NULL) {
428 LOG_ERROR("data is null");
429 goto ERROR;
430 }
431 if ((*schedules)->insert(*schedules, schedule) != RESULT_SUCCESS) {
432 LOG_ERROR("insert schedule failed");
433 DestroyCoAuthSchedule(schedule);
434 goto ERROR;
435 }
436 temp = temp->next;
437 }
438 return RESULT_SUCCESS;
439
440 ERROR:
441 DestroyLinkedList(*schedules);
442 *schedules = NULL;
443 return RESULT_GENERAL_ERROR;
444 }
445
MatchSchedule(void * data,void * condition)446 IAM_STATIC bool MatchSchedule(void *data, void *condition)
447 {
448 if (data == NULL || condition == NULL) {
449 LOG_ERROR("param is null");
450 return false;
451 }
452 CoAuthSchedule *schedule = (CoAuthSchedule *)data;
453 if (schedule->scheduleId == *(uint64_t *)condition) {
454 return true;
455 }
456 return false;
457 }
458
ScheduleOnceFinish(UserAuthContext * context,uint64_t scheduleId)459 ResultCode ScheduleOnceFinish(UserAuthContext *context, uint64_t scheduleId)
460 {
461 if (context == NULL || context->scheduleList == NULL) {
462 LOG_ERROR("param is null");
463 return RESULT_BAD_PARAM;
464 }
465 RemoveCoAuthSchedule(scheduleId);
466 return context->scheduleList->remove(context->scheduleList, &scheduleId, MatchSchedule, true);
467 }
468
MatchContextSelf(void * data,void * condition)469 IAM_STATIC bool MatchContextSelf(void *data, void *condition)
470 {
471 return data == condition;
472 }
473
DestoryContext(UserAuthContext * context)474 void DestoryContext(UserAuthContext *context)
475 {
476 if (context == NULL) {
477 LOG_ERROR("context is null");
478 return;
479 }
480 if (g_contextList == NULL) {
481 LOG_ERROR("context list is null");
482 return;
483 }
484 g_contextList->remove(g_contextList, context, MatchContextSelf, true);
485 }
486
DestroyContextNode(void * data)487 IAM_STATIC void DestroyContextNode(void *data)
488 {
489 if (data == NULL) {
490 return;
491 }
492 LinkedList *schedules = ((UserAuthContext *)data)->scheduleList;
493 if (schedules == NULL) {
494 LOG_ERROR("schedules is null");
495 return;
496 }
497 LinkedListNode *tempNode = schedules->head;
498 while (tempNode != NULL) {
499 CoAuthSchedule *schedule = tempNode->data;
500 if (schedule == NULL) {
501 LOG_ERROR("schedule is null, please check");
502 tempNode = tempNode->next;
503 continue;
504 }
505 RemoveCoAuthSchedule(schedule->scheduleId);
506 tempNode = tempNode->next;
507 }
508 DestroyLinkedList(schedules);
509 Free(data);
510 }
511
DestoryContextbyId(uint64_t contextId)512 ResultCode DestoryContextbyId(uint64_t contextId)
513 {
514 UserAuthContext *authContext = GetContext(contextId);
515 if (authContext == NULL) {
516 LOG_ERROR("get context failed");
517 return RESULT_NOT_FOUND;
518 }
519 DestoryContext(authContext);
520 return RESULT_SUCCESS;
521 }
522
FillInContext(UserAuthContext * context,uint64_t * credentialId,ExecutorResultInfo * info,uint32_t authMode)523 ResultCode FillInContext(UserAuthContext *context, uint64_t *credentialId, ExecutorResultInfo *info,
524 uint32_t authMode)
525 {
526 if (context == NULL || credentialId == NULL || info == NULL) {
527 LOG_ERROR("param is null");
528 return RESULT_BAD_PARAM;
529 }
530 const CoAuthSchedule *schedule = GetCoAuthSchedule(info->scheduleId);
531 if (schedule == NULL) {
532 LOG_ERROR("GetCoAuthSchedule failed");
533 return RESULT_GENERAL_ERROR;
534 }
535 ResultCode ret = QueryScheduleAtl(schedule, info->capabilityLevel, &context->authTrustLevel);
536 if (ret != RESULT_SUCCESS) {
537 LOG_ERROR("QueryScheduleAtl failed");
538 return ret;
539 }
540 ret = RESULT_UNKNOWN;
541 uint32_t veriferSensorHint = GetScheduleVeriferSensorHint(schedule);
542 CredentialCondition condition = {};
543 SetCredentialConditionAuthType(&condition, context->authType);
544 SetCredentialConditionTemplateId(&condition, info->templateId);
545 SetCredentialConditionExecutorSensorHint(&condition, veriferSensorHint);
546 LinkedList *credList = QueryCredentialLimit(&condition);
547 if (credList == NULL || credList->getSize(credList) != 1) {
548 LOG_ERROR("query credential failed");
549 goto EXIT;
550 }
551 if (credList->head == NULL || credList->head->data == NULL) {
552 LOG_ERROR("list node is invalid");
553 goto EXIT;
554 }
555 CredentialInfoHal *credentialNode = (CredentialInfoHal *)credList->head->data;
556 int32_t userId = 0;
557 ret = QueryCredentialUserId(credentialNode->credentialId, &userId);
558 if (ret != RESULT_SUCCESS) {
559 LOG_ERROR("query userId failed");
560 goto EXIT;
561 }
562 if (authMode == SCHEDULE_MODE_IDENTIFY) {
563 context->userId = userId;
564 }
565 if (userId != context->userId) {
566 LOG_ERROR("userId is not matched");
567 ret = RESULT_GENERAL_ERROR;
568 goto EXIT;
569 }
570 *credentialId = credentialNode->credentialId;
571 EXIT:
572 DestroyLinkedList(credList);
573 return ret;
574 }
575