Coverage Report

Created: 2025-07-01 06:54

/work/mbedtls-2.28.8/library/entropy_poll.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 *  Platform-specific and custom entropy polling functions
3
 *
4
 *  Copyright The Mbed TLS Contributors
5
 *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6
 */
7
8
#if defined(__linux__) || defined(__midipix__) && !defined(_GNU_SOURCE)
9
/* Ensure that syscall() is available even when compiling with -std=c99 */
10
#define _GNU_SOURCE
11
#endif
12
13
#include "common.h"
14
15
#include <string.h>
16
17
#if defined(MBEDTLS_ENTROPY_C)
18
19
#include "mbedtls/entropy.h"
20
#include "mbedtls/entropy_poll.h"
21
#include "mbedtls/error.h"
22
23
#if defined(MBEDTLS_TIMING_C)
24
#include "mbedtls/timing.h"
25
#endif
26
#if defined(MBEDTLS_HAVEGE_C)
27
#include "mbedtls/havege.h"
28
#endif
29
#include "mbedtls/platform.h"
30
31
#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
32
33
#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
34
    !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \
35
    !defined(__HAIKU__) && !defined(__midipix__)
36
#error \
37
    "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in config.h"
38
#endif
39
40
#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
41
42
#if !defined(_WIN32_WINNT)
43
#define _WIN32_WINNT 0x0400
44
#endif
45
#include <windows.h>
46
#include <wincrypt.h>
47
48
int mbedtls_platform_entropy_poll(void *data, unsigned char *output, size_t len,
49
                                  size_t *olen)
50
{
51
    HCRYPTPROV provider;
52
    ((void) data);
53
    *olen = 0;
54
55
    if (CryptAcquireContext(&provider, NULL, NULL,
56
                            PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) == FALSE) {
57
        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
58
    }
59
60
    if (CryptGenRandom(provider, (DWORD) len, output) == FALSE) {
61
        CryptReleaseContext(provider, 0);
62
        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
63
    }
64
65
    CryptReleaseContext(provider, 0);
66
    *olen = len;
67
68
    return 0;
69
}
70
#else /* _WIN32 && !EFIX64 && !EFI32 */
71
72
/*
73
 * Test for Linux getrandom() support.
74
 * Since there is no wrapper in the libc yet, use the generic syscall wrapper
75
 * available in GNU libc and compatible libc's (eg uClibc).
76
 */
77
#if ((defined(__linux__) && defined(__GLIBC__)) || defined(__midipix__))
78
#include <unistd.h>
79
#include <sys/syscall.h>
80
#if defined(SYS_getrandom)
81
#define HAVE_GETRANDOM
82
#include <errno.h>
83
84
static int getrandom_wrapper(void *buf, size_t buflen, unsigned int flags)
85
0
{
86
    /* MemSan cannot understand that the syscall writes to the buffer */
87
0
#if defined(__has_feature)
88
#if __has_feature(memory_sanitizer)
89
    memset(buf, 0, buflen);
90
#endif
91
0
#endif
92
0
    return syscall(SYS_getrandom, buf, buflen, flags);
93
0
}
94
#endif /* SYS_getrandom */
95
#endif /* __linux__ || __midipix__ */
96
97
#if defined(__FreeBSD__) || defined(__DragonFly__)
98
#include <sys/param.h>
99
#if (defined(__FreeBSD__) && __FreeBSD_version >= 1200000) || \
100
    (defined(__DragonFly__) && __DragonFly_version >= 500700)
101
#include <errno.h>
102
#include <sys/random.h>
103
#define HAVE_GETRANDOM
104
static int getrandom_wrapper(void *buf, size_t buflen, unsigned int flags)
105
{
106
    return getrandom(buf, buflen, flags);
107
}
108
#endif /* (__FreeBSD__ && __FreeBSD_version >= 1200000) ||
109
          (__DragonFly__ && __DragonFly_version >= 500700) */
110
#endif /* __FreeBSD__ || __DragonFly__ */
111
112
/*
113
 * Some BSD systems provide KERN_ARND.
114
 * This is equivalent to reading from /dev/urandom, only it doesn't require an
115
 * open file descriptor, and provides up to 256 bytes per call (basically the
116
 * same as getentropy(), but with a longer history).
117
 *
118
 * Documentation: https://netbsd.gw.com/cgi-bin/man-cgi?sysctl+7
119
 */
120
#if (defined(__FreeBSD__) || defined(__NetBSD__)) && !defined(HAVE_GETRANDOM)
121
#include <sys/param.h>
122
#include <sys/sysctl.h>
123
#if defined(KERN_ARND)
124
#define HAVE_SYSCTL_ARND
125
126
static int sysctl_arnd_wrapper(unsigned char *buf, size_t buflen)
127
{
128
    int name[2];
129
    size_t len;
130
131
    name[0] = CTL_KERN;
132
    name[1] = KERN_ARND;
133
134
    while (buflen > 0) {
135
        len = buflen > 256 ? 256 : buflen;
136
        if (sysctl(name, 2, buf, &len, NULL, 0) == -1) {
137
            return -1;
138
        }
139
        buflen -= len;
140
        buf += len;
141
    }
142
    return 0;
143
}
144
#endif /* KERN_ARND */
145
#endif /* __FreeBSD__ || __NetBSD__ */
146
147
#include <stdio.h>
148
149
int mbedtls_platform_entropy_poll(void *data,
150
                                  unsigned char *output, size_t len, size_t *olen)
151
0
{
152
0
    FILE *file;
153
0
    size_t read_len;
154
0
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
155
0
    ((void) data);
156
157
0
#if defined(HAVE_GETRANDOM)
158
0
    ret = getrandom_wrapper(output, len, 0);
159
0
    if (ret >= 0) {
160
0
        *olen = ret;
161
0
        return 0;
162
0
    } else if (errno != ENOSYS) {
163
0
        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
164
0
    }
165
    /* Fall through if the system call isn't known. */
166
#else
167
    ((void) ret);
168
#endif /* HAVE_GETRANDOM */
169
170
#if defined(HAVE_SYSCTL_ARND)
171
    ((void) file);
172
    ((void) read_len);
173
    if (sysctl_arnd_wrapper(output, len) == -1) {
174
        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
175
    }
176
    *olen = len;
177
    return 0;
178
#else
179
180
0
    *olen = 0;
181
182
0
    file = fopen("/dev/urandom", "rb");
183
0
    if (file == NULL) {
184
0
        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
185
0
    }
186
187
0
    read_len = fread(output, 1, len, file);
188
0
    if (read_len != len) {
189
0
        fclose(file);
190
0
        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
191
0
    }
192
193
0
    fclose(file);
194
0
    *olen = len;
195
196
0
    return 0;
197
0
#endif /* HAVE_SYSCTL_ARND */
198
0
}
199
#endif /* _WIN32 && !EFIX64 && !EFI32 */
200
#endif /* !MBEDTLS_NO_PLATFORM_ENTROPY */
201
202
#if defined(MBEDTLS_TEST_NULL_ENTROPY)
203
int mbedtls_null_entropy_poll(void *data,
204
                              unsigned char *output, size_t len, size_t *olen)
205
{
206
    ((void) data);
207
    ((void) output);
208
209
    *olen = 0;
210
    if (len < sizeof(unsigned char)) {
211
        return 0;
212
    }
213
214
    output[0] = 0;
215
    *olen = sizeof(unsigned char);
216
    return 0;
217
}
218
#endif
219
220
#if defined(MBEDTLS_TIMING_C)
221
int mbedtls_hardclock_poll(void *data,
222
                           unsigned char *output, size_t len, size_t *olen)
223
0
{
224
0
    unsigned long timer = mbedtls_timing_hardclock();
225
0
    ((void) data);
226
0
    *olen = 0;
227
228
0
    if (len < sizeof(unsigned long)) {
229
0
        return 0;
230
0
    }
231
232
0
    memcpy(output, &timer, sizeof(unsigned long));
233
0
    *olen = sizeof(unsigned long);
234
235
0
    return 0;
236
0
}
237
#endif /* MBEDTLS_TIMING_C */
238
239
#if defined(MBEDTLS_HAVEGE_C)
240
int mbedtls_havege_poll(void *data,
241
                        unsigned char *output, size_t len, size_t *olen)
242
{
243
    mbedtls_havege_state *hs = (mbedtls_havege_state *) data;
244
    *olen = 0;
245
246
    if (mbedtls_havege_random(hs, output, len) != 0) {
247
        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
248
    }
249
250
    *olen = len;
251
252
    return 0;
253
}
254
#endif /* MBEDTLS_HAVEGE_C */
255
256
#if defined(MBEDTLS_ENTROPY_NV_SEED)
257
int mbedtls_nv_seed_poll(void *data,
258
                         unsigned char *output, size_t len, size_t *olen)
259
{
260
    unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
261
    size_t use_len = MBEDTLS_ENTROPY_BLOCK_SIZE;
262
    ((void) data);
263
264
    memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);
265
266
    if (mbedtls_nv_seed_read(buf, MBEDTLS_ENTROPY_BLOCK_SIZE) < 0) {
267
        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
268
    }
269
270
    if (len < use_len) {
271
        use_len = len;
272
    }
273
274
    memcpy(output, buf, use_len);
275
    *olen = use_len;
276
277
    return 0;
278
}
279
#endif /* MBEDTLS_ENTROPY_NV_SEED */
280
281
#endif /* MBEDTLS_ENTROPY_C */