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