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 "hitls_build.h"
17 #ifdef HITLS_BSL_UIO_SCTP
18
19 #include "securec.h"
20 #include "bsl_sal.h"
21 #include "bsl_binlog_id.h"
22 #include "bsl_log_internal.h"
23 #include "bsl_log.h"
24 #include "bsl_err_internal.h"
25 #include "bsl_errno.h"
26 #include "bsl_uio.h"
27 #include "sal_net.h"
28 #include "uio_base.h"
29 #include "uio_abstraction.h"
30
31 #define SCTP_SHARE_AUTHKEY_ID_MAX 65535
32
33 typedef struct {
34 bool peerAuthed; /* Whether auth is enabled at the peer end */
35 /* Whether authkey is added: If authkey is added but not active, success is returned when authkey is added again. */
36 bool isAddAuthkey;
37 bool reserved[2]; /* Four-byte alignment is reserved. */
38
39 uint16_t sendAppStreamId; /* ID of the stream sent by the user-specified app. */
40 uint16_t prevShareKeyId;
41 uint16_t shareKeyId;
42 uint16_t reserved1; /* Four-byte alignment is reserved. */
43 } BslSctpData;
44
45 typedef struct {
46 BslSctpData data;
47 int32_t fd; // Network socket
48 uint32_t ipLen;
49 uint8_t ip[IP_ADDR_MAX_LEN];
50 struct BSL_UIO_MethodStruct method;
51 bool isAppMsg; // whether the message sent is the app message
52 } SctpParameters;
53
BslSctpNew(BSL_UIO * uio)54 static int32_t BslSctpNew(BSL_UIO *uio)
55 {
56 SctpParameters *parameters = (SctpParameters *)BSL_SAL_Calloc(1u, sizeof(SctpParameters));
57 if (parameters == NULL) {
58 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID05031, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
59 "Uio: sctp param malloc fail.", 0, 0, 0, 0);
60 BSL_ERR_PUSH_ERROR(BSL_UIO_FAIL);
61 return BSL_UIO_FAIL;
62 }
63 parameters->fd = -1;
64 parameters->method.uioType = BSL_UIO_SCTP;
65 uio->ctx = parameters;
66 uio->ctxLen = sizeof(SctpParameters);
67 // The default value of init is 0. Set the value of init to 1 after the fd is set.
68 return BSL_SUCCESS;
69 }
70
BslSctpDestroy(BSL_UIO * uio)71 static int32_t BslSctpDestroy(BSL_UIO *uio)
72 {
73 if (uio == NULL) {
74 return BSL_SUCCESS;
75 }
76 SctpParameters *ctx = BSL_UIO_GetCtx(uio);
77 uio->init = 0;
78 if (ctx != NULL) {
79 if (BSL_UIO_GetIsUnderlyingClosedByUio(uio) && ctx->fd != -1) {
80 (void)BSL_SAL_SockClose(ctx->fd);
81 }
82 BSL_SAL_FREE(ctx);
83 BSL_UIO_SetCtx(uio, NULL);
84 }
85 return BSL_SUCCESS;
86 }
87
BslSctpWrite(BSL_UIO * uio,const void * buf,uint32_t len,uint32_t * writeLen)88 static int32_t BslSctpWrite(BSL_UIO *uio, const void *buf, uint32_t len, uint32_t *writeLen)
89 {
90 if (uio == NULL || uio->ctx == NULL || ((SctpParameters *)uio->ctx)->method.uioWrite == NULL) {
91 BSL_ERR_PUSH_ERROR(BSL_INVALID_ARG);
92 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID05081, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
93 "Uio: Sctp write input error.", 0, 0, 0, 0);
94 return BSL_INVALID_ARG;
95 }
96 *writeLen = 0;
97 return ((SctpParameters *)uio->ctx)->method.uioWrite(uio, buf, len, writeLen);
98 }
99
BslSctpRead(BSL_UIO * uio,void * buf,uint32_t len,uint32_t * readLen)100 static int32_t BslSctpRead(BSL_UIO *uio, void *buf, uint32_t len, uint32_t *readLen)
101 {
102 if (uio == NULL || uio->ctx == NULL || ((SctpParameters *)uio->ctx)->method.uioRead == NULL) {
103 BSL_ERR_PUSH_ERROR(BSL_INVALID_ARG);
104 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID05082, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
105 "Uio: Sctp read input error.", 0, 0, 0, 0);
106 return BSL_INVALID_ARG;
107 }
108 *readLen = 0;
109 SctpParameters *parameters = (SctpParameters *)uio->ctx;
110 if (!parameters->data.peerAuthed) {
111 if (parameters->method.uioCtrl == NULL || parameters->method.uioCtrl(uio, BSL_UIO_SCTP_CHECK_PEER_AUTH,
112 sizeof(parameters->data.peerAuthed), ¶meters->data.peerAuthed) != BSL_SUCCESS) {
113 BSL_ERR_PUSH_ERROR(BSL_UIO_IO_EXCEPTION);
114 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID05083, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
115 "Uio: Check peer auth failed.", 0, 0, 0, 0);
116 return BSL_UIO_IO_EXCEPTION;
117 }
118 parameters->data.peerAuthed = true;
119 }
120 return parameters->method.uioRead(uio, buf, len, readLen);
121 }
122
BslSctpAddAuthKey(BSL_UIO * uio,const uint8_t * parg,uint16_t larg)123 static int32_t BslSctpAddAuthKey(BSL_UIO *uio, const uint8_t *parg, uint16_t larg)
124 {
125 SctpParameters *parameters = (SctpParameters *)BSL_UIO_GetCtx(uio);
126 if (parg == NULL || larg != sizeof(BSL_UIO_SctpAuthKey)) {
127 BSL_ERR_PUSH_ERROR(BSL_INVALID_ARG);
128 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID05062, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
129 "add auth key failed", 0, 0, 0, 0);
130 return BSL_INVALID_ARG;
131 }
132
133 if (parameters->data.isAddAuthkey) {
134 return BSL_SUCCESS;
135 }
136
137 uint16_t prevShareKeyId = parameters->data.shareKeyId;
138 if (parameters->data.shareKeyId >= SCTP_SHARE_AUTHKEY_ID_MAX) {
139 parameters->data.shareKeyId = 1;
140 } else {
141 parameters->data.shareKeyId++;
142 }
143 BSL_UIO_SctpAuthKey key = { 0 };
144 key.shareKeyId = parameters->data.shareKeyId;
145 key.authKey = parg;
146 key.authKeySize = larg;
147
148 int32_t ret = parameters->method.uioCtrl(uio, BSL_UIO_SCTP_ADD_AUTH_SHARED_KEY, (int32_t)sizeof(key), &key);
149 if (ret != BSL_SUCCESS) {
150 parameters->data.shareKeyId = prevShareKeyId;
151 BSL_ERR_PUSH_ERROR(BSL_UIO_IO_EXCEPTION);
152 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID05065, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
153 "add auth key failed", 0, 0, 0, 0);
154 return BSL_UIO_IO_EXCEPTION;
155 }
156 parameters->data.isAddAuthkey = true;
157 parameters->data.prevShareKeyId = prevShareKeyId;
158 return BSL_SUCCESS;
159 }
160
BslSctpActiveAuthKey(BSL_UIO * uio)161 static int32_t BslSctpActiveAuthKey(BSL_UIO *uio)
162 {
163 SctpParameters *parameters = BSL_UIO_GetCtx(uio);
164 if (parameters == NULL || parameters->method.uioCtrl == NULL) {
165 BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
166 return BSL_NULL_INPUT;
167 }
168 uint16_t shareKeyId = parameters->data.shareKeyId;
169 int32_t ret = parameters->method.uioCtrl(uio, BSL_UIO_SCTP_ACTIVE_AUTH_SHARED_KEY,
170 (int32_t)sizeof(shareKeyId), &shareKeyId);
171 if (ret != BSL_SUCCESS) {
172 BSL_ERR_PUSH_ERROR(BSL_UIO_IO_EXCEPTION);
173 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID05066, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
174 "active auth key failed", 0, 0, 0, 0);
175 return BSL_UIO_IO_EXCEPTION;
176 }
177 parameters->data.isAddAuthkey = false;
178 return BSL_SUCCESS;
179 }
180
BslSctpDelPreAuthKey(BSL_UIO * uio)181 static int32_t BslSctpDelPreAuthKey(BSL_UIO *uio)
182 {
183 SctpParameters *parameters = BSL_UIO_GetCtx(uio);
184 if (parameters == NULL || parameters->method.uioCtrl == NULL) {
185 BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
186 return BSL_NULL_INPUT;
187 }
188 uint16_t delShareKeyId = parameters->data.prevShareKeyId;
189 int32_t ret = parameters->method.uioCtrl(uio, BSL_UIO_SCTP_DEL_PRE_AUTH_SHARED_KEY,
190 (int32_t)sizeof(delShareKeyId), &delShareKeyId);
191 if (ret != BSL_SUCCESS) {
192 BSL_ERR_PUSH_ERROR(BSL_UIO_IO_EXCEPTION);
193 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID05067, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
194 "del pre auth key failed", 0, 0, 0, 0);
195 return BSL_UIO_IO_EXCEPTION;
196 }
197 return BSL_SUCCESS;
198 }
199
BslSctpIsSndBuffEmpty(BSL_UIO * uio,void * parg,int32_t larg)200 static int32_t BslSctpIsSndBuffEmpty(BSL_UIO *uio, void *parg, int32_t larg)
201 {
202 SctpParameters *parameters = BSL_UIO_GetCtx(uio);
203 if (parameters == NULL || parameters->method.uioCtrl == NULL || parg == NULL || larg != sizeof(bool)) {
204 BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
205 return BSL_NULL_INPUT;
206 }
207 uint8_t isEmpty = 0;
208 if (parameters->method.uioCtrl(uio, BSL_UIO_SCTP_SND_BUFF_IS_EMPTY,
209 (int32_t)sizeof(uint8_t), &isEmpty) != BSL_SUCCESS) {
210 BSL_ERR_PUSH_ERROR(BSL_UIO_IO_EXCEPTION);
211 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID05068, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
212 "get sctp status failed", 0, 0, 0, 0);
213 return BSL_UIO_IO_EXCEPTION;
214 }
215 *(bool *)parg = (isEmpty > 0);
216 return BSL_SUCCESS;
217 }
218
BslSctpGetSendStreamId(const SctpParameters * parameters,void * parg,int32_t larg)219 static int32_t BslSctpGetSendStreamId(const SctpParameters *parameters, void *parg, int32_t larg)
220 {
221 if (larg != (int32_t)sizeof(uint16_t) || parg == NULL) {
222 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID05046, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
223 "Uio: Sctp input err.", 0, 0, 0, 0);
224 BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
225 return BSL_NULL_INPUT;
226 }
227 uint16_t *sendStreamId = (uint16_t *)parg;
228 if (parameters->isAppMsg) {
229 *sendStreamId = parameters->data.sendAppStreamId;
230 } else {
231 *sendStreamId = 0;
232 }
233
234 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID05047, BSL_LOG_LEVEL_DEBUG, BSL_LOG_BINLOG_TYPE_RUN,
235 "Uio: User Get SCTP send StreamId [%hu].", *sendStreamId, 0, 0, 0);
236 return BSL_SUCCESS;
237 }
238
BslSctpSetAppStreamId(SctpParameters * parameters,const void * parg,int32_t larg)239 int32_t BslSctpSetAppStreamId(SctpParameters *parameters, const void *parg, int32_t larg)
240 {
241 if (larg != (int32_t)sizeof(uint16_t) || parg == NULL) {
242 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID05048, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
243 "Uio: Sctp input err.", 0, 0, 0, 0);
244 BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
245 return BSL_NULL_INPUT;
246 }
247 parameters->data.sendAppStreamId = *(const uint16_t *)parg;
248 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID05055, BSL_LOG_LEVEL_DEBUG, BSL_LOG_BINLOG_TYPE_RUN,
249 "Uio: User set SCTP AppStreamId [%hu].", parameters->data.sendAppStreamId, 0, 0, 0);
250 return BSL_SUCCESS;
251 }
252
BslSctpSetPeerIpAddr(SctpParameters * parameters,const uint8_t * addr,int32_t size)253 static int32_t BslSctpSetPeerIpAddr(SctpParameters *parameters, const uint8_t *addr, int32_t size)
254 {
255 if (addr == NULL) {
256 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID05049, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
257 "Uio: NULL error.", 0, 0, 0, 0);
258 BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
259 return BSL_NULL_INPUT;
260 }
261
262 if (size != IP_ADDR_V4_LEN && size != IP_ADDR_V6_LEN) {
263 BSL_ERR_PUSH_ERROR(BSL_UIO_FAIL);
264 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID05050, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
265 "Uio: Set peer ip address input error.", 0, 0, 0, 0);
266 return BSL_UIO_FAIL;
267 }
268
269 (void)memcpy_s(parameters->ip, sizeof(parameters->ip), addr, size);
270 parameters->ipLen = (uint32_t)size;
271 return BSL_SUCCESS;
272 }
273
BslSctpGetPeerIpAddr(SctpParameters * parameters,void * parg,int32_t larg)274 static int32_t BslSctpGetPeerIpAddr(SctpParameters *parameters, void *parg, int32_t larg)
275 {
276 BSL_UIO_CtrlGetPeerIpAddrParam *para = (BSL_UIO_CtrlGetPeerIpAddrParam *)parg;
277 if (parg == NULL || larg != (int32_t)sizeof(BSL_UIO_CtrlGetPeerIpAddrParam) ||
278 para->addr == NULL) {
279 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID05051, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
280 "Uio: Get peer ip address input error.", 0, 0, 0, 0);
281 return BSL_NULL_INPUT;
282 }
283
284 /* Check whether the IP address is set. */
285 if (parameters->ipLen == 0) {
286 BSL_ERR_PUSH_ERROR(BSL_UIO_FAIL);
287 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID05052, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
288 "Uio: Ip address is already existed.", 0, 0, 0, 0);
289 return BSL_UIO_FAIL;
290 }
291
292 if (para->size < parameters->ipLen) {
293 BSL_ERR_PUSH_ERROR(BSL_UIO_FAIL);
294 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID05053, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
295 "Uio: Ip address length err.", 0, 0, 0, 0);
296 return BSL_UIO_FAIL;
297 }
298
299 (void)memcpy_s(para->addr, para->size, parameters->ip, parameters->ipLen);
300 para->size = parameters->ipLen;
301 return BSL_SUCCESS;
302 }
303
BslSctpSetFd(BSL_UIO * uio,void * parg,int32_t larg)304 static int32_t BslSctpSetFd(BSL_UIO *uio, void *parg, int32_t larg)
305 {
306 if (larg != (int32_t)sizeof(int32_t) || parg == NULL) {
307 BSL_ERR_PUSH_ERROR(BSL_INVALID_ARG);
308 return BSL_INVALID_ARG;
309 }
310 int32_t *fd = (int32_t *)parg;
311 SctpParameters *parameters = BSL_UIO_GetCtx(uio);
312 if (parameters->fd != -1) {
313 if (BSL_UIO_GetIsUnderlyingClosedByUio(uio)) {
314 (void)BSL_SAL_SockClose(parameters->fd);
315 }
316 }
317 parameters->fd = *fd;
318 uio->init = true;
319 return BSL_SUCCESS;
320 }
321
BslSctpGetFd(SctpParameters * parameters,void * parg,int32_t larg)322 static int32_t BslSctpGetFd(SctpParameters *parameters, void *parg, int32_t larg)
323 {
324 if (larg != (int32_t)sizeof(int32_t) || parg == NULL) {
325 BSL_ERR_PUSH_ERROR(BSL_INVALID_ARG);
326 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID05054, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
327 "get fd handle invalid parameter.", 0, 0, 0, 0);
328 return BSL_INVALID_ARG;
329 }
330 *(int32_t *)parg = parameters->fd;
331 return BSL_SUCCESS;
332 }
333
BslSctpMaskAppMsg(SctpParameters * parameters,void * parg,int32_t larg)334 static int32_t BslSctpMaskAppMsg(SctpParameters *parameters, void *parg, int32_t larg)
335 {
336 if (parg == NULL || larg != sizeof(bool)) {
337 BSL_ERR_PUSH_ERROR(BSL_INVALID_ARG);
338 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID05030, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
339 "mask app msg failed", 0, 0, 0, 0);
340 return BSL_INVALID_ARG;
341 }
342 parameters->isAppMsg = *(bool *)parg;
343 return BSL_SUCCESS;
344 }
345
BslSctpSetCtxCb(SctpParameters * parameters,int32_t type,void * func)346 static int32_t BslSctpSetCtxCb(SctpParameters *parameters, int32_t type, void *func)
347 {
348 if (parameters == NULL || func == NULL) {
349 BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
350 return BSL_NULL_INPUT;
351 }
352 switch (type) {
353 case BSL_UIO_WRITE_CB:
354 parameters->method.uioWrite = func;
355 break;
356 case BSL_UIO_READ_CB:
357 parameters->method.uioRead = func;
358 break;
359 case BSL_UIO_CTRL_CB:
360 parameters->method.uioCtrl = func;
361 break;
362 default:
363 BSL_ERR_PUSH_ERROR(BSL_INVALID_ARG);
364 return BSL_INVALID_ARG;
365 }
366 return BSL_SUCCESS;
367 }
368
BslSctpCtrl(BSL_UIO * uio,int32_t cmd,int32_t larg,void * parg)369 int32_t BslSctpCtrl(BSL_UIO *uio, int32_t cmd, int32_t larg, void *parg)
370 {
371 if (uio->ctx == NULL) {
372 return BSL_NULL_INPUT;
373 }
374 SctpParameters *parameters = BSL_UIO_GetCtx(uio);
375 switch (cmd) {
376 case BSL_UIO_SET_PEER_IP_ADDR:
377 return BslSctpSetPeerIpAddr(parameters, parg, larg);
378 case BSL_UIO_GET_PEER_IP_ADDR:
379 return BslSctpGetPeerIpAddr(parameters, parg, larg);
380 case BSL_UIO_SET_FD:
381 return BslSctpSetFd(uio, parg, larg);
382 case BSL_UIO_GET_FD:
383 return BslSctpGetFd(parameters, parg, larg);
384 case BSL_UIO_SCTP_GET_SEND_STREAM_ID:
385 return BslSctpGetSendStreamId(parameters, parg, larg);
386 case BSL_UIO_SCTP_SET_APP_STREAM_ID:
387 return BslSctpSetAppStreamId(parameters, parg, larg);
388 case BSL_UIO_SCTP_ADD_AUTH_SHARED_KEY:
389 if (larg < 0 || larg > UINT16_MAX) {
390 break;
391 }
392 return BslSctpAddAuthKey(uio, parg, larg);
393 case BSL_UIO_SCTP_ACTIVE_AUTH_SHARED_KEY:
394 return BslSctpActiveAuthKey(uio);
395 case BSL_UIO_SCTP_DEL_PRE_AUTH_SHARED_KEY:
396 return BslSctpDelPreAuthKey(uio);
397 case BSL_UIO_SCTP_MASK_APP_MESSAGE:
398 return BslSctpMaskAppMsg(parameters, parg, larg);
399 case BSL_UIO_SCTP_SND_BUFF_IS_EMPTY:
400 return BslSctpIsSndBuffEmpty(uio, parg, larg);
401 case BSL_UIO_SCTP_SET_CALLBACK:
402 return BslSctpSetCtxCb(parameters, larg, parg);
403 case BSL_UIO_FLUSH:
404 return BSL_SUCCESS;
405 default:
406 break;
407 }
408 BSL_ERR_PUSH_ERROR(BSL_INVALID_ARG);
409 BSL_LOG_BINLOG_FIXLEN(BINLOG_ID05069, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
410 "invalid args", 0, 0, 0, 0);
411 return BSL_INVALID_ARG;
412 }
413
BSL_UIO_SctpMethod(void)414 const BSL_UIO_Method *BSL_UIO_SctpMethod(void)
415 {
416 static const BSL_UIO_Method method = {
417 BSL_UIO_SCTP,
418 BslSctpWrite,
419 BslSctpRead,
420 BslSctpCtrl,
421 NULL,
422 NULL,
423 BslSctpNew,
424 BslSctpDestroy
425 };
426 return &method;
427 }
428 #endif /* HITLS_BSL_UIO_SCTP */
429