Libav
random_seed.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009 Baptiste Coudurier <baptiste.coudurier@gmail.com>
3  *
4  * This file is part of Libav.
5  *
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.
10  *
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.
15  *
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
19  */
20 
21 #include "config.h"
22 
23 #if HAVE_UNISTD_H
24 #include <unistd.h>
25 #endif
26 #if HAVE_CRYPTGENRANDOM
27 #include <windows.h>
28 #include <wincrypt.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"
39 
40 static int read_random(uint32_t *dst, const char *file)
41 {
42 #if HAVE_UNISTD_H
43  int fd = avpriv_open(file, O_RDONLY);
44  int err = -1;
45 
46  if (fd == -1)
47  return -1;
48  err = read(fd, dst, sizeof(*dst));
49  close(fd);
50 
51  return err;
52 #else
53  return -1;
54 #endif
55 }
56 
57 static uint32_t get_generic_seed(void)
58 {
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;
65 
66  for (;;) {
67  clock_t t = clock();
68 
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;
75  }
76  last_t = t;
77  }
78 
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;
87  }
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);
93 }
94 
95 uint32_t av_get_random_seed(void)
96 {
97  uint32_t seed;
98 
99 #if HAVE_CRYPTGENRANDOM
100  HCRYPTPROV provider;
101  if (CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL,
102  CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
103  BOOL ret = CryptGenRandom(provider, sizeof(seed), (PBYTE) &seed);
104  CryptReleaseContext(provider, 0);
105  if (ret)
106  return seed;
107  }
108 #endif
109 
110  if (read_random(&seed, "/dev/urandom") == sizeof(seed))
111  return seed;
112  if (read_random(&seed, "/dev/random") == sizeof(seed))
113  return seed;
114  return get_generic_seed();
115 }
void av_sha_final(AVSHA *ctx, uint8_t *digest)
Finish hashing and output digest value.
Definition: sha.c:324
void av_sha_update(AVSHA *ctx, const uint8_t *data, unsigned int len)
Update hash value.
Definition: sha.c:297
hash context
Definition: sha.c:34
static int read_random(uint32_t *dst, const char *file)
Definition: random_seed.c:40
av_cold int av_sha_init(AVSHA *ctx, int bits)
Initialize SHA-1 or SHA-2 hashing.
Definition: sha.c:256
memory handling functions
Definition: vf_drawbox.c:37
uint8_t
#define AV_RB32
Definition: intreadwrite.h:130
int avpriv_open(const char *filename, int flags,...)
A wrapper for open() setting O_CLOEXEC.
Definition: file_open.c:71
static uint32_t get_generic_seed(void)
Definition: random_seed.c:57
static float t
Definition: output.c:52
high precision timer, useful to profile code
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:186
common internal API header
static char buffer[20]
Definition: seek-test.c:31
NULL
Definition: eval.c:55
static void close(AVCodecParserContext *s)
Definition: h264_parser.c:489
static unsigned int seed
Definition: videogen.c:78
struct AVSHA * av_sha_alloc(void)
Allocate an AVSHA context.
Definition: sha.c:47
static BOOL(WINAPI *cond_wait)(pthread_cond_t *cond
uint32_t av_get_random_seed(void)
Get random data.
Definition: random_seed.c:95