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 "auth_session_key.h"
17
18 #include <securec.h>
19
20 #include "auth_common.h"
21 #include "auth_log.h"
22 #include "auth_manager.h"
23 #include "auth_session_fsm.h"
24 #include "softbus_adapter_mem.h"
25 #include "softbus_adapter_socket.h"
26 #include "softbus_def.h"
27 #include "softbus_errcode.h"
28
29 #define SESSION_KEY_MAX_NUM 10
30 #define LAST_USE_THRESHOLD_MS (30 * 1000L) /* 30s */
31
32 typedef struct {
33 int32_t index;
34 SessionKey key;
35 uint64_t lastUseTime;
36 ListNode node;
37 } SessionKeyItem;
38
RemoveOldKey(SessionKeyList * list)39 static void RemoveOldKey(SessionKeyList *list)
40 {
41 uint32_t num = 0;
42 SessionKeyItem *item = NULL;
43 LIST_FOR_EACH_ENTRY(item, (const ListNode *)list, SessionKeyItem, node) {
44 num++;
45 }
46 if (num <= SESSION_KEY_MAX_NUM) {
47 return;
48 }
49 item = LIST_ENTRY(GET_LIST_HEAD(list), SessionKeyItem, node);
50 ListDelete(&item->node);
51 AUTH_LOGI(AUTH_FSM, "session key num reach max, remove the oldest, index=%{public}d", item->index);
52 (void)memset_s(&item->key, sizeof(SessionKey), 0, sizeof(SessionKey));
53 SoftBusFree(item);
54 }
55
InitSessionKeyList(SessionKeyList * list)56 void InitSessionKeyList(SessionKeyList *list)
57 {
58 AUTH_CHECK_AND_RETURN_LOGE(list != NULL, AUTH_FSM, "list is NULL");
59 ListInit(list);
60 }
61
DupSessionKeyList(const SessionKeyList * srcList,SessionKeyList * dstList)62 int32_t DupSessionKeyList(const SessionKeyList *srcList, SessionKeyList *dstList)
63 {
64 AUTH_CHECK_AND_RETURN_RET_LOGE(srcList != NULL, SOFTBUS_INVALID_PARAM, AUTH_FSM, "srcList is NULL");
65 AUTH_CHECK_AND_RETURN_RET_LOGE(dstList != NULL, SOFTBUS_INVALID_PARAM, AUTH_FSM, "dstList is NULL");
66 SessionKeyItem *item = NULL;
67 SessionKeyItem *newItem = NULL;
68 LIST_FOR_EACH_ENTRY(item, srcList, SessionKeyItem, node) {
69 newItem = (SessionKeyItem *)DupMemBuffer((uint8_t *)item, sizeof(SessionKeyItem));
70 if (newItem == NULL) {
71 AUTH_LOGE(AUTH_FSM, "malloc newItem fail");
72 DestroySessionKeyList(dstList);
73 return SOFTBUS_MALLOC_ERR;
74 }
75 ListTailInsert(dstList, &newItem->node);
76 }
77 return SOFTBUS_OK;
78 }
79
DestroySessionKeyList(SessionKeyList * list)80 void DestroySessionKeyList(SessionKeyList *list)
81 {
82 AUTH_CHECK_AND_RETURN_LOGE(list != NULL, AUTH_FSM, "list is NULL");
83 SessionKeyItem *item = NULL;
84 SessionKeyItem *next = NULL;
85 LIST_FOR_EACH_ENTRY_SAFE(item, next, list, SessionKeyItem, node) {
86 ListDelete(&item->node);
87 (void)memset_s(&item->key, sizeof(SessionKey), 0, sizeof(SessionKey));
88 SoftBusFree(item);
89 }
90 }
91
HasSessionKey(const SessionKeyList * list)92 bool HasSessionKey(const SessionKeyList *list)
93 {
94 AUTH_CHECK_AND_RETURN_RET_LOGE(list != NULL, false, AUTH_FSM, "list is NULL");
95 return !IsListEmpty(list);
96 }
97
AddSessionKey(SessionKeyList * list,int32_t index,const SessionKey * key)98 int32_t AddSessionKey(SessionKeyList *list, int32_t index, const SessionKey *key)
99 {
100 AUTH_CHECK_AND_RETURN_RET_LOGE(key != NULL, SOFTBUS_INVALID_PARAM, AUTH_FSM, "key is NULL");
101 AUTH_CHECK_AND_RETURN_RET_LOGE(list != NULL, SOFTBUS_INVALID_PARAM, AUTH_FSM, "list is NULL");
102 AUTH_LOGD(AUTH_FSM, "keyLen=%{public}d", key->len);
103 SessionKeyItem *item = (SessionKeyItem *)SoftBusMalloc(sizeof(SessionKeyItem));
104 if (item == NULL) {
105 AUTH_LOGE(AUTH_FSM, "malloc SessionKeyItem fail");
106 return SOFTBUS_MALLOC_ERR;
107 }
108 item->index = index;
109 item->lastUseTime = GetCurrentTimeMs();
110 if (memcpy_s(&item->key, sizeof(item->key), key, sizeof(SessionKey)) != EOK) {
111 AUTH_LOGE(AUTH_FSM, "add session key fail");
112 SoftBusFree(item);
113 return SOFTBUS_MEM_ERR;
114 }
115 ListTailInsert((ListNode *)list, &item->node);
116 RemoveOldKey(list);
117 return SOFTBUS_OK;
118 }
119
GetLatestSessionKey(const SessionKeyList * list,int32_t * index,SessionKey * key)120 int32_t GetLatestSessionKey(const SessionKeyList *list, int32_t *index, SessionKey *key)
121 {
122 AUTH_CHECK_AND_RETURN_RET_LOGE(list != NULL, SOFTBUS_INVALID_PARAM, AUTH_FSM, "list is NULL");
123 AUTH_CHECK_AND_RETURN_RET_LOGE(index != NULL, SOFTBUS_INVALID_PARAM, AUTH_FSM, "index is NULL");
124 AUTH_CHECK_AND_RETURN_RET_LOGE(key != NULL, SOFTBUS_INVALID_PARAM, AUTH_FSM, "key is NULL");
125 if (IsListEmpty((const ListNode *)list)) {
126 AUTH_LOGE(AUTH_FSM, "session key list is empty");
127 return SOFTBUS_ERR;
128 }
129 SessionKeyItem *item = LIST_ENTRY(GET_LIST_TAIL((const ListNode *)list), SessionKeyItem, node);
130 if (item == NULL) {
131 AUTH_LOGE(AUTH_FSM, "invalid session key item");
132 return SOFTBUS_ERR;
133 }
134 if (memcpy_s(key, sizeof(SessionKey), &item->key, sizeof(item->key)) != EOK) {
135 AUTH_LOGE(AUTH_FSM, "copy session key fail.");
136 return SOFTBUS_MEM_ERR;
137 }
138 item->lastUseTime = GetCurrentTimeMs();
139 *index = item->index;
140 AUTH_LOGD(AUTH_FSM, "get session key succ, index=%{public}d", item->index);
141 return SOFTBUS_OK;
142 }
143
GetSessionKeyByIndex(const SessionKeyList * list,int32_t index,SessionKey * key)144 int32_t GetSessionKeyByIndex(const SessionKeyList *list, int32_t index, SessionKey *key)
145 {
146 AUTH_CHECK_AND_RETURN_RET_LOGE(list != NULL, SOFTBUS_INVALID_PARAM, AUTH_FSM, "list is NULL");
147 AUTH_CHECK_AND_RETURN_RET_LOGE(key != NULL, SOFTBUS_INVALID_PARAM, AUTH_FSM, "key is NULL");
148 SessionKeyItem *item = NULL;
149 LIST_FOR_EACH_ENTRY(item, (const ListNode *)list, SessionKeyItem, node) {
150 if (item->index != index) {
151 continue;
152 }
153 if (memcpy_s(key, sizeof(SessionKey), &item->key, sizeof(item->key)) != EOK) {
154 AUTH_LOGE(AUTH_FSM, "get session key fail, index=%{public}d", index);
155 return SOFTBUS_MEM_ERR;
156 }
157 item->lastUseTime = GetCurrentTimeMs();
158 AUTH_LOGD(AUTH_FSM, "get session key succ, index=%{public}d", index);
159 return SOFTBUS_OK;
160 }
161 AUTH_LOGE(AUTH_FSM, "session key not found, index=%{public}d", index);
162 return SOFTBUS_ERR;
163 }
164
RemoveSessionkeyByIndex(SessionKeyList * list,int32_t index)165 void RemoveSessionkeyByIndex(SessionKeyList *list, int32_t index)
166 {
167 AUTH_CHECK_AND_RETURN_LOGE(list != NULL, AUTH_FSM, "list is NULL");
168 bool isFind = false;
169 SessionKeyItem *item = NULL;
170 LIST_FOR_EACH_ENTRY(item, (const ListNode *)list, SessionKeyItem, node) {
171 if (item->index == index) {
172 isFind = true;
173 break;
174 }
175 }
176 if (isFind) {
177 ListDelete(&item->node);
178 SoftBusFree(item);
179 } else {
180 AUTH_LOGE(AUTH_FSM, "Remove Session key not found, index=%{public}d", index);
181 }
182 }
183
EncryptData(const SessionKeyList * list,const uint8_t * inData,uint32_t inLen,uint8_t * outData,uint32_t * outLen)184 int32_t EncryptData(const SessionKeyList *list, const uint8_t *inData, uint32_t inLen,
185 uint8_t *outData, uint32_t *outLen)
186 {
187 if (list == NULL || inData == NULL || inLen == 0 || outData == NULL ||
188 *outLen < (inLen + ENCRYPT_OVER_HEAD_LEN)) {
189 AUTH_LOGE(AUTH_FSM, "invalid param");
190 return SOFTBUS_INVALID_PARAM;
191 }
192 int32_t index = 0;
193 SessionKey sessionKey;
194 if (GetLatestSessionKey(list, &index, &sessionKey) != SOFTBUS_OK) {
195 AUTH_LOGE(AUTH_FSM, "get key fail");
196 return SOFTBUS_ENCRYPT_ERR;
197 }
198 /* pack key index */
199 *(uint32_t *)outData = SoftBusHtoLl((uint32_t)index);
200 AesGcmCipherKey cipherKey = {.keyLen = sessionKey.len};
201 if (memcpy_s(cipherKey.key, SESSION_KEY_LENGTH, sessionKey.value, sessionKey.len) != EOK) {
202 AUTH_LOGE(AUTH_FSM, "set key fail");
203 (void)memset_s(&sessionKey, sizeof(SessionKey), 0, sizeof(SessionKey));
204 return SOFTBUS_MEM_ERR;
205 }
206 (void)memset_s(&sessionKey, sizeof(SessionKey), 0, sizeof(SessionKey));
207 int32_t ret = SoftBusEncryptDataWithSeq(&cipherKey, inData, inLen, outData + ENCRYPT_INDEX_LEN, outLen, index);
208 (void)memset_s(&cipherKey, sizeof(AesGcmCipherKey), 0, sizeof(AesGcmCipherKey));
209 if (ret != SOFTBUS_OK) {
210 AUTH_LOGE(AUTH_FSM, "SoftBusEncryptDataWithSeq fail=%{public}d", ret);
211 return SOFTBUS_ENCRYPT_ERR;
212 }
213 *outLen += ENCRYPT_INDEX_LEN;
214 return SOFTBUS_OK;
215 }
216
DecryptData(const SessionKeyList * list,const uint8_t * inData,uint32_t inLen,uint8_t * outData,uint32_t * outLen)217 int32_t DecryptData(const SessionKeyList *list, const uint8_t *inData, uint32_t inLen,
218 uint8_t *outData, uint32_t *outLen)
219 {
220 if (list == NULL || inData == NULL || outData == NULL || inLen <= ENCRYPT_OVER_HEAD_LEN ||
221 *outLen < (inLen - ENCRYPT_OVER_HEAD_LEN)) {
222 AUTH_LOGE(AUTH_FSM, "invalid param");
223 return SOFTBUS_INVALID_PARAM;
224 }
225 /* unpack key index */
226 int32_t index = (int32_t)SoftBusLtoHl(*(uint32_t *)inData);
227 SessionKey sessionKey;
228 if (GetSessionKeyByIndex(list, index, &sessionKey) != SOFTBUS_OK) {
229 AUTH_LOGE(AUTH_FSM, "get key fail");
230 return SOFTBUS_DECRYPT_ERR;
231 }
232 AesGcmCipherKey cipherKey = {.keyLen = sessionKey.len};
233 if (memcpy_s(cipherKey.key, SESSION_KEY_LENGTH, sessionKey.value, sessionKey.len) != EOK) {
234 AUTH_LOGE(AUTH_FSM, "set key fail");
235 (void)memset_s(&sessionKey, sizeof(SessionKey), 0, sizeof(SessionKey));
236 return SOFTBUS_MEM_ERR;
237 }
238 (void)memset_s(&sessionKey, sizeof(SessionKey), 0, sizeof(SessionKey));
239 int32_t ret = SoftBusDecryptDataWithSeq(&cipherKey, inData + ENCRYPT_INDEX_LEN, inLen - ENCRYPT_INDEX_LEN,
240 outData, outLen, index);
241 (void)memset_s(&cipherKey, sizeof(AesGcmCipherKey), 0, sizeof(AesGcmCipherKey));
242 if (ret != SOFTBUS_OK) {
243 AUTH_LOGE(AUTH_FSM, "SoftBusDecryptDataWithSeq fail=%{public}d", ret);
244 return SOFTBUS_DECRYPT_ERR;
245 }
246 return SOFTBUS_OK;
247 }
248
EncryptInner(const SessionKeyList * list,const uint8_t * inData,uint32_t inLen,uint8_t ** outData,uint32_t * outLen)249 int32_t EncryptInner(const SessionKeyList *list, const uint8_t *inData, uint32_t inLen,
250 uint8_t **outData, uint32_t *outLen)
251 {
252 if (list == NULL || inData == NULL || inLen == 0 || outData == NULL || outLen == NULL) {
253 AUTH_LOGE(AUTH_FSM, "invalid param");
254 return SOFTBUS_INVALID_PARAM;
255 }
256 uint32_t encDataLen = inLen + ENCRYPT_OVER_HEAD_LEN;
257 uint8_t *encData = (uint8_t *)SoftBusCalloc(encDataLen);
258 if (encData == NULL) {
259 AUTH_LOGE(AUTH_FSM, "malloc encrypt data fail");
260 return SOFTBUS_MALLOC_ERR;
261 }
262 if (EncryptData(list, inData, inLen, encData, &encDataLen) != SOFTBUS_OK) {
263 AUTH_LOGE(AUTH_FSM, "encrypt data fail");
264 SoftBusFree(encData);
265 return SOFTBUS_ENCRYPT_ERR;
266 }
267 *outData = encData;
268 *outLen = encDataLen;
269 return SOFTBUS_OK;
270 }
271
DecryptInner(const SessionKeyList * list,const uint8_t * inData,uint32_t inLen,uint8_t ** outData,uint32_t * outLen)272 int32_t DecryptInner(const SessionKeyList *list, const uint8_t *inData, uint32_t inLen,
273 uint8_t **outData, uint32_t *outLen)
274 {
275 if (list == NULL || inData == NULL || inLen <= ENCRYPT_OVER_HEAD_LEN || outData == NULL || outLen == NULL) {
276 AUTH_LOGE(AUTH_FSM, "invalid param");
277 return SOFTBUS_INVALID_PARAM;
278 }
279 uint32_t decDataLen = inLen - ENCRYPT_OVER_HEAD_LEN + 1; /* for '\0' */
280 uint8_t *decData = (uint8_t *)SoftBusCalloc(decDataLen);
281 if (decData == NULL) {
282 AUTH_LOGE(AUTH_FSM, "malloc decrypt data fail");
283 return SOFTBUS_MALLOC_ERR;
284 }
285 if (DecryptData(list, inData, inLen, decData, &decDataLen) != SOFTBUS_OK) {
286 AUTH_LOGE(AUTH_FSM, "decrypt data fail");
287 SoftBusFree(decData);
288 return SOFTBUS_DECRYPT_ERR;
289 }
290 *outData = decData;
291 *outLen = decDataLen;
292 return SOFTBUS_OK;
293 }
294
295 /* For Debug */
DumpSessionkeyList(const SessionKeyList * list)296 void DumpSessionkeyList(const SessionKeyList *list)
297 {
298 AUTH_CHECK_AND_RETURN_LOGE(list != NULL, AUTH_FSM, "list is NULL");
299 uint32_t keyNum = 0;
300 SessionKeyItem *item = NULL;
301 LIST_FOR_EACH_ENTRY(item, (const ListNode *)list, SessionKeyItem, node) {
302 AUTH_LOGD(AUTH_FSM,
303 "[Dump] SessionKey keyNum=%{public}d, index=%{public}d, keyLen=%{public}u, key=XX, "
304 "lastUseTime=%{public}" PRIu64 "",
305 keyNum, item->index, item->key.len, item->lastUseTime);
306 keyNum++;
307 }
308 AUTH_LOGD(AUTH_FSM, "[Dump] SessionKey total num=%{public}u", keyNum);
309 }
310
HandleUpdateSessionKeyEvent(const void * obj)311 static void HandleUpdateSessionKeyEvent(const void *obj)
312 {
313 AUTH_CHECK_AND_RETURN_LOGE(obj != NULL, AUTH_FSM, "obj is NULL");
314 int64_t authId = *(int64_t *)(obj);
315 AUTH_LOGI(AUTH_FSM, "update session key begin, authId=%{public}" PRId64, authId);
316 AuthManager *auth = GetAuthManagerByAuthId(authId);
317 if (auth == NULL) {
318 return;
319 }
320 if (AuthSessionStartAuth(GenSeq(false), AuthGenRequestId(),
321 auth->connId, &auth->connInfo, false, false) != SOFTBUS_OK) {
322 AUTH_LOGI(AUTH_FSM, "start auth session to update session key fail, authId=%{public}" PRId64, authId);
323 }
324 DelAuthManager(auth, false);
325 }
326
RemoveUpdateSessionKeyFunc(const void * obj,void * para)327 static int32_t RemoveUpdateSessionKeyFunc(const void *obj, void *para)
328 {
329 AUTH_CHECK_AND_RETURN_RET_LOGE(obj != NULL, SOFTBUS_ERR, AUTH_FSM, "obj is NULL");
330 AUTH_CHECK_AND_RETURN_RET_LOGE(para != NULL, SOFTBUS_ERR, AUTH_FSM, "para is NULL");
331 int64_t authId = *(int64_t *)(obj);
332 if (authId == *(int64_t *)(para)) {
333 AUTH_LOGI(AUTH_FSM, "remove update session key event, authId=%{public}" PRId64, authId);
334 return SOFTBUS_OK;
335 }
336 return SOFTBUS_ERR;
337 }
338
ScheduleUpdateSessionKey(int64_t authId,uint64_t delayMs)339 void ScheduleUpdateSessionKey(int64_t authId, uint64_t delayMs)
340 {
341 RemoveAuthEvent(EVENT_UPDATE_SESSION_KEY, RemoveUpdateSessionKeyFunc, (void *)(&authId));
342 PostAuthEvent(EVENT_UPDATE_SESSION_KEY, HandleUpdateSessionKeyEvent, &authId, sizeof(authId), delayMs);
343 }
344
CancelUpdateSessionKey(int64_t authId)345 void CancelUpdateSessionKey(int64_t authId)
346 {
347 RemoveAuthEvent(EVENT_UPDATE_SESSION_KEY, RemoveUpdateSessionKeyFunc, (void *)(&authId));
348 }