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_MEM
18 #include "securec.h"
19 #include "bsl_buffer.h"
20 #include "bsl_errno.h"
21 #include "bsl_err_internal.h"
22 #include "uio_base.h"
23 #include "uio_abstraction.h"
24 #include "bsl_uio.h"
25
26 typedef struct {
27 BSL_BufMem *buf;
28 BSL_BufMem *tmpBuf; // only used in read-only mode
29 size_t readIndex;
30 int32_t eof; // Behavior when reading empty memory. If the value is not 0, retry will be set.
31 } UIO_BufMem;
32
MemNewBuf(BSL_UIO * uio,int32_t len,void * buf)33 static int32_t MemNewBuf(BSL_UIO *uio, int32_t len, void *buf)
34 {
35 if (buf == NULL || len < 0) {
36 BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
37 return BSL_NULL_INPUT;
38 }
39
40 UIO_BufMem *ubm = BSL_UIO_GetCtx(uio);
41 if (ubm == NULL || ubm->buf == NULL) {
42 BSL_ERR_PUSH_ERROR(BSL_UIO_FAIL);
43 return BSL_UIO_FAIL;
44 }
45 BSL_BufMem *bm = ubm->buf;
46 if (bm->data != NULL && (uio->flags & BSL_UIO_FLAGS_MEM_READ_ONLY) == 0) {
47 /* If the uio mode is not read-only, need to release the memory first.
48 * Otherwise, the internal memory applied for read/write mode will be overwritten,
49 */
50 BSL_ERR_PUSH_ERROR(BSL_UIO_MEM_NOT_NULL);
51 return BSL_UIO_MEM_NOT_NULL;
52 }
53 if (ubm->tmpBuf == NULL) {
54 ubm->tmpBuf = BSL_BufMemNew();
55 if (ubm->tmpBuf == NULL) {
56 BSL_ERR_PUSH_ERROR(BSL_MALLOC_FAIL);
57 return BSL_MALLOC_FAIL;
58 }
59 }
60
61 ubm->readIndex = 0;
62 ubm->eof = 0;
63 bm->length = (size_t)len;
64 bm->max = (size_t)len;
65 bm->data = (void *)buf;
66 uio->flags = BSL_UIO_FLAGS_MEM_READ_ONLY;
67 return BSL_SUCCESS;
68 }
69
UioBufMemSync(UIO_BufMem * ubm)70 static int32_t UioBufMemSync(UIO_BufMem *ubm)
71 {
72 if (ubm != NULL && ubm->readIndex != 0) {
73 if (memmove_s(ubm->buf->data, ubm->buf->length, ubm->buf->data + ubm->readIndex,
74 ubm->buf->length - ubm->readIndex) != EOK) {
75 BSL_ERR_PUSH_ERROR(BSL_UIO_FAIL);
76 return BSL_UIO_FAIL;
77 }
78 ubm->buf->length -= ubm->readIndex;
79 ubm->readIndex = 0;
80 }
81 return BSL_SUCCESS;
82 }
83
MemWrite(BSL_UIO * uio,const void * buf,uint32_t len,uint32_t * writeLen)84 static int32_t MemWrite(BSL_UIO *uio, const void *buf, uint32_t len, uint32_t *writeLen)
85 {
86 if (BSL_UIO_GetCtx(uio) == NULL) {
87 BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
88 return BSL_NULL_INPUT;
89 }
90 if ((uio->flags & BSL_UIO_FLAGS_MEM_READ_ONLY) != 0) {
91 BSL_ERR_PUSH_ERROR(BSL_UIO_WRITE_NOT_ALLOWED);
92 return BSL_UIO_WRITE_NOT_ALLOWED;
93 }
94 (void)BSL_UIO_ClearFlags(uio, BSL_UIO_FLAGS_RWS | BSL_UIO_FLAGS_SHOULD_RETRY);
95 *writeLen = 0;
96 if (len == 0) {
97 return BSL_SUCCESS;
98 }
99 UIO_BufMem *ubm = BSL_UIO_GetCtx(uio);
100 if (ubm == NULL || ubm->buf == NULL) {
101 BSL_ERR_PUSH_ERROR(BSL_UIO_FAIL);
102 return BSL_UIO_FAIL;
103 }
104 if (UioBufMemSync(ubm) != BSL_SUCCESS) {
105 BSL_ERR_PUSH_ERROR(BSL_MEMMOVE_FAIL);
106 return BSL_MEMMOVE_FAIL;
107 }
108
109 const size_t origLen = ubm->buf->length;
110 if (BSL_BufMemGrowClean(ubm->buf, origLen + len) == 0) {
111 BSL_ERR_PUSH_ERROR(BSL_UIO_MEM_GROW_FAIL);
112 return BSL_UIO_MEM_GROW_FAIL;
113 }
114
115 // memory grow guarantee of success here
116 (void)memcpy_s(ubm->buf->data + origLen, len, buf, len);
117
118 *writeLen = len;
119 return BSL_SUCCESS;
120 }
121
MemRead(BSL_UIO * uio,void * buf,uint32_t len,uint32_t * readLen)122 static int32_t MemRead(BSL_UIO *uio, void *buf, uint32_t len, uint32_t *readLen)
123 {
124 if (BSL_UIO_GetCtx(uio) == NULL) {
125 BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
126 return BSL_NULL_INPUT;
127 }
128 (void)BSL_UIO_ClearFlags(uio, BSL_UIO_FLAGS_RWS | BSL_UIO_FLAGS_SHOULD_RETRY);
129 *readLen = 0;
130 UIO_BufMem *ubm = BSL_UIO_GetCtx(uio);
131 if (ubm == NULL || ubm->buf == NULL) {
132 BSL_ERR_PUSH_ERROR(BSL_UIO_FAIL);
133 return BSL_UIO_FAIL;
134 }
135 size_t real = (size_t)len;
136 if (real > ubm->buf->length - ubm->readIndex) {
137 real = ubm->buf->length - ubm->readIndex;
138 }
139 if (buf != NULL && real > 0) {
140 (void)memcpy_s(buf, len, ubm->buf->data + ubm->readIndex, real);
141 ubm->readIndex += real;
142 *readLen = (uint32_t)real;
143 }
144 if (*readLen > 0) {
145 return BSL_SUCCESS;
146 }
147 /* when real = 0, it is necessary to determine whether to retry based on eof */
148 if (ubm->eof != 0) { // retry if eof is not zero
149 (void)BSL_UIO_SetFlags(uio, BSL_UIO_FLAGS_READ | BSL_UIO_FLAGS_SHOULD_RETRY);
150 }
151 return BSL_SUCCESS;
152 }
153
MemPending(BSL_UIO * uio,int32_t larg,int64_t * ret)154 static int32_t MemPending(BSL_UIO *uio, int32_t larg, int64_t *ret)
155 {
156 if (ret == NULL) {
157 BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
158 return BSL_NULL_INPUT;
159 }
160 if (larg != sizeof(int64_t)) {
161 BSL_ERR_PUSH_ERROR(BSL_INVALID_ARG);
162 return BSL_INVALID_ARG;
163 }
164
165 UIO_BufMem *ubm = BSL_UIO_GetCtx(uio);
166 if (ubm == NULL || ubm->buf == NULL) {
167 BSL_ERR_PUSH_ERROR(BSL_UIO_FAIL);
168 return BSL_UIO_FAIL;
169 }
170
171 *ret = (int64_t)(ubm->buf->length - ubm->readIndex);
172 return BSL_SUCCESS;
173 }
174
MemWpending(int32_t larg,int64_t * ret)175 static int32_t MemWpending(int32_t larg, int64_t *ret)
176 {
177 if (ret == NULL) {
178 BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
179 return BSL_NULL_INPUT;
180 }
181 if (larg != sizeof(int64_t)) {
182 BSL_ERR_PUSH_ERROR(BSL_INVALID_ARG);
183 return BSL_INVALID_ARG;
184 }
185 *ret = 0; // For the UIO of the mem type, return 0
186 return BSL_SUCCESS;
187 }
188
MemGetInfo(BSL_UIO * uio,int32_t larg,BSL_UIO_CtrlGetInfoParam * param)189 static int32_t MemGetInfo(BSL_UIO *uio, int32_t larg, BSL_UIO_CtrlGetInfoParam *param)
190 {
191 if (param == NULL) {
192 BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
193 return BSL_NULL_INPUT;
194 }
195
196 if (larg != sizeof(BSL_UIO_CtrlGetInfoParam)) {
197 BSL_ERR_PUSH_ERROR(BSL_INVALID_ARG);
198 return BSL_INVALID_ARG;
199 }
200
201 UIO_BufMem *ubm = BSL_UIO_GetCtx(uio);
202 if (ubm == NULL || ubm->buf == NULL) {
203 BSL_ERR_PUSH_ERROR(BSL_UIO_FAIL);
204 return BSL_UIO_FAIL;
205 }
206
207 param->data = (uint8_t *)(&ubm->buf->data[ubm->readIndex]);
208 param->size = ubm->buf->length - ubm->readIndex;
209
210 return BSL_SUCCESS;
211 }
212
MemGetPtr(BSL_UIO * uio,int32_t size,BSL_BufMem ** ptr)213 static int32_t MemGetPtr(BSL_UIO *uio, int32_t size, BSL_BufMem **ptr)
214 {
215 if (ptr == NULL) {
216 BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
217 return BSL_NULL_INPUT;
218 }
219
220 if (size != sizeof(BSL_BufMem *)) {
221 BSL_ERR_PUSH_ERROR(BSL_INVALID_ARG);
222 return BSL_INVALID_ARG;
223 }
224
225 UIO_BufMem *ubm = BSL_UIO_GetCtx(uio);
226 if (ubm == NULL) {
227 BSL_ERR_PUSH_ERROR(BSL_UIO_FAIL);
228 return BSL_UIO_FAIL;
229 }
230 if ((uio->flags & BSL_UIO_FLAGS_MEM_READ_ONLY) == 0) {
231 if (UioBufMemSync(ubm) != BSL_SUCCESS) {
232 BSL_ERR_PUSH_ERROR(BSL_MEMMOVE_FAIL);
233 return BSL_MEMMOVE_FAIL;
234 }
235 *ptr = ubm->buf;
236 } else {
237 ubm->tmpBuf->data = ubm->buf->data + ubm->readIndex;
238 ubm->tmpBuf->length = ubm->buf->length - ubm->readIndex;
239 ubm->tmpBuf->max = ubm->buf->max - ubm->readIndex;
240 *ptr = ubm->tmpBuf;
241 }
242 return BSL_SUCCESS;
243 }
244
MemSetEof(BSL_UIO * uio,int32_t larg,const int32_t * eof)245 static int32_t MemSetEof(BSL_UIO *uio, int32_t larg, const int32_t *eof)
246 {
247 if (eof == NULL) {
248 BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
249 return BSL_NULL_INPUT;
250 }
251 if (larg != (int32_t)sizeof(int32_t)) {
252 BSL_ERR_PUSH_ERROR(BSL_INVALID_ARG);
253 return BSL_INVALID_ARG;
254 }
255
256 UIO_BufMem *ubm = BSL_UIO_GetCtx(uio);
257 if (ubm == NULL) {
258 BSL_ERR_PUSH_ERROR(BSL_UIO_FAIL);
259 return BSL_UIO_FAIL;
260 }
261
262 ubm->eof = *eof;
263 return BSL_SUCCESS;
264 }
265
MemGetEof(BSL_UIO * uio,int32_t larg,int32_t * eof)266 static int32_t MemGetEof(BSL_UIO *uio, int32_t larg, int32_t *eof)
267 {
268 if (eof == NULL) {
269 BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
270 return BSL_NULL_INPUT;
271 }
272 if (larg != (int32_t)sizeof(int32_t)) {
273 BSL_ERR_PUSH_ERROR(BSL_INVALID_ARG);
274 return BSL_INVALID_ARG;
275 }
276
277 UIO_BufMem *ubm = BSL_UIO_GetCtx(uio);
278 if (ubm == NULL) {
279 BSL_ERR_PUSH_ERROR(BSL_UIO_FAIL);
280 return BSL_UIO_FAIL;
281 }
282
283 *eof = ubm->eof;
284 return BSL_SUCCESS;
285 }
286
MemReset(BSL_UIO * uio)287 static int32_t MemReset(BSL_UIO *uio)
288 {
289 UIO_BufMem *ubm = BSL_UIO_GetCtx(uio);
290 if (ubm == NULL || ubm->buf == NULL || ubm->buf->data == NULL) {
291 BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
292 return BSL_NULL_INPUT;
293 }
294 if ((uio->flags & BSL_UIO_FLAGS_MEM_READ_ONLY) != 0) {
295 // Read-only mode: The read index is reset and data can be read again
296 ubm->readIndex = 0;
297 } else {
298 // Read/Write mode: Clear all data
299 (void)memset_s(ubm->buf->data, ubm->buf->max, 0, ubm->buf->max);
300 ubm->buf->length = 0;
301 ubm->readIndex = 0;
302 }
303 return BSL_SUCCESS;
304 }
305
MemFlush(int32_t larg,void * parg)306 static int32_t MemFlush(int32_t larg, void *parg)
307 {
308 if (parg != NULL || larg != 0) {
309 BSL_ERR_PUSH_ERROR(BSL_INVALID_ARG);
310 return BSL_INVALID_ARG;
311 }
312 return BSL_SUCCESS;
313 }
314
MemCtrl(BSL_UIO * uio,int32_t cmd,int32_t larg,void * parg)315 static int32_t MemCtrl(BSL_UIO *uio, int32_t cmd, int32_t larg, void *parg)
316 {
317 switch (cmd) {
318 case BSL_UIO_PENDING:
319 return MemPending(uio, larg, parg);
320 case BSL_UIO_MEM_GET_INFO:
321 return MemGetInfo(uio, larg, parg);
322 case BSL_UIO_WPENDING:
323 return MemWpending(larg, parg);
324 case BSL_UIO_FLUSH:
325 return MemFlush(larg, parg);
326 case BSL_UIO_MEM_NEW_BUF:
327 return MemNewBuf(uio, larg, parg);
328 case BSL_UIO_MEM_GET_PTR:
329 return MemGetPtr(uio, larg, parg);
330 case BSL_UIO_MEM_SET_EOF:
331 return MemSetEof(uio, larg, parg);
332 case BSL_UIO_MEM_GET_EOF:
333 return MemGetEof(uio, larg, parg);
334 case BSL_UIO_RESET:
335 return MemReset(uio);
336 default:
337 BSL_ERR_PUSH_ERROR(BSL_UIO_FAIL);
338 return BSL_UIO_FAIL;
339 }
340 }
341
MemDestroy(BSL_UIO * uio)342 static int32_t MemDestroy(BSL_UIO *uio)
343 {
344 UIO_BufMem *ubm = BSL_UIO_GetCtx(uio);
345 if (BSL_UIO_GetIsUnderlyingClosedByUio(uio) && ubm != NULL) {
346 if ((uio->flags & BSL_UIO_FLAGS_MEM_READ_ONLY) != 0) {
347 ubm->buf->data = NULL;
348 if (ubm->tmpBuf != NULL) {
349 ubm->tmpBuf->data = NULL;
350 BSL_BufMemFree(ubm->tmpBuf);
351 }
352 }
353 BSL_BufMemFree(ubm->buf);
354 BSL_SAL_FREE(ubm);
355 }
356
357 BSL_UIO_SetCtx(uio, NULL);
358 uio->init = false;
359 return BSL_SUCCESS;
360 }
361
MemCreate(BSL_UIO * uio)362 static int32_t MemCreate(BSL_UIO *uio)
363 {
364 UIO_BufMem *ubm = (UIO_BufMem *)BSL_SAL_Calloc(1, sizeof(UIO_BufMem));
365 if (ubm == NULL) {
366 BSL_ERR_PUSH_ERROR(BSL_MALLOC_FAIL);
367 return BSL_MALLOC_FAIL;
368 }
369
370 ubm->buf = BSL_BufMemNew();
371 if (ubm->buf == NULL) {
372 BSL_SAL_FREE(ubm);
373 BSL_ERR_PUSH_ERROR(BSL_MALLOC_FAIL);
374 return BSL_MALLOC_FAIL;
375 }
376
377 ubm->eof = -1;
378 BSL_UIO_SetCtx(uio, ubm);
379 BSL_UIO_SetIsUnderlyingClosedByUio(uio, true); // memory buffer is created here and will be closed here by default.
380 uio->init = true;
381 return BSL_SUCCESS;
382 }
383
BSL_UIO_MemMethod(void)384 const BSL_UIO_Method *BSL_UIO_MemMethod(void)
385 {
386 static const BSL_UIO_Method method = {
387 BSL_UIO_MEM,
388 MemWrite,
389 MemRead,
390 MemCtrl,
391 NULL,
392 NULL,
393 MemCreate,
394 MemDestroy
395 };
396 return &method;
397 }
398
399 #endif /* HITLS_BSL_UIO_MEM */
400