• 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 
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