xref: /optee_os/core/tee/tee_svc_storage.c (revision 03c42787bbb0d574300fdc79ef82316837aef3a3)
1 /*
2  * Copyright (c) 2014, STMicroelectronics International N.V.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <tee/tee_svc_storage.h>
29 
30 #include <kernel/tee_ta_manager.h>
31 #include <tee_api_defines.h>
32 #include <kernel/tee_misc.h>
33 #include <tee/tee_fs.h>
34 #include <tee/tee_fs_defs.h>
35 #include <tee/tee_obj.h>
36 #include <tee/tee_svc.h>
37 #include <mm/tee_mmu.h>
38 #include <tee/tee_pobj.h>
39 #include <kernel/tee_core_trace.h>
40 
41 /* SSF (Secure Storage File version 00 */
42 #define TEE_SVC_STORAGE_MAGIC 0x53534600;
43 
44 /* Header of GP formated secure storage files */
45 struct tee_svc_storage_head {
46 	uint32_t magic;
47 	uint32_t head_size;
48 	uint32_t meta_size;
49 	uint32_t ds_size;
50 };
51 
52 struct tee_storage_enum {
53 	TAILQ_ENTRY(tee_storage_enum) link;
54 	tee_fs_dir *dir;
55 };
56 
57 static TEE_Result tee_svc_storage_get_enum(struct tee_ta_ctx *ctx,
58 					   uint32_t enum_id,
59 					   struct tee_storage_enum **e_out)
60 {
61 	struct tee_storage_enum *e;
62 
63 	TAILQ_FOREACH(e, &ctx->storage_enums, link) {
64 		if (enum_id == (uint32_t) e) {
65 			*e_out = e;
66 			return TEE_SUCCESS;
67 		}
68 	}
69 	return TEE_ERROR_BAD_PARAMETERS;
70 }
71 
72 static TEE_Result tee_svc_close_enum(struct tee_ta_ctx *ctx,
73 				     struct tee_storage_enum *e)
74 {
75 	int ret;
76 
77 	if (e == NULL || ctx == NULL)
78 		return TEE_ERROR_BAD_PARAMETERS;
79 
80 	TAILQ_REMOVE(&ctx->storage_enums, e, link);
81 
82 	ret = tee_fs_closedir(e->dir);
83 	e->dir = NULL;
84 
85 	free(e);
86 
87 	if (ret != 0)
88 		return TEE_ERROR_ITEM_NOT_FOUND;
89 
90 	return TEE_SUCCESS;
91 }
92 
93 static char *tee_svc_storage_create_filename(struct tee_ta_session *sess,
94 					     void *object_id,
95 					     uint32_t object_id_len)
96 {
97 	uint8_t *file = NULL;
98 	/* +1 for the '/' */
99 	uint32_t hslen =
100 	    TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID) + object_id_len) + 1;
101 	uint32_t pos;
102 
103 	file = malloc(hslen);
104 
105 	if (file == NULL)
106 		return NULL;
107 
108 	pos = tee_b2hs((uint8_t *)&sess->ctx->head->uuid, file,
109 		       sizeof(TEE_UUID), hslen);
110 	file[pos] = '/';
111 	pos++;
112 	tee_b2hs(object_id, file + pos, object_id_len, hslen - pos);
113 
114 	return (char *)file;
115 }
116 
117 static char *tee_svc_storage_create_dirname(struct tee_ta_session *sess)
118 {
119 	uint8_t *dir = NULL;
120 	uint32_t hslen = TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID));
121 
122 	dir = malloc(hslen);
123 
124 	if (dir == NULL)
125 		return NULL;
126 
127 	tee_b2hs((uint8_t *)&sess->ctx->head->uuid, dir, sizeof(TEE_UUID),
128 		 hslen);
129 
130 	return (char *)dir;
131 }
132 
133 static uint32_t tee_svc_storage_conv_oflags(uint32_t flags)
134 {
135 	uint32_t out = 0;
136 
137 	if (flags & (TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_SHARE_READ)) {
138 		if (flags & (TEE_DATA_FLAG_ACCESS_WRITE |
139 			     TEE_DATA_FLAG_ACCESS_WRITE_META |
140 			     TEE_DATA_FLAG_SHARE_WRITE))
141 			out |= TEE_FS_O_RDWR;
142 		else
143 			out |= TEE_FS_O_RDONLY;
144 	} else {
145 		if (flags & (TEE_DATA_FLAG_ACCESS_WRITE |
146 			     TEE_DATA_FLAG_ACCESS_WRITE_META |
147 			     TEE_DATA_FLAG_SHARE_WRITE))
148 			out |= TEE_FS_O_WRONLY;
149 	}
150 
151 	if (flags & TEE_DATA_FLAG_EXCLUSIVE)
152 		out |= TEE_FS_O_EXCL;
153 
154 	return out;
155 }
156 
157 static int tee_svc_storage_conv_whence(TEE_Whence whence)
158 {
159 	switch (whence) {
160 	case TEE_DATA_SEEK_SET:
161 		return TEE_FS_SEEK_SET;
162 	case TEE_DATA_SEEK_CUR:
163 		return TEE_FS_SEEK_CUR;
164 	case TEE_DATA_SEEK_END:
165 		return TEE_FS_SEEK_END;
166 	default:
167 		return -1;
168 	}
169 }
170 
171 static TEE_Result tee_svc_storage_create_file(struct tee_ta_session *sess,
172 					      char *file, int *fd,
173 					      uint32_t flags)
174 {
175 	TEE_Result res = TEE_SUCCESS;
176 	char *dir = NULL;
177 	int tmp;
178 	uint32_t cflags = TEE_FS_O_WRONLY | TEE_FS_O_CREATE;
179 
180 	if (flags & TEE_DATA_FLAG_EXCLUSIVE)
181 		cflags |= TEE_FS_O_EXCL;
182 
183 	*fd = tee_fs_open(file, cflags);
184 
185 	if (*fd < 0) {
186 		/* try and make directory */
187 		dir = tee_svc_storage_create_dirname(sess);
188 		if (dir == NULL) {
189 			res = TEE_ERROR_OUT_OF_MEMORY;
190 			goto exit;
191 		}
192 
193 		tmp = tee_fs_mkdir(dir, TEE_FS_S_IRUSR | TEE_FS_S_IWUSR);
194 		free(dir);
195 
196 		if (tmp < 0) {
197 			/* error codes needs better granularity */
198 			res = TEE_ERROR_GENERIC;
199 			goto exit;
200 		}
201 
202 		/* try and open again */
203 		*fd = tee_fs_open(file, cflags);
204 
205 		if (*fd < 0) {
206 			/* error codes needs better granularity */
207 			res = TEE_ERROR_GENERIC;
208 			goto exit;
209 		}
210 	}
211 
212 exit:
213 	return res;
214 }
215 
216 static TEE_Result tee_svc_storage_read_head(struct tee_ta_session *sess,
217 					    struct tee_obj *o)
218 {
219 	TEE_Result res = TEE_SUCCESS;
220 	int fd = -1;
221 	int err;
222 	struct tee_svc_storage_head head;
223 	char *file = NULL;
224 
225 	if (o == NULL || o->pobj == NULL)
226 		return TEE_ERROR_BAD_PARAMETERS;
227 
228 	file =
229 	    tee_svc_storage_create_filename(sess, o->pobj->obj_id,
230 					    o->pobj->obj_id_len);
231 	if (file == NULL) {
232 		res = TEE_ERROR_OUT_OF_MEMORY;
233 		goto exit;
234 	}
235 
236 	fd = tee_fs_open(file, TEE_FS_O_RDONLY);
237 	free(file);
238 
239 	/* error codes needs better granularity */
240 	if (fd < 0)
241 		return TEE_ERROR_ITEM_NOT_FOUND;
242 
243 	/* read head */
244 	err = tee_fs_read(fd, &head, sizeof(struct tee_svc_storage_head));
245 	if (err != sizeof(struct tee_svc_storage_head)) {
246 		res = TEE_ERROR_BAD_FORMAT;
247 		goto exit;
248 	}
249 
250 	o->data_size = head.meta_size;
251 	o->info.dataSize = head.ds_size;
252 
253 	o->data = malloc(o->data_size);
254 	if (o->data == NULL) {
255 		res = TEE_ERROR_OUT_OF_MEMORY;
256 		goto exit;
257 	}
258 
259 	/* read meta */
260 	err = tee_fs_read(fd, o->data, o->data_size);
261 	if (err != (int)o->data_size) {
262 		free(o->data);
263 		o->data = NULL;
264 		res = TEE_ERROR_NO_DATA;
265 	}
266 
267 exit:
268 	tee_fs_close(fd);
269 
270 	return res;
271 }
272 
273 static TEE_Result tee_svc_storage_init_file(struct tee_ta_session *sess,
274 					    struct tee_obj *o,
275 					    struct tee_obj *attr_o, void *data,
276 					    uint32_t len, uint32_t flags)
277 {
278 	TEE_Result res = TEE_SUCCESS;
279 	int fd;
280 	int err;
281 	struct tee_svc_storage_head head;
282 	char *file = NULL;
283 
284 	if (o == NULL || o->pobj == NULL)
285 		return TEE_ERROR_BAD_PARAMETERS;
286 
287 	free(o->data);
288 
289 	if (attr_o && attr_o->data_size) {
290 		o->data_size = attr_o->data_size;
291 		o->data = malloc(attr_o->data_size);
292 		if (o->data == NULL)
293 			return TEE_ERROR_OUT_OF_MEMORY;
294 
295 		memcpy(o->data, attr_o->data, attr_o->data_size);
296 		o->have_attrs = attr_o->have_attrs;
297 		o->info.objectUsage = attr_o->info.objectUsage;
298 		o->info.objectType = attr_o->info.objectType;
299 	} else {
300 		o->data = NULL;
301 		o->data_size = 0;
302 		o->have_attrs = 0;
303 		o->info.objectUsage = TEE_USAGE_DEFAULT;
304 		o->info.objectType = 0;
305 	}
306 
307 	/* write head */
308 	head.magic = TEE_SVC_STORAGE_MAGIC;
309 	head.head_size = sizeof(struct tee_svc_storage_head);
310 	head.meta_size = o->data_size;
311 	head.ds_size = len;
312 
313 	file =
314 	    tee_svc_storage_create_filename(sess, o->pobj->obj_id,
315 					    o->pobj->obj_id_len);
316 	if (file == NULL)
317 		return TEE_ERROR_OUT_OF_MEMORY;
318 
319 	res = tee_svc_storage_create_file(sess, file, &fd, flags);
320 	free(file);
321 	if (res != TEE_SUCCESS)
322 		return res;
323 
324 	/* error codes needs better granularity */
325 	if (fd < 0)
326 		return TEE_ERROR_GENERIC;
327 
328 	/* write head */
329 	err = tee_fs_write(fd, &head, sizeof(struct tee_svc_storage_head));
330 	/* error codes needs better granularity */
331 	if (err != sizeof(struct tee_svc_storage_head)) {
332 		res = TEE_ERROR_GENERIC;
333 		goto exit;
334 	}
335 
336 	/* write meta */
337 	err = tee_fs_write(fd, o->data, o->data_size);
338 	/* error codes needs better granularity */
339 	if (err != (int)o->data_size) {
340 		res = TEE_ERROR_GENERIC;
341 		goto exit;
342 	}
343 
344 	/* write init data */
345 	o->info.dataSize = len;
346 
347 	/* write data to fs if needed */
348 	if (data && len) {
349 		err = tee_fs_write(fd, data, len);
350 
351 		if (err != (int)len) {
352 			/* error codes needs better granularity */
353 			res = TEE_ERROR_GENERIC;
354 			return res;
355 		}
356 	}
357 
358 exit:
359 	tee_fs_close(fd);
360 
361 	return TEE_SUCCESS;
362 }
363 
364 static TEE_Result tee_svc_storage_remove(struct tee_ta_session *sess,
365 					 uint32_t storage_id, void *object_id,
366 					 uint32_t object_id_len)
367 {
368 	TEE_Result res = TEE_SUCCESS;
369 	char *file = NULL;
370 	int err;
371 
372 	if (sess == NULL)
373 		return TEE_ERROR_BAD_PARAMETERS;
374 
375 	if (storage_id != TEE_STORAGE_PRIVATE)
376 		return TEE_ERROR_ITEM_NOT_FOUND;
377 
378 	file = tee_svc_storage_create_filename(sess, object_id, object_id_len);
379 	if (file == NULL)
380 		return TEE_ERROR_OUT_OF_MEMORY;
381 
382 	err = tee_fs_unlink(file);
383 	free(file);
384 	if (err != 0)
385 		/* error codes needs better granularity */
386 		res = TEE_ERROR_GENERIC;
387 
388 	return res;
389 }
390 
391 TEE_Result tee_svc_storage_obj_open(uint32_t storage_id, void *object_id,
392 				    uint32_t object_id_len, uint32_t flags,
393 				    uint32_t *obj)
394 {
395 	TEE_Result res;
396 	struct tee_ta_session *sess;
397 	struct tee_obj *o;
398 	char *file = NULL;
399 	int fs_flags;
400 	int fd = -1;
401 	tee_fs_off_t off;
402 	tee_fs_off_t e_off;
403 	struct tee_pobj *po = NULL;
404 
405 	if (storage_id != TEE_STORAGE_PRIVATE)
406 		return TEE_ERROR_ITEM_NOT_FOUND;
407 
408 	if (object_id_len > TEE_OBJECT_ID_MAX_LEN)
409 		return TEE_ERROR_BAD_PARAMETERS;
410 
411 	res = tee_ta_get_current_session(&sess);
412 	if (res != TEE_SUCCESS)
413 		goto exit;
414 
415 	res =
416 	    tee_mmu_check_access_rights(sess->ctx,
417 					TEE_MEMORY_ACCESS_READ |
418 					TEE_MEMORY_ACCESS_ANY_OWNER,
419 					(tee_uaddr_t) object_id, object_id_len);
420 	if (res != TEE_SUCCESS)
421 		goto exit;
422 
423 	res = tee_pobj_get((void *)&sess->ctx->head->uuid, object_id,
424 			   object_id_len, flags, &po);
425 	if (res != TEE_SUCCESS)
426 		goto exit;
427 
428 	fs_flags = tee_svc_storage_conv_oflags(flags);
429 
430 	o = calloc(1, sizeof(*o));
431 	if (o == NULL) {
432 		res = TEE_ERROR_OUT_OF_MEMORY;
433 		goto exit;
434 	}
435 
436 	o->info.handleFlags =
437 	    TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED;
438 	o->info.objectUsage = TEE_USAGE_DEFAULT;
439 	o->flags = flags;
440 	o->pobj = po;
441 
442 	res = tee_svc_storage_read_head(sess, o);
443 	if (res != TEE_SUCCESS) {
444 		free(o);
445 		goto exit;
446 	}
447 
448 	file = tee_svc_storage_create_filename(sess, object_id, object_id_len);
449 	if (file == NULL) {
450 		res = TEE_ERROR_OUT_OF_MEMORY;
451 		goto exit;
452 	}
453 
454 	fd = tee_fs_open(file, fs_flags);
455 	free(file);
456 	if (fd < 0) {
457 		res = TEE_ERROR_ITEM_NOT_FOUND;
458 		goto exit;
459 	}
460 	o->fd = fd;
461 
462 	tee_obj_add(sess->ctx, o);
463 
464 	res = tee_svc_copy_to_user(sess, obj, &o, sizeof(o));
465 	if (res != TEE_SUCCESS)
466 		tee_obj_close(sess->ctx, o);
467 
468 	e_off = sizeof(struct tee_svc_storage_head) + o->data_size;
469 	off = tee_fs_lseek(fd, e_off, TEE_FS_SEEK_SET);
470 	if (off != e_off) {
471 		res = TEE_ERROR_NO_DATA;
472 		goto exit;
473 	}
474 
475 exit:
476 	if (res != TEE_SUCCESS) {
477 		if (res == TEE_ERROR_NO_DATA || res == TEE_ERROR_BAD_FORMAT) {
478 			/* the file is corrupt, delete */
479 			tee_svc_storage_remove(sess, storage_id, object_id,
480 					       object_id_len);
481 
482 			/* "greaceful" return */
483 			res = TEE_ERROR_ITEM_NOT_FOUND;
484 		}
485 
486 		if (fd >= 0)
487 			tee_fs_close(fd);
488 		if (po)
489 			tee_pobj_release(po);
490 	}
491 
492 	return res;
493 }
494 
495 TEE_Result tee_svc_storage_obj_create(uint32_t storage_id, void *object_id,
496 				      uint32_t object_id_len, uint32_t flags,
497 				      uint32_t attr, void *data, uint32_t len,
498 				      uint32_t *obj)
499 {
500 	TEE_Result res;
501 	struct tee_ta_session *sess;
502 	struct tee_obj *o = NULL;
503 	struct tee_obj *attr_o = NULL;
504 	char *file = NULL;
505 	int fd = -1;
506 	int fs_flags;
507 	tee_fs_off_t off;
508 	tee_fs_off_t e_off;
509 	struct tee_pobj *po = NULL;
510 
511 	if (storage_id != TEE_STORAGE_PRIVATE)
512 		return TEE_ERROR_ITEM_NOT_FOUND;
513 
514 	if (object_id_len > TEE_OBJECT_ID_MAX_LEN)
515 		return TEE_ERROR_BAD_PARAMETERS;
516 
517 	res = tee_ta_get_current_session(&sess);
518 	if (res != TEE_SUCCESS)
519 		return res;
520 
521 	res =
522 	    tee_mmu_check_access_rights(sess->ctx,
523 					TEE_MEMORY_ACCESS_READ |
524 					TEE_MEMORY_ACCESS_ANY_OWNER,
525 					(tee_uaddr_t) object_id, object_id_len);
526 	if (res != TEE_SUCCESS)
527 		goto exit;
528 
529 	res = tee_pobj_get((void *)&sess->ctx->head->uuid, object_id,
530 			   object_id_len, flags, &po);
531 	if (res != TEE_SUCCESS)
532 		goto exit;
533 
534 	/* Init attributes if attibutes are provided */
535 	if (attr != TEE_HANDLE_NULL) {
536 		res = tee_obj_get(sess->ctx, attr, &attr_o);
537 		if (res != TEE_SUCCESS)
538 			goto exit;
539 	}
540 
541 	/* check rights of the provided buffer */
542 	if (data && len) {
543 		res =
544 		    tee_mmu_check_access_rights(sess->ctx,
545 						TEE_MEMORY_ACCESS_READ |
546 						TEE_MEMORY_ACCESS_ANY_OWNER,
547 						(tee_uaddr_t) data, len);
548 
549 		if (res != TEE_SUCCESS)
550 			goto exit;
551 	}
552 
553 	o = calloc(1, sizeof(*o));
554 	if (o == NULL) {
555 		res = TEE_ERROR_OUT_OF_MEMORY;
556 		goto exit;
557 	}
558 
559 	o->info.handleFlags =
560 	    TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED;
561 	o->flags = flags;
562 	o->pobj = po;
563 
564 	res = tee_svc_storage_init_file(sess, o, attr_o, data, len, flags);
565 	if (res != TEE_SUCCESS) {
566 		free(o);
567 		goto exit;
568 	}
569 
570 	fs_flags = tee_svc_storage_conv_oflags(flags);
571 
572 	file = tee_svc_storage_create_filename(sess, object_id, object_id_len);
573 	if (file == NULL) {
574 		res = TEE_ERROR_OUT_OF_MEMORY;
575 		goto exit;
576 	}
577 
578 	fd = tee_fs_open(file, fs_flags);
579 	free(file);
580 	file = NULL;
581 	if (fd < 0) {
582 		res = TEE_ERROR_ITEM_NOT_FOUND;
583 		goto exit;
584 	}
585 	o->fd = fd;
586 
587 	tee_obj_add(sess->ctx, o);
588 
589 	res = tee_svc_copy_to_user(sess, obj, &o, sizeof(o));
590 	if (res != TEE_SUCCESS)
591 		tee_obj_close(sess->ctx, o);
592 
593 	e_off = sizeof(struct tee_svc_storage_head) + o->data_size;
594 	off = tee_fs_lseek(fd, e_off, TEE_FS_SEEK_SET);
595 	if (off != e_off) {
596 		res = TEE_ERROR_NO_DATA;
597 		goto exit;
598 	}
599 
600 exit:
601 	if (res != TEE_SUCCESS) {
602 		if (fd >= 0)
603 			tee_fs_close(fd);
604 		if (po)
605 			tee_pobj_release(po);
606 	}
607 
608 	return res;
609 }
610 
611 TEE_Result tee_svc_storage_obj_del(uint32_t obj)
612 {
613 	TEE_Result res;
614 	struct tee_ta_session *sess;
615 	struct tee_obj *o;
616 	int err;
617 	char *file;
618 	char *dir;
619 
620 	res = tee_ta_get_current_session(&sess);
621 	if (res != TEE_SUCCESS)
622 		return res;
623 
624 	res = tee_obj_get(sess->ctx, obj, &o);
625 	if (res != TEE_SUCCESS)
626 		return res;
627 
628 	if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE_META))
629 		return TEE_ERROR_ACCESS_CONFLICT;
630 
631 	if (o->pobj == NULL || o->pobj->obj_id == NULL)
632 		return TEE_ERROR_BAD_STATE;
633 
634 	file =
635 	    tee_svc_storage_create_filename(sess, o->pobj->obj_id,
636 					    o->pobj->obj_id_len);
637 	if (file == NULL)
638 		return TEE_ERROR_OUT_OF_MEMORY;
639 
640 	tee_obj_close(sess->ctx, o);
641 
642 	err = tee_fs_unlink(file);
643 	free(file);
644 	if (err != 0)
645 		/* error codes needs better granularity */
646 		return TEE_ERROR_GENERIC;
647 
648 	/* try and remove dir */
649 	dir = tee_svc_storage_create_dirname(sess);
650 	if (dir == NULL)
651 		return TEE_ERROR_OUT_OF_MEMORY;
652 	/* ignore result */
653 	tee_fs_rmdir(dir);
654 	free(dir);
655 
656 	return TEE_SUCCESS;
657 }
658 
659 TEE_Result tee_svc_storage_obj_rename(uint32_t obj, void *object_id,
660 				      uint32_t object_id_len)
661 {
662 	TEE_Result res;
663 	struct tee_ta_session *sess;
664 	struct tee_obj *o;
665 	struct tee_pobj *po = NULL;
666 	char *new_file = NULL;
667 	char *old_file = NULL;
668 	int err = -1;
669 
670 	if (object_id_len > TEE_OBJECT_ID_MAX_LEN)
671 		return TEE_ERROR_BAD_PARAMETERS;
672 
673 	res = tee_ta_get_current_session(&sess);
674 	if (res != TEE_SUCCESS)
675 		return res;
676 
677 	res = tee_obj_get(sess->ctx, obj, &o);
678 	if (res != TEE_SUCCESS)
679 		return res;
680 
681 	if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE_META)) {
682 		res = TEE_ERROR_BAD_STATE;
683 		goto exit;
684 	}
685 
686 	if (o->pobj == NULL || o->pobj->obj_id == NULL)
687 		return TEE_ERROR_BAD_STATE;
688 
689 	res =
690 	    tee_mmu_check_access_rights(sess->ctx,
691 					TEE_MEMORY_ACCESS_READ |
692 					TEE_MEMORY_ACCESS_ANY_OWNER,
693 					(tee_uaddr_t) object_id, object_id_len);
694 	if (res != TEE_SUCCESS)
695 		goto exit;
696 
697 	/* get new ds name */
698 	new_file =
699 	    tee_svc_storage_create_filename(sess, object_id, object_id_len);
700 	if (new_file == NULL) {
701 		res = TEE_ERROR_OUT_OF_MEMORY;
702 		goto exit;
703 	}
704 
705 	old_file =
706 	    tee_svc_storage_create_filename(sess, o->pobj->obj_id,
707 					    o->pobj->obj_id_len);
708 	if (old_file == NULL) {
709 		res = TEE_ERROR_OUT_OF_MEMORY;
710 		goto exit;
711 	}
712 
713 	/* reserve dest name */
714 	res = tee_pobj_get((void *)&sess->ctx->head->uuid, object_id,
715 			   object_id_len, TEE_DATA_FLAG_ACCESS_WRITE_META, &po);
716 	if (res != TEE_SUCCESS)
717 		goto exit;
718 
719 	err = tee_fs_access(new_file, TEE_FS_F_OK);
720 	if (err == 0) {
721 		/* file exists */
722 		res = TEE_ERROR_ACCESS_CONFLICT;
723 		goto exit;
724 	}
725 
726 	/* move */
727 	err = tee_fs_rename(old_file, new_file);
728 	if (err) {
729 		/* error codes needs better granularity */
730 		res = TEE_ERROR_GENERIC;
731 		goto exit;
732 	}
733 
734 	res = tee_pobj_rename(o->pobj, object_id, object_id_len);
735 
736 exit:
737 	tee_pobj_release(po);
738 
739 	free(new_file);
740 	free(old_file);
741 
742 	return res;
743 }
744 
745 TEE_Result tee_svc_storage_alloc_enum(uint32_t *obj_enum)
746 {
747 	struct tee_storage_enum *e;
748 	struct tee_ta_session *sess;
749 	TEE_Result res;
750 
751 	if (obj_enum == NULL)
752 		return TEE_ERROR_BAD_PARAMETERS;
753 
754 	res = tee_ta_get_current_session(&sess);
755 	if (res != TEE_SUCCESS)
756 		return res;
757 
758 	e = malloc(sizeof(struct tee_storage_enum));
759 
760 	if (e == NULL)
761 		return TEE_ERROR_OUT_OF_MEMORY;
762 
763 	e->dir = NULL;
764 	TAILQ_INSERT_TAIL(&sess->ctx->storage_enums, e, link);
765 
766 	return tee_svc_copy_to_user(sess, obj_enum, &e,
767 				    sizeof(TEE_ObjectEnumHandle *));
768 }
769 
770 TEE_Result tee_svc_storage_free_enum(uint32_t obj_enum)
771 {
772 	struct tee_storage_enum *e;
773 	TEE_Result res;
774 	struct tee_ta_session *sess;
775 
776 	if (obj_enum == TEE_HANDLE_NULL)
777 		return TEE_SUCCESS;
778 
779 	res = tee_ta_get_current_session(&sess);
780 	if (res != TEE_SUCCESS)
781 		return res;
782 
783 	res = tee_svc_storage_get_enum(sess->ctx, obj_enum, &e);
784 	if (res != TEE_SUCCESS)
785 		return res;
786 
787 	return tee_svc_close_enum(sess->ctx, e);
788 }
789 
790 TEE_Result tee_svc_storage_reset_enum(uint32_t obj_enum)
791 {
792 	struct tee_storage_enum *e;
793 	int res;
794 	struct tee_ta_session *sess;
795 
796 	res = tee_ta_get_current_session(&sess);
797 	if (res != TEE_SUCCESS)
798 		return res;
799 
800 	if (obj_enum == TEE_HANDLE_NULL)
801 		return TEE_SUCCESS;
802 
803 	res = tee_svc_storage_get_enum(sess->ctx, obj_enum, &e);
804 	if (res != TEE_SUCCESS)
805 		return res;
806 
807 	res = tee_fs_closedir(e->dir);
808 	e->dir = NULL;
809 	if (res != 0)
810 		return TEE_ERROR_GENERIC;
811 
812 	return TEE_SUCCESS;
813 }
814 
815 TEE_Result tee_svc_storage_start_enum(uint32_t obj_enum, uint32_t storage_id)
816 {
817 	struct tee_storage_enum *e;
818 	char *dir;
819 	TEE_Result res;
820 	struct tee_ta_session *sess;
821 
822 	if (obj_enum == TEE_HANDLE_NULL)
823 		return TEE_ERROR_BAD_PARAMETERS;
824 
825 	res = tee_ta_get_current_session(&sess);
826 	if (res != TEE_SUCCESS)
827 		return res;
828 
829 	res = tee_svc_storage_get_enum(sess->ctx, obj_enum, &e);
830 	if (res != TEE_SUCCESS)
831 		return res;
832 
833 	if (storage_id != TEE_STORAGE_PRIVATE)
834 		return TEE_ERROR_ITEM_NOT_FOUND;
835 
836 	dir = tee_svc_storage_create_dirname(sess);
837 	if (dir == NULL)
838 		return TEE_ERROR_OUT_OF_MEMORY;
839 
840 	e->dir = tee_fs_opendir(dir);
841 	free(dir);
842 
843 	if (e->dir == NULL)
844 		/* error codes needs better granularity */
845 		return TEE_ERROR_ITEM_NOT_FOUND;
846 
847 	return TEE_SUCCESS;
848 }
849 
850 TEE_Result tee_svc_storage_next_enum(uint32_t obj_enum, TEE_ObjectInfo *info,
851 				     void *obj_id, size_t *len)
852 {
853 	struct tee_storage_enum *e;
854 	struct tee_fs_dirent *d;
855 	TEE_Result res = TEE_SUCCESS;
856 	struct tee_ta_session *sess;
857 	struct tee_obj *o = NULL;
858 	uint32_t blen;
859 	uint32_t hslen;
860 
861 	res = tee_ta_get_current_session(&sess);
862 	if (res != TEE_SUCCESS)
863 		return res;
864 
865 	if (obj_enum == TEE_HANDLE_NULL)
866 		return TEE_ERROR_BAD_PARAMETERS;
867 
868 	res = tee_svc_storage_get_enum(sess->ctx, obj_enum, &e);
869 	if (res != TEE_SUCCESS)
870 		return res;
871 
872 	/* check rights of the provided buffers */
873 	res =
874 	    tee_mmu_check_access_rights(sess->ctx,
875 					TEE_MEMORY_ACCESS_WRITE |
876 					TEE_MEMORY_ACCESS_ANY_OWNER,
877 					(tee_uaddr_t) info,
878 					sizeof(TEE_ObjectInfo));
879 	if (res != TEE_SUCCESS)
880 		return res;
881 
882 	res =
883 	    tee_mmu_check_access_rights(sess->ctx,
884 					TEE_MEMORY_ACCESS_WRITE |
885 					TEE_MEMORY_ACCESS_ANY_OWNER,
886 					(tee_uaddr_t) obj_id,
887 					TEE_OBJECT_ID_MAX_LEN);
888 	if (res != TEE_SUCCESS)
889 		return res;
890 
891 	d = tee_fs_readdir(e->dir);
892 	if (d == NULL)
893 		return TEE_ERROR_ITEM_NOT_FOUND;
894 
895 	o = calloc(1, sizeof(struct tee_obj));
896 	if (o == NULL) {
897 		res = TEE_ERROR_OUT_OF_MEMORY;
898 		goto exit;
899 	}
900 
901 	o->pobj = calloc(1, sizeof(struct tee_pobj));
902 	if (!o->pobj) {
903 		res = TEE_ERROR_OUT_OF_MEMORY;
904 		goto exit;
905 	}
906 
907 	o->info.handleFlags =
908 	    TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED;
909 	o->info.objectUsage = TEE_USAGE_DEFAULT;
910 
911 	/*
912 	 * NOTE: Special usage of pobj due to not ref cnt should be inc
913 	 */
914 	hslen = strlen(d->d_name);
915 	blen = TEE_HS2B_BBUF_SIZE(hslen);
916 	o->pobj->obj_id = malloc(blen);
917 	if (o->pobj->obj_id == NULL) {
918 		res = TEE_ERROR_OUT_OF_MEMORY;
919 		goto exit;
920 	}
921 	tee_hs2b((uint8_t *)d->d_name, o->pobj->obj_id, hslen, blen);
922 	o->pobj->obj_id_len = blen;
923 
924 	res = tee_svc_storage_read_head(sess, o);
925 	if (res != TEE_SUCCESS) {
926 		/* TODO: handle corrupt files in a greaceful way */
927 		goto exit;
928 	}
929 	memcpy(info, &o->info, sizeof(TEE_ObjectInfo));
930 	memcpy(obj_id, o->pobj->obj_id, o->pobj->obj_id_len);
931 
932 	res =
933 	    tee_svc_copy_to_user(sess, len, &o->pobj->obj_id_len,
934 				 sizeof(uint32_t));
935 
936 exit:
937 	if (o) {
938 		if (o->pobj)
939 			free(o->pobj->obj_id);
940 		free(o->pobj);
941 		free(o->data);
942 	}
943 	free(o);
944 
945 	return res;
946 }
947 
948 TEE_Result tee_svc_storage_obj_read(uint32_t obj, void *data, size_t len,
949 				    uint32_t *count)
950 {
951 	TEE_Result res;
952 	struct tee_ta_session *sess;
953 	struct tee_obj *o;
954 	int n_count;
955 	uint32_t u_count;
956 
957 	res = tee_ta_get_current_session(&sess);
958 	if (res != TEE_SUCCESS)
959 		return res;
960 
961 	res = tee_obj_get(sess->ctx, obj, &o);
962 	if (res != TEE_SUCCESS)
963 		return res;
964 
965 	if (!(o->flags & TEE_DATA_FLAG_ACCESS_READ))
966 		return TEE_ERROR_ACCESS_CONFLICT;
967 
968 	/* check rights of the provided buffer */
969 	res =
970 	    tee_mmu_check_access_rights(sess->ctx,
971 					TEE_MEMORY_ACCESS_WRITE |
972 					TEE_MEMORY_ACCESS_ANY_OWNER,
973 					(tee_uaddr_t) data, len);
974 	if (res != TEE_SUCCESS)
975 		return res;
976 
977 	n_count = tee_fs_read(o->fd, data, len);
978 	u_count = (uint32_t) ((n_count < 0) ? 0 : n_count);
979 
980 	res = tee_svc_copy_to_user(sess, count, &u_count, sizeof(uint32_t));
981 
982 	o->info.dataPosition += u_count;
983 
984 	return TEE_SUCCESS;
985 }
986 
987 TEE_Result tee_svc_storage_obj_write(uint32_t obj, void *data, size_t len)
988 {
989 	TEE_Result res;
990 	struct tee_ta_session *sess;
991 	struct tee_obj *o;
992 	int err;
993 
994 	res = tee_ta_get_current_session(&sess);
995 	if (res != TEE_SUCCESS)
996 		return res;
997 
998 	res = tee_obj_get(sess->ctx, obj, &o);
999 	if (res != TEE_SUCCESS)
1000 		return res;
1001 
1002 	if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE))
1003 		return TEE_ERROR_ACCESS_CONFLICT;
1004 
1005 	/* check rights of the provided buffer */
1006 	res =
1007 	    tee_mmu_check_access_rights(sess->ctx,
1008 					TEE_MEMORY_ACCESS_READ |
1009 					TEE_MEMORY_ACCESS_ANY_OWNER,
1010 					(tee_uaddr_t) data, len);
1011 
1012 	err = tee_fs_write(o->fd, data, len);
1013 
1014 	if (err != (int)len) {
1015 		/* error codes needs better granularity */
1016 		res = TEE_ERROR_GENERIC;
1017 		return res;
1018 	}
1019 
1020 	o->info.dataPosition += len;
1021 	if (o->info.dataPosition > o->info.dataSize)
1022 		o->info.dataSize = o->info.dataPosition;
1023 
1024 	return TEE_SUCCESS;
1025 }
1026 
1027 TEE_Result tee_svc_storage_obj_trunc(uint32_t obj, size_t len)
1028 {
1029 	TEE_Result res;
1030 	struct tee_ta_session *sess;
1031 	struct tee_obj *o;
1032 	int err;
1033 	tee_fs_off_t off;
1034 
1035 	res = tee_ta_get_current_session(&sess);
1036 	if (res != TEE_SUCCESS)
1037 		return res;
1038 
1039 	res = tee_obj_get(sess->ctx, obj, &o);
1040 	if (res != TEE_SUCCESS)
1041 		return res;
1042 
1043 	if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE))
1044 		return TEE_ERROR_ACCESS_CONFLICT;
1045 
1046 	off = sizeof(struct tee_svc_storage_head) + o->data_size;
1047 	err = tee_fs_ftruncate(o->fd, len + off);
1048 
1049 	if (err != 0)
1050 		/* error codes needs better granularity */
1051 		return TEE_ERROR_GENERIC;
1052 
1053 	return TEE_SUCCESS;
1054 }
1055 
1056 TEE_Result tee_svc_storage_obj_seek(uint32_t obj, int32_t offset,
1057 				    TEE_Whence whence)
1058 {
1059 	TEE_Result res;
1060 	struct tee_ta_session *sess;
1061 	struct tee_obj *o;
1062 	int fw;
1063 	tee_fs_off_t off;
1064 	tee_fs_off_t e_off = 0;
1065 
1066 	res = tee_ta_get_current_session(&sess);
1067 	if (res != TEE_SUCCESS)
1068 		return res;
1069 
1070 	res = tee_obj_get(sess->ctx, obj, &o);
1071 	if (res != TEE_SUCCESS)
1072 		return res;
1073 
1074 	if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT))
1075 		return TEE_ERROR_BAD_STATE;
1076 
1077 	fw = tee_svc_storage_conv_whence(whence);
1078 
1079 	if (whence == TEE_DATA_SEEK_SET)
1080 		e_off = sizeof(struct tee_svc_storage_head) + o->data_size;
1081 
1082 	off = tee_fs_lseek(o->fd, e_off + offset, fw);
1083 	if (off > -1 && off >= e_off)
1084 		o->info.dataPosition =
1085 		    off - sizeof(struct tee_svc_storage_head) + o->data_size;
1086 	else
1087 		return TEE_ERROR_GENERIC;
1088 
1089 	return TEE_SUCCESS;
1090 }
1091 
1092 void tee_svc_storage_close_all_enum(struct tee_ta_ctx *ctx)
1093 {
1094 	struct tee_storage_enum_head *eh = &ctx->storage_enums;
1095 
1096 	/* disregard return value */
1097 	while (!TAILQ_EMPTY(eh))
1098 		tee_svc_close_enum(ctx, TAILQ_FIRST(eh));
1099 }
1100