optee_rpmb.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright 2020 NXP
  4. */
  5. #include <command.h>
  6. #include <common.h>
  7. #include <env.h>
  8. #include <errno.h>
  9. #include <image.h>
  10. #include <malloc.h>
  11. #include <mmc.h>
  12. #include <tee.h>
  13. #include <tee/optee_ta_avb.h>
  14. static struct udevice *tee;
  15. static u32 session;
  16. static int avb_ta_open_session(void)
  17. {
  18. const struct tee_optee_ta_uuid uuid = TA_AVB_UUID;
  19. struct tee_open_session_arg arg;
  20. int rc;
  21. tee = tee_find_device(tee, NULL, NULL, NULL);
  22. if (!tee)
  23. return -ENODEV;
  24. memset(&arg, 0, sizeof(arg));
  25. tee_optee_ta_uuid_to_octets(arg.uuid, &uuid);
  26. rc = tee_open_session(tee, &arg, 0, NULL);
  27. if (!rc)
  28. session = arg.session;
  29. return 0;
  30. }
  31. static int invoke_func(u32 func, ulong num_param, struct tee_param *param)
  32. {
  33. struct tee_invoke_arg arg;
  34. if (!tee)
  35. if (avb_ta_open_session())
  36. return -ENODEV;
  37. memset(&arg, 0, sizeof(arg));
  38. arg.func = func;
  39. arg.session = session;
  40. if (tee_invoke_func(tee, &arg, num_param, param))
  41. return -EFAULT;
  42. switch (arg.ret) {
  43. case TEE_SUCCESS:
  44. return 0;
  45. case TEE_ERROR_OUT_OF_MEMORY:
  46. case TEE_ERROR_STORAGE_NO_SPACE:
  47. return -ENOSPC;
  48. case TEE_ERROR_ITEM_NOT_FOUND:
  49. return -EIO;
  50. case TEE_ERROR_TARGET_DEAD:
  51. /*
  52. * The TA has paniced, close the session to reload the TA
  53. * for the next request.
  54. */
  55. tee_close_session(tee, session);
  56. tee = NULL;
  57. return -EIO;
  58. default:
  59. return -EIO;
  60. }
  61. }
  62. static int read_persistent_value(const char *name,
  63. size_t buffer_size,
  64. u8 *out_buffer,
  65. size_t *out_num_bytes_read)
  66. {
  67. int rc = 0;
  68. struct tee_shm *shm_name;
  69. struct tee_shm *shm_buf;
  70. struct tee_param param[2];
  71. size_t name_size = strlen(name) + 1;
  72. if (!tee)
  73. if (avb_ta_open_session())
  74. return -ENODEV;
  75. rc = tee_shm_alloc(tee, name_size,
  76. TEE_SHM_ALLOC, &shm_name);
  77. if (rc)
  78. return -ENOMEM;
  79. rc = tee_shm_alloc(tee, buffer_size,
  80. TEE_SHM_ALLOC, &shm_buf);
  81. if (rc) {
  82. rc = -ENOMEM;
  83. goto free_name;
  84. }
  85. memcpy(shm_name->addr, name, name_size);
  86. memset(param, 0, sizeof(param));
  87. param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
  88. param[0].u.memref.shm = shm_name;
  89. param[0].u.memref.size = name_size;
  90. param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT;
  91. param[1].u.memref.shm = shm_buf;
  92. param[1].u.memref.size = buffer_size;
  93. rc = invoke_func(TA_AVB_CMD_READ_PERSIST_VALUE,
  94. 2, param);
  95. if (rc)
  96. goto out;
  97. if (param[1].u.memref.size > buffer_size) {
  98. rc = -EINVAL;
  99. goto out;
  100. }
  101. *out_num_bytes_read = param[1].u.memref.size;
  102. memcpy(out_buffer, shm_buf->addr, *out_num_bytes_read);
  103. out:
  104. tee_shm_free(shm_buf);
  105. free_name:
  106. tee_shm_free(shm_name);
  107. return rc;
  108. }
  109. static int write_persistent_value(const char *name,
  110. size_t value_size,
  111. const u8 *value)
  112. {
  113. int rc = 0;
  114. struct tee_shm *shm_name;
  115. struct tee_shm *shm_buf;
  116. struct tee_param param[2];
  117. size_t name_size = strlen(name) + 1;
  118. if (!tee) {
  119. if (avb_ta_open_session())
  120. return -ENODEV;
  121. }
  122. if (!value_size)
  123. return -EINVAL;
  124. rc = tee_shm_alloc(tee, name_size,
  125. TEE_SHM_ALLOC, &shm_name);
  126. if (rc)
  127. return -ENOMEM;
  128. rc = tee_shm_alloc(tee, value_size,
  129. TEE_SHM_ALLOC, &shm_buf);
  130. if (rc) {
  131. rc = -ENOMEM;
  132. goto free_name;
  133. }
  134. memcpy(shm_name->addr, name, name_size);
  135. memcpy(shm_buf->addr, value, value_size);
  136. memset(param, 0, sizeof(param));
  137. param[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
  138. param[0].u.memref.shm = shm_name;
  139. param[0].u.memref.size = name_size;
  140. param[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
  141. param[1].u.memref.shm = shm_buf;
  142. param[1].u.memref.size = value_size;
  143. rc = invoke_func(TA_AVB_CMD_WRITE_PERSIST_VALUE,
  144. 2, param);
  145. if (rc)
  146. goto out;
  147. out:
  148. tee_shm_free(shm_buf);
  149. free_name:
  150. tee_shm_free(shm_name);
  151. return rc;
  152. }
  153. int do_optee_rpmb_read(struct cmd_tbl *cmdtp, int flag, int argc,
  154. char * const argv[])
  155. {
  156. const char *name;
  157. size_t bytes;
  158. size_t bytes_read;
  159. void *buffer;
  160. char *endp;
  161. if (argc != 3)
  162. return CMD_RET_USAGE;
  163. name = argv[1];
  164. bytes = dectoul(argv[2], &endp);
  165. if (*endp && *endp != '\n')
  166. return CMD_RET_USAGE;
  167. buffer = malloc(bytes);
  168. if (!buffer)
  169. return CMD_RET_FAILURE;
  170. if (read_persistent_value(name, bytes, buffer, &bytes_read) == 0) {
  171. printf("Read %zu bytes, value = %s\n", bytes_read,
  172. (char *)buffer);
  173. free(buffer);
  174. return CMD_RET_SUCCESS;
  175. }
  176. printf("Failed to read persistent value\n");
  177. free(buffer);
  178. return CMD_RET_FAILURE;
  179. }
  180. int do_optee_rpmb_write(struct cmd_tbl *cmdtp, int flag, int argc,
  181. char * const argv[])
  182. {
  183. const char *name;
  184. const char *value;
  185. if (argc != 3)
  186. return CMD_RET_USAGE;
  187. name = argv[1];
  188. value = argv[2];
  189. if (write_persistent_value(name, strlen(value) + 1,
  190. (const uint8_t *)value) == 0) {
  191. printf("Wrote %zu bytes\n", strlen(value) + 1);
  192. return CMD_RET_SUCCESS;
  193. }
  194. printf("Failed to write persistent value\n");
  195. return CMD_RET_FAILURE;
  196. }
  197. static struct cmd_tbl cmd_optee_rpmb[] = {
  198. U_BOOT_CMD_MKENT(read_pvalue, 3, 0, do_optee_rpmb_read, "", ""),
  199. U_BOOT_CMD_MKENT(write_pvalue, 3, 0, do_optee_rpmb_write, "", ""),
  200. };
  201. static int do_optee_rpmb(struct cmd_tbl *cmdtp, int flag, int argc,
  202. char * const argv[])
  203. {
  204. struct cmd_tbl *cp;
  205. cp = find_cmd_tbl(argv[1], cmd_optee_rpmb, ARRAY_SIZE(cmd_optee_rpmb));
  206. argc--;
  207. argv++;
  208. if (!cp || argc > cp->maxargs)
  209. return CMD_RET_USAGE;
  210. if (flag == CMD_FLAG_REPEAT)
  211. return CMD_RET_FAILURE;
  212. return cp->cmd(cmdtp, flag, argc, argv);
  213. }
  214. U_BOOT_CMD (
  215. optee_rpmb, 29, 0, do_optee_rpmb,
  216. "Provides commands for testing secure storage on RPMB on OPTEE",
  217. "read_pvalue <name> <bytes> - read a persistent value <name>\n"
  218. "optee_rpmb write_pvalue <name> <value> - write a persistent value <name>\n"
  219. );