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