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 "user_idm_funcs.h"
17
18 #include "securec.h"
19
20 #include "adaptor_log.h"
21 #include "adaptor_memory.h"
22 #include "coauth.h"
23 #include "enroll_specification_check.h"
24 #include "executor_message.h"
25 #include "idm_database.h"
26
27 #ifdef IAM_TEST_ENABLE
28 #define IAM_STATIC
29 #else
30 #define IAM_STATIC static
31 #endif
32
GenerateIdmSchedule(const PermissionCheckParam * param)33 IAM_STATIC CoAuthSchedule *GenerateIdmSchedule(const PermissionCheckParam *param)
34 {
35 ScheduleParam scheduleParam = {};
36 scheduleParam.associateId.userId = param->userId;
37 scheduleParam.authType = param->authType;
38 scheduleParam.scheduleMode = SCHEDULE_MODE_ENROLL;
39 scheduleParam.collectorSensorHint = param->executorSensorHint;
40 if (scheduleParam.collectorSensorHint != INVALID_SENSOR_HINT) {
41 ResultCode ret = QueryCollecterMatcher(scheduleParam.authType, scheduleParam.collectorSensorHint,
42 &scheduleParam.executorMatcher);
43 if (ret != RESULT_SUCCESS) {
44 LOG_ERROR("QueryCollecterMatcher failed");
45 return NULL;
46 }
47 }
48
49 LinkedList *credList = NULL;
50 if (QueryCredentialFunc(param->userId, param->authType, &credList) != RESULT_SUCCESS) {
51 LOG_ERROR("query credential failed");
52 return NULL;
53 }
54 uint64_t templateIdsBuffer[MAX_CREDENTIAL_OUTPUT];
55 uint32_t len = 0;
56 LinkedListNode *temp = credList->head;
57 while (temp != NULL) {
58 if (temp->data == NULL) {
59 LOG_ERROR("list node is invalid");
60 DestroyLinkedList(credList);
61 return NULL;
62 }
63 CredentialInfoHal *credentialHal = (CredentialInfoHal *)(temp->data);
64 if (len >= MAX_CREDENTIAL_OUTPUT) {
65 LOG_ERROR("len out of bound");
66 DestroyLinkedList(credList);
67 return NULL;
68 }
69 templateIdsBuffer[len] = credentialHal->templateId;
70 ++len;
71 temp = temp->next;
72 }
73
74 Uint64Array templateIds = { templateIdsBuffer, len };
75 scheduleParam.templateIds = &templateIds;
76
77 DestroyLinkedList(credList);
78 return GenerateSchedule(&scheduleParam);
79 }
80
GenerateCoAuthSchedule(PermissionCheckParam * param,bool isUpdate,uint64_t * scheduleId)81 IAM_STATIC ResultCode GenerateCoAuthSchedule(PermissionCheckParam *param, bool isUpdate, uint64_t *scheduleId)
82 {
83 CoAuthSchedule *enrollSchedule = GenerateIdmSchedule(param);
84 if (enrollSchedule == NULL) {
85 LOG_ERROR("enrollSchedule malloc failed");
86 return RESULT_NO_MEMORY;
87 }
88 ResultCode ret = AddCoAuthSchedule(enrollSchedule);
89 if (ret != RESULT_SUCCESS) {
90 LOG_ERROR("add coauth schedule failed");
91 goto EXIT;
92 }
93 ret = AssociateCoauthSchedule(enrollSchedule->scheduleId, param->authType, isUpdate);
94 if (ret != RESULT_SUCCESS) {
95 LOG_ERROR("idm associate coauth schedule failed");
96 RemoveCoAuthSchedule(enrollSchedule->scheduleId);
97 goto EXIT;
98 }
99 *scheduleId = enrollSchedule->scheduleId;
100
101 EXIT:
102 DestroyCoAuthSchedule(enrollSchedule);
103 return ret;
104 }
105
CheckEnrollPermission(PermissionCheckParam param,uint64_t * scheduleId)106 ResultCode CheckEnrollPermission(PermissionCheckParam param, uint64_t *scheduleId)
107 {
108 if (scheduleId == NULL) {
109 LOG_ERROR("scheduleId is null");
110 return RESULT_BAD_PARAM;
111 }
112 if (!IsSessionValid(param.userId)) {
113 LOG_ERROR("session is invalid");
114 return RESULT_GENERAL_ERROR;
115 }
116 UserAuthTokenHal *authToken = (UserAuthTokenHal *)param.token;
117 ResultCode ret = CheckSpecification(param.userId, param.authType);
118 if (ret != RESULT_SUCCESS) {
119 LOG_ERROR("check specification failed, authType is %{public}u, ret is %{public}d", param.authType, ret);
120 return ret;
121 }
122 if (param.authType != PIN_AUTH) {
123 ret = CheckIdmOperationToken(param.userId, authToken);
124 if (ret != RESULT_SUCCESS) {
125 LOG_ERROR("a valid token is required");
126 return RESULT_VERIFY_TOKEN_FAIL;
127 }
128 }
129
130 return GenerateCoAuthSchedule(¶m, false, scheduleId);
131 }
132
CheckUpdatePermission(PermissionCheckParam param,uint64_t * scheduleId)133 ResultCode CheckUpdatePermission(PermissionCheckParam param, uint64_t *scheduleId)
134 {
135 if (scheduleId == NULL || param.authType != PIN_AUTH) {
136 LOG_ERROR("param is invalid");
137 return RESULT_BAD_PARAM;
138 }
139 if (!IsSessionValid(param.userId)) {
140 LOG_ERROR("session is invalid");
141 return RESULT_GENERAL_ERROR;
142 }
143 ResultCode ret = CheckSpecification(param.userId, param.authType);
144 if (ret != RESULT_EXCEED_LIMIT) {
145 LOG_ERROR("no pin or exception, authType is %{public}u, ret is %{public}d", param.authType, ret);
146 return ret;
147 }
148 UserAuthTokenHal *authToken = (UserAuthTokenHal *)param.token;
149 ret = CheckIdmOperationToken(param.userId, authToken);
150 if (ret != RESULT_SUCCESS) {
151 LOG_ERROR("a valid token is required");
152 return RESULT_VERIFY_TOKEN_FAIL;
153 }
154
155 return GenerateCoAuthSchedule(¶m, true, scheduleId);
156 }
157
GetInfoFromResult(CredentialInfoHal * credentialInfo,const ExecutorResultInfo * result,const CoAuthSchedule * schedule)158 IAM_STATIC void GetInfoFromResult(CredentialInfoHal *credentialInfo, const ExecutorResultInfo *result,
159 const CoAuthSchedule *schedule)
160 {
161 credentialInfo->authType = schedule->authType;
162 credentialInfo->templateId = result->templateId;
163 credentialInfo->capabilityLevel = result->capabilityLevel;
164 credentialInfo->executorSensorHint = GetScheduleVeriferSensorHint(schedule);
165 credentialInfo->executorMatcher = schedule->executors[0].executorMatcher;
166 }
167
GetCredentialInfoFromSchedule(const ExecutorResultInfo * executorInfo,CredentialInfoHal * credentialInfo)168 IAM_STATIC ResultCode GetCredentialInfoFromSchedule(const ExecutorResultInfo *executorInfo,
169 CredentialInfoHal *credentialInfo)
170 {
171 uint64_t currentScheduleId;
172 uint32_t scheduleAuthType;
173 ResultCode ret = GetEnrollScheduleInfo(¤tScheduleId, &scheduleAuthType);
174 if (ret != RESULT_SUCCESS || executorInfo->scheduleId != currentScheduleId || IsSessionTimeout()) {
175 LOG_ERROR("schedule is mismatch");
176 return RESULT_GENERAL_ERROR;
177 }
178 const CoAuthSchedule *schedule = GetCoAuthSchedule(executorInfo->scheduleId);
179 if (schedule == NULL) {
180 LOG_ERROR("schedule is null");
181 return RESULT_GENERAL_ERROR;
182 }
183 GetInfoFromResult(credentialInfo, executorInfo, schedule);
184 return RESULT_SUCCESS;
185 }
186
AddCredentialFunc(int32_t userId,const Buffer * scheduleResult,uint64_t * credentialId,Buffer ** rootSecret)187 ResultCode AddCredentialFunc(int32_t userId, const Buffer *scheduleResult, uint64_t *credentialId, Buffer **rootSecret)
188 {
189 if (!IsBufferValid(scheduleResult) || credentialId == NULL || rootSecret == NULL) {
190 LOG_ERROR("param is null");
191 return RESULT_BAD_PARAM;
192 }
193 int32_t sessionUserId;
194 ResultCode ret = GetUserId(&sessionUserId);
195 if (ret != RESULT_SUCCESS || sessionUserId != userId) {
196 LOG_ERROR("userId mismatch");
197 return RESULT_UNKNOWN;
198 }
199 ExecutorResultInfo *executorResultInfo = CreateExecutorResultInfo(scheduleResult);
200 if (executorResultInfo == NULL) {
201 LOG_ERROR("executorResultInfo is null");
202 return RESULT_UNKNOWN;
203 }
204 CredentialInfoHal credentialInfo;
205 ret = GetCredentialInfoFromSchedule(executorResultInfo, &credentialInfo);
206 if (ret != RESULT_SUCCESS) {
207 LOG_ERROR("failed to get credential info result");
208 goto EXIT;
209 }
210 ret = AddCredentialInfo(userId, &credentialInfo);
211 if (ret != RESULT_SUCCESS) {
212 LOG_ERROR("add credential failed");
213 goto EXIT;
214 }
215 *credentialId = credentialInfo.credentialId;
216 if (credentialInfo.authType != PIN_AUTH) {
217 goto EXIT;
218 }
219 ret = SetPinSubType(userId, executorResultInfo->authSubType);
220 if (ret != RESULT_SUCCESS) {
221 LOG_ERROR("set pin sub type failed");
222 goto EXIT;
223 }
224 *rootSecret = CopyBuffer(executorResultInfo->rootSecret);
225 if (!IsBufferValid(*rootSecret)) {
226 LOG_ERROR("rootSecret is invalid");
227 ret = RESULT_NO_MEMORY;
228 }
229
230 EXIT:
231 DestoryExecutorResultInfo(executorResultInfo);
232 return ret;
233 }
234
DeleteCredentialFunc(CredentialDeleteParam param,CredentialInfoHal * credentialInfo)235 ResultCode DeleteCredentialFunc(CredentialDeleteParam param, CredentialInfoHal *credentialInfo)
236 {
237 if (credentialInfo == NULL) {
238 LOG_ERROR("param is null");
239 return RESULT_BAD_PARAM;
240 }
241 UserAuthTokenHal token;
242 if (memcpy_s(&token, sizeof(UserAuthTokenHal), param.token, AUTH_TOKEN_LEN) != EOK) {
243 LOG_ERROR("token copy failed");
244 return RESULT_BAD_COPY;
245 }
246 ResultCode ret = CheckIdmOperationToken(param.userId, &token);
247 if (ret != RESULT_SUCCESS) {
248 LOG_ERROR("token is invalid");
249 return RESULT_VERIFY_TOKEN_FAIL;
250 }
251
252 ret = DeleteCredentialInfo(param.userId, param.credentialId, credentialInfo);
253 if (ret != RESULT_SUCCESS) {
254 LOG_ERROR("delete database info failed");
255 return RESULT_BAD_SIGN;
256 }
257 return ret;
258 }
259
QueryCredentialFunc(int32_t userId,uint32_t authType,LinkedList ** creds)260 ResultCode QueryCredentialFunc(int32_t userId, uint32_t authType, LinkedList **creds)
261 {
262 if (creds == NULL) {
263 LOG_ERROR("creds is null");
264 return RESULT_BAD_PARAM;
265 }
266 CredentialCondition condition = {};
267 SetCredentialConditionUserId(&condition, userId);
268 if (authType != DEFAULT_AUTH_TYPE) {
269 SetCredentialConditionAuthType(&condition, authType);
270 }
271 *creds = QueryCredentialLimit(&condition);
272 if (*creds == NULL) {
273 LOG_ERROR("query credential failed");
274 return RESULT_UNKNOWN;
275 }
276 LOG_INFO("query credential success");
277 return RESULT_SUCCESS;
278 }
279
GetUserInfoFunc(int32_t userId,uint64_t * secureUid,uint64_t * pinSubType,EnrolledInfoHal ** enrolledInfoArray,uint32_t * enrolledNum)280 ResultCode GetUserInfoFunc(int32_t userId, uint64_t *secureUid, uint64_t *pinSubType,
281 EnrolledInfoHal **enrolledInfoArray, uint32_t *enrolledNum)
282 {
283 if (secureUid == NULL || pinSubType == NULL || enrolledInfoArray == NULL || enrolledNum == NULL) {
284 LOG_ERROR("param is null");
285 return RESULT_BAD_PARAM;
286 }
287 ResultCode ret = GetSecureUid(userId, secureUid);
288 if (ret != RESULT_SUCCESS) {
289 LOG_ERROR("get secureUid failed");
290 return ret;
291 }
292 ret = GetPinSubType(userId, pinSubType);
293 if (ret != RESULT_SUCCESS) {
294 LOG_ERROR("get pinSubType failed");
295 return ret;
296 }
297 return GetEnrolledInfo(userId, enrolledInfoArray, enrolledNum);
298 }
299
GetDeletedCredential(int32_t userId,CredentialInfoHal * deletedCredential)300 IAM_STATIC ResultCode GetDeletedCredential(int32_t userId, CredentialInfoHal *deletedCredential)
301 {
302 CredentialCondition condition = {};
303 SetCredentialConditionAuthType(&condition, PIN_AUTH);
304 SetCredentialConditionUserId(&condition, userId);
305 LinkedList *credList = QueryCredentialLimit(&condition);
306 if (credList == NULL || credList->head == NULL || credList->head->data == NULL) {
307 LOG_ERROR("query credential failed");
308 DestroyLinkedList(credList);
309 return RESULT_UNKNOWN;
310 }
311 if (credList->getSize(credList) != MAX_NUMBER_OF_PIN_PER_USER) {
312 LOG_ERROR("pin num is invalid");
313 DestroyLinkedList(credList);
314 return RESULT_UNKNOWN;
315 }
316 *deletedCredential = *((CredentialInfoHal *)credList->head->data);
317 DestroyLinkedList(credList);
318 return RESULT_SUCCESS;
319 }
320
CheckResultValid(uint64_t scheduleId,int32_t userId)321 IAM_STATIC ResultCode CheckResultValid(uint64_t scheduleId, int32_t userId)
322 {
323 uint64_t currentScheduleId;
324 uint32_t scheduleAuthType;
325 ResultCode ret = GetEnrollScheduleInfo(¤tScheduleId, &scheduleAuthType);
326 if (ret != RESULT_SUCCESS || scheduleId != currentScheduleId || IsSessionTimeout()) {
327 LOG_ERROR("schedule is mismatch");
328 return RESULT_GENERAL_ERROR;
329 }
330 int32_t userIdGet;
331 ret = GetUserId(&userIdGet);
332 if (ret != RESULT_SUCCESS || userId != userIdGet) {
333 LOG_ERROR("check userId failed");
334 return RESULT_REACH_LIMIT;
335 }
336 if (scheduleAuthType != PIN_AUTH) {
337 LOG_ERROR("only pin is allowed to be updated");
338 return RESULT_UNKNOWN;
339 }
340 return RESULT_SUCCESS;
341 }
342
UpdateCredentialFunc(int32_t userId,const Buffer * scheduleResult,uint64_t * credentialId,CredentialInfoHal * deletedCredential,Buffer ** rootSecret)343 ResultCode UpdateCredentialFunc(int32_t userId, const Buffer *scheduleResult, uint64_t *credentialId,
344 CredentialInfoHal *deletedCredential, Buffer **rootSecret)
345 {
346 if (!IsBufferValid(scheduleResult) || credentialId == NULL || deletedCredential == NULL || rootSecret == NULL) {
347 LOG_ERROR("param is invalid");
348 return RESULT_BAD_PARAM;
349 }
350 ExecutorResultInfo *executorResultInfo = CreateExecutorResultInfo(scheduleResult);
351 if (executorResultInfo == NULL) {
352 LOG_ERROR("executorResultInfo is null");
353 return RESULT_UNKNOWN;
354 }
355 ResultCode ret = CheckResultValid(executorResultInfo->scheduleId, userId);
356 if (ret != RESULT_SUCCESS) {
357 LOG_ERROR("check result failed");
358 goto EXIT;
359 }
360 ret = GetDeletedCredential(userId, deletedCredential);
361 if (ret != RESULT_SUCCESS) {
362 LOG_ERROR("get old credential failed");
363 goto EXIT;
364 }
365 ret = DeleteCredentialInfo(userId, deletedCredential->credentialId, deletedCredential);
366 if (ret != RESULT_SUCCESS) {
367 LOG_ERROR("delete failed");
368 goto EXIT;
369 }
370 const CoAuthSchedule *schedule = GetCoAuthSchedule(executorResultInfo->scheduleId);
371 if (schedule == NULL) {
372 LOG_ERROR("schedule is null");
373 ret = RESULT_UNKNOWN;
374 goto EXIT;
375 }
376 CredentialInfoHal credentialInfo;
377 GetInfoFromResult(&credentialInfo, executorResultInfo, schedule);
378 ret = AddCredentialInfo(userId, &credentialInfo);
379 if (ret != RESULT_SUCCESS) {
380 LOG_ERROR("failed to add credential");
381 goto EXIT;
382 }
383 *credentialId = credentialInfo.credentialId;
384 *rootSecret = CopyBuffer(executorResultInfo->rootSecret);
385 if (!IsBufferValid(*rootSecret)) {
386 LOG_ERROR("rootSecret is invalid");
387 ret = RESULT_NO_MEMORY;
388 }
389
390 EXIT:
391 DestoryExecutorResultInfo(executorResultInfo);
392 return ret;
393 }
394