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