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