No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 

234 líneas
6.0 KiB

  1. /* Jitter RNG: Internal timer implementation
  2. *
  3. * Copyright (C) 2021 - 2022, Stephan Mueller <smueller@chronox.de>
  4. *
  5. * License: see LICENSE file in root directory
  6. *
  7. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  8. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  9. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
  10. * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
  11. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  12. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
  13. * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  14. * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  15. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  16. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  17. * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
  18. * DAMAGE.
  19. */
  20. #include "jitterentropy-base.h"
  21. #include "jitterentropy-timer.h"
  22. #ifdef JENT_CONF_ENABLE_INTERNAL_TIMER
  23. /***************************************************************************
  24. * Thread handler
  25. ***************************************************************************/
  26. JENT_PRIVATE_STATIC
  27. int jent_notime_init(void **ctx)
  28. {
  29. struct jent_notime_ctx *thread_ctx;
  30. long ncpu = jent_ncpu();
  31. if (ncpu < 0)
  32. return (int)ncpu;
  33. /* We need at least two CPUs to enable the timer thread */
  34. if (ncpu < 2)
  35. return -EOPNOTSUPP;
  36. thread_ctx = calloc(1, sizeof(struct jent_notime_ctx));
  37. if (!thread_ctx)
  38. return -errno;
  39. *ctx = thread_ctx;
  40. return 0;
  41. }
  42. JENT_PRIVATE_STATIC
  43. void jent_notime_fini(void *ctx)
  44. {
  45. struct jent_notime_ctx *thread_ctx = (struct jent_notime_ctx *)ctx;
  46. if (thread_ctx)
  47. free(thread_ctx);
  48. }
  49. static int jent_notime_start(void *ctx,
  50. void *(*start_routine) (void *), void *arg)
  51. {
  52. struct jent_notime_ctx *thread_ctx = (struct jent_notime_ctx *)ctx;
  53. int ret;
  54. if (!thread_ctx)
  55. return -EINVAL;
  56. ret = -pthread_attr_init(&thread_ctx->notime_pthread_attr);
  57. if (ret)
  58. return ret;
  59. return -pthread_create(&thread_ctx->notime_thread_id,
  60. &thread_ctx->notime_pthread_attr,
  61. start_routine, arg);
  62. }
  63. static void jent_notime_stop(void *ctx)
  64. {
  65. struct jent_notime_ctx *thread_ctx = (struct jent_notime_ctx *)ctx;
  66. pthread_join(thread_ctx->notime_thread_id, NULL);
  67. pthread_attr_destroy(&thread_ctx->notime_pthread_attr);
  68. }
  69. static struct jent_notime_thread jent_notime_thread_builtin = {
  70. .jent_notime_init = jent_notime_init,
  71. .jent_notime_fini = jent_notime_fini,
  72. .jent_notime_start = jent_notime_start,
  73. .jent_notime_stop = jent_notime_stop
  74. };
  75. /***************************************************************************
  76. * Timer-less timer replacement
  77. *
  78. * If there is no high-resolution hardware timer available, we create one
  79. * ourselves. This logic is only used when the initialization identifies
  80. * that no suitable time source is available.
  81. ***************************************************************************/
  82. static int jent_force_internal_timer = 0;
  83. static int jent_notime_switch_blocked = 0;
  84. void jent_notime_block_switch(void)
  85. {
  86. jent_notime_switch_blocked = 1;
  87. }
  88. static struct jent_notime_thread *notime_thread = &jent_notime_thread_builtin;
  89. /**
  90. * Timer-replacement loop
  91. *
  92. * @brief The measurement loop triggers the read of the value from the
  93. * counter function. It conceptually acts as the low resolution
  94. * samples timer from a ring oscillator.
  95. */
  96. static void *jent_notime_sample_timer(void *arg)
  97. {
  98. struct rand_data *ec = (struct rand_data *)arg;
  99. ec->notime_timer = 0;
  100. while (1) {
  101. if (ec->notime_interrupt)
  102. return NULL;
  103. ec->notime_timer++;
  104. }
  105. return NULL;
  106. }
  107. /*
  108. * Enable the clock: spawn a new thread that holds a counter.
  109. *
  110. * Note, although creating a thread is expensive, we do that every time a
  111. * caller wants entropy from us and terminate the thread afterwards. This
  112. * is to ensure an attacker cannot easily identify the ticking thread.
  113. */
  114. int jent_notime_settick(struct rand_data *ec)
  115. {
  116. if (!ec->enable_notime || !notime_thread)
  117. return 0;
  118. ec->notime_interrupt = 0;
  119. ec->notime_prev_timer = 0;
  120. ec->notime_timer = 0;
  121. return notime_thread->jent_notime_start(ec->notime_thread_ctx,
  122. jent_notime_sample_timer, ec);
  123. }
  124. void jent_notime_unsettick(struct rand_data *ec)
  125. {
  126. if (!ec->enable_notime || !notime_thread)
  127. return;
  128. ec->notime_interrupt = 1;
  129. notime_thread->jent_notime_stop(ec->notime_thread_ctx);
  130. }
  131. void jent_get_nstime_internal(struct rand_data *ec, uint64_t *out)
  132. {
  133. if (ec->enable_notime) {
  134. /*
  135. * Allow the counting thread to be initialized and guarantee
  136. * that it ticked since last time we looked.
  137. *
  138. * Note, we do not use an atomic operation here for reading
  139. * jent_notime_timer since if this integer is garbled, it even
  140. * adds to entropy. But on most architectures, read/write
  141. * of an uint64_t should be atomic anyway.
  142. */
  143. while (ec->notime_timer == ec->notime_prev_timer)
  144. jent_yield();
  145. ec->notime_prev_timer = ec->notime_timer;
  146. *out = ec->notime_prev_timer;
  147. } else {
  148. jent_get_nstime(out);
  149. }
  150. }
  151. static inline int jent_notime_enable_thread(struct rand_data *ec)
  152. {
  153. if (notime_thread)
  154. return notime_thread->jent_notime_init(&ec->notime_thread_ctx);
  155. return 0;
  156. }
  157. void jent_notime_disable(struct rand_data *ec)
  158. {
  159. if (notime_thread)
  160. notime_thread->jent_notime_fini(ec->notime_thread_ctx);
  161. }
  162. int jent_notime_enable(struct rand_data *ec, unsigned int flags)
  163. {
  164. /* Use internal timer */
  165. if (jent_force_internal_timer || (flags & JENT_FORCE_INTERNAL_TIMER)) {
  166. /* Self test not run yet */
  167. if (!jent_force_internal_timer &&
  168. jent_time_entropy_init(ec->osr,
  169. flags | JENT_FORCE_INTERNAL_TIMER))
  170. return EHEALTH;
  171. ec->enable_notime = 1;
  172. return jent_notime_enable_thread(ec);
  173. }
  174. return 0;
  175. }
  176. int jent_notime_switch(struct jent_notime_thread *new_thread)
  177. {
  178. if (jent_notime_switch_blocked)
  179. return -EAGAIN;
  180. notime_thread = new_thread;
  181. return 0;
  182. }
  183. void jent_notime_force(void)
  184. {
  185. jent_force_internal_timer = 1;
  186. }
  187. int jent_notime_forced(void)
  188. {
  189. return jent_force_internal_timer;
  190. }
  191. #endif /* JENT_CONF_ENABLE_INTERNAL_TIMER */