guest-random.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  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. #include "exec/replay-core.h"
  17. static __thread GRand *thread_rand;
  18. static bool deterministic;
  19. static int glib_random_bytes(void *buf, size_t len)
  20. {
  21. GRand *rand = thread_rand;
  22. size_t i;
  23. uint32_t x;
  24. if (unlikely(rand == NULL)) {
  25. /* Thread not initialized for a cpu, or main w/o -seed. */
  26. thread_rand = rand = g_rand_new();
  27. }
  28. for (i = 0; i + 4 <= len; i += 4) {
  29. x = g_rand_int(rand);
  30. __builtin_memcpy(buf + i, &x, 4);
  31. }
  32. if (i < len) {
  33. x = g_rand_int(rand);
  34. __builtin_memcpy(buf + i, &x, len - i);
  35. }
  36. return 0;
  37. }
  38. int qemu_guest_getrandom(void *buf, size_t len, Error **errp)
  39. {
  40. int ret;
  41. if (replay_mode == REPLAY_MODE_PLAY) {
  42. return replay_read_random(buf, len);
  43. }
  44. if (unlikely(deterministic)) {
  45. /* Deterministic implementation using Glib's Mersenne Twister. */
  46. ret = glib_random_bytes(buf, len);
  47. } else {
  48. /* Non-deterministic implementation using crypto routines. */
  49. ret = qcrypto_random_bytes(buf, len, errp);
  50. }
  51. if (replay_mode == REPLAY_MODE_RECORD) {
  52. replay_save_random(ret, buf, len);
  53. }
  54. return ret;
  55. }
  56. void qemu_guest_getrandom_nofail(void *buf, size_t len)
  57. {
  58. (void)qemu_guest_getrandom(buf, len, &error_fatal);
  59. }
  60. uint64_t qemu_guest_random_seed_thread_part1(void)
  61. {
  62. if (deterministic) {
  63. uint64_t ret;
  64. glib_random_bytes(&ret, sizeof(ret));
  65. return ret;
  66. }
  67. return 0;
  68. }
  69. void qemu_guest_random_seed_thread_part2(uint64_t seed)
  70. {
  71. g_assert(thread_rand == NULL);
  72. if (deterministic) {
  73. thread_rand =
  74. g_rand_new_with_seed_array((const guint32 *)&seed,
  75. sizeof(seed) / sizeof(guint32));
  76. }
  77. }
  78. int qemu_guest_random_seed_main(const char *optarg, Error **errp)
  79. {
  80. unsigned long long seed;
  81. if (parse_uint_full(optarg, &seed, 0)) {
  82. error_setg(errp, "Invalid seed number: %s", optarg);
  83. return -1;
  84. } else {
  85. deterministic = true;
  86. qemu_guest_random_seed_thread_part2(seed);
  87. return 0;
  88. }
  89. }