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