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
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <stdbool.h>
19 #include <unistd.h>
20 #include <fcntl.h>
21 #include <sys/types.h>
22 #include <sys/socket.h>
23 #include <sys/time.h>
24
25 #include "hitls_error.h"
26 #include "hitls_type.h"
27 #include "hitls.h"
28 #include "tls.h"
29 #include "hs_ctx.h"
30 #include "bsl_errno.h"
31 #include "uio_base.h"
32
33 #include "frame_msg.h"
34 #include "logger.h"
35 #include "hlt_type.h"
36
37 #define SUCCESS 0
38 #define ERROR (-1)
39
40 #define MAX_LEN (20 * 1024)
41
42 /* set block mode. */
SetBlockMode(int32_t sd,bool isBlock)43 int32_t SetBlockMode(int32_t sd, bool isBlock)
44 {
45 if (isBlock) {
46 LOG_DEBUG("Socket Set Block Mode");
47 int flag;
48 flag = fcntl(sd, F_GETFL, 0);
49 flag &= ~O_NONBLOCK;
50 if (fcntl(sd, F_SETFL, flag) < 0) {
51 LOG_ERROR("fcntl fail");
52 return ERROR;
53 }
54 } else {
55 LOG_DEBUG("Socket Set Unblock Mode");
56 int flag;
57 flag = fcntl(sd, F_GETFL, 0);
58 flag |= O_NONBLOCK;
59 if (fcntl(sd, F_SETFL, flag) < 0) {
60 LOG_ERROR("fcntl fail");
61 return ERROR;
62 }
63 }
64 return SUCCESS;
65 }
66
67 /**
68 * @brief Check whether there are fatal I/O errors
69 *
70 * @param err [IN] Error type
71 *
72 * @return true :A fatal error occurs
73 * false:No fatal error occurs
74 */
IsNonFatalErr(int32_t err)75 bool IsNonFatalErr(int32_t err)
76 {
77 bool ret = true;
78 /** @alias Check whether err is a fatal error and modify ret */
79 switch (err) {
80 #if defined(ENOTCONN)
81 case ENOTCONN:
82 #endif
83
84 #ifdef EINTR
85 case EINTR:
86 #endif
87
88 #ifdef EINPROGRESS
89 case EINPROGRESS:
90 #endif
91
92 #ifdef EWOULDBLOCK
93 #if !defined(WSAEWOULDBLOCK) || WSAEWOULDBLOCK != EWOULDBLOCK
94 case EWOULDBLOCK:
95 #endif
96 #endif
97
98 #ifdef EAGAIN
99 #if EWOULDBLOCK != EAGAIN
100 case EAGAIN:
101 #endif
102 #endif
103
104 #ifdef EALREADY
105 case EALREADY:
106 #endif
107
108 #ifdef EPROTO
109 case EPROTO:
110 #endif
111 ret = true;
112 break;
113 default:
114 ret = false;
115 break;
116 }
117 return ret;
118 }
119
120 static HLT_FrameHandle g_frameHandle;
121
SetFrameHandle(HLT_FrameHandle * frameHandle)122 int32_t SetFrameHandle(HLT_FrameHandle *frameHandle)
123 {
124 if (frameHandle == NULL || frameHandle->ctx == NULL) {
125 return HITLS_NULL_INPUT;
126 }
127 g_frameHandle.ctx = frameHandle->ctx;
128 g_frameHandle.frameCallBack = frameHandle->frameCallBack;
129 g_frameHandle.userData = frameHandle->userData;
130 g_frameHandle.expectHsType = frameHandle->expectHsType;
131 g_frameHandle.expectReType = frameHandle->expectReType;
132 g_frameHandle.ioState = frameHandle->ioState;
133 g_frameHandle.pointType = frameHandle->pointType;
134 g_frameHandle.method.uioWrite = frameHandle->method.uioWrite;
135 g_frameHandle.method.uioRead = frameHandle->method.uioRead;
136 g_frameHandle.method.uioCtrl = frameHandle->method.uioCtrl;
137
138 return HITLS_SUCCESS;
139 }
140
CleanFrameHandle(void)141 void CleanFrameHandle(void)
142 {
143 g_frameHandle.ctx = NULL;
144 g_frameHandle.frameCallBack = NULL;
145 g_frameHandle.userData = NULL;
146 g_frameHandle.expectHsType = 0;
147 g_frameHandle.expectReType = 0;
148 g_frameHandle.ioState = 0;
149 g_frameHandle.pointType = 0;
150 g_frameHandle.method.uioWrite = NULL;
151 g_frameHandle.method.uioRead = NULL;
152 g_frameHandle.method.uioCtrl = NULL;
153 }
154
GetFrameHandle(void)155 HLT_FrameHandle *GetFrameHandle(void)
156 {
157 return &g_frameHandle;
158 }
159
160 /* Obtain the frameType. The input parameters frameHandle and frameType must not be empty */
GetFrameType(HLT_FrameHandle * frameHandle,FRAME_Type * frameType)161 static int32_t GetFrameType(HLT_FrameHandle *frameHandle, FRAME_Type *frameType)
162 {
163 if (frameHandle->ctx == NULL) {
164 return HITLS_NULL_INPUT;
165 }
166 TLS_Ctx *tmpCtx = (TLS_Ctx *)frameHandle->ctx;
167 frameType->versionType = tmpCtx->negotiatedInfo.version > 0 ?
168 tmpCtx->negotiatedInfo.version : tmpCtx->config.tlsConfig.maxVersion;
169 frameType->keyExType = tmpCtx->hsCtx->kxCtx->keyExchAlgo;
170 frameType->recordType = frameHandle->expectReType;
171 frameType->handshakeType = frameHandle->expectHsType;
172 return HITLS_SUCCESS;
173 }
174
175 /* Verify whether the parsed msg meets the requirements. Restrict the msg input parameter */
CheckHandleType(FRAME_Msg * msg)176 static bool CheckHandleType(FRAME_Msg *msg)
177 {
178 if (msg->recType.data != REC_TYPE_HANDSHAKE) {
179 if ((int32_t)msg->recType.data == g_frameHandle.expectReType) {
180 return true;
181 }
182 } else {
183 if ((int32_t)msg->recType.data == g_frameHandle.expectReType &&
184 (int32_t)msg->body.hsMsg.type.data == g_frameHandle.expectHsType) {
185 return true;
186 }
187 }
188 return false;
189 }
190
191 /* Release the newbuf */
FreeNewBuf(void * newBuf)192 void FreeNewBuf(void *newBuf)
193 {
194 if (newBuf != NULL) {
195 free(newBuf);
196 newBuf = NULL;
197 }
198 }
199
200 /* Obtain the newbuf by parsing the buffer. The input parameter of the packageLen constraint is not empty */
GetNewBuf(const void * buf,uint32_t len,uint32_t * packLen)201 uint8_t *GetNewBuf(const void *buf, uint32_t len, uint32_t *packLen)
202 {
203 uint32_t packLenTmp = 0;
204 /* Obtain the frameType */
205 FRAME_Type frameType = { 0 };
206 if (GetFrameType(&g_frameHandle, &frameType) != HITLS_SUCCESS) {
207 return NULL;
208 }
209 /* Unpack the buffer into the msg structure */
210 uint32_t parseLen = 0;
211 FRAME_Msg msg = { 0 };
212 uint32_t offset = 0;
213 uint8_t *newBuf = (uint8_t *)calloc(MAX_LEN, sizeof(uint8_t));
214 uint32_t newOffset = 0;
215
216 while (offset < *packLen) {
217 /* Currently, encryption and decryption are not performed.
218 * Therefore, the return value is not determined
219 * because the encrypted messages such as finished messages will fail to be parsed
220 */
221 (void)FRAME_ParseMsg(&frameType, &((uint8_t*)buf)[offset], len - offset, &msg, &parseLen);
222
223 if (CheckHandleType(&msg)) {
224 if (g_frameHandle.ioState == EXP_IO_BUSY) {
225 FRAME_CleanMsg(&frameType, &msg);
226 /* Set I/O to busy */
227 *packLen = 0;
228 FreeNewBuf(newBuf);
229 return NULL;
230 }
231 if (g_frameHandle.userData == NULL) {
232 g_frameHandle.userData = (void *)&frameType;
233 }
234 g_frameHandle.frameCallBack(&msg, g_frameHandle.userData);
235 if (g_frameHandle.userData == (void *)&frameType) {
236 g_frameHandle.userData = NULL;
237 }
238 /* Pack the newly constructed msg into a buffer */
239 if (FRAME_PackMsg(&frameType, &msg, &newBuf[newOffset], MAX_LEN - newOffset, &packLenTmp) != HITLS_SUCCESS) {
240 FRAME_CleanMsg(&frameType, &msg);
241 FreeNewBuf(newBuf);
242 return NULL;
243 }
244 newOffset += packLenTmp;
245 } else {
246 memcpy_s(&newBuf[newOffset], MAX_LEN - newOffset, &((uint8_t*)buf)[offset], parseLen);
247 newOffset += parseLen;
248 }
249 offset += parseLen;
250 FRAME_CleanMsg(&frameType, &msg);
251 }
252
253 /* Check whether the package is reassembled. If not, *packLen should not be changed */
254 if (packLenTmp == 0) {
255 FreeNewBuf(newBuf);
256 return NULL;
257 }
258
259 *packLen = newOffset;
260 return newBuf;
261 }