qemu

Форк
0
/
guest-random.c 
101 строка · 2.5 Кб
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 "exec/replay-core.h"
18

19

20
static __thread GRand *thread_rand;
21
static bool deterministic;
22

23

24
static 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

46
int 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

65
void qemu_guest_getrandom_nofail(void *buf, size_t len)
66
{
67
    (void)qemu_guest_getrandom(buf, len, &error_fatal);
68
}
69

70
uint64_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

80
void 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

90
int qemu_guest_random_seed_main(const char *seedstr, Error **errp)
91
{
92
    uint64_t seed;
93
    if (parse_uint_full(seedstr, 0, &seed)) {
94
        error_setg(errp, "Invalid seed number: %s", seedstr);
95
        return -1;
96
    } else {
97
        deterministic = true;
98
        qemu_guest_random_seed_thread_part2(seed);
99
        return 0;
100
    }
101
}
102

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.