xref: /optee_os/core/tee/tee_svc_storage.c (revision c61c04b837302c854a3c9f650118dd7be548302b)
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 <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 == (vaddr_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_file_ops.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_file_ops.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_file_ops.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_file_ops.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_file_ops.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_file_ops.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_file_ops.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_file_ops.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_file_ops.write(fd, &head,
330 			sizeof(struct tee_svc_storage_head));
331 	/* error codes needs better granularity */
332 	if (err != sizeof(struct tee_svc_storage_head)) {
333 		res = TEE_ERROR_GENERIC;
334 		goto exit;
335 	}
336 
337 	/* write meta */
338 	err = tee_file_ops.write(fd, o->data, o->data_size);
339 	/* error codes needs better granularity */
340 	if (err != (int)o->data_size) {
341 		res = TEE_ERROR_GENERIC;
342 		goto exit;
343 	}
344 
345 	/* write init data */
346 	o->info.dataSize = len;
347 
348 	/* write data to fs if needed */
349 	if (data && len) {
350 		err = tee_file_ops.write(fd, data, len);
351 
352 		if (err != (int)len) {
353 			/* error codes needs better granularity */
354 			res = TEE_ERROR_GENERIC;
355 			return res;
356 		}
357 	}
358 
359 exit:
360 	tee_file_ops.close(fd);
361 
362 	return TEE_SUCCESS;
363 }
364 
365 static TEE_Result tee_svc_storage_remove(struct tee_ta_session *sess,
366 					 uint32_t storage_id, void *object_id,
367 					 uint32_t object_id_len)
368 {
369 	TEE_Result res = TEE_SUCCESS;
370 	char *file = NULL;
371 	int err;
372 
373 	if (sess == NULL)
374 		return TEE_ERROR_BAD_PARAMETERS;
375 
376 	if (storage_id != TEE_STORAGE_PRIVATE)
377 		return TEE_ERROR_ITEM_NOT_FOUND;
378 
379 	file = tee_svc_storage_create_filename(sess, object_id, object_id_len);
380 	if (file == NULL)
381 		return TEE_ERROR_OUT_OF_MEMORY;
382 
383 	err = tee_file_ops.unlink(file);
384 	free(file);
385 	if (err != 0)
386 		/* error codes needs better granularity */
387 		res = TEE_ERROR_GENERIC;
388 
389 	return res;
390 }
391 
392 TEE_Result tee_svc_storage_obj_open(uint32_t storage_id, void *object_id,
393 				    uint32_t object_id_len, uint32_t flags,
394 				    uint32_t *obj)
395 {
396 	TEE_Result res;
397 	struct tee_ta_session *sess;
398 	struct tee_obj *o;
399 	char *file = NULL;
400 	int fs_flags;
401 	int fd = -1;
402 	tee_fs_off_t off;
403 	tee_fs_off_t e_off;
404 	struct tee_pobj *po = NULL;
405 
406 	if (storage_id != TEE_STORAGE_PRIVATE)
407 		return TEE_ERROR_ITEM_NOT_FOUND;
408 
409 	if (object_id_len > TEE_OBJECT_ID_MAX_LEN)
410 		return TEE_ERROR_BAD_PARAMETERS;
411 
412 	res = tee_ta_get_current_session(&sess);
413 	if (res != TEE_SUCCESS)
414 		goto exit;
415 
416 	res =
417 	    tee_mmu_check_access_rights(sess->ctx,
418 					TEE_MEMORY_ACCESS_READ |
419 					TEE_MEMORY_ACCESS_ANY_OWNER,
420 					(tee_uaddr_t) object_id, object_id_len);
421 	if (res != TEE_SUCCESS)
422 		goto exit;
423 
424 	res = tee_pobj_get((void *)&sess->ctx->head->uuid, object_id,
425 			   object_id_len, flags, &po);
426 	if (res != TEE_SUCCESS)
427 		goto exit;
428 
429 	fs_flags = tee_svc_storage_conv_oflags(flags);
430 
431 	o = calloc(1, sizeof(*o));
432 	if (o == NULL) {
433 		res = TEE_ERROR_OUT_OF_MEMORY;
434 		goto exit;
435 	}
436 
437 	o->info.handleFlags =
438 	    TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED;
439 	o->info.objectUsage = TEE_USAGE_DEFAULT;
440 	o->flags = flags;
441 	o->pobj = po;
442 
443 	res = tee_svc_storage_read_head(sess, o);
444 	if (res != TEE_SUCCESS) {
445 		free(o);
446 		goto exit;
447 	}
448 
449 	file = tee_svc_storage_create_filename(sess, object_id, object_id_len);
450 	if (file == NULL) {
451 		res = TEE_ERROR_OUT_OF_MEMORY;
452 		goto exit;
453 	}
454 
455 	fd = tee_file_ops.open(file, fs_flags);
456 	free(file);
457 	if (fd < 0) {
458 		res = TEE_ERROR_ITEM_NOT_FOUND;
459 		goto exit;
460 	}
461 	o->fd = fd;
462 
463 	tee_obj_add(sess->ctx, o);
464 
465 	res = tee_svc_copy_to_user(sess, obj, &o, sizeof(o));
466 	if (res != TEE_SUCCESS)
467 		tee_obj_close(sess->ctx, o);
468 
469 	e_off = sizeof(struct tee_svc_storage_head) + o->data_size;
470 	off = tee_file_ops.lseek(fd, e_off, TEE_FS_SEEK_SET);
471 	if (off != e_off) {
472 		res = TEE_ERROR_NO_DATA;
473 		goto exit;
474 	}
475 
476 exit:
477 	if (res != TEE_SUCCESS) {
478 		if (res == TEE_ERROR_NO_DATA || res == TEE_ERROR_BAD_FORMAT) {
479 			/* the file is corrupt, delete */
480 			tee_svc_storage_remove(sess, storage_id, object_id,
481 					       object_id_len);
482 
483 			/* "greaceful" return */
484 			res = TEE_ERROR_ITEM_NOT_FOUND;
485 		}
486 
487 		if (fd >= 0)
488 			tee_file_ops.close(fd);
489 		if (po)
490 			tee_pobj_release(po);
491 	}
492 
493 	return res;
494 }
495 
496 TEE_Result tee_svc_storage_obj_create(uint32_t storage_id, void *object_id,
497 				      uint32_t object_id_len, uint32_t flags,
498 				      uint32_t attr, void *data, uint32_t len,
499 				      uint32_t *obj)
500 {
501 	TEE_Result res;
502 	struct tee_ta_session *sess;
503 	struct tee_obj *o = NULL;
504 	struct tee_obj *attr_o = NULL;
505 	char *file = NULL;
506 	int fd = -1;
507 	int fs_flags;
508 	tee_fs_off_t off;
509 	tee_fs_off_t e_off;
510 	struct tee_pobj *po = NULL;
511 
512 	if (storage_id != TEE_STORAGE_PRIVATE)
513 		return TEE_ERROR_ITEM_NOT_FOUND;
514 
515 	if (object_id_len > TEE_OBJECT_ID_MAX_LEN)
516 		return TEE_ERROR_BAD_PARAMETERS;
517 
518 	res = tee_ta_get_current_session(&sess);
519 	if (res != TEE_SUCCESS)
520 		return res;
521 
522 	res =
523 	    tee_mmu_check_access_rights(sess->ctx,
524 					TEE_MEMORY_ACCESS_READ |
525 					TEE_MEMORY_ACCESS_ANY_OWNER,
526 					(tee_uaddr_t) object_id, object_id_len);
527 	if (res != TEE_SUCCESS)
528 		goto exit;
529 
530 	res = tee_pobj_get((void *)&sess->ctx->head->uuid, object_id,
531 			   object_id_len, flags, &po);
532 	if (res != TEE_SUCCESS)
533 		goto exit;
534 
535 	/* Init attributes if attibutes are provided */
536 	if (attr != TEE_HANDLE_NULL) {
537 		res = tee_obj_get(sess->ctx, attr, &attr_o);
538 		if (res != TEE_SUCCESS)
539 			goto exit;
540 	}
541 
542 	/* check rights of the provided buffer */
543 	if (data && len) {
544 		res =
545 		    tee_mmu_check_access_rights(sess->ctx,
546 						TEE_MEMORY_ACCESS_READ |
547 						TEE_MEMORY_ACCESS_ANY_OWNER,
548 						(tee_uaddr_t) data, len);
549 
550 		if (res != TEE_SUCCESS)
551 			goto exit;
552 	}
553 
554 	o = calloc(1, sizeof(*o));
555 	if (o == NULL) {
556 		res = TEE_ERROR_OUT_OF_MEMORY;
557 		goto exit;
558 	}
559 
560 	o->info.handleFlags =
561 	    TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED;
562 	o->flags = flags;
563 	o->pobj = po;
564 
565 	res = tee_svc_storage_init_file(sess, o, attr_o, data, len, flags);
566 	if (res != TEE_SUCCESS) {
567 		free(o);
568 		goto exit;
569 	}
570 
571 	fs_flags = tee_svc_storage_conv_oflags(flags);
572 
573 	file = tee_svc_storage_create_filename(sess, object_id, object_id_len);
574 	if (file == NULL) {
575 		res = TEE_ERROR_OUT_OF_MEMORY;
576 		goto exit;
577 	}
578 
579 	fd = tee_file_ops.open(file, fs_flags);
580 	free(file);
581 	file = NULL;
582 	if (fd < 0) {
583 		res = TEE_ERROR_ITEM_NOT_FOUND;
584 		goto exit;
585 	}
586 	o->fd = fd;
587 
588 	tee_obj_add(sess->ctx, o);
589 
590 	res = tee_svc_copy_to_user(sess, obj, &o, sizeof(o));
591 	if (res != TEE_SUCCESS)
592 		tee_obj_close(sess->ctx, o);
593 
594 	e_off = sizeof(struct tee_svc_storage_head) + o->data_size;
595 	off = tee_file_ops.lseek(fd, e_off, TEE_FS_SEEK_SET);
596 	if (off != e_off) {
597 		res = TEE_ERROR_NO_DATA;
598 		goto exit;
599 	}
600 
601 exit:
602 	if (res != TEE_SUCCESS) {
603 		if (fd >= 0)
604 			tee_file_ops.close(fd);
605 		if (po)
606 			tee_pobj_release(po);
607 	}
608 
609 	return res;
610 }
611 
612 TEE_Result tee_svc_storage_obj_del(uint32_t obj)
613 {
614 	TEE_Result res;
615 	struct tee_ta_session *sess;
616 	struct tee_obj *o;
617 	int err;
618 	char *file;
619 	char *dir;
620 
621 	res = tee_ta_get_current_session(&sess);
622 	if (res != TEE_SUCCESS)
623 		return res;
624 
625 	res = tee_obj_get(sess->ctx, obj, &o);
626 	if (res != TEE_SUCCESS)
627 		return res;
628 
629 	if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE_META))
630 		return TEE_ERROR_ACCESS_CONFLICT;
631 
632 	if (o->pobj == NULL || o->pobj->obj_id == NULL)
633 		return TEE_ERROR_BAD_STATE;
634 
635 	file = 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 	/* TODO add TEE_ERROR_STORAGE_NOT_AVAILABLE implementation */
643 
644 	err = tee_file_ops.unlink(file);
645 	free(file);
646 	if (err != 0)
647 		/* error codes needs better granularity */
648 		return TEE_ERROR_GENERIC;
649 
650 	/* try and remove dir */
651 	dir = tee_svc_storage_create_dirname(sess);
652 	if (dir == NULL)
653 		return TEE_ERROR_OUT_OF_MEMORY;
654 	/* ignore result */
655 	tee_file_ops.rmdir(dir);
656 	free(dir);
657 
658 	return TEE_SUCCESS;
659 }
660 
661 TEE_Result tee_svc_storage_obj_rename(uint32_t obj, void *object_id,
662 				      uint32_t object_id_len)
663 {
664 	TEE_Result res;
665 	struct tee_ta_session *sess;
666 	struct tee_obj *o;
667 	struct tee_pobj *po = NULL;
668 	char *new_file = NULL;
669 	char *old_file = NULL;
670 	int err = -1;
671 
672 	if (object_id_len > TEE_OBJECT_ID_MAX_LEN)
673 		return TEE_ERROR_BAD_PARAMETERS;
674 
675 	res = tee_ta_get_current_session(&sess);
676 	if (res != TEE_SUCCESS)
677 		return res;
678 
679 	res = tee_obj_get(sess->ctx, obj, &o);
680 	if (res != TEE_SUCCESS)
681 		return res;
682 
683 	if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE_META)) {
684 		res = TEE_ERROR_BAD_STATE;
685 		goto exit;
686 	}
687 
688 	if (o->pobj == NULL || o->pobj->obj_id == NULL)
689 		return TEE_ERROR_BAD_STATE;
690 
691 	res =
692 	    tee_mmu_check_access_rights(sess->ctx,
693 					TEE_MEMORY_ACCESS_READ |
694 					TEE_MEMORY_ACCESS_ANY_OWNER,
695 					(tee_uaddr_t) object_id, object_id_len);
696 	if (res != TEE_SUCCESS)
697 		goto exit;
698 
699 	/* get new ds name */
700 	new_file =
701 	    tee_svc_storage_create_filename(sess, object_id, object_id_len);
702 	if (new_file == NULL) {
703 		res = TEE_ERROR_OUT_OF_MEMORY;
704 		goto exit;
705 	}
706 
707 	old_file =
708 	    tee_svc_storage_create_filename(sess, o->pobj->obj_id,
709 					    o->pobj->obj_id_len);
710 	if (old_file == NULL) {
711 		res = TEE_ERROR_OUT_OF_MEMORY;
712 		goto exit;
713 	}
714 
715 	/* reserve dest name */
716 	res = tee_pobj_get((void *)&sess->ctx->head->uuid, object_id,
717 			   object_id_len, TEE_DATA_FLAG_ACCESS_WRITE_META, &po);
718 	if (res != TEE_SUCCESS)
719 		goto exit;
720 
721 	err = tee_file_ops.access(new_file, TEE_FS_F_OK);
722 	if (err == 0) {
723 		/* file exists */
724 		res = TEE_ERROR_ACCESS_CONFLICT;
725 		goto exit;
726 	}
727 
728 	/* move */
729 	err = tee_file_ops.rename(old_file, new_file);
730 	if (err) {
731 		/* error codes needs better granularity */
732 		res = TEE_ERROR_GENERIC;
733 		goto exit;
734 	}
735 
736 	res = tee_pobj_rename(o->pobj, object_id, object_id_len);
737 
738 exit:
739 	tee_pobj_release(po);
740 
741 	free(new_file);
742 	free(old_file);
743 
744 	return res;
745 }
746 
747 TEE_Result tee_svc_storage_alloc_enum(uint32_t *obj_enum)
748 {
749 	struct tee_storage_enum *e;
750 	struct tee_ta_session *sess;
751 	TEE_Result res;
752 
753 	if (obj_enum == NULL)
754 		return TEE_ERROR_BAD_PARAMETERS;
755 
756 	res = tee_ta_get_current_session(&sess);
757 	if (res != TEE_SUCCESS)
758 		return res;
759 
760 	e = malloc(sizeof(struct tee_storage_enum));
761 
762 	if (e == NULL)
763 		return TEE_ERROR_OUT_OF_MEMORY;
764 
765 	e->dir = NULL;
766 	TAILQ_INSERT_TAIL(&sess->ctx->storage_enums, e, link);
767 
768 	return tee_svc_copy_to_user(sess, obj_enum, &e,
769 				    sizeof(TEE_ObjectEnumHandle *));
770 }
771 
772 TEE_Result tee_svc_storage_free_enum(uint32_t obj_enum)
773 {
774 	struct tee_storage_enum *e;
775 	TEE_Result res;
776 	struct tee_ta_session *sess;
777 
778 	if (obj_enum == TEE_HANDLE_NULL)
779 		return TEE_SUCCESS;
780 
781 	res = tee_ta_get_current_session(&sess);
782 	if (res != TEE_SUCCESS)
783 		return res;
784 
785 	res = tee_svc_storage_get_enum(sess->ctx, obj_enum, &e);
786 	if (res != TEE_SUCCESS)
787 		return res;
788 
789 	return tee_svc_close_enum(sess->ctx, e);
790 }
791 
792 TEE_Result tee_svc_storage_reset_enum(uint32_t obj_enum)
793 {
794 	struct tee_storage_enum *e;
795 	int res;
796 	struct tee_ta_session *sess;
797 
798 	res = tee_ta_get_current_session(&sess);
799 	if (res != TEE_SUCCESS)
800 		return res;
801 
802 	if (obj_enum == TEE_HANDLE_NULL)
803 		return TEE_SUCCESS;
804 
805 	res = tee_svc_storage_get_enum(sess->ctx, obj_enum, &e);
806 	if (res != TEE_SUCCESS)
807 		return res;
808 
809 	res = tee_file_ops.closedir(e->dir);
810 	e->dir = NULL;
811 	if (res != 0)
812 		return TEE_ERROR_GENERIC;
813 
814 	return TEE_SUCCESS;
815 }
816 
817 TEE_Result tee_svc_storage_start_enum(uint32_t obj_enum, uint32_t storage_id)
818 {
819 	struct tee_storage_enum *e;
820 	char *dir;
821 	TEE_Result res;
822 	struct tee_ta_session *sess;
823 
824 	if (obj_enum == TEE_HANDLE_NULL)
825 		return TEE_ERROR_BAD_PARAMETERS;
826 
827 	res = tee_ta_get_current_session(&sess);
828 	if (res != TEE_SUCCESS)
829 		return res;
830 
831 	res = tee_svc_storage_get_enum(sess->ctx, obj_enum, &e);
832 	if (res != TEE_SUCCESS)
833 		return res;
834 
835 	if (storage_id != TEE_STORAGE_PRIVATE)
836 		return TEE_ERROR_ITEM_NOT_FOUND;
837 
838 	dir = tee_svc_storage_create_dirname(sess);
839 	if (dir == NULL)
840 		return TEE_ERROR_OUT_OF_MEMORY;
841 
842 	e->dir = tee_file_ops.opendir(dir);
843 	free(dir);
844 
845 	if (e->dir == NULL)
846 		/* error codes needs better granularity */
847 		return TEE_ERROR_ITEM_NOT_FOUND;
848 
849 	return TEE_SUCCESS;
850 }
851 
852 TEE_Result tee_svc_storage_next_enum(uint32_t obj_enum, TEE_ObjectInfo *info,
853 				     void *obj_id, uint32_t *len)
854 {
855 	struct tee_storage_enum *e;
856 	struct tee_fs_dirent *d;
857 	TEE_Result res = TEE_SUCCESS;
858 	struct tee_ta_session *sess;
859 	struct tee_obj *o = NULL;
860 	uint32_t blen;
861 	uint32_t hslen;
862 
863 	res = tee_ta_get_current_session(&sess);
864 	if (res != TEE_SUCCESS)
865 		return res;
866 
867 	if (obj_enum == TEE_HANDLE_NULL)
868 		return TEE_ERROR_BAD_PARAMETERS;
869 
870 	res = tee_svc_storage_get_enum(sess->ctx, obj_enum, &e);
871 	if (res != TEE_SUCCESS)
872 		return res;
873 
874 	/* check rights of the provided buffers */
875 	res =
876 	    tee_mmu_check_access_rights(sess->ctx,
877 					TEE_MEMORY_ACCESS_WRITE |
878 					TEE_MEMORY_ACCESS_ANY_OWNER,
879 					(tee_uaddr_t) info,
880 					sizeof(TEE_ObjectInfo));
881 	if (res != TEE_SUCCESS)
882 		return res;
883 
884 	res =
885 	    tee_mmu_check_access_rights(sess->ctx,
886 					TEE_MEMORY_ACCESS_WRITE |
887 					TEE_MEMORY_ACCESS_ANY_OWNER,
888 					(tee_uaddr_t) obj_id,
889 					TEE_OBJECT_ID_MAX_LEN);
890 	if (res != TEE_SUCCESS)
891 		return res;
892 
893 	d = tee_file_ops.readdir(e->dir);
894 	if (d == NULL)
895 		return TEE_ERROR_ITEM_NOT_FOUND;
896 
897 	o = calloc(1, sizeof(struct tee_obj));
898 	if (o == NULL) {
899 		res = TEE_ERROR_OUT_OF_MEMORY;
900 		goto exit;
901 	}
902 
903 	o->pobj = calloc(1, sizeof(struct tee_pobj));
904 	if (!o->pobj) {
905 		res = TEE_ERROR_OUT_OF_MEMORY;
906 		goto exit;
907 	}
908 
909 	o->info.handleFlags =
910 	    TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED;
911 	o->info.objectUsage = TEE_USAGE_DEFAULT;
912 
913 	/*
914 	 * NOTE: Special usage of pobj due to not ref cnt should be inc
915 	 */
916 	hslen = strlen(d->d_name);
917 	blen = TEE_HS2B_BBUF_SIZE(hslen);
918 	o->pobj->obj_id = malloc(blen);
919 	if (o->pobj->obj_id == NULL) {
920 		res = TEE_ERROR_OUT_OF_MEMORY;
921 		goto exit;
922 	}
923 	tee_hs2b((uint8_t *)d->d_name, o->pobj->obj_id, hslen, blen);
924 	o->pobj->obj_id_len = blen;
925 
926 	res = tee_svc_storage_read_head(sess, o);
927 	if (res != TEE_SUCCESS) {
928 		/* TODO: handle corrupt files in a greaceful way */
929 		goto exit;
930 	}
931 	memcpy(info, &o->info, sizeof(TEE_ObjectInfo));
932 	memcpy(obj_id, o->pobj->obj_id, o->pobj->obj_id_len);
933 
934 	res =
935 	    tee_svc_copy_to_user(sess, len, &o->pobj->obj_id_len,
936 				 sizeof(uint32_t));
937 
938 exit:
939 	if (o) {
940 		if (o->pobj)
941 			free(o->pobj->obj_id);
942 		free(o->pobj);
943 		free(o->data);
944 	}
945 	free(o);
946 
947 	return res;
948 }
949 
950 TEE_Result tee_svc_storage_obj_read(uint32_t obj, void *data, size_t len,
951 				    uint32_t *count)
952 {
953 	TEE_Result res;
954 	struct tee_ta_session *sess;
955 	struct tee_obj *o;
956 	int n_count;
957 	uint32_t u_count;
958 
959 	res = tee_ta_get_current_session(&sess);
960 	if (res != TEE_SUCCESS)
961 		return res;
962 
963 	res = tee_obj_get(sess->ctx, obj, &o);
964 	if (res != TEE_SUCCESS)
965 		return res;
966 
967 	if (!(o->flags & TEE_DATA_FLAG_ACCESS_READ))
968 		return TEE_ERROR_ACCESS_CONFLICT;
969 
970 	/* check rights of the provided buffer */
971 	res =
972 	    tee_mmu_check_access_rights(sess->ctx,
973 					TEE_MEMORY_ACCESS_WRITE |
974 					TEE_MEMORY_ACCESS_ANY_OWNER,
975 					(tee_uaddr_t) data, len);
976 	if (res != TEE_SUCCESS)
977 		return res;
978 
979 	n_count = tee_file_ops.read(o->fd, data, len);
980 	u_count = (uint32_t) ((n_count < 0) ? 0 : n_count);
981 
982 	res = tee_svc_copy_to_user(sess, count, &u_count, sizeof(uint32_t));
983 
984 	o->info.dataPosition += u_count;
985 
986 	return TEE_SUCCESS;
987 }
988 
989 TEE_Result tee_svc_storage_obj_write(uint32_t obj, void *data, size_t len)
990 {
991 	TEE_Result res;
992 	struct tee_ta_session *sess;
993 	struct tee_obj *o;
994 	int err;
995 
996 	res = tee_ta_get_current_session(&sess);
997 	if (res != TEE_SUCCESS)
998 		return res;
999 
1000 	res = tee_obj_get(sess->ctx, obj, &o);
1001 	if (res != TEE_SUCCESS)
1002 		return res;
1003 
1004 	if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE))
1005 		return TEE_ERROR_ACCESS_CONFLICT;
1006 
1007 	/* check rights of the provided buffer */
1008 	res =
1009 	    tee_mmu_check_access_rights(sess->ctx,
1010 					TEE_MEMORY_ACCESS_READ |
1011 					TEE_MEMORY_ACCESS_ANY_OWNER,
1012 					(tee_uaddr_t) data, len);
1013 
1014 	err = tee_file_ops.write(o->fd, data, len);
1015 
1016 	if (err != (int)len) {
1017 		/* error codes needs better granularity */
1018 		res = TEE_ERROR_GENERIC;
1019 		return res;
1020 	}
1021 
1022 	o->info.dataPosition += len;
1023 	if (o->info.dataPosition > o->info.dataSize)
1024 		o->info.dataSize = o->info.dataPosition;
1025 
1026 	return TEE_SUCCESS;
1027 }
1028 
1029 TEE_Result tee_svc_storage_obj_trunc(uint32_t obj, size_t len)
1030 {
1031 	TEE_Result res;
1032 	struct tee_ta_session *sess;
1033 	struct tee_obj *o;
1034 	int err;
1035 	tee_fs_off_t off;
1036 
1037 	res = tee_ta_get_current_session(&sess);
1038 	if (res != TEE_SUCCESS)
1039 		return res;
1040 
1041 	res = tee_obj_get(sess->ctx, obj, &o);
1042 	if (res != TEE_SUCCESS)
1043 		return res;
1044 
1045 	if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE))
1046 		return TEE_ERROR_ACCESS_CONFLICT;
1047 
1048 	off = sizeof(struct tee_svc_storage_head) + o->data_size;
1049 	err = tee_file_ops.ftruncate(o->fd, len + off);
1050 
1051 	if (err != 0)
1052 		/* error codes needs better granularity */
1053 		return TEE_ERROR_GENERIC;
1054 
1055 	return TEE_SUCCESS;
1056 }
1057 
1058 TEE_Result tee_svc_storage_obj_seek(uint32_t obj, int32_t offset,
1059 				    TEE_Whence whence)
1060 {
1061 	TEE_Result res;
1062 	struct tee_ta_session *sess;
1063 	struct tee_obj *o;
1064 	int fw;
1065 	tee_fs_off_t off;
1066 	tee_fs_off_t e_off = 0;
1067 
1068 	res = tee_ta_get_current_session(&sess);
1069 	if (res != TEE_SUCCESS)
1070 		return res;
1071 
1072 	res = tee_obj_get(sess->ctx, obj, &o);
1073 	if (res != TEE_SUCCESS)
1074 		return res;
1075 
1076 	if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT))
1077 		return TEE_ERROR_BAD_STATE;
1078 
1079 	fw = tee_svc_storage_conv_whence(whence);
1080 
1081 	if (whence == TEE_DATA_SEEK_SET)
1082 		e_off = sizeof(struct tee_svc_storage_head) + o->data_size;
1083 
1084 	off = tee_file_ops.lseek(o->fd, e_off + offset, fw);
1085 	if (off > -1 && off >= e_off)
1086 		o->info.dataPosition =
1087 		    off - sizeof(struct tee_svc_storage_head) + o->data_size;
1088 	else
1089 		return TEE_ERROR_GENERIC;
1090 
1091 	return TEE_SUCCESS;
1092 }
1093 
1094 void tee_svc_storage_close_all_enum(struct tee_ta_ctx *ctx)
1095 {
1096 	struct tee_storage_enum_head *eh = &ctx->storage_enums;
1097 
1098 	/* disregard return value */
1099 	while (!TAILQ_EMPTY(eh))
1100 		tee_svc_close_enum(ctx, TAILQ_FIRST(eh));
1101 }
1102