LCOV - code coverage report
Current view: top level - src/libavutil - random_seed.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 36 43 83.7 %
Date: 2017-01-21 09:32:20 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2009 Baptiste Coudurier <baptiste.coudurier@gmail.com>
       3             :  *
       4             :  * This file is part of FFmpeg.
       5             :  *
       6             :  * FFmpeg 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             :  * FFmpeg 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 FFmpeg; 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_IO_H
      27             : #include <io.h>
      28             : #endif
      29             : #if HAVE_CRYPTGENRANDOM
      30             : #include <windows.h>
      31             : #include <wincrypt.h>
      32             : #endif
      33             : #include <fcntl.h>
      34             : #include <math.h>
      35             : #include <time.h>
      36             : #include <string.h>
      37             : #include "avassert.h"
      38             : #include "internal.h"
      39             : #include "intreadwrite.h"
      40             : #include "timer.h"
      41             : #include "random_seed.h"
      42             : #include "sha.h"
      43             : 
      44             : #ifndef TEST
      45             : #define TEST 0
      46             : #endif
      47             : 
      48         277 : static int read_random(uint32_t *dst, const char *file)
      49             : {
      50             : #if HAVE_UNISTD_H
      51         277 :     int fd = avpriv_open(file, O_RDONLY);
      52         277 :     int err = -1;
      53             : 
      54         277 :     if (fd == -1)
      55           0 :         return -1;
      56         277 :     err = read(fd, dst, sizeof(*dst));
      57         277 :     close(fd);
      58             : 
      59         277 :     return err;
      60             : #else
      61             :     return -1;
      62             : #endif
      63             : }
      64             : 
      65         256 : static uint32_t get_generic_seed(void)
      66             : {
      67             :     uint64_t tmp[120/8];
      68         256 :     struct AVSHA *sha = (void*)tmp;
      69         256 :     clock_t last_t  = 0;
      70         256 :     clock_t last_td = 0;
      71         256 :     clock_t init_t = 0;
      72             :     static uint64_t i = 0;
      73             :     static uint32_t buffer[512] = { 0 };
      74             :     unsigned char digest[20];
      75         256 :     uint64_t last_i = i;
      76             : 
      77         256 :     av_assert0(sizeof(tmp) >= av_sha_size);
      78             : 
      79             :     if(TEST){
      80         256 :         memset(buffer, 0, sizeof(buffer));
      81         256 :         last_i = i = 0;
      82             :     }else{
      83             : #ifdef AV_READ_TIME
      84           0 :         buffer[13] ^= AV_READ_TIME();
      85           0 :         buffer[41] ^= AV_READ_TIME()>>32;
      86             : #endif
      87             :     }
      88             : 
      89    32711491 :     for (;;) {
      90    32711747 :         clock_t t = clock();
      91    32711747 :         if (last_t + 2*last_td + (CLOCKS_PER_SEC > 1000) >= t) {
      92    32706000 :             last_td = t - last_t;
      93    32706000 :             buffer[i & 511] = 1664525*buffer[i & 511] + 1013904223 + (last_td % 3294638521U);
      94             :         } else {
      95        5747 :             last_td = t - last_t;
      96        5747 :             buffer[++i & 511] += last_td % 3294638521U;
      97        5747 :             if ((t - init_t) >= CLOCKS_PER_SEC>>5)
      98         511 :                 if (last_i && i - last_i > 4 || i - last_i > 64 || TEST && i - last_i > 8)
      99             :                     break;
     100             :         }
     101    32711491 :         last_t = t;
     102    32711491 :         if (!init_t)
     103         256 :             init_t = t;
     104             :     }
     105             : 
     106             :     if(TEST) {
     107         256 :         buffer[0] = buffer[1] = 0;
     108             :     } else {
     109             : #ifdef AV_READ_TIME
     110           0 :         buffer[111] += AV_READ_TIME();
     111             : #endif
     112             :     }
     113             : 
     114         256 :     av_sha_init(sha, 160);
     115         256 :     av_sha_update(sha, (const uint8_t *)buffer, sizeof(buffer));
     116         256 :     av_sha_final(sha, digest);
     117         256 :     return AV_RB32(digest) + AV_RB32(digest + 16);
     118             : }
     119             : 
     120         277 : uint32_t av_get_random_seed(void)
     121             : {
     122             :     uint32_t seed;
     123             : 
     124             : #if HAVE_CRYPTGENRANDOM
     125             :     HCRYPTPROV provider;
     126             :     if (CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL,
     127             :                             CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
     128             :         BOOL ret = CryptGenRandom(provider, sizeof(seed), (PBYTE) &seed);
     129             :         CryptReleaseContext(provider, 0);
     130             :         if (ret)
     131             :             return seed;
     132             :     }
     133             : #endif
     134             : 
     135             : #if HAVE_ARC4RANDOM
     136             :     return arc4random();
     137             : #endif
     138             : 
     139         277 :     if (read_random(&seed, "/dev/urandom") == sizeof(seed))
     140         277 :         return seed;
     141           0 :     if (read_random(&seed, "/dev/random")  == sizeof(seed))
     142           0 :         return seed;
     143           0 :     return get_generic_seed();
     144             : }

Generated by: LCOV version 1.12