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