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