yading@11: /* yading@11: * Copyright (c) 2009 Baptiste Coudurier yading@11: * yading@11: * This file is part of FFmpeg. yading@11: * yading@11: * FFmpeg is free software; you can redistribute it and/or yading@11: * modify it under the terms of the GNU Lesser General Public yading@11: * License as published by the Free Software Foundation; either yading@11: * version 2.1 of the License, or (at your option) any later version. yading@11: * yading@11: * FFmpeg is distributed in the hope that it will be useful, yading@11: * but WITHOUT ANY WARRANTY; without even the implied warranty of yading@11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU yading@11: * Lesser General Public License for more details. yading@11: * yading@11: * You should have received a copy of the GNU Lesser General Public yading@11: * License along with FFmpeg; if not, write to the Free Software yading@11: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA yading@11: */ yading@11: yading@11: #include "config.h" yading@11: yading@11: #if HAVE_UNISTD_H yading@11: #include yading@11: #endif yading@11: #if HAVE_CRYPTGENRANDOM yading@11: #include yading@11: #include yading@11: #endif yading@11: #include yading@11: #include yading@11: #include yading@11: #include yading@11: #include "avassert.h" yading@11: #include "timer.h" yading@11: #include "random_seed.h" yading@11: #include "sha.h" yading@11: #include "intreadwrite.h" yading@11: yading@11: #ifndef TEST yading@11: #define TEST 0 yading@11: #endif yading@11: yading@11: static int read_random(uint32_t *dst, const char *file) yading@11: { yading@11: #if HAVE_UNISTD_H yading@11: int fd = open(file, O_RDONLY); yading@11: int err = -1; yading@11: yading@11: if (fd == -1) yading@11: return -1; yading@11: err = read(fd, dst, sizeof(*dst)); yading@11: close(fd); yading@11: yading@11: return err; yading@11: #else yading@11: return -1; yading@11: #endif yading@11: } yading@11: yading@11: static uint32_t get_generic_seed(void) yading@11: { yading@11: uint8_t tmp[120]; yading@11: struct AVSHA *sha = (void*)tmp; yading@11: clock_t last_t = 0; yading@11: static uint64_t i = 0; yading@11: static uint32_t buffer[512] = {0}; yading@11: unsigned char digest[20]; yading@11: uint64_t last_i = i; yading@11: yading@11: av_assert0(sizeof(tmp) >= av_sha_size); yading@11: yading@11: if(TEST){ yading@11: memset(buffer, 0, sizeof(buffer)); yading@11: last_i = i = 0; yading@11: }else{ yading@11: #ifdef AV_READ_TIME yading@11: buffer[13] ^= AV_READ_TIME(); yading@11: buffer[41] ^= AV_READ_TIME()>>32; yading@11: #endif yading@11: } yading@11: yading@11: for (;;) { yading@11: clock_t t = clock(); yading@11: yading@11: if(last_t == t){ yading@11: buffer[i&511]++; yading@11: }else{ yading@11: buffer[++i&511]+= (t-last_t) % 3294638521U; yading@11: if(last_i && i-last_i > 4 || i-last_i > 64 || TEST && i-last_i > 8) yading@11: break; yading@11: } yading@11: last_t = t; yading@11: } yading@11: yading@11: if(TEST) yading@11: buffer[0] = buffer[1] = 0; yading@11: yading@11: av_sha_init(sha, 160); yading@11: av_sha_update(sha, (uint8_t*)buffer, sizeof(buffer)); yading@11: av_sha_final(sha, digest); yading@11: return AV_RB32(digest) + AV_RB32(digest+16); yading@11: } yading@11: yading@11: uint32_t av_get_random_seed(void) yading@11: { yading@11: uint32_t seed; yading@11: yading@11: #if HAVE_CRYPTGENRANDOM yading@11: HCRYPTPROV provider; yading@11: if (CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, yading@11: CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { yading@11: BOOL ret = CryptGenRandom(provider, sizeof(seed), (PBYTE) &seed); yading@11: CryptReleaseContext(provider, 0); yading@11: if (ret) yading@11: return seed; yading@11: } yading@11: #endif yading@11: yading@11: if (read_random(&seed, "/dev/urandom") == sizeof(seed)) yading@11: return seed; yading@11: if (read_random(&seed, "/dev/random") == sizeof(seed)) yading@11: return seed; yading@11: return get_generic_seed(); yading@11: } yading@11: yading@11: #if TEST yading@11: #undef printf yading@11: #define N 256 yading@11: #include yading@11: yading@11: int main(void) yading@11: { yading@11: int i, j, retry; yading@11: uint32_t seeds[N]; yading@11: yading@11: for (retry=0; retry<3; retry++){ yading@11: for (i=0; i