aarch64: Add assembly support for -fsanitize=hwaddress tagged globals.
[libav.git] / libavutil / random_seed.c
blob388cb401ba3ece2ec327a2382475df6fa9b4896d
1 /*
2 * Copyright (c) 2009 Baptiste Coudurier <baptiste.coudurier@gmail.com>
4 * This file is part of Libav.
6 * Libav is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * Libav is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Libav; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "config.h"
23 #if HAVE_UNISTD_H
24 #include <unistd.h>
25 #endif
26 #if HAVE_BCRYPT
27 #include <windows.h>
28 #include <bcrypt.h>
29 #endif
30 #include <fcntl.h>
31 #include <math.h>
32 #include <time.h>
33 #include "internal.h"
34 #include "intreadwrite.h"
35 #include "mem.h"
36 #include "timer.h"
37 #include "random_seed.h"
38 #include "sha.h"
40 static int read_random(uint32_t *dst, const char *file)
42 #if HAVE_UNISTD_H
43 int fd = avpriv_open(file, O_RDONLY);
44 int err = -1;
46 if (fd == -1)
47 return -1;
48 err = read(fd, dst, sizeof(*dst));
49 close(fd);
51 return err;
52 #else
53 return -1;
54 #endif
57 static uint32_t get_generic_seed(void)
59 struct AVSHA *sha = av_sha_alloc();
60 clock_t last_t = 0;
61 static uint64_t i = 0;
62 static uint32_t buffer[512] = { 0 };
63 unsigned char digest[20];
64 uint64_t last_i = i;
66 for (;;) {
67 clock_t t = clock();
69 if (last_t == t) {
70 buffer[i & 511]++;
71 } else {
72 buffer[++i & 511] += (t - last_t) % 3294638521U;
73 if (last_i && i - last_i > 4 || i - last_i > 64)
74 break;
76 last_t = t;
79 if (!sha) {
80 uint32_t seed = 0;
81 int j;
82 // Unable to allocate an SHA context, just XOR the buffer together
83 // to create something hopefully unique.
84 for (j = 0; j < 512; j++)
85 seed ^= buffer[j];
86 return seed;
88 av_sha_init(sha, 160);
89 av_sha_update(sha, (const uint8_t *) buffer, sizeof(buffer));
90 av_sha_final(sha, digest);
91 av_free(sha);
92 return AV_RB32(digest) + AV_RB32(digest + 16);
95 uint32_t av_get_random_seed(void)
97 uint32_t seed;
99 #if HAVE_BCRYPT
100 BCRYPT_ALG_HANDLE algo_handle;
101 NTSTATUS ret = BCryptOpenAlgorithmProvider(&algo_handle, BCRYPT_RNG_ALGORITHM,
102 MS_PRIMITIVE_PROVIDER, 0);
103 if (BCRYPT_SUCCESS(ret)) {
104 NTSTATUS ret = BCryptGenRandom(algo_handle, (UCHAR*)&seed, sizeof(seed), 0);
105 BCryptCloseAlgorithmProvider(algo_handle, 0);
106 if (BCRYPT_SUCCESS(ret))
107 return seed;
109 #endif
111 if (read_random(&seed, "/dev/urandom") == sizeof(seed))
112 return seed;
113 if (read_random(&seed, "/dev/random") == sizeof(seed))
114 return seed;
115 return get_generic_seed();