rand.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:4k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * rand.c : non-predictible random bytes generator
  3.  *****************************************************************************
  4.  * Copyright © 2007 Rémi Denis-Courmont
  5.  * $Id: 81bc1850b3300b7466009659dc1301aa538b7bc1 $
  6.  *
  7.  * This program is free software; you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License as published by
  9.  * the Free Software Foundation; either version 2 of the License, or
  10.  * (at your option) any later version.
  11.  *
  12.  * This program is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  * GNU General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU General Public License
  18.  * along with this program; if not, write to the Free Software
  19.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  20.  *****************************************************************************/
  21. #ifdef HAVE_CONFIG_H
  22. # include "config.h"
  23. #endif
  24. #include <vlc_common.h>
  25. #include <vlc_rand.h>
  26. #ifndef WIN32
  27. #include <stdint.h>
  28. #include <string.h>
  29. #include <stdlib.h>
  30. #include <sys/types.h>
  31. #include <fcntl.h>
  32. #include <unistd.h>
  33. #include <pthread.h>
  34. #include <vlc_md5.h>
  35. /*
  36.  * Pseudo-random number generator using a HMAC-MD5 in counter mode.
  37.  * Probably not very secure (expert patches welcome) but definitely
  38.  * better than rand() which is defined to be reproducible...
  39.  */
  40. #define BLOCK_SIZE 64
  41. static uint8_t okey[BLOCK_SIZE], ikey[BLOCK_SIZE];
  42. static void vlc_rand_init (void)
  43. {
  44. #if defined (__OpenBSD__) || defined (__OpenBSD_kernel__)
  45.     static const char randfile[] = "/dev/random";
  46. #else
  47.     static const char randfile[] = "/dev/urandom";
  48. #endif
  49.     uint8_t key[BLOCK_SIZE];
  50.     /* Get non-predictible value as key for HMAC */
  51.     int fd = open (randfile, O_RDONLY);
  52.     if (fd == -1)
  53.         return; /* Uho! */
  54.     for (size_t i = 0; i < sizeof (key);)
  55.     {
  56.          ssize_t val = read (fd, key + i, sizeof (key) - i);
  57.          if (val > 0)
  58.              i += val;
  59.     }
  60.     /* Precompute outer and inner keys for HMAC */
  61.     for (size_t i = 0; i < sizeof (key); i++)
  62.     {
  63.         okey[i] = key[i] ^ 0x5c;
  64.         ikey[i] = key[i] ^ 0x36;
  65.     }
  66.     close (fd);
  67. }
  68. void vlc_rand_bytes (void *buf, size_t len)
  69. {
  70.     static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
  71.     static uint64_t counter = 0;
  72.     uint64_t stamp = NTPtime64 ();
  73.     while (len > 0)
  74.     {
  75.         uint64_t val;
  76.         struct md5_s mdi, mdo;
  77.         pthread_mutex_lock (&lock);
  78.         if (counter == 0)
  79.             vlc_rand_init ();
  80.         val = counter++;
  81.         pthread_mutex_unlock (&lock);
  82.         InitMD5 (&mdi);
  83.         AddMD5 (&mdi, ikey, sizeof (ikey));
  84.         AddMD5 (&mdi, &stamp, sizeof (stamp));
  85.         AddMD5 (&mdi, &val, sizeof (val));
  86.         EndMD5 (&mdi);
  87.         InitMD5 (&mdo);
  88.         AddMD5 (&mdo, okey, sizeof (okey));
  89.         AddMD5 (&mdo, mdi.p_digest, sizeof (mdi.p_digest));
  90.         EndMD5 (&mdo);
  91.         if (len < sizeof (mdo.p_digest))
  92.         {
  93.             memcpy (buf, mdo.p_digest, len);
  94.             break;
  95.         }
  96.         memcpy (buf, mdo.p_digest, sizeof (mdo.p_digest));
  97.         len -= sizeof (mdo.p_digest);
  98.         buf = ((uint8_t *)buf) + sizeof (mdo.p_digest);
  99.     }
  100. }
  101. #else /* WIN32 */
  102. #include <wincrypt.h>
  103. void vlc_rand_bytes (void *buf, size_t len)
  104. {
  105.     HCRYPTPROV hProv;
  106.     size_t count = len;
  107.     uint8_t *p_buf = (uint8_t *)buf;
  108.     /* fill buffer with pseudo-random data */
  109.     while (count > 0)
  110.     {
  111.         unsigned int val;
  112.         val = rand();
  113.         if (count < sizeof (val))
  114.         {
  115.             memcpy (p_buf, &val, count);
  116.             break;
  117.         }
  118.  
  119.         memcpy (p_buf, &val, sizeof (val));
  120.         count -= sizeof (val);
  121.         p_buf += sizeof (val);
  122.     }
  123.     /* acquire default encryption context */
  124.     if( CryptAcquireContext(
  125.         &hProv,            // Variable to hold returned handle.
  126.         NULL,              // Use default key container.
  127.         MS_DEF_PROV,       // Use default CSP.
  128.         PROV_RSA_FULL,     // Type of provider to acquire.
  129.         0) )
  130.     {
  131.         /* fill buffer with pseudo-random data, intial buffer content
  132.            is used as auxillary random seed */
  133.         CryptGenRandom(hProv, len, buf);
  134.         CryptReleaseContext(hProv, 0);
  135.     }
  136. }
  137. #endif