xref: /optee_os/core/tee/tee_svc_storage.c (revision 3f4b5250f820ec567422230370fa94e3d6277265)
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 					     bool transient)
97 {
98 	uint8_t *file = NULL;
99 	/* +1 for the '/' (default) */
100 	uint32_t hslen =
101 	    TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID) + object_id_len) + 1;
102 	uint32_t pos;
103 
104 	/* +1 for the '.' (temporary persistent object) */
105 	if (transient)
106 		hslen++;
107 
108 	file = malloc(hslen);
109 
110 	if (file == NULL)
111 		return NULL;
112 
113 	pos = tee_b2hs((uint8_t *)&sess->ctx->head->uuid, file,
114 		       sizeof(TEE_UUID), hslen);
115 	file[pos] = '/';
116 	pos++;
117 
118 	/* temporary persistent object : uuid/.object_id_len_of(object_id) */
119 	if (transient) {
120 		file[pos] = '.';
121 		pos++;
122 	}
123 
124 	tee_b2hs(object_id, file + pos, object_id_len, hslen - pos);
125 
126 	return (char *)file;
127 }
128 
129 static char *tee_svc_storage_create_dirname(struct tee_ta_session *sess)
130 {
131 	uint8_t *dir = NULL;
132 	uint32_t hslen = TEE_B2HS_HSBUF_SIZE(sizeof(TEE_UUID));
133 
134 	dir = malloc(hslen);
135 
136 	if (dir == NULL)
137 		return NULL;
138 
139 	tee_b2hs((uint8_t *)&sess->ctx->head->uuid, dir, sizeof(TEE_UUID),
140 		 hslen);
141 
142 	return (char *)dir;
143 }
144 
145 static uint32_t tee_svc_storage_conv_oflags(uint32_t flags)
146 {
147 	uint32_t out = 0;
148 
149 	if (flags & (TEE_DATA_FLAG_ACCESS_READ | TEE_DATA_FLAG_SHARE_READ)) {
150 		if (flags & (TEE_DATA_FLAG_ACCESS_WRITE |
151 			     TEE_DATA_FLAG_ACCESS_WRITE_META |
152 			     TEE_DATA_FLAG_SHARE_WRITE))
153 			out |= TEE_FS_O_RDWR;
154 		else
155 			out |= TEE_FS_O_RDONLY;
156 	} else {
157 		if (flags & (TEE_DATA_FLAG_ACCESS_WRITE |
158 			     TEE_DATA_FLAG_ACCESS_WRITE_META |
159 			     TEE_DATA_FLAG_SHARE_WRITE))
160 			out |= TEE_FS_O_WRONLY;
161 	}
162 
163 	return out;
164 }
165 
166 static int tee_svc_storage_conv_whence(TEE_Whence whence)
167 {
168 	switch (whence) {
169 	case TEE_DATA_SEEK_SET:
170 		return TEE_FS_SEEK_SET;
171 	case TEE_DATA_SEEK_CUR:
172 		return TEE_FS_SEEK_CUR;
173 	case TEE_DATA_SEEK_END:
174 		return TEE_FS_SEEK_END;
175 	default:
176 		return -1;
177 	}
178 }
179 
180 static TEE_Result tee_svc_storage_create_file(struct tee_ta_session *sess,
181 					      char *file, int *fd)
182 {
183 	TEE_Result res = TEE_SUCCESS;
184 	char *dir = NULL;
185 	int tmp;
186 	uint32_t cflags = TEE_FS_O_WRONLY | TEE_FS_O_CREATE;
187 
188 	*fd = tee_file_ops.open(file, cflags);
189 
190 	if (*fd < 0) {
191 		/* try and make directory */
192 		dir = tee_svc_storage_create_dirname(sess);
193 		if (dir == NULL) {
194 			res = TEE_ERROR_OUT_OF_MEMORY;
195 			goto exit;
196 		}
197 
198 		tmp = tee_file_ops.mkdir(dir, TEE_FS_S_IRUSR | TEE_FS_S_IWUSR);
199 		free(dir);
200 
201 		if (tmp < 0) {
202 			/* error codes needs better granularity */
203 			res = TEE_ERROR_GENERIC;
204 			goto exit;
205 		}
206 
207 		/* try and open again */
208 		*fd = tee_file_ops.open(file, cflags);
209 
210 		if (*fd < 0) {
211 			/* error codes needs better granularity */
212 			res = TEE_ERROR_GENERIC;
213 			goto exit;
214 		}
215 	}
216 
217 exit:
218 
219 	return res;
220 }
221 
222 static TEE_Result tee_svc_storage_read_head(struct tee_ta_session *sess,
223 					    struct tee_obj *o)
224 {
225 	TEE_Result res = TEE_SUCCESS;
226 	int fd = -1;
227 	int err;
228 	struct tee_svc_storage_head head;
229 	char *file = NULL;
230 
231 	if (o == NULL || o->pobj == NULL)
232 		return TEE_ERROR_BAD_PARAMETERS;
233 
234 	file = tee_svc_storage_create_filename(sess,
235 					       o->pobj->obj_id,
236 					       o->pobj->obj_id_len,
237 					       false);
238 	if (file == NULL) {
239 		res = TEE_ERROR_OUT_OF_MEMORY;
240 		goto exit;
241 	}
242 
243 	fd = tee_file_ops.open(file, TEE_FS_O_RDONLY);
244 	free(file);
245 
246 	/* error codes needs better granularity */
247 	if (fd < 0)
248 		return TEE_ERROR_ITEM_NOT_FOUND;
249 
250 	/* read head */
251 	err = tee_file_ops.read(fd, &head, sizeof(struct tee_svc_storage_head));
252 	if (err != sizeof(struct tee_svc_storage_head)) {
253 		res = TEE_ERROR_BAD_FORMAT;
254 		goto exit;
255 	}
256 
257 	o->data_size = head.meta_size;
258 	o->info.dataSize = head.ds_size;
259 
260 	o->data = malloc(o->data_size);
261 	if (o->data == NULL) {
262 		res = TEE_ERROR_OUT_OF_MEMORY;
263 		goto exit;
264 	}
265 
266 	/* read meta */
267 	err = tee_file_ops.read(fd, o->data, o->data_size);
268 	if (err != (int)o->data_size) {
269 		free(o->data);
270 		o->data = NULL;
271 		res = TEE_ERROR_NO_DATA;
272 	}
273 
274 exit:
275 	tee_file_ops.close(fd);
276 
277 	return res;
278 }
279 
280 static TEE_Result tee_svc_storage_init_file(struct tee_ta_session *sess,
281 					    struct tee_obj *o,
282 					    struct tee_obj *attr_o, void *data,
283 					    uint32_t len)
284 {
285 	TEE_Result res = TEE_SUCCESS;
286 	int fd = -1;
287 	int err = -1;
288 	struct tee_svc_storage_head head;
289 	char *tmpfile = NULL;
290 
291 	if (o == NULL || o->pobj == NULL)
292 		return TEE_ERROR_BAD_PARAMETERS;
293 
294 	free(o->data);
295 
296 	/* create temporary persistent object filename */
297 	tmpfile = tee_svc_storage_create_filename(sess,
298 						   o->pobj->obj_id,
299 						   o->pobj->obj_id_len,
300 						   true);
301 
302 	if (tmpfile == NULL) {
303 		res = TEE_ERROR_OUT_OF_MEMORY;
304 		goto exit;
305 	}
306 
307 	res = tee_svc_storage_create_file(sess, tmpfile, &fd);
308 	if (res != TEE_SUCCESS)
309 		goto exit;
310 
311 	if (attr_o && attr_o->data_size) {
312 		o->data_size = attr_o->data_size;
313 		o->data = malloc(attr_o->data_size);
314 		if (o->data == NULL) {
315 			res = TEE_ERROR_OUT_OF_MEMORY;
316 			goto exit;
317 		}
318 
319 		memcpy(o->data, attr_o->data, attr_o->data_size);
320 		o->have_attrs = attr_o->have_attrs;
321 		o->info.objectUsage = attr_o->info.objectUsage;
322 		o->info.objectType = attr_o->info.objectType;
323 	} else {
324 		o->data = NULL;
325 		o->data_size = 0;
326 		o->have_attrs = 0;
327 		o->info.objectUsage = TEE_USAGE_DEFAULT;
328 		o->info.objectType = TEE_TYPE_DATA;
329 	}
330 
331 	/* write head */
332 	head.magic = TEE_SVC_STORAGE_MAGIC;
333 	head.head_size = sizeof(struct tee_svc_storage_head);
334 	head.meta_size = o->data_size;
335 	head.ds_size = len;
336 
337 	/* write head */
338 	err = tee_file_ops.write(fd, &head,
339 			sizeof(struct tee_svc_storage_head));
340 	/* error codes needs better granularity */
341 	if (err != sizeof(struct tee_svc_storage_head)) {
342 		res = TEE_ERROR_GENERIC;
343 		goto exit;
344 	}
345 
346 	/* write meta */
347 	err = tee_file_ops.write(fd, o->data, o->data_size);
348 	/* error codes needs better granularity */
349 	if (err != (int)o->data_size) {
350 		res = TEE_ERROR_GENERIC;
351 		goto exit;
352 	}
353 
354 	/* write init data */
355 	o->info.dataSize = len;
356 
357 	/* write data to fs if needed */
358 	if (data && len) {
359 		err = tee_file_ops.write(fd, data, len);
360 
361 		if (err != (int)len) {
362 			/* error codes needs better granularity */
363 			res = TEE_ERROR_GENERIC;
364 			goto exit;
365 		}
366 	}
367 
368 exit:
369 	free(tmpfile);
370 	tmpfile = NULL;
371 	if (fd != -1)
372 		tee_file_ops.close(fd);
373 
374 	return res;
375 }
376 
377 static TEE_Result tee_svc_storage_remove(struct tee_ta_session *sess,
378 					 uint32_t storage_id, void *object_id,
379 					 uint32_t object_id_len)
380 {
381 	TEE_Result res = TEE_SUCCESS;
382 	char *file = NULL;
383 	int err;
384 
385 	if (sess == NULL)
386 		return TEE_ERROR_BAD_PARAMETERS;
387 
388 	if (storage_id != TEE_STORAGE_PRIVATE)
389 		return TEE_ERROR_ITEM_NOT_FOUND;
390 
391 	file = tee_svc_storage_create_filename(sess, object_id,
392 					       object_id_len, false);
393 	if (file == NULL)
394 		return TEE_ERROR_OUT_OF_MEMORY;
395 
396 	err = tee_file_ops.unlink(file);
397 	free(file);
398 	if (err != 0)
399 		/* error codes needs better granularity */
400 		res = TEE_ERROR_GENERIC;
401 
402 	return res;
403 }
404 
405 TEE_Result tee_svc_storage_obj_open(uint32_t storage_id, void *object_id,
406 				    uint32_t object_id_len, uint32_t flags,
407 				    uint32_t *obj)
408 {
409 	TEE_Result res;
410 	struct tee_ta_session *sess;
411 	struct tee_obj *o;
412 	char *file = NULL;
413 	int fs_flags;
414 	int fd = -1;
415 	tee_fs_off_t off;
416 	tee_fs_off_t e_off;
417 	struct tee_pobj *po = NULL;
418 
419 	if (storage_id != TEE_STORAGE_PRIVATE)
420 		return TEE_ERROR_ITEM_NOT_FOUND;
421 
422 	if (object_id_len > TEE_OBJECT_ID_MAX_LEN)
423 		return TEE_ERROR_BAD_PARAMETERS;
424 
425 	res = tee_ta_get_current_session(&sess);
426 	if (res != TEE_SUCCESS)
427 		goto exit;
428 
429 	res =
430 	    tee_mmu_check_access_rights(sess->ctx,
431 					TEE_MEMORY_ACCESS_READ |
432 					TEE_MEMORY_ACCESS_ANY_OWNER,
433 					(tee_uaddr_t) object_id, object_id_len);
434 	if (res != TEE_SUCCESS)
435 		goto exit;
436 
437 	res = tee_pobj_get((void *)&sess->ctx->head->uuid, object_id,
438 			   object_id_len, flags, &po);
439 	if (res != TEE_SUCCESS)
440 		goto exit;
441 
442 	fs_flags = tee_svc_storage_conv_oflags(flags);
443 
444 	o = calloc(1, sizeof(*o));
445 	if (o == NULL) {
446 		res = TEE_ERROR_OUT_OF_MEMORY;
447 		goto exit;
448 	}
449 
450 	o->info.handleFlags =
451 	    TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED;
452 	o->info.objectUsage = TEE_USAGE_DEFAULT;
453 	o->flags = flags;
454 	o->pobj = po;
455 
456 	res = tee_svc_storage_read_head(sess, o);
457 	if (res != TEE_SUCCESS) {
458 		free(o);
459 		goto exit;
460 	}
461 
462 	file = tee_svc_storage_create_filename(sess, object_id,
463 					       object_id_len, false);
464 	if (file == NULL) {
465 		res = TEE_ERROR_OUT_OF_MEMORY;
466 		goto exit;
467 	}
468 
469 	fd = tee_file_ops.open(file, fs_flags);
470 	free(file);
471 	if (fd < 0) {
472 		res = TEE_ERROR_ITEM_NOT_FOUND;
473 		goto exit;
474 	}
475 	o->fd = fd;
476 
477 	tee_obj_add(sess->ctx, o);
478 
479 	res = tee_svc_copy_kaddr_to_user32(sess, obj, o);
480 	if (res != TEE_SUCCESS)
481 		tee_obj_close(sess->ctx, o);
482 
483 	e_off = sizeof(struct tee_svc_storage_head) + o->data_size;
484 	off = tee_file_ops.lseek(fd, e_off, TEE_FS_SEEK_SET);
485 	if (off != e_off) {
486 		res = TEE_ERROR_NO_DATA;
487 		goto exit;
488 	}
489 
490 exit:
491 	if (res != TEE_SUCCESS) {
492 		if (res == TEE_ERROR_NO_DATA || res == TEE_ERROR_BAD_FORMAT) {
493 			/* the file is corrupt, delete */
494 			tee_svc_storage_remove(sess, storage_id, object_id,
495 					       object_id_len);
496 
497 			/* "greaceful" return */
498 			res = TEE_ERROR_ITEM_NOT_FOUND;
499 		}
500 
501 		if (fd >= 0)
502 			tee_file_ops.close(fd);
503 		if (po)
504 			tee_pobj_release(po);
505 	}
506 
507 	return res;
508 }
509 
510 TEE_Result tee_svc_storage_obj_create(uint32_t storage_id, void *object_id,
511 				      uint32_t object_id_len, uint32_t flags,
512 				      uint32_t attr, void *data, uint32_t len,
513 				      uint32_t *obj)
514 {
515 	TEE_Result res;
516 	struct tee_ta_session *sess;
517 	struct tee_obj *o = NULL;
518 	struct tee_obj *attr_o = NULL;
519 	char *file = NULL;
520 	int fd = -1;
521 	int fs_flags;
522 	tee_fs_off_t off;
523 	tee_fs_off_t e_off;
524 	struct tee_pobj *po = NULL;
525 	char *tmpfile = NULL;
526 	int err = -1;
527 
528 	if (storage_id != TEE_STORAGE_PRIVATE)
529 		return TEE_ERROR_ITEM_NOT_FOUND;
530 
531 	if (object_id_len > TEE_OBJECT_ID_MAX_LEN)
532 		return TEE_ERROR_BAD_PARAMETERS;
533 
534 	res = tee_ta_get_current_session(&sess);
535 	if (res != TEE_SUCCESS)
536 		return res;
537 
538 	res = tee_mmu_check_access_rights(sess->ctx,
539 					  TEE_MEMORY_ACCESS_READ |
540 					  TEE_MEMORY_ACCESS_ANY_OWNER,
541 					  (tee_uaddr_t) object_id,
542 					  object_id_len);
543 	if (res != TEE_SUCCESS)
544 		goto err;
545 
546 	res = tee_pobj_get((void *)&sess->ctx->head->uuid, object_id,
547 			   object_id_len, flags, &po);
548 	if (res != TEE_SUCCESS)
549 		goto err;
550 
551 	/* check rights of the provided buffer */
552 	if (data && len) {
553 		res = tee_mmu_check_access_rights(sess->ctx,
554 						  TEE_MEMORY_ACCESS_READ |
555 						  TEE_MEMORY_ACCESS_ANY_OWNER,
556 						  (tee_uaddr_t) data, len);
557 
558 		if (res != TEE_SUCCESS)
559 			goto err;
560 	}
561 
562 	o = calloc(1, sizeof(*o));
563 	if (o == NULL) {
564 		res = TEE_ERROR_OUT_OF_MEMORY;
565 		goto err;
566 	}
567 
568 	o->info.handleFlags =
569 	    TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED;
570 	o->flags = flags;
571 	o->pobj = po;
572 
573 	if (attr != TEE_HANDLE_NULL) {
574 		/* init attributes  if provided */
575 		res = tee_obj_get(sess->ctx, attr, &attr_o);
576 		if (res != TEE_SUCCESS)
577 			goto err;
578 	}
579 
580 	res = tee_svc_storage_init_file(sess, o, attr_o, data, len);
581 	if (res != TEE_SUCCESS)
582 		goto err;
583 
584 	/* create persistent object filename */
585 	file = tee_svc_storage_create_filename(sess, object_id,
586 					       object_id_len, false);
587 	if (file == NULL) {
588 		res = TEE_ERROR_OUT_OF_MEMORY;
589 		goto err;
590 	}
591 
592 	err = tee_file_ops.access(file, TEE_FS_F_OK);
593 	if (!err) {
594 		/* file exists */
595 		if (!(flags & TEE_DATA_FLAG_OVERWRITE)) {
596 			res = TEE_ERROR_ACCESS_CONFLICT;
597 			goto rmfile;
598 		}
599 	}
600 
601 	/* create temporary persistent object filename */
602 	tmpfile = tee_svc_storage_create_filename(sess, object_id,
603 						   object_id_len,
604 						   true);
605 	if (tmpfile == NULL) {
606 		res = TEE_ERROR_OUT_OF_MEMORY;
607 		goto err;
608 	}
609 
610 	/* rename temporary persistent object filename */
611 	err = tee_file_ops.rename(tmpfile, file);
612 	if (err) {
613 		/* error codes needs better granularity */
614 		res = TEE_ERROR_GENERIC;
615 		goto rmfile;
616 	}
617 
618 	fs_flags = tee_svc_storage_conv_oflags(flags);
619 
620 	fd = tee_file_ops.open(file, fs_flags);
621 	if (fd < 0) {
622 		res = TEE_ERROR_ITEM_NOT_FOUND;
623 		goto err;
624 	}
625 	o->fd = fd;
626 
627 	tee_obj_add(sess->ctx, o);
628 
629 	res = tee_svc_copy_kaddr_to_user32(sess, obj, o);
630 	if (res != TEE_SUCCESS)
631 		goto oclose;
632 
633 	e_off = sizeof(struct tee_svc_storage_head) + o->data_size;
634 	off = tee_file_ops.lseek(fd, e_off, TEE_FS_SEEK_SET);
635 	if (off != e_off) {
636 		res = TEE_ERROR_NO_DATA;
637 		goto oclose;
638 	}
639 
640 	goto exit;
641 
642 oclose:
643 	tee_obj_close(sess->ctx, o);
644 	goto exit;
645 
646 rmfile:
647 	tee_file_ops.unlink(tmpfile);
648 
649 err:
650 	if (fd >= 0)
651 		tee_file_ops.close(fd);
652 	if (po)
653 		tee_pobj_release(po);
654 	if (o)
655 		free(o);
656 
657 exit:
658 	free(file);
659 	file = NULL;
660 	free(tmpfile);
661 	tmpfile = NULL;
662 
663 	return res;
664 }
665 
666 TEE_Result tee_svc_storage_obj_del(uint32_t obj)
667 {
668 	TEE_Result res;
669 	struct tee_ta_session *sess;
670 	struct tee_obj *o;
671 	int err;
672 	char *file;
673 	char *dir;
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 		return TEE_ERROR_ACCESS_CONFLICT;
685 
686 	if (o->pobj == NULL || o->pobj->obj_id == NULL)
687 		return TEE_ERROR_BAD_STATE;
688 
689 	file = tee_svc_storage_create_filename(sess, o->pobj->obj_id,
690 						o->pobj->obj_id_len, false);
691 	if (file == NULL)
692 		return TEE_ERROR_OUT_OF_MEMORY;
693 
694 	tee_obj_close(sess->ctx, o);
695 
696 	/* TODO add TEE_ERROR_STORAGE_NOT_AVAILABLE implementation */
697 
698 	err = tee_file_ops.unlink(file);
699 	free(file);
700 	if (err != 0)
701 		/* error codes needs better granularity */
702 		return TEE_ERROR_GENERIC;
703 
704 	/* try and remove dir */
705 	dir = tee_svc_storage_create_dirname(sess);
706 	if (dir == NULL)
707 		return TEE_ERROR_OUT_OF_MEMORY;
708 	/* ignore result */
709 	tee_file_ops.rmdir(dir);
710 	free(dir);
711 
712 	return TEE_SUCCESS;
713 }
714 
715 TEE_Result tee_svc_storage_obj_rename(uint32_t obj, void *object_id,
716 				      uint32_t object_id_len)
717 {
718 	TEE_Result res;
719 	struct tee_ta_session *sess;
720 	struct tee_obj *o;
721 	struct tee_pobj *po = NULL;
722 	char *new_file = NULL;
723 	char *old_file = NULL;
724 	int err = -1;
725 
726 	if (object_id_len > TEE_OBJECT_ID_MAX_LEN)
727 		return TEE_ERROR_BAD_PARAMETERS;
728 
729 	res = tee_ta_get_current_session(&sess);
730 	if (res != TEE_SUCCESS)
731 		return res;
732 
733 	res = tee_obj_get(sess->ctx, obj, &o);
734 	if (res != TEE_SUCCESS)
735 		return res;
736 
737 	if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE_META)) {
738 		res = TEE_ERROR_BAD_STATE;
739 		goto exit;
740 	}
741 
742 	if (o->pobj == NULL || o->pobj->obj_id == NULL)
743 		return TEE_ERROR_BAD_STATE;
744 
745 	res =
746 	    tee_mmu_check_access_rights(sess->ctx,
747 					TEE_MEMORY_ACCESS_READ |
748 					TEE_MEMORY_ACCESS_ANY_OWNER,
749 					(tee_uaddr_t) object_id, object_id_len);
750 	if (res != TEE_SUCCESS)
751 		goto exit;
752 
753 	/* get new ds name */
754 	new_file = tee_svc_storage_create_filename(sess, object_id,
755 						   object_id_len, false);
756 	if (new_file == NULL) {
757 		res = TEE_ERROR_OUT_OF_MEMORY;
758 		goto exit;
759 	}
760 
761 	old_file = tee_svc_storage_create_filename(sess, o->pobj->obj_id,
762 						   o->pobj->obj_id_len, false);
763 	if (old_file == NULL) {
764 		res = TEE_ERROR_OUT_OF_MEMORY;
765 		goto exit;
766 	}
767 
768 	/* reserve dest name */
769 	res = tee_pobj_get((void *)&sess->ctx->head->uuid, object_id,
770 			   object_id_len, TEE_DATA_FLAG_ACCESS_WRITE_META, &po);
771 	if (res != TEE_SUCCESS)
772 		goto exit;
773 
774 	err = tee_file_ops.access(new_file, TEE_FS_F_OK);
775 	if (err == 0) {
776 		/* file exists */
777 		res = TEE_ERROR_ACCESS_CONFLICT;
778 		goto exit;
779 	}
780 
781 	/* move */
782 	err = tee_file_ops.rename(old_file, new_file);
783 	if (err) {
784 		/* error codes needs better granularity */
785 		res = TEE_ERROR_GENERIC;
786 		goto exit;
787 	}
788 
789 	res = tee_pobj_rename(o->pobj, object_id, object_id_len);
790 
791 exit:
792 	tee_pobj_release(po);
793 
794 	free(new_file);
795 	free(old_file);
796 
797 	return res;
798 }
799 
800 TEE_Result tee_svc_storage_alloc_enum(uint32_t *obj_enum)
801 {
802 	struct tee_storage_enum *e;
803 	struct tee_ta_session *sess;
804 	TEE_Result res;
805 
806 	if (obj_enum == NULL)
807 		return TEE_ERROR_BAD_PARAMETERS;
808 
809 	res = tee_ta_get_current_session(&sess);
810 	if (res != TEE_SUCCESS)
811 		return res;
812 
813 	e = malloc(sizeof(struct tee_storage_enum));
814 
815 	if (e == NULL)
816 		return TEE_ERROR_OUT_OF_MEMORY;
817 
818 	e->dir = NULL;
819 	TAILQ_INSERT_TAIL(&sess->ctx->storage_enums, e, link);
820 
821 	return tee_svc_copy_kaddr_to_user32(sess, obj_enum, e);
822 }
823 
824 TEE_Result tee_svc_storage_free_enum(uint32_t obj_enum)
825 {
826 	struct tee_storage_enum *e;
827 	TEE_Result res;
828 	struct tee_ta_session *sess;
829 
830 	if (obj_enum == TEE_HANDLE_NULL)
831 		return TEE_SUCCESS;
832 
833 	res = tee_ta_get_current_session(&sess);
834 	if (res != TEE_SUCCESS)
835 		return res;
836 
837 	res = tee_svc_storage_get_enum(sess->ctx, obj_enum, &e);
838 	if (res != TEE_SUCCESS)
839 		return res;
840 
841 	return tee_svc_close_enum(sess->ctx, e);
842 }
843 
844 TEE_Result tee_svc_storage_reset_enum(uint32_t obj_enum)
845 {
846 	struct tee_storage_enum *e;
847 	int res;
848 	struct tee_ta_session *sess;
849 
850 	res = tee_ta_get_current_session(&sess);
851 	if (res != TEE_SUCCESS)
852 		return res;
853 
854 	if (obj_enum == TEE_HANDLE_NULL)
855 		return TEE_SUCCESS;
856 
857 	res = tee_svc_storage_get_enum(sess->ctx, obj_enum, &e);
858 	if (res != TEE_SUCCESS)
859 		return res;
860 
861 	res = tee_file_ops.closedir(e->dir);
862 	e->dir = NULL;
863 	if (res != 0)
864 		return TEE_ERROR_GENERIC;
865 
866 	return TEE_SUCCESS;
867 }
868 
869 TEE_Result tee_svc_storage_start_enum(uint32_t obj_enum, uint32_t storage_id)
870 {
871 	struct tee_storage_enum *e;
872 	char *dir;
873 	TEE_Result res;
874 	struct tee_ta_session *sess;
875 
876 	if (obj_enum == TEE_HANDLE_NULL)
877 		return TEE_ERROR_BAD_PARAMETERS;
878 
879 	res = tee_ta_get_current_session(&sess);
880 	if (res != TEE_SUCCESS)
881 		return res;
882 
883 	res = tee_svc_storage_get_enum(sess->ctx, obj_enum, &e);
884 	if (res != TEE_SUCCESS)
885 		return res;
886 
887 	if (storage_id != TEE_STORAGE_PRIVATE)
888 		return TEE_ERROR_ITEM_NOT_FOUND;
889 
890 	dir = tee_svc_storage_create_dirname(sess);
891 	if (dir == NULL)
892 		return TEE_ERROR_OUT_OF_MEMORY;
893 
894 	e->dir = tee_file_ops.opendir(dir);
895 	free(dir);
896 
897 	if (e->dir == NULL)
898 		/* error codes needs better granularity */
899 		return TEE_ERROR_ITEM_NOT_FOUND;
900 
901 	return TEE_SUCCESS;
902 }
903 
904 TEE_Result tee_svc_storage_next_enum(uint32_t obj_enum, TEE_ObjectInfo *info,
905 				     void *obj_id, uint32_t *len)
906 {
907 	struct tee_storage_enum *e;
908 	struct tee_fs_dirent *d;
909 	TEE_Result res = TEE_SUCCESS;
910 	struct tee_ta_session *sess;
911 	struct tee_obj *o = NULL;
912 	uint32_t blen;
913 	uint32_t hslen;
914 
915 	res = tee_ta_get_current_session(&sess);
916 	if (res != TEE_SUCCESS)
917 		return res;
918 
919 	if (obj_enum == TEE_HANDLE_NULL)
920 		return TEE_ERROR_BAD_PARAMETERS;
921 
922 	res = tee_svc_storage_get_enum(sess->ctx, obj_enum, &e);
923 	if (res != TEE_SUCCESS)
924 		return res;
925 
926 	/* check rights of the provided buffers */
927 	res =
928 	    tee_mmu_check_access_rights(sess->ctx,
929 					TEE_MEMORY_ACCESS_WRITE |
930 					TEE_MEMORY_ACCESS_ANY_OWNER,
931 					(tee_uaddr_t) info,
932 					sizeof(TEE_ObjectInfo));
933 	if (res != TEE_SUCCESS)
934 		return res;
935 
936 	res =
937 	    tee_mmu_check_access_rights(sess->ctx,
938 					TEE_MEMORY_ACCESS_WRITE |
939 					TEE_MEMORY_ACCESS_ANY_OWNER,
940 					(tee_uaddr_t) obj_id,
941 					TEE_OBJECT_ID_MAX_LEN);
942 	if (res != TEE_SUCCESS)
943 		return res;
944 
945 	d = tee_file_ops.readdir(e->dir);
946 	if (d == NULL)
947 		return TEE_ERROR_ITEM_NOT_FOUND;
948 
949 	o = calloc(1, sizeof(struct tee_obj));
950 	if (o == NULL) {
951 		res = TEE_ERROR_OUT_OF_MEMORY;
952 		goto exit;
953 	}
954 
955 	o->pobj = calloc(1, sizeof(struct tee_pobj));
956 	if (!o->pobj) {
957 		res = TEE_ERROR_OUT_OF_MEMORY;
958 		goto exit;
959 	}
960 
961 	o->info.handleFlags =
962 	    TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED;
963 	o->info.objectUsage = TEE_USAGE_DEFAULT;
964 
965 	/*
966 	 * NOTE: Special usage of pobj due to not ref cnt should be inc
967 	 */
968 	hslen = strlen(d->d_name);
969 	blen = TEE_HS2B_BBUF_SIZE(hslen);
970 	o->pobj->obj_id = malloc(blen);
971 	if (o->pobj->obj_id == NULL) {
972 		res = TEE_ERROR_OUT_OF_MEMORY;
973 		goto exit;
974 	}
975 	tee_hs2b((uint8_t *)d->d_name, o->pobj->obj_id, hslen, blen);
976 	o->pobj->obj_id_len = blen;
977 
978 	res = tee_svc_storage_read_head(sess, o);
979 	if (res != TEE_SUCCESS) {
980 		/* TODO: handle corrupt files in a greaceful way */
981 		goto exit;
982 	}
983 	memcpy(info, &o->info, sizeof(TEE_ObjectInfo));
984 	memcpy(obj_id, o->pobj->obj_id, o->pobj->obj_id_len);
985 
986 	res =
987 	    tee_svc_copy_to_user(sess, len, &o->pobj->obj_id_len,
988 				 sizeof(uint32_t));
989 
990 exit:
991 	if (o) {
992 		if (o->pobj)
993 			free(o->pobj->obj_id);
994 		free(o->pobj);
995 		free(o->data);
996 	}
997 	free(o);
998 
999 	return res;
1000 }
1001 
1002 TEE_Result tee_svc_storage_obj_read(uint32_t obj, void *data, size_t len,
1003 				    uint32_t *count)
1004 {
1005 	TEE_Result res;
1006 	struct tee_ta_session *sess;
1007 	struct tee_obj *o;
1008 	int n_count;
1009 	uint32_t u_count;
1010 
1011 	res = tee_ta_get_current_session(&sess);
1012 	if (res != TEE_SUCCESS)
1013 		return res;
1014 
1015 	res = tee_obj_get(sess->ctx, obj, &o);
1016 	if (res != TEE_SUCCESS)
1017 		return res;
1018 
1019 	if (!(o->flags & TEE_DATA_FLAG_ACCESS_READ))
1020 		return TEE_ERROR_ACCESS_CONFLICT;
1021 
1022 	/* check rights of the provided buffer */
1023 	res =
1024 	    tee_mmu_check_access_rights(sess->ctx,
1025 					TEE_MEMORY_ACCESS_WRITE |
1026 					TEE_MEMORY_ACCESS_ANY_OWNER,
1027 					(tee_uaddr_t) data, len);
1028 	if (res != TEE_SUCCESS)
1029 		return res;
1030 
1031 	n_count = tee_file_ops.read(o->fd, data, len);
1032 	u_count = (uint32_t) ((n_count < 0) ? 0 : n_count);
1033 
1034 	res = tee_svc_copy_to_user(sess, count, &u_count, sizeof(uint32_t));
1035 
1036 	o->info.dataPosition += u_count;
1037 
1038 	return TEE_SUCCESS;
1039 }
1040 
1041 TEE_Result tee_svc_storage_obj_write(uint32_t obj, void *data, size_t len)
1042 {
1043 	TEE_Result res;
1044 	struct tee_ta_session *sess;
1045 	struct tee_obj *o;
1046 	int err;
1047 
1048 	res = tee_ta_get_current_session(&sess);
1049 	if (res != TEE_SUCCESS)
1050 		return res;
1051 
1052 	res = tee_obj_get(sess->ctx, obj, &o);
1053 	if (res != TEE_SUCCESS)
1054 		return res;
1055 
1056 	if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE))
1057 		return TEE_ERROR_ACCESS_CONFLICT;
1058 
1059 	/* check rights of the provided buffer */
1060 	res =
1061 	    tee_mmu_check_access_rights(sess->ctx,
1062 					TEE_MEMORY_ACCESS_READ |
1063 					TEE_MEMORY_ACCESS_ANY_OWNER,
1064 					(tee_uaddr_t) data, len);
1065 
1066 	err = tee_file_ops.write(o->fd, data, len);
1067 
1068 	if (err != (int)len) {
1069 		/* error codes needs better granularity */
1070 		res = TEE_ERROR_GENERIC;
1071 		return res;
1072 	}
1073 
1074 	o->info.dataPosition += len;
1075 	if (o->info.dataPosition > o->info.dataSize)
1076 		o->info.dataSize = o->info.dataPosition;
1077 
1078 	return TEE_SUCCESS;
1079 }
1080 
1081 TEE_Result tee_svc_storage_obj_trunc(uint32_t obj, size_t len)
1082 {
1083 	TEE_Result res;
1084 	struct tee_ta_session *sess;
1085 	struct tee_obj *o;
1086 	int err;
1087 	tee_fs_off_t off;
1088 
1089 	res = tee_ta_get_current_session(&sess);
1090 	if (res != TEE_SUCCESS)
1091 		return res;
1092 
1093 	res = tee_obj_get(sess->ctx, obj, &o);
1094 	if (res != TEE_SUCCESS)
1095 		return res;
1096 
1097 	if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE))
1098 		return TEE_ERROR_ACCESS_CONFLICT;
1099 
1100 	off = sizeof(struct tee_svc_storage_head) + o->data_size;
1101 	err = tee_file_ops.ftruncate(o->fd, len + off);
1102 
1103 	if (err != 0)
1104 		/* error codes needs better granularity */
1105 		return TEE_ERROR_GENERIC;
1106 
1107 	return TEE_SUCCESS;
1108 }
1109 
1110 TEE_Result tee_svc_storage_obj_seek(uint32_t obj, int32_t offset,
1111 				    TEE_Whence whence)
1112 {
1113 	TEE_Result res;
1114 	struct tee_ta_session *sess;
1115 	struct tee_obj *o;
1116 	int fw;
1117 	tee_fs_off_t off;
1118 	tee_fs_off_t e_off = 0;
1119 
1120 	res = tee_ta_get_current_session(&sess);
1121 	if (res != TEE_SUCCESS)
1122 		return res;
1123 
1124 	res = tee_obj_get(sess->ctx, obj, &o);
1125 	if (res != TEE_SUCCESS)
1126 		return res;
1127 
1128 	if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT))
1129 		return TEE_ERROR_BAD_STATE;
1130 
1131 	fw = tee_svc_storage_conv_whence(whence);
1132 
1133 	if (whence == TEE_DATA_SEEK_SET)
1134 		e_off = sizeof(struct tee_svc_storage_head) + o->data_size;
1135 
1136 	off = tee_file_ops.lseek(o->fd, e_off + offset, fw);
1137 	if (off > -1 && off >= e_off)
1138 		o->info.dataPosition = off -
1139 			(sizeof(struct tee_svc_storage_head) + o->data_size);
1140 	else
1141 		return TEE_ERROR_GENERIC;
1142 
1143 	return TEE_SUCCESS;
1144 }
1145 
1146 void tee_svc_storage_close_all_enum(struct tee_ta_ctx *ctx)
1147 {
1148 	struct tee_storage_enum_head *eh = &ctx->storage_enums;
1149 
1150 	/* disregard return value */
1151 	while (!TAILQ_EMPTY(eh))
1152 		tee_svc_close_enum(ctx, TAILQ_FIRST(eh));
1153 }
1154