• 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 "idm_session.h"
17 
18 #include <inttypes.h>
19 #include "securec.h"
20 
21 #include "adaptor_algorithm.h"
22 #include "adaptor_log.h"
23 #include "adaptor_memory.h"
24 #include "adaptor_time.h"
25 #include "coauth.h"
26 #include "buffer.h"
27 #include "linked_list.h"
28 #include "idm_database.h"
29 
30 #define SESSION_VALIDITY_PERIOD (10 * 60 * 1000)
31 #define MAX_CHALLENGE_GENERATION_TIMES 5
32 
33 #ifdef IAM_TEST_ENABLE
34 #define IAM_STATIC
35 #else
36 #define IAM_STATIC static
37 #endif
38 
39 // User IDM session information.
40 struct SessionInfo {
41     int32_t userId;
42     uint32_t authType;
43     uint64_t time;
44     uint64_t validAuthTokenTime;
45     uint8_t challenge[CHALLENGE_LEN];
46     uint64_t scheduleId;
47     ScheduleType scheduleType;
48     bool isScheduleValid;
49     PinChangeScence pinChangeScence;
50     Buffer *oldRootSecret;
51     Buffer *curRootSecret;
52     Buffer *newRootSecret;
53 } *g_session;
54 
IsSessionExist(void)55 IAM_STATIC bool IsSessionExist(void)
56 {
57     if (g_session == NULL) {
58         LOG_INFO("the session does not exist");
59         return false;
60     }
61     return true;
62 }
63 
GenerateChallenge(uint8_t * challenge,uint32_t challengeLen)64 IAM_STATIC ResultCode GenerateChallenge(uint8_t *challenge, uint32_t challengeLen)
65 {
66     for (uint32_t i = 0; i < MAX_CHALLENGE_GENERATION_TIMES; ++i) {
67         if (SecureRandom(challenge, challengeLen) != RESULT_SUCCESS) {
68             LOG_ERROR("get challenge failed");
69             return RESULT_GENERAL_ERROR;
70         }
71         for (uint32_t j = 0; j < challengeLen; j++) {
72             if (challenge[j] != 0) {
73                 return RESULT_SUCCESS;
74             }
75         }
76         LOG_INFO("challenge is invalid, get again.");
77     }
78     LOG_ERROR("a rare failture");
79     return RESULT_GENERAL_ERROR;
80 }
81 
OpenEditSession(int32_t userId,uint8_t * challenge,uint32_t challengeLen)82 ResultCode OpenEditSession(int32_t userId, uint8_t *challenge, uint32_t challengeLen)
83 {
84     if (challenge == NULL || challengeLen != CHALLENGE_LEN) {
85         LOG_ERROR("challenge is null");
86         return RESULT_BAD_PARAM;
87     }
88     (void)memset_s(challenge, CHALLENGE_LEN, 0, CHALLENGE_LEN);
89     if (IsSessionExist()) {
90         (void)CloseEditSession();
91     }
92     g_session = Malloc(sizeof(struct SessionInfo));
93     if (g_session == NULL) {
94         LOG_ERROR("g_session malloc failed");
95         return RESULT_NO_MEMORY;
96     }
97     if (memset_s(g_session, sizeof(struct SessionInfo), 0, sizeof(struct SessionInfo)) != EOK) {
98         LOG_ERROR("g_session set failed");
99         Free(g_session);
100         g_session = NULL;
101         return RESULT_GENERAL_ERROR;
102     }
103     g_session->userId = userId;
104     ResultCode ret = GenerateChallenge(g_session->challenge, CHALLENGE_LEN);
105     if (ret != RESULT_SUCCESS) {
106         LOG_ERROR("failed to generate challenge");
107         Free(g_session);
108         g_session = NULL;
109         return ret;
110     }
111     g_session->time = GetSystemTime();
112     g_session->validAuthTokenTime = g_session->time;
113 
114     if (memcpy_s(challenge, CHALLENGE_LEN, g_session->challenge, CHALLENGE_LEN) != EOK) {
115         LOG_ERROR("failed to copy challenge");
116         Free(g_session);
117         g_session = NULL;
118         return RESULT_BAD_COPY;
119     }
120     g_session->isScheduleValid = false;
121     return RESULT_SUCCESS;
122 }
123 
RefreshValidTokenTime(void)124 void RefreshValidTokenTime(void)
125 {
126     if (!IsSessionExist()) {
127         LOG_ERROR("session is invalid");
128         return;
129     }
130     g_session->validAuthTokenTime = GetSystemTime();
131 }
132 
IsValidTokenTime(uint64_t tokenTime)133 bool IsValidTokenTime(uint64_t tokenTime)
134 {
135     if (!IsSessionExist()) {
136         LOG_ERROR("session is invalid");
137         return false;
138     }
139     return tokenTime >= g_session->validAuthTokenTime;
140 }
141 
CloseEditSession(void)142 ResultCode CloseEditSession(void)
143 {
144     if (!IsSessionExist()) {
145         return RESULT_GENERAL_ERROR;
146     }
147     ClearCachePin(g_session->userId);
148     DestoryBuffer(g_session->oldRootSecret);
149     DestoryBuffer(g_session->curRootSecret);
150     DestoryBuffer(g_session->newRootSecret);
151     Free(g_session);
152     g_session = NULL;
153     return RESULT_SUCCESS;
154 }
155 
GetUserId(int32_t * userId)156 ResultCode GetUserId(int32_t *userId)
157 {
158     if (userId == NULL || !IsSessionExist()) {
159         LOG_ERROR("param is invalid");
160         return RESULT_BAD_PARAM;
161     }
162     *userId = g_session->userId;
163     return RESULT_SUCCESS;
164 }
165 
CheckChallenge(const uint8_t * challenge,uint32_t challengeLen)166 ResultCode CheckChallenge(const uint8_t *challenge, uint32_t challengeLen)
167 {
168     if (challenge == NULL || challengeLen != CHALLENGE_LEN) {
169         LOG_ERROR("param is invalid");
170         return RESULT_BAD_PARAM;
171     }
172     if (!IsSessionExist()) {
173         LOG_ERROR("param is invalid");
174         return RESULT_NEED_INIT;
175     }
176     if (memcmp(challenge, g_session->challenge, CHALLENGE_LEN) != EOK) {
177         LOG_ERROR("failed to compare challenge");
178         return RESULT_BAD_MATCH;
179     }
180     return RESULT_SUCCESS;
181 }
182 
AssociateCoauthSchedule(uint64_t scheduleId,uint32_t authType,ScheduleType scheduleType)183 ResultCode AssociateCoauthSchedule(uint64_t scheduleId, uint32_t authType, ScheduleType scheduleType)
184 {
185     LOG_INFO("start");
186     if (!IsSessionExist()) {
187         LOG_ERROR("session is not exist");
188         return RESULT_NEED_INIT;
189     }
190     g_session->scheduleId = scheduleId;
191     g_session->authType = authType;
192     g_session->scheduleType = scheduleType;
193     g_session->isScheduleValid = true;
194     return RESULT_SUCCESS;
195 }
196 
BreakOffCoauthSchedule(void)197 void BreakOffCoauthSchedule(void)
198 {
199     if (!IsSessionExist()) {
200         return;
201     }
202     if (g_session->isScheduleValid) {
203         RemoveCoAuthSchedule(g_session->scheduleId);
204     }
205     g_session->isScheduleValid = false;
206 }
207 
GetEnrollScheduleInfo(uint64_t * scheduleId,uint32_t * authType)208 ResultCode GetEnrollScheduleInfo(uint64_t *scheduleId, uint32_t *authType)
209 {
210     if (scheduleId == NULL || authType == NULL) {
211         LOG_ERROR("param is null");
212         return RESULT_BAD_PARAM;
213     }
214     if (!IsSessionExist() || g_session->isScheduleValid == false) {
215         return RESULT_NEED_INIT;
216     }
217     *scheduleId = g_session->scheduleId;
218     *authType = g_session->authType;
219     return RESULT_SUCCESS;
220 }
221 
CheckSessionTimeout(void)222 ResultCode CheckSessionTimeout(void)
223 {
224     if (!IsSessionExist()) {
225         return RESULT_NEED_INIT;
226     }
227     uint64_t currentTime = GetSystemTime();
228     if (currentTime < g_session->time) {
229         LOG_ERROR("bad time, currentTime: %{public}" PRIu64 ", sessionTime: %{public}" PRIu64,
230             currentTime, g_session->time);
231         return RESULT_GENERAL_ERROR;
232     }
233     if (currentTime - g_session->time > SESSION_VALIDITY_PERIOD) {
234         LOG_ERROR("timeout, currentTime: %{public}" PRIu64 ", sessionTime: %{public}" PRIu64,
235             currentTime, g_session->time);
236         DestoryBuffer(g_session->oldRootSecret);
237         ClearCachePin(g_session->userId);
238         return RESULT_TIMEOUT;
239     }
240     return RESULT_SUCCESS;
241 }
242 
GetScheduleType(ScheduleType * scheduleType)243 ResultCode GetScheduleType(ScheduleType *scheduleType)
244 {
245     if (scheduleType == NULL) {
246         LOG_ERROR("param is invalid");
247         return RESULT_BAD_PARAM;
248     }
249     if (!IsSessionExist() || g_session->isScheduleValid == false) {
250         LOG_ERROR("session need init");
251         return RESULT_NEED_INIT;
252     }
253     *scheduleType = g_session->scheduleType;
254     return RESULT_SUCCESS;
255 }
256 
CheckSessionValid(int32_t userId)257 ResultCode CheckSessionValid(int32_t userId)
258 {
259     ResultCode ret = CheckSessionTimeout();
260     if (ret != RESULT_SUCCESS) {
261         return ret;
262     }
263     if (g_session->userId != userId) {
264         return RESULT_GENERAL_ERROR;
265     }
266     return RESULT_SUCCESS;
267 }
268 
GetChallenge(uint8_t * challenge,uint32_t challengeLen)269 ResultCode GetChallenge(uint8_t *challenge, uint32_t challengeLen)
270 {
271     if ((challenge == NULL) || (challengeLen != CHALLENGE_LEN)) {
272         LOG_ERROR("challenge is invalid");
273         return RESULT_BAD_PARAM;
274     }
275 
276     ResultCode ret = CheckSessionTimeout();
277     if (ret != RESULT_SUCCESS) {
278         LOG_ERROR("session does not exist");
279         return ret;
280     }
281     if (memcpy_s(challenge, challengeLen, g_session->challenge, CHALLENGE_LEN) != EOK) {
282         LOG_ERROR("copy challenge failed");
283         return RESULT_GENERAL_ERROR;
284     }
285 
286     return RESULT_SUCCESS;
287 }
288 
IsValidUserType(int32_t userType)289 ResultCode IsValidUserType(int32_t userType)
290 {
291     if (userType != MAIN_USER && userType != SUB_USER && userType != PRIVATE_USER) {
292         LOG_ERROR("userType is invalid");
293         return RESULT_BAD_PARAM;
294     }
295     LOG_INFO("userType is valid");
296     return RESULT_SUCCESS;
297 }
298 
SetPinChangeScence(int32_t userId,uint32_t authIntent)299 void SetPinChangeScence(int32_t userId, uint32_t authIntent)
300 {
301     if (CheckSessionValid(userId) != RESULT_SUCCESS) {
302         LOG_ERROR("session is invalid, userId: %{public}d", userId);
303         return;
304     }
305     if (authIntent == ABANDONED_PIN_AUTH) {
306         g_session->pinChangeScence = PIN_RESET_SCENCE;
307     } else {
308         g_session->pinChangeScence = PIN_UPDATE_SCENCE;
309     }
310     LOG_INFO("pinChangeScence: %{public}d", g_session->pinChangeScence);
311     return;
312 }
313 
GetPinChangeScence(int32_t userId)314 PinChangeScence GetPinChangeScence(int32_t userId)
315 {
316     if (CheckSessionValid(userId) != RESULT_SUCCESS) {
317         LOG_ERROR("session is invalid, userId: %{public}d", userId);
318         return 0;
319     }
320     LOG_INFO("pinChangeScence: %{public}d", g_session->pinChangeScence);
321     return g_session->pinChangeScence;
322 }
323 
SetOldRootSecret(int32_t userId,Buffer * rootSecret)324 void SetOldRootSecret(int32_t userId, Buffer *rootSecret)
325 {
326     if (CheckSessionValid(userId) != RESULT_SUCCESS) {
327         LOG_ERROR("session is invalid, userId: %{public}d", userId);
328         return;
329     }
330 
331     if (!CheckBufferWithSize(rootSecret, ROOT_SECRET_LEN)) {
332         LOG_ERROR("rootSecret is invalid, userId: %{public}d", userId);
333         return;
334     }
335 
336     DestoryBuffer(g_session->oldRootSecret);
337     g_session->oldRootSecret = CreateBufferByData(rootSecret->buf, rootSecret->contentSize);
338     if (g_session->oldRootSecret == NULL) {
339         LOG_ERROR("CreateBufferByData fail, userId: %{public}d", userId);
340         return;
341     }
342 
343     return;
344 }
345 
GetOldRootSecret(int32_t userId)346 Buffer *GetOldRootSecret(int32_t userId)
347 {
348     if (CheckSessionValid(userId) != RESULT_SUCCESS) {
349         LOG_ERROR("session is invalid, userId: %{public}d", userId);
350         return NULL;
351     }
352     return g_session->oldRootSecret;
353 }
354 
SetCurRootSecret(int32_t userId,Buffer * rootSecret)355 void SetCurRootSecret(int32_t userId, Buffer *rootSecret)
356 {
357     if (CheckSessionValid(userId) != RESULT_SUCCESS) {
358         LOG_ERROR("session is invalid, userId: %{public}d", userId);
359         return;
360     }
361 
362     if (!CheckBufferWithSize(rootSecret, ROOT_SECRET_LEN)) {
363         LOG_ERROR("rootSecret is invalid, userId: %{public}d", userId);
364         return;
365     }
366 
367     DestoryBuffer(g_session->curRootSecret);
368     g_session->curRootSecret = CreateBufferByData(rootSecret->buf, rootSecret->contentSize);
369     if (g_session->curRootSecret == NULL) {
370         LOG_ERROR("CreateBufferByData fail, userId: %{public}d", userId);
371         return;
372     }
373 
374     return;
375 }
376 
GetCurRootSecret(int32_t userId)377 Buffer *GetCurRootSecret(int32_t userId)
378 {
379     if (CheckSessionValid(userId) != RESULT_SUCCESS) {
380         LOG_ERROR("session is invalid, userId: %{public}d", userId);
381         return NULL;
382     }
383     return g_session->curRootSecret;
384 }
385 
SetNewRootSecret(int32_t userId,Buffer * rootSecret)386 ResultCode SetNewRootSecret(int32_t userId, Buffer *rootSecret)
387 {
388     if (CheckSessionValid(userId) != RESULT_SUCCESS) {
389         LOG_ERROR("session is invalid, userId: %{public}d", userId);
390         return RESULT_GENERAL_ERROR;
391     }
392 
393     if (!CheckBufferWithSize(rootSecret, ROOT_SECRET_LEN)) {
394         LOG_ERROR("rootSecret is invalid, userId: %{public}d", userId);
395         return RESULT_GENERAL_ERROR;
396     }
397 
398     DestoryBuffer(g_session->newRootSecret);
399     g_session->newRootSecret = CreateBufferByData(rootSecret->buf, rootSecret->contentSize);
400     if (g_session->newRootSecret == NULL) {
401         LOG_ERROR("CreateBufferByData fail, userId: %{public}d", userId);
402         return RESULT_NO_MEMORY;
403     }
404 
405     return RESULT_SUCCESS;
406 }
407 
GetNewRootSecret(int32_t userId)408 Buffer *GetNewRootSecret(int32_t userId)
409 {
410     if (CheckSessionValid(userId) != RESULT_SUCCESS) {
411         LOG_ERROR("session is invalid, userId: %{public}d", userId);
412         return NULL;
413     }
414     return g_session->newRootSecret;
415 }