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