cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

guest-random.c (2578B)


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