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 = 636 tee_svc_storage_create_filename(sess, o->pobj->obj_id, 637 o->pobj->obj_id_len); 638 if (file == NULL) 639 return TEE_ERROR_OUT_OF_MEMORY; 640 641 tee_obj_close(sess->ctx, o); 642 643 err = tee_file_ops.unlink(file); 644 free(file); 645 if (err != 0) 646 /* error codes needs better granularity */ 647 return TEE_ERROR_GENERIC; 648 649 /* try and remove dir */ 650 dir = tee_svc_storage_create_dirname(sess); 651 if (dir == NULL) 652 return TEE_ERROR_OUT_OF_MEMORY; 653 /* ignore result */ 654 tee_file_ops.rmdir(dir); 655 free(dir); 656 657 return TEE_SUCCESS; 658 } 659 660 TEE_Result tee_svc_storage_obj_rename(uint32_t obj, void *object_id, 661 uint32_t object_id_len) 662 { 663 TEE_Result res; 664 struct tee_ta_session *sess; 665 struct tee_obj *o; 666 struct tee_pobj *po = NULL; 667 char *new_file = NULL; 668 char *old_file = NULL; 669 int err = -1; 670 671 if (object_id_len > TEE_OBJECT_ID_MAX_LEN) 672 return TEE_ERROR_BAD_PARAMETERS; 673 674 res = tee_ta_get_current_session(&sess); 675 if (res != TEE_SUCCESS) 676 return res; 677 678 res = tee_obj_get(sess->ctx, obj, &o); 679 if (res != TEE_SUCCESS) 680 return res; 681 682 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE_META)) { 683 res = TEE_ERROR_BAD_STATE; 684 goto exit; 685 } 686 687 if (o->pobj == NULL || o->pobj->obj_id == NULL) 688 return TEE_ERROR_BAD_STATE; 689 690 res = 691 tee_mmu_check_access_rights(sess->ctx, 692 TEE_MEMORY_ACCESS_READ | 693 TEE_MEMORY_ACCESS_ANY_OWNER, 694 (tee_uaddr_t) object_id, object_id_len); 695 if (res != TEE_SUCCESS) 696 goto exit; 697 698 /* get new ds name */ 699 new_file = 700 tee_svc_storage_create_filename(sess, object_id, object_id_len); 701 if (new_file == NULL) { 702 res = TEE_ERROR_OUT_OF_MEMORY; 703 goto exit; 704 } 705 706 old_file = 707 tee_svc_storage_create_filename(sess, o->pobj->obj_id, 708 o->pobj->obj_id_len); 709 if (old_file == NULL) { 710 res = TEE_ERROR_OUT_OF_MEMORY; 711 goto exit; 712 } 713 714 /* reserve dest name */ 715 res = tee_pobj_get((void *)&sess->ctx->head->uuid, object_id, 716 object_id_len, TEE_DATA_FLAG_ACCESS_WRITE_META, &po); 717 if (res != TEE_SUCCESS) 718 goto exit; 719 720 err = tee_file_ops.access(new_file, TEE_FS_F_OK); 721 if (err == 0) { 722 /* file exists */ 723 res = TEE_ERROR_ACCESS_CONFLICT; 724 goto exit; 725 } 726 727 /* move */ 728 err = tee_file_ops.rename(old_file, new_file); 729 if (err) { 730 /* error codes needs better granularity */ 731 res = TEE_ERROR_GENERIC; 732 goto exit; 733 } 734 735 res = tee_pobj_rename(o->pobj, object_id, object_id_len); 736 737 exit: 738 tee_pobj_release(po); 739 740 free(new_file); 741 free(old_file); 742 743 return res; 744 } 745 746 TEE_Result tee_svc_storage_alloc_enum(uint32_t *obj_enum) 747 { 748 struct tee_storage_enum *e; 749 struct tee_ta_session *sess; 750 TEE_Result res; 751 752 if (obj_enum == NULL) 753 return TEE_ERROR_BAD_PARAMETERS; 754 755 res = tee_ta_get_current_session(&sess); 756 if (res != TEE_SUCCESS) 757 return res; 758 759 e = malloc(sizeof(struct tee_storage_enum)); 760 761 if (e == NULL) 762 return TEE_ERROR_OUT_OF_MEMORY; 763 764 e->dir = NULL; 765 TAILQ_INSERT_TAIL(&sess->ctx->storage_enums, e, link); 766 767 return tee_svc_copy_to_user(sess, obj_enum, &e, 768 sizeof(TEE_ObjectEnumHandle *)); 769 } 770 771 TEE_Result tee_svc_storage_free_enum(uint32_t obj_enum) 772 { 773 struct tee_storage_enum *e; 774 TEE_Result res; 775 struct tee_ta_session *sess; 776 777 if (obj_enum == TEE_HANDLE_NULL) 778 return TEE_SUCCESS; 779 780 res = tee_ta_get_current_session(&sess); 781 if (res != TEE_SUCCESS) 782 return res; 783 784 res = tee_svc_storage_get_enum(sess->ctx, obj_enum, &e); 785 if (res != TEE_SUCCESS) 786 return res; 787 788 return tee_svc_close_enum(sess->ctx, e); 789 } 790 791 TEE_Result tee_svc_storage_reset_enum(uint32_t obj_enum) 792 { 793 struct tee_storage_enum *e; 794 int res; 795 struct tee_ta_session *sess; 796 797 res = tee_ta_get_current_session(&sess); 798 if (res != TEE_SUCCESS) 799 return res; 800 801 if (obj_enum == TEE_HANDLE_NULL) 802 return TEE_SUCCESS; 803 804 res = tee_svc_storage_get_enum(sess->ctx, obj_enum, &e); 805 if (res != TEE_SUCCESS) 806 return res; 807 808 res = tee_file_ops.closedir(e->dir); 809 e->dir = NULL; 810 if (res != 0) 811 return TEE_ERROR_GENERIC; 812 813 return TEE_SUCCESS; 814 } 815 816 TEE_Result tee_svc_storage_start_enum(uint32_t obj_enum, uint32_t storage_id) 817 { 818 struct tee_storage_enum *e; 819 char *dir; 820 TEE_Result res; 821 struct tee_ta_session *sess; 822 823 if (obj_enum == TEE_HANDLE_NULL) 824 return TEE_ERROR_BAD_PARAMETERS; 825 826 res = tee_ta_get_current_session(&sess); 827 if (res != TEE_SUCCESS) 828 return res; 829 830 res = tee_svc_storage_get_enum(sess->ctx, obj_enum, &e); 831 if (res != TEE_SUCCESS) 832 return res; 833 834 if (storage_id != TEE_STORAGE_PRIVATE) 835 return TEE_ERROR_ITEM_NOT_FOUND; 836 837 dir = tee_svc_storage_create_dirname(sess); 838 if (dir == NULL) 839 return TEE_ERROR_OUT_OF_MEMORY; 840 841 e->dir = tee_file_ops.opendir(dir); 842 free(dir); 843 844 if (e->dir == NULL) 845 /* error codes needs better granularity */ 846 return TEE_ERROR_ITEM_NOT_FOUND; 847 848 return TEE_SUCCESS; 849 } 850 851 TEE_Result tee_svc_storage_next_enum(uint32_t obj_enum, TEE_ObjectInfo *info, 852 void *obj_id, uint32_t *len) 853 { 854 struct tee_storage_enum *e; 855 struct tee_fs_dirent *d; 856 TEE_Result res = TEE_SUCCESS; 857 struct tee_ta_session *sess; 858 struct tee_obj *o = NULL; 859 uint32_t blen; 860 uint32_t hslen; 861 862 res = tee_ta_get_current_session(&sess); 863 if (res != TEE_SUCCESS) 864 return res; 865 866 if (obj_enum == TEE_HANDLE_NULL) 867 return TEE_ERROR_BAD_PARAMETERS; 868 869 res = tee_svc_storage_get_enum(sess->ctx, obj_enum, &e); 870 if (res != TEE_SUCCESS) 871 return res; 872 873 /* check rights of the provided buffers */ 874 res = 875 tee_mmu_check_access_rights(sess->ctx, 876 TEE_MEMORY_ACCESS_WRITE | 877 TEE_MEMORY_ACCESS_ANY_OWNER, 878 (tee_uaddr_t) info, 879 sizeof(TEE_ObjectInfo)); 880 if (res != TEE_SUCCESS) 881 return res; 882 883 res = 884 tee_mmu_check_access_rights(sess->ctx, 885 TEE_MEMORY_ACCESS_WRITE | 886 TEE_MEMORY_ACCESS_ANY_OWNER, 887 (tee_uaddr_t) obj_id, 888 TEE_OBJECT_ID_MAX_LEN); 889 if (res != TEE_SUCCESS) 890 return res; 891 892 d = tee_file_ops.readdir(e->dir); 893 if (d == NULL) 894 return TEE_ERROR_ITEM_NOT_FOUND; 895 896 o = calloc(1, sizeof(struct tee_obj)); 897 if (o == NULL) { 898 res = TEE_ERROR_OUT_OF_MEMORY; 899 goto exit; 900 } 901 902 o->pobj = calloc(1, sizeof(struct tee_pobj)); 903 if (!o->pobj) { 904 res = TEE_ERROR_OUT_OF_MEMORY; 905 goto exit; 906 } 907 908 o->info.handleFlags = 909 TEE_HANDLE_FLAG_PERSISTENT | TEE_HANDLE_FLAG_INITIALIZED; 910 o->info.objectUsage = TEE_USAGE_DEFAULT; 911 912 /* 913 * NOTE: Special usage of pobj due to not ref cnt should be inc 914 */ 915 hslen = strlen(d->d_name); 916 blen = TEE_HS2B_BBUF_SIZE(hslen); 917 o->pobj->obj_id = malloc(blen); 918 if (o->pobj->obj_id == NULL) { 919 res = TEE_ERROR_OUT_OF_MEMORY; 920 goto exit; 921 } 922 tee_hs2b((uint8_t *)d->d_name, o->pobj->obj_id, hslen, blen); 923 o->pobj->obj_id_len = blen; 924 925 res = tee_svc_storage_read_head(sess, o); 926 if (res != TEE_SUCCESS) { 927 /* TODO: handle corrupt files in a greaceful way */ 928 goto exit; 929 } 930 memcpy(info, &o->info, sizeof(TEE_ObjectInfo)); 931 memcpy(obj_id, o->pobj->obj_id, o->pobj->obj_id_len); 932 933 res = 934 tee_svc_copy_to_user(sess, len, &o->pobj->obj_id_len, 935 sizeof(uint32_t)); 936 937 exit: 938 if (o) { 939 if (o->pobj) 940 free(o->pobj->obj_id); 941 free(o->pobj); 942 free(o->data); 943 } 944 free(o); 945 946 return res; 947 } 948 949 TEE_Result tee_svc_storage_obj_read(uint32_t obj, void *data, size_t len, 950 uint32_t *count) 951 { 952 TEE_Result res; 953 struct tee_ta_session *sess; 954 struct tee_obj *o; 955 int n_count; 956 uint32_t u_count; 957 958 res = tee_ta_get_current_session(&sess); 959 if (res != TEE_SUCCESS) 960 return res; 961 962 res = tee_obj_get(sess->ctx, obj, &o); 963 if (res != TEE_SUCCESS) 964 return res; 965 966 if (!(o->flags & TEE_DATA_FLAG_ACCESS_READ)) 967 return TEE_ERROR_ACCESS_CONFLICT; 968 969 /* check rights of the provided buffer */ 970 res = 971 tee_mmu_check_access_rights(sess->ctx, 972 TEE_MEMORY_ACCESS_WRITE | 973 TEE_MEMORY_ACCESS_ANY_OWNER, 974 (tee_uaddr_t) data, len); 975 if (res != TEE_SUCCESS) 976 return res; 977 978 n_count = tee_file_ops.read(o->fd, data, len); 979 u_count = (uint32_t) ((n_count < 0) ? 0 : n_count); 980 981 res = tee_svc_copy_to_user(sess, count, &u_count, sizeof(uint32_t)); 982 983 o->info.dataPosition += u_count; 984 985 return TEE_SUCCESS; 986 } 987 988 TEE_Result tee_svc_storage_obj_write(uint32_t obj, void *data, size_t len) 989 { 990 TEE_Result res; 991 struct tee_ta_session *sess; 992 struct tee_obj *o; 993 int err; 994 995 res = tee_ta_get_current_session(&sess); 996 if (res != TEE_SUCCESS) 997 return res; 998 999 res = tee_obj_get(sess->ctx, obj, &o); 1000 if (res != TEE_SUCCESS) 1001 return res; 1002 1003 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE)) 1004 return TEE_ERROR_ACCESS_CONFLICT; 1005 1006 /* check rights of the provided buffer */ 1007 res = 1008 tee_mmu_check_access_rights(sess->ctx, 1009 TEE_MEMORY_ACCESS_READ | 1010 TEE_MEMORY_ACCESS_ANY_OWNER, 1011 (tee_uaddr_t) data, len); 1012 1013 err = tee_file_ops.write(o->fd, data, len); 1014 1015 if (err != (int)len) { 1016 /* error codes needs better granularity */ 1017 res = TEE_ERROR_GENERIC; 1018 return res; 1019 } 1020 1021 o->info.dataPosition += len; 1022 if (o->info.dataPosition > o->info.dataSize) 1023 o->info.dataSize = o->info.dataPosition; 1024 1025 return TEE_SUCCESS; 1026 } 1027 1028 TEE_Result tee_svc_storage_obj_trunc(uint32_t obj, size_t len) 1029 { 1030 TEE_Result res; 1031 struct tee_ta_session *sess; 1032 struct tee_obj *o; 1033 int err; 1034 tee_fs_off_t off; 1035 1036 res = tee_ta_get_current_session(&sess); 1037 if (res != TEE_SUCCESS) 1038 return res; 1039 1040 res = tee_obj_get(sess->ctx, obj, &o); 1041 if (res != TEE_SUCCESS) 1042 return res; 1043 1044 if (!(o->flags & TEE_DATA_FLAG_ACCESS_WRITE)) 1045 return TEE_ERROR_ACCESS_CONFLICT; 1046 1047 off = sizeof(struct tee_svc_storage_head) + o->data_size; 1048 err = tee_file_ops.ftruncate(o->fd, len + off); 1049 1050 if (err != 0) 1051 /* error codes needs better granularity */ 1052 return TEE_ERROR_GENERIC; 1053 1054 return TEE_SUCCESS; 1055 } 1056 1057 TEE_Result tee_svc_storage_obj_seek(uint32_t obj, int32_t offset, 1058 TEE_Whence whence) 1059 { 1060 TEE_Result res; 1061 struct tee_ta_session *sess; 1062 struct tee_obj *o; 1063 int fw; 1064 tee_fs_off_t off; 1065 tee_fs_off_t e_off = 0; 1066 1067 res = tee_ta_get_current_session(&sess); 1068 if (res != TEE_SUCCESS) 1069 return res; 1070 1071 res = tee_obj_get(sess->ctx, obj, &o); 1072 if (res != TEE_SUCCESS) 1073 return res; 1074 1075 if (!(o->info.handleFlags & TEE_HANDLE_FLAG_PERSISTENT)) 1076 return TEE_ERROR_BAD_STATE; 1077 1078 fw = tee_svc_storage_conv_whence(whence); 1079 1080 if (whence == TEE_DATA_SEEK_SET) 1081 e_off = sizeof(struct tee_svc_storage_head) + o->data_size; 1082 1083 off = tee_file_ops.lseek(o->fd, e_off + offset, fw); 1084 if (off > -1 && off >= e_off) 1085 o->info.dataPosition = 1086 off - sizeof(struct tee_svc_storage_head) + o->data_size; 1087 else 1088 return TEE_ERROR_GENERIC; 1089 1090 return TEE_SUCCESS; 1091 } 1092 1093 void tee_svc_storage_close_all_enum(struct tee_ta_ctx *ctx) 1094 { 1095 struct tee_storage_enum_head *eh = &ctx->storage_enums; 1096 1097 /* disregard return value */ 1098 while (!TAILQ_EMPTY(eh)) 1099 tee_svc_close_enum(ctx, TAILQ_FIRST(eh)); 1100 } 1101