Branch data Line data Source code
1 : : /***
2 : : This file is part of PulseAudio.
3 : :
4 : : Copyright 2004-2006 Lennart Poettering
5 : : Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6 : :
7 : : PulseAudio is free software; you can redistribute it and/or modify
8 : : it under the terms of the GNU Lesser General Public License as
9 : : published by the Free Software Foundation; either version 2.1 of the
10 : : License, or (at your option) any later version.
11 : :
12 : : PulseAudio is distributed in the hope that it will be useful, but
13 : : WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : : Lesser General Public License for more details.
16 : :
17 : : You should have received a copy of the GNU Lesser General Public
18 : : License along with PulseAudio; if not, write to the Free Software
19 : : Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 : : USA.
21 : : ***/
22 : :
23 : : #ifdef HAVE_CONFIG_H
24 : : #include <config.h>
25 : : #endif
26 : :
27 : : #include <fcntl.h>
28 : : #include <unistd.h>
29 : : #include <errno.h>
30 : : #include <stdlib.h>
31 : : #include <time.h>
32 : :
33 : : #ifdef HAVE_WINDOWS_H
34 : : #include <windows.h>
35 : : #include <wincrypt.h>
36 : : #endif
37 : :
38 : : #include <pulsecore/core-util.h>
39 : : #include <pulsecore/log.h>
40 : : #include <pulsecore/macro.h>
41 : :
42 : : #include "random.h"
43 : :
44 : : static pa_bool_t has_whined = FALSE;
45 : :
46 : : static const char * const devices[] = { "/dev/urandom", "/dev/random", NULL };
47 : :
48 : 3 : static int random_proper(void *ret_data, size_t length) {
49 : : #ifdef OS_IS_WIN32
50 : : int ret = -1;
51 : :
52 : : HCRYPTPROV hCryptProv = 0;
53 : :
54 : : pa_assert(ret_data);
55 : : pa_assert(length > 0);
56 : :
57 : : if (CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
58 : : if(CryptGenRandom(hCryptProv, length, ret_data))
59 : : ret = 0;
60 : : CryptReleaseContext(hCryptProv, 0);
61 : : }
62 : :
63 : : return ret;
64 : :
65 : : #else /* OS_IS_WIN32 */
66 : :
67 : 3 : int fd, ret = -1;
68 : 3 : ssize_t r = 0;
69 : : const char *const * device;
70 : :
71 [ - + ]: 3 : pa_assert(ret_data);
72 [ + - ]: 3 : pa_assert(length > 0);
73 : :
74 : : device = devices;
75 : :
76 [ + - ]: 3 : while (*device) {
77 : 3 : ret = 0;
78 : :
79 [ + - ]: 3 : if ((fd = pa_open_cloexec(*device, O_RDONLY, 0)) >= 0) {
80 : :
81 [ + - ][ - + ]: 3 : if ((r = pa_loop_read(fd, ret_data, length, NULL)) < 0 || (size_t) r != length)
82 : 0 : ret = -1;
83 : :
84 : 3 : pa_close(fd);
85 : : } else
86 : : ret = -1;
87 : :
88 [ - + ]: 3 : if (ret == 0)
89 : : break;
90 : :
91 : 0 : device++;
92 : : }
93 : :
94 : 3 : return ret;
95 : : #endif /* OS_IS_WIN32 */
96 : : }
97 : :
98 : 0 : void pa_random_seed(void) {
99 : : unsigned int seed;
100 : :
101 [ # # ]: 0 : if (random_proper(&seed, sizeof(unsigned int)) < 0) {
102 : :
103 [ # # ]: 0 : if (!has_whined) {
104 : 0 : pa_log_warn("Failed to get proper entropy. Falling back to seeding with current time.");
105 : 0 : has_whined = TRUE;
106 : : }
107 : :
108 : 0 : seed = (unsigned int) time(NULL);
109 : : }
110 : :
111 : 0 : srand(seed);
112 : 0 : }
113 : :
114 : 3 : void pa_random(void *ret_data, size_t length) {
115 : : uint8_t *p;
116 : : size_t l;
117 : :
118 [ - + ]: 3 : pa_assert(ret_data);
119 [ - + ]: 3 : pa_assert(length > 0);
120 : :
121 [ - + ]: 3 : if (random_proper(ret_data, length) >= 0)
122 : 3 : return;
123 : :
124 [ # # ]: 0 : if (!has_whined) {
125 : 0 : pa_log_warn("Failed to get proper entropy. Falling back to unsecure pseudo RNG.");
126 : 0 : has_whined = TRUE;
127 : : }
128 : :
129 [ # # ]: 0 : for (p = ret_data, l = length; l > 0; p++, l--)
130 : 0 : *p = (uint8_t) rand();
131 : : }
|