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