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