153a5a1b3Sopenharmony_ci/*** 253a5a1b3Sopenharmony_ci This file is part of PulseAudio. 353a5a1b3Sopenharmony_ci 453a5a1b3Sopenharmony_ci Copyright 2004-2006 Lennart Poettering 553a5a1b3Sopenharmony_ci Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB 653a5a1b3Sopenharmony_ci 753a5a1b3Sopenharmony_ci PulseAudio is free software; you can redistribute it and/or modify 853a5a1b3Sopenharmony_ci it under the terms of the GNU Lesser General Public License as 953a5a1b3Sopenharmony_ci published by the Free Software Foundation; either version 2.1 of the 1053a5a1b3Sopenharmony_ci License, or (at your option) any later version. 1153a5a1b3Sopenharmony_ci 1253a5a1b3Sopenharmony_ci PulseAudio is distributed in the hope that it will be useful, but 1353a5a1b3Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 1453a5a1b3Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1553a5a1b3Sopenharmony_ci Lesser General Public License for more details. 1653a5a1b3Sopenharmony_ci 1753a5a1b3Sopenharmony_ci You should have received a copy of the GNU Lesser General Public 1853a5a1b3Sopenharmony_ci License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. 1953a5a1b3Sopenharmony_ci***/ 2053a5a1b3Sopenharmony_ci 2153a5a1b3Sopenharmony_ci#ifdef HAVE_CONFIG_H 2253a5a1b3Sopenharmony_ci#include <config.h> 2353a5a1b3Sopenharmony_ci#endif 2453a5a1b3Sopenharmony_ci 2553a5a1b3Sopenharmony_ci#include <fcntl.h> 2653a5a1b3Sopenharmony_ci#include <unistd.h> 2753a5a1b3Sopenharmony_ci#include <errno.h> 2853a5a1b3Sopenharmony_ci#include <stdlib.h> 2953a5a1b3Sopenharmony_ci#include <time.h> 3053a5a1b3Sopenharmony_ci 3153a5a1b3Sopenharmony_ci#ifdef HAVE_WINDOWS_H 3253a5a1b3Sopenharmony_ci#include <windows.h> 3353a5a1b3Sopenharmony_ci#include <wincrypt.h> 3453a5a1b3Sopenharmony_ci#endif 3553a5a1b3Sopenharmony_ci 3653a5a1b3Sopenharmony_ci#include <pulsecore/core-util.h> 3753a5a1b3Sopenharmony_ci#include <pulsecore/log.h> 3853a5a1b3Sopenharmony_ci#include <pulsecore/macro.h> 3953a5a1b3Sopenharmony_ci 4053a5a1b3Sopenharmony_ci#include "random.h" 4153a5a1b3Sopenharmony_ci 4253a5a1b3Sopenharmony_cistatic bool has_whined = false; 4353a5a1b3Sopenharmony_ci 4453a5a1b3Sopenharmony_cistatic const char * const devices[] = { "/dev/urandom", "/dev/random", NULL }; 4553a5a1b3Sopenharmony_ci 4653a5a1b3Sopenharmony_cistatic int random_proper(void *ret_data, size_t length) { 4753a5a1b3Sopenharmony_ci#ifdef OS_IS_WIN32 4853a5a1b3Sopenharmony_ci int ret = -1; 4953a5a1b3Sopenharmony_ci 5053a5a1b3Sopenharmony_ci HCRYPTPROV hCryptProv = 0; 5153a5a1b3Sopenharmony_ci 5253a5a1b3Sopenharmony_ci pa_assert(ret_data); 5353a5a1b3Sopenharmony_ci pa_assert(length > 0); 5453a5a1b3Sopenharmony_ci 5553a5a1b3Sopenharmony_ci if (CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { 5653a5a1b3Sopenharmony_ci if (CryptGenRandom(hCryptProv, length, ret_data)) 5753a5a1b3Sopenharmony_ci ret = 0; 5853a5a1b3Sopenharmony_ci CryptReleaseContext(hCryptProv, 0); 5953a5a1b3Sopenharmony_ci } 6053a5a1b3Sopenharmony_ci 6153a5a1b3Sopenharmony_ci return ret; 6253a5a1b3Sopenharmony_ci 6353a5a1b3Sopenharmony_ci#else /* OS_IS_WIN32 */ 6453a5a1b3Sopenharmony_ci 6553a5a1b3Sopenharmony_ci int fd, ret = -1; 6653a5a1b3Sopenharmony_ci ssize_t r = 0; 6753a5a1b3Sopenharmony_ci const char *const * device; 6853a5a1b3Sopenharmony_ci 6953a5a1b3Sopenharmony_ci pa_assert(ret_data); 7053a5a1b3Sopenharmony_ci pa_assert(length > 0); 7153a5a1b3Sopenharmony_ci 7253a5a1b3Sopenharmony_ci device = devices; 7353a5a1b3Sopenharmony_ci 7453a5a1b3Sopenharmony_ci while (*device) { 7553a5a1b3Sopenharmony_ci ret = 0; 7653a5a1b3Sopenharmony_ci 7753a5a1b3Sopenharmony_ci if ((fd = pa_open_cloexec(*device, O_RDONLY, 0)) >= 0) { 7853a5a1b3Sopenharmony_ci 7953a5a1b3Sopenharmony_ci if ((r = pa_loop_read(fd, ret_data, length, NULL)) < 0 || (size_t) r != length) 8053a5a1b3Sopenharmony_ci ret = -1; 8153a5a1b3Sopenharmony_ci 8253a5a1b3Sopenharmony_ci pa_close(fd); 8353a5a1b3Sopenharmony_ci } else 8453a5a1b3Sopenharmony_ci ret = -1; 8553a5a1b3Sopenharmony_ci 8653a5a1b3Sopenharmony_ci if (ret == 0) 8753a5a1b3Sopenharmony_ci break; 8853a5a1b3Sopenharmony_ci 8953a5a1b3Sopenharmony_ci device++; 9053a5a1b3Sopenharmony_ci } 9153a5a1b3Sopenharmony_ci 9253a5a1b3Sopenharmony_ci return ret; 9353a5a1b3Sopenharmony_ci#endif /* OS_IS_WIN32 */ 9453a5a1b3Sopenharmony_ci} 9553a5a1b3Sopenharmony_ci 9653a5a1b3Sopenharmony_civoid pa_random_seed(void) { 9753a5a1b3Sopenharmony_ci unsigned int seed; 9853a5a1b3Sopenharmony_ci 9953a5a1b3Sopenharmony_ci if (random_proper(&seed, sizeof(unsigned int)) < 0) { 10053a5a1b3Sopenharmony_ci 10153a5a1b3Sopenharmony_ci if (!has_whined) { 10253a5a1b3Sopenharmony_ci pa_log_warn("Failed to get proper entropy. Falling back to seeding with current time."); 10353a5a1b3Sopenharmony_ci has_whined = true; 10453a5a1b3Sopenharmony_ci } 10553a5a1b3Sopenharmony_ci 10653a5a1b3Sopenharmony_ci seed = (unsigned int) time(NULL); 10753a5a1b3Sopenharmony_ci } 10853a5a1b3Sopenharmony_ci 10953a5a1b3Sopenharmony_ci srand(seed); 11053a5a1b3Sopenharmony_ci} 11153a5a1b3Sopenharmony_ci 11253a5a1b3Sopenharmony_civoid pa_random(void *ret_data, size_t length) { 11353a5a1b3Sopenharmony_ci uint8_t *p; 11453a5a1b3Sopenharmony_ci size_t l; 11553a5a1b3Sopenharmony_ci 11653a5a1b3Sopenharmony_ci pa_assert(ret_data); 11753a5a1b3Sopenharmony_ci pa_assert(length > 0); 11853a5a1b3Sopenharmony_ci 11953a5a1b3Sopenharmony_ci if (random_proper(ret_data, length) >= 0) 12053a5a1b3Sopenharmony_ci return; 12153a5a1b3Sopenharmony_ci 12253a5a1b3Sopenharmony_ci if (!has_whined) { 12353a5a1b3Sopenharmony_ci pa_log_warn("Failed to get proper entropy. Falling back to unsecure pseudo RNG."); 12453a5a1b3Sopenharmony_ci has_whined = true; 12553a5a1b3Sopenharmony_ci } 12653a5a1b3Sopenharmony_ci 12753a5a1b3Sopenharmony_ci for (p = ret_data, l = length; l > 0; p++, l--) 12853a5a1b3Sopenharmony_ci *p = (uint8_t) rand(); 12953a5a1b3Sopenharmony_ci} 130