• 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 "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 }