2
0

guest-random.c 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. /*
  2. * QEMU guest-visible random functions
  3. *
  4. * Copyright 2019 Linaro, Ltd.
  5. *
  6. * This program is free software; you can redistribute it and/or modify it
  7. * under the terms of the GNU General Public License as published by the Free
  8. * Software Foundation; either version 2 of the License, or (at your option)
  9. * any later version.
  10. */
  11. #include "qemu/osdep.h"
  12. #include "qemu/cutils.h"
  13. #include "qapi/error.h"
  14. #include "qemu/guest-random.h"
  15. #include "crypto/random.h"
  16. static __thread GRand *thread_rand;
  17. static bool deterministic;
  18. static int glib_random_bytes(void *buf, size_t len)
  19. {
  20. GRand *rand = thread_rand;
  21. size_t i;
  22. uint32_t x;
  23. if (unlikely(rand == NULL)) {
  24. /* Thread not initialized for a cpu, or main w/o -seed. */
  25. thread_rand = rand = g_rand_new();
  26. }
  27. for (i = 0; i + 4 <= len; i += 4) {
  28. x = g_rand_int(rand);
  29. __builtin_memcpy(buf + i, &x, 4);
  30. }
  31. if (i < len) {
  32. x = g_rand_int(rand);
  33. __builtin_memcpy(buf + i, &x, i - len);
  34. }
  35. return 0;
  36. }
  37. int qemu_guest_getrandom(void *buf, size_t len, Error **errp)
  38. {
  39. if (unlikely(deterministic)) {
  40. /* Deterministic implementation using Glib's Mersenne Twister. */
  41. return glib_random_bytes(buf, len);
  42. } else {
  43. /* Non-deterministic implementation using crypto routines. */
  44. return qcrypto_random_bytes(buf, len, errp);
  45. }
  46. }
  47. void qemu_guest_getrandom_nofail(void *buf, size_t len)
  48. {
  49. (void)qemu_guest_getrandom(buf, len, &error_fatal);
  50. }
  51. uint64_t qemu_guest_random_seed_thread_part1(void)
  52. {
  53. if (deterministic) {
  54. uint64_t ret;
  55. glib_random_bytes(&ret, sizeof(ret));
  56. return ret;
  57. }
  58. return 0;
  59. }
  60. void qemu_guest_random_seed_thread_part2(uint64_t seed)
  61. {
  62. g_assert(thread_rand == NULL);
  63. if (deterministic) {
  64. thread_rand =
  65. g_rand_new_with_seed_array((const guint32 *)&seed,
  66. sizeof(seed) / sizeof(guint32));
  67. }
  68. }
  69. int qemu_guest_random_seed_main(const char *optarg, Error **errp)
  70. {
  71. unsigned long long seed;
  72. if (parse_uint_full(optarg, &seed, 0)) {
  73. error_setg(errp, "Invalid seed number: %s", optarg);
  74. return -1;
  75. } else {
  76. deterministic = true;
  77. qemu_guest_random_seed_thread_part2(seed);
  78. return 0;
  79. }
  80. }