00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "config.h"
00022
00023 #if HAVE_UNISTD_H
00024 #include <unistd.h>
00025 #endif
00026 #include <fcntl.h>
00027 #include <math.h>
00028 #include <time.h>
00029 #include <string.h>
00030 #include "avassert.h"
00031 #include "timer.h"
00032 #include "random_seed.h"
00033 #include "sha.h"
00034 #include "intreadwrite.h"
00035
00036 #ifndef TEST
00037 #define TEST 0
00038 #endif
00039
00040 static int read_random(uint32_t *dst, const char *file)
00041 {
00042 #if HAVE_UNISTD_H
00043 int fd = open(file, O_RDONLY);
00044 int err = -1;
00045
00046 if (fd == -1)
00047 return -1;
00048 err = read(fd, dst, sizeof(*dst));
00049 close(fd);
00050
00051 return err;
00052 #else
00053 return -1;
00054 #endif
00055 }
00056
00057 static uint32_t get_generic_seed(void)
00058 {
00059 uint8_t tmp[120];
00060 struct AVSHA *sha = (void*)tmp;
00061 clock_t last_t = 0;
00062 static uint64_t i = 0;
00063 static uint32_t buffer[512] = {0};
00064 unsigned char digest[32];
00065 uint64_t last_i = i;
00066
00067 av_assert0(sizeof(tmp) >= av_sha_size);
00068
00069 if(TEST){
00070 memset(buffer, 0, sizeof(buffer));
00071 last_i = i = 0;
00072 }else{
00073 #ifdef AV_READ_TIME
00074 buffer[13] ^= AV_READ_TIME();
00075 buffer[41] ^= AV_READ_TIME()>>32;
00076 #endif
00077 }
00078
00079 for (;;) {
00080 clock_t t = clock();
00081
00082 if(last_t == t){
00083 buffer[i&511]++;
00084 }else{
00085 buffer[++i&511]+= (t-last_t) % 3294638521U;
00086 if(last_i && i-last_i > 4 || i-last_i > 64 || TEST && i-last_i > 8)
00087 break;
00088 }
00089 last_t = t;
00090 }
00091
00092 if(TEST)
00093 buffer[0] = buffer[1] = 0;
00094
00095 av_sha_init(sha, 160);
00096 av_sha_update(sha, (uint8_t*)buffer, sizeof(buffer));
00097 av_sha_final(sha, digest);
00098 return AV_RB32(digest) + AV_RB32(digest+32);
00099 }
00100
00101 uint32_t av_get_random_seed(void)
00102 {
00103 uint32_t seed;
00104
00105 if (read_random(&seed, "/dev/urandom") == sizeof(seed))
00106 return seed;
00107 if (read_random(&seed, "/dev/random") == sizeof(seed))
00108 return seed;
00109 return get_generic_seed();
00110 }
00111
00112 #if TEST
00113 #undef printf
00114 #define N 256
00115 #include <stdio.h>
00116
00117 int main(void)
00118 {
00119 int i, j, retry;
00120 uint32_t seeds[N];
00121
00122 for (retry=0; retry<3; retry++){
00123 for (i=0; i<N; i++){
00124 seeds[i] = av_get_random_seed();
00125 for (j=0; j<i; j++)
00126 if (seeds[j] == seeds[i])
00127 goto retry;
00128 }
00129 printf("seeds OK\n");
00130 return 0;
00131 retry:;
00132 }
00133 printf("FAIL at %d with %X\n", j, seeds[j]);
00134 return 1;
00135 }
00136 #endif