1094332d3Sopenharmony_ci/* 2094332d3Sopenharmony_ci * Copyright (C) 2022 Huawei Device Co., Ltd. 3094332d3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4094332d3Sopenharmony_ci * you may not use this file except in compliance with the License. 5094332d3Sopenharmony_ci * You may obtain a copy of the License at 6094332d3Sopenharmony_ci * 7094332d3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8094332d3Sopenharmony_ci * 9094332d3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10094332d3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11094332d3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12094332d3Sopenharmony_ci * See the License for the specific language governing permissions and 13094332d3Sopenharmony_ci * limitations under the License. 14094332d3Sopenharmony_ci */ 15094332d3Sopenharmony_ci 16094332d3Sopenharmony_ci#include "idm_session.h" 17094332d3Sopenharmony_ci 18094332d3Sopenharmony_ci#include <inttypes.h> 19094332d3Sopenharmony_ci#include "securec.h" 20094332d3Sopenharmony_ci 21094332d3Sopenharmony_ci#include "adaptor_algorithm.h" 22094332d3Sopenharmony_ci#include "adaptor_log.h" 23094332d3Sopenharmony_ci#include "adaptor_memory.h" 24094332d3Sopenharmony_ci#include "adaptor_time.h" 25094332d3Sopenharmony_ci#include "coauth.h" 26094332d3Sopenharmony_ci#include "linked_list.h" 27094332d3Sopenharmony_ci#include "idm_database.h" 28094332d3Sopenharmony_ci 29094332d3Sopenharmony_ci#define SESSION_VALIDITY_PERIOD (10 * 60 * 1000) 30094332d3Sopenharmony_ci#define MAX_CHALLENGE_GENERATION_TIMES 5 31094332d3Sopenharmony_ci 32094332d3Sopenharmony_ci#ifdef IAM_TEST_ENABLE 33094332d3Sopenharmony_ci#define IAM_STATIC 34094332d3Sopenharmony_ci#else 35094332d3Sopenharmony_ci#define IAM_STATIC static 36094332d3Sopenharmony_ci#endif 37094332d3Sopenharmony_ci 38094332d3Sopenharmony_ci// User IDM session information. 39094332d3Sopenharmony_cistruct SessionInfo { 40094332d3Sopenharmony_ci int32_t userId; 41094332d3Sopenharmony_ci uint32_t authType; 42094332d3Sopenharmony_ci uint64_t time; 43094332d3Sopenharmony_ci uint64_t validAuthTokenTime; 44094332d3Sopenharmony_ci uint8_t challenge[CHALLENGE_LEN]; 45094332d3Sopenharmony_ci uint64_t scheduleId; 46094332d3Sopenharmony_ci bool isUpdate; 47094332d3Sopenharmony_ci bool isScheduleValid; 48094332d3Sopenharmony_ci} *g_session; 49094332d3Sopenharmony_ci 50094332d3Sopenharmony_ciIAM_STATIC Buffer *g_cacheRootSecret = NULL; 51094332d3Sopenharmony_ci 52094332d3Sopenharmony_ciIAM_STATIC void DestroyCacheRootSecret(void) 53094332d3Sopenharmony_ci{ 54094332d3Sopenharmony_ci DestoryBuffer(g_cacheRootSecret); 55094332d3Sopenharmony_ci g_cacheRootSecret = NULL; 56094332d3Sopenharmony_ci} 57094332d3Sopenharmony_ci 58094332d3Sopenharmony_ciIAM_STATIC bool IsSessionExist(void) 59094332d3Sopenharmony_ci{ 60094332d3Sopenharmony_ci if (g_session == NULL) { 61094332d3Sopenharmony_ci LOG_INFO("the session does not exist"); 62094332d3Sopenharmony_ci return false; 63094332d3Sopenharmony_ci } 64094332d3Sopenharmony_ci return true; 65094332d3Sopenharmony_ci} 66094332d3Sopenharmony_ci 67094332d3Sopenharmony_ciIAM_STATIC ResultCode GenerateChallenge(uint8_t *challenge, uint32_t challengeLen) 68094332d3Sopenharmony_ci{ 69094332d3Sopenharmony_ci for (uint32_t i = 0; i < MAX_CHALLENGE_GENERATION_TIMES; ++i) { 70094332d3Sopenharmony_ci if (SecureRandom(challenge, challengeLen) != RESULT_SUCCESS) { 71094332d3Sopenharmony_ci LOG_ERROR("get challenge failed"); 72094332d3Sopenharmony_ci return RESULT_GENERAL_ERROR; 73094332d3Sopenharmony_ci } 74094332d3Sopenharmony_ci for (uint32_t j = 0; j < challengeLen; j++) { 75094332d3Sopenharmony_ci if (challenge[j] != 0) { 76094332d3Sopenharmony_ci return RESULT_SUCCESS; 77094332d3Sopenharmony_ci } 78094332d3Sopenharmony_ci } 79094332d3Sopenharmony_ci LOG_INFO("challenge is invalid, get again."); 80094332d3Sopenharmony_ci } 81094332d3Sopenharmony_ci LOG_ERROR("a rare failture"); 82094332d3Sopenharmony_ci return RESULT_GENERAL_ERROR; 83094332d3Sopenharmony_ci} 84094332d3Sopenharmony_ci 85094332d3Sopenharmony_ciResultCode OpenEditSession(int32_t userId, uint8_t *challenge, uint32_t challengeLen) 86094332d3Sopenharmony_ci{ 87094332d3Sopenharmony_ci if (challenge == NULL || challengeLen != CHALLENGE_LEN) { 88094332d3Sopenharmony_ci LOG_ERROR("challenge is null"); 89094332d3Sopenharmony_ci return RESULT_BAD_PARAM; 90094332d3Sopenharmony_ci } 91094332d3Sopenharmony_ci (void)memset_s(challenge, CHALLENGE_LEN, 0, CHALLENGE_LEN); 92094332d3Sopenharmony_ci if (IsSessionExist()) { 93094332d3Sopenharmony_ci (void)CloseEditSession(); 94094332d3Sopenharmony_ci } 95094332d3Sopenharmony_ci g_session = Malloc(sizeof(struct SessionInfo)); 96094332d3Sopenharmony_ci if (g_session == NULL) { 97094332d3Sopenharmony_ci LOG_ERROR("g_session malloc failed"); 98094332d3Sopenharmony_ci return RESULT_NO_MEMORY; 99094332d3Sopenharmony_ci } 100094332d3Sopenharmony_ci if (memset_s(g_session, sizeof(struct SessionInfo), 0, sizeof(struct SessionInfo)) != EOK) { 101094332d3Sopenharmony_ci LOG_ERROR("g_session set failed"); 102094332d3Sopenharmony_ci Free(g_session); 103094332d3Sopenharmony_ci g_session = NULL; 104094332d3Sopenharmony_ci return RESULT_GENERAL_ERROR; 105094332d3Sopenharmony_ci } 106094332d3Sopenharmony_ci g_session->userId = userId; 107094332d3Sopenharmony_ci ResultCode ret = GenerateChallenge(g_session->challenge, CHALLENGE_LEN); 108094332d3Sopenharmony_ci if (ret != RESULT_SUCCESS) { 109094332d3Sopenharmony_ci LOG_ERROR("failed to generate challenge"); 110094332d3Sopenharmony_ci Free(g_session); 111094332d3Sopenharmony_ci g_session = NULL; 112094332d3Sopenharmony_ci return ret; 113094332d3Sopenharmony_ci } 114094332d3Sopenharmony_ci g_session->time = GetSystemTime(); 115094332d3Sopenharmony_ci g_session->validAuthTokenTime = g_session->time; 116094332d3Sopenharmony_ci 117094332d3Sopenharmony_ci if (memcpy_s(challenge, CHALLENGE_LEN, g_session->challenge, CHALLENGE_LEN) != EOK) { 118094332d3Sopenharmony_ci LOG_ERROR("failed to copy challenge"); 119094332d3Sopenharmony_ci Free(g_session); 120094332d3Sopenharmony_ci g_session = NULL; 121094332d3Sopenharmony_ci return RESULT_BAD_COPY; 122094332d3Sopenharmony_ci } 123094332d3Sopenharmony_ci g_session->isScheduleValid = false; 124094332d3Sopenharmony_ci return RESULT_SUCCESS; 125094332d3Sopenharmony_ci} 126094332d3Sopenharmony_ci 127094332d3Sopenharmony_civoid RefreshValidTokenTime(void) 128094332d3Sopenharmony_ci{ 129094332d3Sopenharmony_ci if (!IsSessionExist()) { 130094332d3Sopenharmony_ci LOG_ERROR("session is invalid"); 131094332d3Sopenharmony_ci return; 132094332d3Sopenharmony_ci } 133094332d3Sopenharmony_ci g_session->validAuthTokenTime = GetSystemTime(); 134094332d3Sopenharmony_ci} 135094332d3Sopenharmony_ci 136094332d3Sopenharmony_cibool IsValidTokenTime(uint64_t tokenTime) 137094332d3Sopenharmony_ci{ 138094332d3Sopenharmony_ci if (!IsSessionExist()) { 139094332d3Sopenharmony_ci LOG_ERROR("session is invalid"); 140094332d3Sopenharmony_ci return false; 141094332d3Sopenharmony_ci } 142094332d3Sopenharmony_ci return tokenTime >= g_session->validAuthTokenTime; 143094332d3Sopenharmony_ci} 144094332d3Sopenharmony_ci 145094332d3Sopenharmony_ciResultCode CloseEditSession(void) 146094332d3Sopenharmony_ci{ 147094332d3Sopenharmony_ci if (!IsSessionExist()) { 148094332d3Sopenharmony_ci return RESULT_GENERAL_ERROR; 149094332d3Sopenharmony_ci } 150094332d3Sopenharmony_ci DestroyCacheRootSecret(); 151094332d3Sopenharmony_ci ClearCachePin(g_session->userId); 152094332d3Sopenharmony_ci Free(g_session); 153094332d3Sopenharmony_ci g_session = NULL; 154094332d3Sopenharmony_ci return RESULT_SUCCESS; 155094332d3Sopenharmony_ci} 156094332d3Sopenharmony_ci 157094332d3Sopenharmony_ciResultCode GetUserId(int32_t *userId) 158094332d3Sopenharmony_ci{ 159094332d3Sopenharmony_ci if (userId == NULL || !IsSessionExist()) { 160094332d3Sopenharmony_ci LOG_ERROR("param is invalid"); 161094332d3Sopenharmony_ci return RESULT_BAD_PARAM; 162094332d3Sopenharmony_ci } 163094332d3Sopenharmony_ci *userId = g_session->userId; 164094332d3Sopenharmony_ci return RESULT_SUCCESS; 165094332d3Sopenharmony_ci} 166094332d3Sopenharmony_ci 167094332d3Sopenharmony_ciResultCode CheckChallenge(uint8_t *challenge, uint32_t challengeLen) 168094332d3Sopenharmony_ci{ 169094332d3Sopenharmony_ci if (challenge == NULL || challengeLen != CHALLENGE_LEN) { 170094332d3Sopenharmony_ci LOG_ERROR("param is invalid"); 171094332d3Sopenharmony_ci return RESULT_BAD_PARAM; 172094332d3Sopenharmony_ci } 173094332d3Sopenharmony_ci if (!IsSessionExist()) { 174094332d3Sopenharmony_ci LOG_ERROR("param is invalid"); 175094332d3Sopenharmony_ci return RESULT_NEED_INIT; 176094332d3Sopenharmony_ci } 177094332d3Sopenharmony_ci if (memcmp(challenge, g_session->challenge, CHALLENGE_LEN) != EOK) { 178094332d3Sopenharmony_ci LOG_ERROR("failed to compare challenge"); 179094332d3Sopenharmony_ci return RESULT_BAD_MATCH; 180094332d3Sopenharmony_ci } 181094332d3Sopenharmony_ci return RESULT_SUCCESS; 182094332d3Sopenharmony_ci} 183094332d3Sopenharmony_ci 184094332d3Sopenharmony_ciResultCode AssociateCoauthSchedule(uint64_t scheduleId, uint32_t authType, bool isUpdate) 185094332d3Sopenharmony_ci{ 186094332d3Sopenharmony_ci if (!IsSessionExist()) { 187094332d3Sopenharmony_ci return RESULT_NEED_INIT; 188094332d3Sopenharmony_ci } 189094332d3Sopenharmony_ci g_session->scheduleId = scheduleId; 190094332d3Sopenharmony_ci g_session->authType = authType; 191094332d3Sopenharmony_ci g_session->isUpdate = isUpdate; 192094332d3Sopenharmony_ci g_session->isScheduleValid = true; 193094332d3Sopenharmony_ci return RESULT_SUCCESS; 194094332d3Sopenharmony_ci} 195094332d3Sopenharmony_ci 196094332d3Sopenharmony_civoid BreakOffCoauthSchedule(void) 197094332d3Sopenharmony_ci{ 198094332d3Sopenharmony_ci if (!IsSessionExist()) { 199094332d3Sopenharmony_ci return; 200094332d3Sopenharmony_ci } 201094332d3Sopenharmony_ci if (g_session->isScheduleValid) { 202094332d3Sopenharmony_ci RemoveCoAuthSchedule(g_session->scheduleId); 203094332d3Sopenharmony_ci } 204094332d3Sopenharmony_ci g_session->isScheduleValid = false; 205094332d3Sopenharmony_ci} 206094332d3Sopenharmony_ci 207094332d3Sopenharmony_ciResultCode GetEnrollScheduleInfo(uint64_t *scheduleId, uint32_t *authType) 208094332d3Sopenharmony_ci{ 209094332d3Sopenharmony_ci if (scheduleId == NULL || authType == NULL) { 210094332d3Sopenharmony_ci LOG_ERROR("param is null"); 211094332d3Sopenharmony_ci return RESULT_BAD_PARAM; 212094332d3Sopenharmony_ci } 213094332d3Sopenharmony_ci if (!IsSessionExist() || g_session->isScheduleValid == false) { 214094332d3Sopenharmony_ci return RESULT_NEED_INIT; 215094332d3Sopenharmony_ci } 216094332d3Sopenharmony_ci *scheduleId = g_session->scheduleId; 217094332d3Sopenharmony_ci *authType = g_session->authType; 218094332d3Sopenharmony_ci return RESULT_SUCCESS; 219094332d3Sopenharmony_ci} 220094332d3Sopenharmony_ci 221094332d3Sopenharmony_ciResultCode CheckSessionTimeout(void) 222094332d3Sopenharmony_ci{ 223094332d3Sopenharmony_ci if (!IsSessionExist()) { 224094332d3Sopenharmony_ci return RESULT_NEED_INIT; 225094332d3Sopenharmony_ci } 226094332d3Sopenharmony_ci uint64_t currentTime = GetSystemTime(); 227094332d3Sopenharmony_ci if (currentTime < g_session->time) { 228094332d3Sopenharmony_ci LOG_ERROR("bad time, currentTime: %{public}" PRIu64 ", sessionTime: %{public}" PRIu64, 229094332d3Sopenharmony_ci currentTime, g_session->time); 230094332d3Sopenharmony_ci return RESULT_GENERAL_ERROR; 231094332d3Sopenharmony_ci } 232094332d3Sopenharmony_ci if (currentTime - g_session->time > SESSION_VALIDITY_PERIOD) { 233094332d3Sopenharmony_ci LOG_ERROR("timeout, currentTime: %{public}" PRIu64 ", sessionTime: %{public}" PRIu64, 234094332d3Sopenharmony_ci currentTime, g_session->time); 235094332d3Sopenharmony_ci DestroyCacheRootSecret(); 236094332d3Sopenharmony_ci ClearCachePin(g_session->userId); 237094332d3Sopenharmony_ci return RESULT_TIMEOUT; 238094332d3Sopenharmony_ci } 239094332d3Sopenharmony_ci return RESULT_SUCCESS; 240094332d3Sopenharmony_ci} 241094332d3Sopenharmony_ci 242094332d3Sopenharmony_ciResultCode GetIsUpdate(bool *isUpdate) 243094332d3Sopenharmony_ci{ 244094332d3Sopenharmony_ci if (isUpdate == NULL) { 245094332d3Sopenharmony_ci LOG_ERROR("param is invalid"); 246094332d3Sopenharmony_ci return RESULT_BAD_PARAM; 247094332d3Sopenharmony_ci } 248094332d3Sopenharmony_ci if (!IsSessionExist() || g_session->isScheduleValid == false) { 249094332d3Sopenharmony_ci LOG_ERROR("session need init"); 250094332d3Sopenharmony_ci return RESULT_NEED_INIT; 251094332d3Sopenharmony_ci } 252094332d3Sopenharmony_ci *isUpdate = g_session->isUpdate; 253094332d3Sopenharmony_ci return RESULT_SUCCESS; 254094332d3Sopenharmony_ci} 255094332d3Sopenharmony_ci 256094332d3Sopenharmony_ciResultCode CheckSessionValid(int32_t userId) 257094332d3Sopenharmony_ci{ 258094332d3Sopenharmony_ci ResultCode ret = CheckSessionTimeout(); 259094332d3Sopenharmony_ci if (ret != RESULT_SUCCESS) { 260094332d3Sopenharmony_ci return ret; 261094332d3Sopenharmony_ci } 262094332d3Sopenharmony_ci if (g_session->userId != userId) { 263094332d3Sopenharmony_ci return RESULT_GENERAL_ERROR; 264094332d3Sopenharmony_ci } 265094332d3Sopenharmony_ci return RESULT_SUCCESS; 266094332d3Sopenharmony_ci} 267094332d3Sopenharmony_ci 268094332d3Sopenharmony_civoid CacheRootSecret(int32_t userId, Buffer *rootSecret) 269094332d3Sopenharmony_ci{ 270094332d3Sopenharmony_ci /* The presence of a session is the pin change phase */ 271094332d3Sopenharmony_ci if (CheckSessionTimeout() != RESULT_SUCCESS) { 272094332d3Sopenharmony_ci return; 273094332d3Sopenharmony_ci } 274094332d3Sopenharmony_ci if (g_session->userId != userId) { 275094332d3Sopenharmony_ci LOG_ERROR("CacheRootSecret check user id fail"); 276094332d3Sopenharmony_ci return; 277094332d3Sopenharmony_ci } 278094332d3Sopenharmony_ci if (!CheckBufferWithSize(rootSecret, ROOT_SECRET_LEN)) { 279094332d3Sopenharmony_ci LOG_ERROR("check root secret fail"); 280094332d3Sopenharmony_ci return; 281094332d3Sopenharmony_ci } 282094332d3Sopenharmony_ci DestroyCacheRootSecret(); 283094332d3Sopenharmony_ci g_cacheRootSecret = CopyBuffer(rootSecret); 284094332d3Sopenharmony_ci if (g_cacheRootSecret == NULL) { 285094332d3Sopenharmony_ci LOG_ERROR("copy cache root secret fail"); 286094332d3Sopenharmony_ci } 287094332d3Sopenharmony_ci} 288094332d3Sopenharmony_ci 289094332d3Sopenharmony_ciBuffer *GetCacheRootSecret(int32_t userId) 290094332d3Sopenharmony_ci{ 291094332d3Sopenharmony_ci if (CheckSessionTimeout() != RESULT_SUCCESS) { 292094332d3Sopenharmony_ci return NULL; 293094332d3Sopenharmony_ci } 294094332d3Sopenharmony_ci if (g_session->userId != userId) { 295094332d3Sopenharmony_ci LOG_ERROR("GetCacheRootSecret check user id fail"); 296094332d3Sopenharmony_ci return NULL; 297094332d3Sopenharmony_ci } 298094332d3Sopenharmony_ci if (g_cacheRootSecret == NULL) { 299094332d3Sopenharmony_ci LOG_ERROR("no cache root secret"); 300094332d3Sopenharmony_ci return NULL; 301094332d3Sopenharmony_ci } 302094332d3Sopenharmony_ci return CopyBuffer(g_cacheRootSecret); 303094332d3Sopenharmony_ci} 304094332d3Sopenharmony_ci 305094332d3Sopenharmony_ciResultCode GetChallenge(uint8_t *challenge, uint32_t challengeLen) 306094332d3Sopenharmony_ci{ 307094332d3Sopenharmony_ci if ((challenge == NULL) || (challengeLen != CHALLENGE_LEN)) { 308094332d3Sopenharmony_ci LOG_ERROR("challenge is invalid"); 309094332d3Sopenharmony_ci return RESULT_BAD_PARAM; 310094332d3Sopenharmony_ci } 311094332d3Sopenharmony_ci 312094332d3Sopenharmony_ci ResultCode ret = CheckSessionTimeout(); 313094332d3Sopenharmony_ci if (ret != RESULT_SUCCESS) { 314094332d3Sopenharmony_ci LOG_ERROR("session does not exist"); 315094332d3Sopenharmony_ci return ret; 316094332d3Sopenharmony_ci } 317094332d3Sopenharmony_ci if (memcpy_s(challenge, challengeLen, g_session->challenge, CHALLENGE_LEN) != EOK) { 318094332d3Sopenharmony_ci LOG_ERROR("copy challenge failed"); 319094332d3Sopenharmony_ci return RESULT_GENERAL_ERROR; 320094332d3Sopenharmony_ci } 321094332d3Sopenharmony_ci 322094332d3Sopenharmony_ci return RESULT_SUCCESS; 323094332d3Sopenharmony_ci} 324094332d3Sopenharmony_ci 325094332d3Sopenharmony_ciResultCode IsValidUserType(int32_t userType) 326094332d3Sopenharmony_ci{ 327094332d3Sopenharmony_ci if (userType != MAIN_USER && userType != SUB_USER && userType != PRIVATE_USER) { 328094332d3Sopenharmony_ci LOG_ERROR("userType is invalid"); 329094332d3Sopenharmony_ci return RESULT_BAD_PARAM; 330094332d3Sopenharmony_ci } 331094332d3Sopenharmony_ci LOG_INFO("userType is valid"); 332094332d3Sopenharmony_ci return RESULT_SUCCESS; 333094332d3Sopenharmony_ci}