optee_rng.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. // SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause
  2. /*
  3. * Copyright (C) 2022, STMicroelectronics - All Rights Reserved
  4. */
  5. #define LOG_CATEGORY UCLASS_RNG
  6. #include <common.h>
  7. #include <rng.h>
  8. #include <tee.h>
  9. #include <dm/device.h>
  10. #include <dm/device_compat.h>
  11. #include <linux/sizes.h>
  12. #include <tee/optee_service.h>
  13. #define DRIVER_NAME "optee-rng"
  14. #define TEE_ERROR_HEALTH_TEST_FAIL 0x00000001
  15. /*
  16. * TA_CMD_GET_ENTROPY - Get Entropy from RNG
  17. *
  18. * param[0] (inout memref) - Entropy buffer memory reference
  19. * param[1] unused
  20. * param[2] unused
  21. * param[3] unused
  22. *
  23. * Result:
  24. * TEE_SUCCESS - Invoke command success
  25. * TEE_ERROR_BAD_PARAMETERS - Incorrect input param
  26. * TEE_ERROR_NOT_SUPPORTED - Requested entropy size greater than size of pool
  27. * TEE_ERROR_HEALTH_TEST_FAIL - Continuous health testing failed
  28. */
  29. #define TA_CMD_GET_ENTROPY 0x0
  30. #define MAX_ENTROPY_REQ_SZ SZ_4K
  31. #define TA_HWRNG_UUID { 0xab7a617c, 0xb8e7, 0x4d8f, \
  32. { 0x83, 0x01, 0xd0, 0x9b, 0x61, 0x03, 0x6b, 0x64 } }
  33. OPTEE_SERVICE_DRIVER(optee_rng, TA_HWRNG_UUID, DRIVER_NAME);
  34. /** open_session_ta_hwrng() - Open session with hwrng Trusted App
  35. *
  36. * @dev: device
  37. * @session_id: return the RNG TA session identifier
  38. * Return: 0 if ok
  39. */
  40. static int open_session_ta_hwrng(struct udevice *dev, u32 *session_id)
  41. {
  42. const struct tee_optee_ta_uuid uuid = TA_HWRNG_UUID;
  43. struct tee_open_session_arg sess_arg = {0};
  44. int ret;
  45. /* Open session with hwrng Trusted App */
  46. tee_optee_ta_uuid_to_octets(sess_arg.uuid, &uuid);
  47. sess_arg.clnt_login = TEE_LOGIN_PUBLIC;
  48. ret = tee_open_session(dev->parent, &sess_arg, 0, NULL);
  49. if (ret || sess_arg.ret) {
  50. if (!ret)
  51. ret = -EIO;
  52. return ret;
  53. }
  54. *session_id = sess_arg.session;
  55. return 0;
  56. }
  57. /**
  58. * get_optee_rng_data() - read RNG data from OP-TEE TA
  59. *
  60. * @dev: device
  61. * @session_id: the RNG TA session identifier
  62. * @entropy_shm_pool: shared memory pool used for TEE message
  63. * @buf: buffer to receive data
  64. * @size: size of buffer, limited by entropy_shm_pool size
  65. * Return: 0 if ok
  66. */
  67. static int get_optee_rng_data(struct udevice *dev, u32 session_id,
  68. struct tee_shm *entropy_shm_pool,
  69. void *buf, size_t *size)
  70. {
  71. int ret = 0;
  72. struct tee_invoke_arg arg = {0};
  73. struct tee_param param = {0};
  74. /* Invoke TA_CMD_GET_ENTROPY function of Trusted App */
  75. arg.func = TA_CMD_GET_ENTROPY;
  76. arg.session = session_id;
  77. /* Fill invoke cmd params */
  78. param.attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT;
  79. param.u.memref.shm = entropy_shm_pool;
  80. param.u.memref.size = *size;
  81. ret = tee_invoke_func(dev->parent, &arg, 1, &param);
  82. if (ret || arg.ret) {
  83. if (!ret)
  84. ret = -EPROTO;
  85. dev_err(dev, "TA_CMD_GET_ENTROPY invoke err: %d 0x%x\n", ret, arg.ret);
  86. *size = 0;
  87. return ret;
  88. }
  89. memcpy(buf, param.u.memref.shm->addr, param.u.memref.size);
  90. *size = param.u.memref.size;
  91. return 0;
  92. }
  93. /**
  94. * optee_rng_read() - rng read ops for OP-TEE RNG device
  95. *
  96. * @dev: device
  97. * @buf: buffer to receive data
  98. * @len: size of buffer
  99. * Return: 0 if ok
  100. */
  101. static int optee_rng_read(struct udevice *dev, void *buf, size_t len)
  102. {
  103. size_t read = 0, rng_size = 0;
  104. struct tee_shm *entropy_shm_pool;
  105. u8 *data = buf;
  106. int ret;
  107. u32 session_id = 0;
  108. ret = open_session_ta_hwrng(dev, &session_id);
  109. if (ret) {
  110. dev_err(dev, "can't open session: %d\n", ret);
  111. return ret;
  112. }
  113. ret = tee_shm_alloc(dev->parent, MAX_ENTROPY_REQ_SZ, 0, &entropy_shm_pool);
  114. if (ret) {
  115. dev_err(dev, "tee_shm_alloc failed: %d\n", ret);
  116. goto session_close;
  117. }
  118. while (read < len) {
  119. rng_size = min(len - read, (size_t)MAX_ENTROPY_REQ_SZ);
  120. ret = get_optee_rng_data(dev, session_id, entropy_shm_pool, data, &rng_size);
  121. if (ret)
  122. goto shm_free;
  123. data += rng_size;
  124. read += rng_size;
  125. }
  126. shm_free:
  127. tee_shm_free(entropy_shm_pool);
  128. session_close:
  129. tee_close_session(dev->parent, session_id);
  130. return ret;
  131. }
  132. /**
  133. * optee_rng_probe() - probe function for OP-TEE RNG device
  134. *
  135. * @dev: device
  136. * Return: 0 if ok
  137. */
  138. static int optee_rng_probe(struct udevice *dev)
  139. {
  140. int ret;
  141. u32 session_id;
  142. ret = open_session_ta_hwrng(dev, &session_id);
  143. if (ret) {
  144. dev_err(dev, "can't open session: %d\n", ret);
  145. return ret;
  146. }
  147. tee_close_session(dev->parent, session_id);
  148. return 0;
  149. }
  150. static const struct dm_rng_ops optee_rng_ops = {
  151. .read = optee_rng_read,
  152. };
  153. U_BOOT_DRIVER(optee_rng) = {
  154. .name = DRIVER_NAME,
  155. .id = UCLASS_RNG,
  156. .ops = &optee_rng_ops,
  157. .probe = optee_rng_probe,
  158. };