trng_main.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. /*
  2. * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. */
  6. #include <assert.h>
  7. #include <stdbool.h>
  8. #include <stdint.h>
  9. #include <arch_features.h>
  10. #include <lib/smccc.h>
  11. #include <services/trng_svc.h>
  12. #include <smccc_helpers.h>
  13. #include <plat/common/plat_trng.h>
  14. #include "trng_entropy_pool.h"
  15. static const uuid_t uuid_null;
  16. /* handle the RND call in SMC 32 bit mode */
  17. static uintptr_t trng_rnd32(uint32_t nbits, void *handle)
  18. {
  19. uint32_t mask = ~0U;
  20. uint64_t ent[2] = {0};
  21. if (nbits == 0U || nbits > TRNG_RND32_ENTROPY_MAXBITS) {
  22. SMC_RET1(handle, TRNG_E_INVALID_PARAMS);
  23. }
  24. if (!trng_pack_entropy(nbits, &ent[0])) {
  25. SMC_RET1(handle, TRNG_E_NO_ENTROPY);
  26. }
  27. if ((nbits % 32U) != 0U) {
  28. mask >>= 32U - (nbits % 32U);
  29. }
  30. switch ((nbits - 1U) / 32U) {
  31. case 0:
  32. SMC_RET4(handle, TRNG_E_SUCCESS, 0, 0, ent[0] & mask);
  33. break; /* unreachable */
  34. case 1:
  35. SMC_RET4(handle, TRNG_E_SUCCESS, 0, (ent[0] >> 32) & mask,
  36. ent[0] & 0xFFFFFFFF);
  37. break; /* unreachable */
  38. case 2:
  39. SMC_RET4(handle, TRNG_E_SUCCESS, ent[1] & mask,
  40. (ent[0] >> 32) & 0xFFFFFFFF, ent[0] & 0xFFFFFFFF);
  41. break; /* unreachable */
  42. default:
  43. SMC_RET1(handle, TRNG_E_INVALID_PARAMS);
  44. break; /* unreachable */
  45. }
  46. }
  47. /* handle the RND call in SMC 64 bit mode */
  48. static uintptr_t trng_rnd64(uint32_t nbits, void *handle)
  49. {
  50. uint64_t mask = ~0ULL;
  51. uint64_t ent[3] = {0};
  52. if (nbits == 0U || nbits > TRNG_RND64_ENTROPY_MAXBITS) {
  53. SMC_RET1(handle, TRNG_E_INVALID_PARAMS);
  54. }
  55. if (!trng_pack_entropy(nbits, &ent[0])) {
  56. SMC_RET1(handle, TRNG_E_NO_ENTROPY);
  57. }
  58. /* Mask off higher bits if only part of register requested */
  59. if ((nbits % 64U) != 0U) {
  60. mask >>= 64U - (nbits % 64U);
  61. }
  62. switch ((nbits - 1U) / 64U) {
  63. case 0:
  64. SMC_RET4(handle, TRNG_E_SUCCESS, 0, 0, ent[0] & mask);
  65. break; /* unreachable */
  66. case 1:
  67. SMC_RET4(handle, TRNG_E_SUCCESS, 0, ent[1] & mask, ent[0]);
  68. break; /* unreachable */
  69. case 2:
  70. SMC_RET4(handle, TRNG_E_SUCCESS, ent[2] & mask, ent[1], ent[0]);
  71. break; /* unreachable */
  72. default:
  73. SMC_RET1(handle, TRNG_E_INVALID_PARAMS);
  74. break; /* unreachable */
  75. }
  76. }
  77. void trng_setup(void)
  78. {
  79. trng_entropy_pool_setup();
  80. plat_entropy_setup();
  81. }
  82. /* Predicate indicating that a function id is part of TRNG */
  83. bool is_trng_fid(uint32_t smc_fid)
  84. {
  85. return ((smc_fid == ARM_TRNG_VERSION) ||
  86. (smc_fid == ARM_TRNG_FEATURES) ||
  87. (smc_fid == ARM_TRNG_GET_UUID) ||
  88. (smc_fid == ARM_TRNG_RND32) ||
  89. (smc_fid == ARM_TRNG_RND64));
  90. }
  91. uintptr_t trng_smc_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2,
  92. u_register_t x3, u_register_t x4, void *cookie,
  93. void *handle, u_register_t flags)
  94. {
  95. if (!memcmp(&plat_trng_uuid, &uuid_null, sizeof(uuid_t))) {
  96. SMC_RET1(handle, TRNG_E_NOT_IMPLEMENTED);
  97. }
  98. switch (smc_fid) {
  99. case ARM_TRNG_VERSION:
  100. SMC_RET1(handle, MAKE_SMCCC_VERSION(
  101. TRNG_VERSION_MAJOR, TRNG_VERSION_MINOR));
  102. break; /* unreachable */
  103. case ARM_TRNG_FEATURES:
  104. if (is_trng_fid((uint32_t)x1)) {
  105. SMC_RET1(handle, TRNG_E_SUCCESS);
  106. } else {
  107. SMC_RET1(handle, TRNG_E_NOT_SUPPORTED);
  108. }
  109. break; /* unreachable */
  110. case ARM_TRNG_GET_UUID:
  111. SMC_UUID_RET(handle, plat_trng_uuid);
  112. break; /* unreachable */
  113. case ARM_TRNG_RND32:
  114. return trng_rnd32((uint32_t)x1, handle);
  115. case ARM_TRNG_RND64:
  116. return trng_rnd64((uint32_t)x1, handle);
  117. default:
  118. WARN("Unimplemented TRNG Service Call: 0x%x\n", smc_fid);
  119. SMC_RET1(handle, TRNG_E_NOT_IMPLEMENTED);
  120. break; /* unreachable */
  121. }
  122. }