• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * This file is part of the openHiTLS project.
3  *
4  * openHiTLS is licensed under the Mulan PSL v2.
5  * You can use this software according to the terms and conditions of the Mulan PSL v2.
6  * You may obtain a copy of Mulan PSL v2 at:
7  *
8  *     http://license.coscl.org.cn/MulanPSL2
9  *
10  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13  * See the Mulan PSL v2 for more details.
14  */
15 #include "hitls_build.h"
16 #ifdef HITLS_TLS_PROTO_DTLS12
17 #include "securec.h"
18 #include "tls_binlog_id.h"
19 #include "bsl_log_internal.h"
20 #include "bsl_log.h"
21 #include "bsl_sal.h"
22 #include "bsl_err_internal.h"
23 #include "bsl_module_list.h"
24 #include "bsl_bytes.h"
25 #include "hitls_error.h"
26 #include "hs_common.h"
27 #include "hs_ctx.h"
28 #include "hs_msg.h"
29 #include "hs_reass.h"
30 
31 #define MAX_NUM_EXCEED_EXPECT 10
32 
33 static const uint8_t g_startMaskMap[] = { 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80 };
34 static const uint8_t g_endMaskMap[] = { 0x1, 0x3, 0x7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF };
35 
SetReassBitMap(uint8_t * reassBitMap,uint32_t fragmentOffset,uint32_t fragmentLength)36 static void SetReassBitMap(uint8_t *reassBitMap, uint32_t fragmentOffset, uint32_t fragmentLength)
37 {
38     /* start indicates the first digit of the flag to be set, and end indicates the last digit of the flag to be set */
39     uint32_t start = fragmentOffset;
40     uint32_t end = fragmentOffset + fragmentLength - 1;
41     /* When the length is less than 8, the bitmap is set by bit. When the length is greater than or equal to 8, the
42      * bitmap is set in three steps */
43     if (end - start < 8) {
44         for (uint32_t i = start; i <= end; i++) {
45             /** >>3 indicates divided by 8, & 7 is the remainder 8 */
46             reassBitMap[(i) >> 3] |= 1 << (i & 7);
47         }
48     } else {
49         uint32_t startOffset = start >> 3; /* bitmap to be set, >> 3 indicates the division by 8 */
50         uint32_t endOffset = end >> 3;     /* last byte of the bitmap to be set, >> 3 is divided by 8 */
51         /* Assign the first byte, &7 indicates the remainder 8 */
52         reassBitMap[startOffset] |= g_startMaskMap[start & 7];
53         /* Assign a value to the middle byte */
54         uint32_t copyLen = endOffset - startOffset - 1;
55         (void)memset_s(&reassBitMap[startOffset + 1], copyLen, 0xFF, copyLen);
56         /* Assign the last byte, &7 indicates the remainder 8 */
57         reassBitMap[endOffset] |= g_endMaskMap[end & 7];
58     }
59     return;
60 }
61 
IsReassComplete(const uint8_t * reassBitMap,uint32_t msgLen)62 static bool IsReassComplete(const uint8_t *reassBitMap, uint32_t msgLen)
63 {
64     uint32_t i;
65     /* bit map from 0 to (msgLen-1) */
66     uint32_t maxIndex = msgLen - 1;
67     /* Check the last byte, >> 3 indicates the division by 8, and &7 indicates the remainder by 8 */
68     if (reassBitMap[maxIndex >> 3] != g_endMaskMap[maxIndex & 7]) {
69         return false;
70     }
71     /* Check the 0th byte to the last 2nd byte, >> 3 is divided by 8 */
72     for (i = 0; i < (maxIndex >> 3); i++) {
73         if (reassBitMap[i] != 0xFF) {
74             return false;
75         }
76     }
77     return true;
78 }
79 
HS_ReassNew(void)80 HS_ReassQueue *HS_ReassNew(void)
81 {
82     HS_ReassQueue *reassQueue = (HS_ReassQueue *)BSL_SAL_Calloc(1u, sizeof(HS_ReassQueue));
83     if (reassQueue == NULL) {
84         BSL_ERR_PUSH_ERROR(HITLS_MEMALLOC_FAIL);
85         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15751, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
86             "reassQueue malloc fail when new a reassQueue.", 0, 0, 0, 0);
87         return NULL;
88     }
89     LIST_INIT(&reassQueue->head);
90     return reassQueue;
91 }
92 
HS_ReassFree(HS_ReassQueue * reassQueue)93 void HS_ReassFree(HS_ReassQueue *reassQueue)
94 {
95     if (reassQueue == NULL) {
96         return;
97     }
98 
99     ListHead *node = NULL;
100     ListHead *tmpNode = NULL;
101     HS_ReassQueue *cur = NULL;
102     LIST_FOR_EACH_ITEM_SAFE(node, tmpNode, &(reassQueue->head))
103     {
104         cur = LIST_ENTRY(node, HS_ReassQueue, head);
105         LIST_REMOVE(&cur->head);        /* Delete the node from the queue. */
106         BSL_SAL_FREE(cur->reassBitMap); /* Release node content. */
107         BSL_SAL_FREE(cur->msg);         /* Release node content. */
108         BSL_SAL_FREE(cur);              /* Release the node. */
109     }
110     BSL_SAL_FREE(reassQueue);
111     return;
112 }
113 
GetReassNode(HS_ReassQueue * reassQueue,uint16_t sequence)114 static HS_ReassQueue *GetReassNode(HS_ReassQueue *reassQueue, uint16_t sequence)
115 {
116     ListHead *node = NULL;
117     ListHead *tmpNode = NULL;
118     HS_ReassQueue *cur = NULL;
119 
120     /* Find the node with the corresponding sequence number in the reassembly queue */
121     LIST_FOR_EACH_ITEM_SAFE(node, tmpNode, &(reassQueue->head)) {
122         cur = LIST_ENTRY(node, HS_ReassQueue, head);
123         if (cur->sequence == sequence) {
124             return cur;
125         }
126     }
127     return NULL;
128 }
129 
ReassNodeNew(HS_ReassQueue * reassQueue,HS_MsgInfo * msgInfo)130 static HS_ReassQueue *ReassNodeNew(HS_ReassQueue *reassQueue, HS_MsgInfo *msgInfo)
131 {
132     HS_ReassQueue *node = (HS_ReassQueue *)BSL_SAL_Calloc(1u, sizeof(HS_ReassQueue));
133     if (node == NULL) {
134         BSL_ERR_PUSH_ERROR(HITLS_MEMALLOC_FAIL);
135         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15752, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
136             "node malloc fail when inser a msg to reassQueue.", 0, 0, 0, 0);
137         return NULL;
138     }
139     LIST_INIT(&node->head);
140 
141     if (msgInfo->length != 0) {
142         /* 8 is the number of bits of one byte. The addition of 7 is used to supplement the number of bits. Ensure that
143          * the correct allocated bytes are obtained after each number is divided by 8. */
144         uint32_t bitMapSize = (msgInfo->length + 7) / 8;
145         node->reassBitMap = BSL_SAL_Calloc(1u, bitMapSize);
146         if (node->reassBitMap == NULL) {
147             BSL_SAL_FREE(node);
148             BSL_ERR_PUSH_ERROR(HITLS_MEMALLOC_FAIL);
149             BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15753, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
150                 "bitMap malloc fail when inser a msg to reassQueue.", 0, 0, 0, 0);
151             return NULL;
152         }
153     }
154 
155     /* Apply for the space that can be used to cache the entire message */
156     uint32_t msgLen = DTLS_HS_MSG_HEADER_SIZE + msgInfo->length;
157     node->msg = BSL_SAL_Calloc(1u, msgLen);
158     if (node->msg == NULL) {
159         BSL_SAL_FREE(node->reassBitMap);
160         BSL_SAL_FREE(node);
161         BSL_ERR_PUSH_ERROR(HITLS_MEMALLOC_FAIL);
162         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15754, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
163             "msg malloc fail when inser a msg to reassQueue.", 0, 0, 0, 0);
164         return NULL;
165     }
166 
167     node->type = msgInfo->type;
168     node->sequence = msgInfo->sequence;
169     node->isReassComplete = false;
170     node->msgLen = msgLen;
171 
172     /* Insert a new node */
173     LIST_ADD_BEFORE(&reassQueue->head, &node->head);
174     return node;
175 }
176 
ReassembleMsg(TLS_Ctx * ctx,HS_MsgInfo * msgInfo,HS_ReassQueue * node)177 static int32_t ReassembleMsg(TLS_Ctx *ctx, HS_MsgInfo *msgInfo, HS_ReassQueue *node)
178 {
179     /* Check message */
180     uint32_t bufOffset = DTLS_HS_MSG_HEADER_SIZE + msgInfo->fragmentOffset;
181     if ((node->msgLen < bufOffset) ||
182         (node->type != msgInfo->type) ||
183         ((node->msgLen - DTLS_HS_MSG_HEADER_SIZE) != msgInfo->length)) {
184         BSL_ERR_PUSH_ERROR(HITLS_REASS_INVALID_FRAGMENT);
185         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15755, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
186             "reassemble message fail, fragmentOffset %u; msgType %u, expect %u; msgLen %u",
187             msgInfo->fragmentOffset, msgInfo->type, node->type, msgInfo->length);
188         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15759, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
189             "expect %u", node->msgLen - DTLS_HS_MSG_HEADER_SIZE, 0, 0, 0);
190         ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_DECODE_ERROR);
191         return HITLS_REASS_INVALID_FRAGMENT;
192     }
193 
194     /* Copy the message header */
195     if (msgInfo->fragmentOffset == 0u) {
196         if (memcpy_s(&node->msg[0], node->msgLen, &msgInfo->rawMsg[0], DTLS_HS_MSG_HEADER_SIZE) != EOK) {
197             BSL_ERR_PUSH_ERROR(HITLS_MEMCPY_FAIL);
198             BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15756, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
199                 "msg header copy fail when append to reassQueue.", 0, 0, 0, 0);
200             ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
201             return HITLS_MEMCPY_FAIL;
202         }
203     }
204 
205     if (node->msgLen == DTLS_HS_MSG_HEADER_SIZE) {
206         /* The message is empty and does not need to be reassembled */
207         node->isReassComplete = true;
208         return HITLS_SUCCESS;
209     }
210 
211     /* Message reassembly */
212     if (memcpy_s(&node->msg[bufOffset], node->msgLen - bufOffset,
213                  &msgInfo->rawMsg[DTLS_HS_MSG_HEADER_SIZE], msgInfo->fragmentLength) != EOK) {
214         BSL_ERR_PUSH_ERROR(HITLS_MEMCPY_FAIL);
215         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15757, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
216             "msg copy fail when append to reassQueue.", 0, 0, 0, 0);
217         ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
218         return HITLS_MEMCPY_FAIL;
219     }
220 
221     /* Set the bitmap and check whether the bitmap is complete */
222     SetReassBitMap(node->reassBitMap, msgInfo->fragmentOffset, msgInfo->fragmentLength);
223     if (IsReassComplete(node->reassBitMap, node->msgLen - DTLS_HS_MSG_HEADER_SIZE)) {
224         /* Bitmap complete, updated fragment length */
225         BSL_Uint24ToByte(msgInfo->length, &node->msg[DTLS_HS_FRAGMENT_LEN_ADDR]);
226         node->isReassComplete = true;
227     }
228 
229     return HITLS_SUCCESS;
230 }
231 
HS_ReassAppend(TLS_Ctx * ctx,HS_MsgInfo * msgInfo)232 int32_t HS_ReassAppend(TLS_Ctx *ctx, HS_MsgInfo *msgInfo)
233 {
234     /* If the number of a message exceeds the expected number, discard the message to prevent unlimited memory
235      * application */
236     if (msgInfo->sequence > ctx->hsCtx->expectRecvSeq + MAX_NUM_EXCEED_EXPECT) {
237         return HITLS_SUCCESS;
238     }
239 
240     HS_ReassQueue *reassQueue = ctx->hsCtx->reassMsg;
241     /* Check whether there are messages in the reassembly queue */
242     HS_ReassQueue *node = GetReassNode(reassQueue, msgInfo->sequence);
243     if (node == NULL) {
244         /* If no message has the corresponding sequence number, create a new queue node to buffer the message */
245         node = ReassNodeNew(reassQueue, msgInfo);
246         if (node == NULL) {
247             BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17027, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
248                 "ReassNodeNew fail", 0, 0, 0, 0);
249             ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
250             return HITLS_MEMALLOC_FAIL;
251         }
252     }
253 
254     return ReassembleMsg(ctx, msgInfo, node);
255 }
256 
HS_GetReassMsg(TLS_Ctx * ctx,HS_MsgInfo * msgInfo,uint32_t * len)257 int32_t HS_GetReassMsg(TLS_Ctx *ctx, HS_MsgInfo *msgInfo, uint32_t *len)
258 {
259     /* Check whether there are messages in the reassembly queue */
260     HS_ReassQueue *node = GetReassNode(ctx->hsCtx->reassMsg, ctx->hsCtx->expectRecvSeq);
261     if (node == NULL) {
262         *len = 0;
263         return HITLS_SUCCESS;
264     }
265 
266     /* If a message exists, check whether the message is complete. If the message is incomplete, return the message and
267      * continue to read the message from the record layer */
268     if (!node->isReassComplete) {
269         *len = 0;
270         return HITLS_SUCCESS;
271     }
272 
273     /* If the message is a complete message, copy the message */
274     msgInfo->type = node->type;
275     msgInfo->length = node->msgLen - DTLS_HS_MSG_HEADER_SIZE;
276     msgInfo->sequence = node->sequence;
277     msgInfo->fragmentOffset = 0u;
278     msgInfo->fragmentLength = node->msgLen - DTLS_HS_MSG_HEADER_SIZE;
279     int32_t ret = HS_ReSizeMsgBuf(ctx, node->msgLen);
280     if (ret != HITLS_SUCCESS) {
281         return ret;
282     }
283     if (memcpy_s(ctx->hsCtx->msgBuf, ctx->hsCtx->bufferLen, node->msg, node->msgLen) != EOK) {
284         BSL_ERR_PUSH_ERROR(HITLS_MEMCPY_FAIL);
285         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15758, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
286             "msg copy fail when get a msg from reassQueue.", 0, 0, 0, 0);
287         ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_INTERNAL_ERROR);
288         return HITLS_MEMCPY_FAIL;
289     }
290     msgInfo->rawMsg = ctx->hsCtx->msgBuf;
291     *len = node->msgLen;             /* Set the message length. */
292     LIST_REMOVE(&node->head);        /* Delete the node from the queue. */
293     BSL_SAL_FREE(node->reassBitMap); /* Release node content. */
294     BSL_SAL_FREE(node->msg);         /* Release node content. */
295     BSL_SAL_FREE(node);              /* Release the node. */
296 
297     return HITLS_SUCCESS;
298 }
299 
300 #endif /* end #ifdef HITLS_TLS_PROTO_DTLS12 */
301