• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&param, 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(&param, 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(&currentScheduleId, &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(&currentScheduleId, &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