2 * QEMU guest-visible random functions
4 * Copyright 2019 Linaro, Ltd.
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)
12 #include "qemu/osdep.h"
13 #include "qemu/cutils.h"
14 #include "qapi/error.h"
15 #include "qemu/guest-random.h"
16 #include "crypto/random.h"
17 #include "sysemu/replay.h"
20 static __thread GRand
*thread_rand
;
21 static bool deterministic
;
24 static int glib_random_bytes(void *buf
, size_t len
)
26 GRand
*rand
= thread_rand
;
30 if (unlikely(rand
== NULL
)) {
31 /* Thread not initialized for a cpu, or main w/o -seed. */
32 thread_rand
= rand
= g_rand_new();
35 for (i
= 0; i
+ 4 <= len
; i
+= 4) {
37 __builtin_memcpy(buf
+ i
, &x
, 4);
41 __builtin_memcpy(buf
+ i
, &x
, i
- len
);
46 int qemu_guest_getrandom(void *buf
, size_t len
, Error
**errp
)
49 if (replay_mode
== REPLAY_MODE_PLAY
) {
50 return replay_read_random(buf
, len
);
52 if (unlikely(deterministic
)) {
53 /* Deterministic implementation using Glib's Mersenne Twister. */
54 ret
= glib_random_bytes(buf
, len
);
56 /* Non-deterministic implementation using crypto routines. */
57 ret
= qcrypto_random_bytes(buf
, len
, errp
);
59 if (replay_mode
== REPLAY_MODE_RECORD
) {
60 replay_save_random(ret
, buf
, len
);
65 void qemu_guest_getrandom_nofail(void *buf
, size_t len
)
67 (void)qemu_guest_getrandom(buf
, len
, &error_fatal
);
70 uint64_t qemu_guest_random_seed_thread_part1(void)
74 glib_random_bytes(&ret
, sizeof(ret
));
80 void qemu_guest_random_seed_thread_part2(uint64_t seed
)
82 g_assert(thread_rand
== NULL
);
85 g_rand_new_with_seed_array((const guint32
*)&seed
,
86 sizeof(seed
) / sizeof(guint32
));
90 int qemu_guest_random_seed_main(const char *optarg
, Error
**errp
)
92 unsigned long long seed
;
93 if (parse_uint_full(optarg
, &seed
, 0)) {
94 error_setg(errp
, "Invalid seed number: %s", optarg
);
98 qemu_guest_random_seed_thread_part2(seed
);