LCOV - code coverage report
Current view: top level - third_party/heimdal/lib/hcrypto - rand.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 25 119 21.0 %
Date: 2024-04-21 15:09:00 Functions: 4 13 30.8 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
       3             :  * (Royal Institute of Technology, Stockholm, Sweden).
       4             :  * All rights reserved.
       5             :  *
       6             :  * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
       7             :  *
       8             :  * Redistribution and use in source and binary forms, with or without
       9             :  * modification, are permitted provided that the following conditions
      10             :  * are met:
      11             :  *
      12             :  * 1. Redistributions of source code must retain the above copyright
      13             :  *    notice, this list of conditions and the following disclaimer.
      14             :  *
      15             :  * 2. Redistributions in binary form must reproduce the above copyright
      16             :  *    notice, this list of conditions and the following disclaimer in the
      17             :  *    documentation and/or other materials provided with the distribution.
      18             :  *
      19             :  * 3. Neither the name of the Institute nor the names of its contributors
      20             :  *    may be used to endorse or promote products derived from this software
      21             :  *    without specific prior written permission.
      22             :  *
      23             :  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
      24             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      25             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      26             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
      27             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      28             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      29             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      30             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      31             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      32             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      33             :  * SUCH DAMAGE.
      34             :  */
      35             : 
      36             : #include <config.h>
      37             : #include <roken.h>
      38             : 
      39             : #include <rand.h>
      40             : #include <randi.h>
      41             : 
      42             : #ifndef O_BINARY
      43             : #define O_BINARY 0
      44             : #endif
      45             : 
      46             : #ifdef _WIN32
      47             : #include<shlobj.h>
      48             : #endif
      49             : 
      50             : /**
      51             :  * @page page_rand RAND - random number
      52             :  *
      53             :  * See the library functions here: @ref hcrypto_rand
      54             :  */
      55             : 
      56             : static const RAND_METHOD *selected_meth = NULL;
      57             : static ENGINE *selected_engine = NULL;
      58             : 
      59             : static void
      60     3566361 : init_method(void)
      61             : {
      62     3566361 :     if (selected_meth != NULL)
      63     3484034 :         return;
      64             : #if defined(_WIN32)
      65             :     selected_meth = &hc_rand_w32crypto_method;
      66             : #elif defined(__APPLE__)
      67             :     selected_meth = &hc_rand_unix_method;
      68             : #else
      69       33851 :     selected_meth = &hc_rand_fortuna_method;
      70             : #endif
      71             : }
      72             : 
      73             : /**
      74             :  * Seed that random number generator. Secret material can securely be
      75             :  * feed into the function, they will never be returned.
      76             :  *
      77             :  * @param indata seed data
      78             :  * @param size length seed data
      79             :  *
      80             :  * @ingroup hcrypto_rand
      81             :  */
      82             : 
      83             : void
      84           0 : RAND_seed(const void *indata, size_t size)
      85             : {
      86           0 :     init_method();
      87           0 :     (*selected_meth->seed)(indata, size);
      88           0 : }
      89             : 
      90             : /**
      91             :  * Get a random block from the random generator, can be used for key material.
      92             :  *
      93             :  * @param outdata random data
      94             :  * @param size length random data
      95             :  *
      96             :  * @return 1 on success, 0 on failure.
      97             :  *
      98             :  * @ingroup hcrypto_rand
      99             :  */
     100             : int
     101     3498659 : RAND_bytes(void *outdata, size_t size)
     102             : {
     103     3498659 :     if (size == 0)
     104           0 :         return 1;
     105     3498659 :     init_method();
     106     3498659 :     return (*selected_meth->bytes)(outdata, size);
     107             : }
     108             : 
     109             : /**
     110             :  * Reset and free memory used by the random generator.
     111             :  *
     112             :  * @ingroup hcrypto_rand
     113             :  */
     114             : 
     115             : void
     116           0 : RAND_cleanup(void)
     117             : {
     118           0 :     const RAND_METHOD *meth = selected_meth;
     119           0 :     ENGINE *engine = selected_engine;
     120             : 
     121           0 :     selected_meth = NULL;
     122           0 :     selected_engine = NULL;
     123             : 
     124           0 :     if (meth)
     125           0 :         (*meth->cleanup)();
     126           0 :     if (engine)
     127           0 :         ENGINE_finish(engine);
     128           0 : }
     129             : 
     130             : /**
     131             :  * Seed that random number generator. Secret material can securely be
     132             :  * feed into the function, they will never be returned.
     133             :  *
     134             :  * @param indata the input data.
     135             :  * @param size size of in data.
     136             :  * @param entropi entropi in data.
     137             :  *
     138             :  *
     139             :  * @ingroup hcrypto_rand
     140             :  */
     141             : 
     142             : void
     143           0 : RAND_add(const void *indata, size_t size, double entropi)
     144             : {
     145           0 :     init_method();
     146           0 :     (*selected_meth->add)(indata, size, entropi);
     147           0 : }
     148             : 
     149             : /**
     150             :  * Get a random block from the random generator, should NOT be used for key material.
     151             :  *
     152             :  * @param outdata random data
     153             :  * @param size length random data
     154             :  *
     155             :  * @return 1 on success, 0 on failure.
     156             :  *
     157             :  * @ingroup hcrypto_rand
     158             :  */
     159             : 
     160             : int
     161           0 : RAND_pseudo_bytes(void *outdata, size_t size)
     162             : {
     163           0 :     init_method();
     164           0 :     return (*selected_meth->pseudorand)(outdata, size);
     165             : }
     166             : 
     167             : /**
     168             :  * Return status of the random generator
     169             :  *
     170             :  * @return 1 if the random generator can deliver random data.
     171             :  *
     172             :  * @ingroup hcrypto_rand
     173             :  */
     174             : 
     175             : int
     176       67702 : RAND_status(void)
     177             : {
     178       67702 :     init_method();
     179       67702 :     return (*selected_meth->status)();
     180             : }
     181             : 
     182             : /**
     183             :  * Set the default random method.
     184             :  *
     185             :  * @param meth set the new default method.
     186             :  *
     187             :  * @return 1 on success.
     188             :  *
     189             :  * @ingroup hcrypto_rand
     190             :  */
     191             : 
     192             : int
     193           0 : RAND_set_rand_method(const RAND_METHOD *meth)
     194             : {
     195           0 :     const RAND_METHOD *old = selected_meth;
     196           0 :     selected_meth = meth;
     197           0 :     if (old)
     198           0 :         (*old->cleanup)();
     199           0 :     if (selected_engine) {
     200           0 :         ENGINE_finish(selected_engine);
     201           0 :         selected_engine = NULL;
     202             :     }
     203           0 :     return 1;
     204             : }
     205             : 
     206             : /**
     207             :  * Get the default random method.
     208             :  *
     209             :  * @return Returns a RAND_METHOD
     210             :  *
     211             :  * @ingroup hcrypto_rand
     212             :  */
     213             : 
     214             : const RAND_METHOD *
     215           0 : RAND_get_rand_method(void)
     216             : {
     217           0 :     init_method();
     218           0 :     return selected_meth;
     219             : }
     220             : 
     221             : /**
     222             :  * Set the default random method from engine.
     223             :  *
     224             :  * @param engine use engine, if NULL is passed it, old method and engine is cleared.
     225             :  *
     226             :  * @return 1 on success, 0 on failure.
     227             :  *
     228             :  * @ingroup hcrypto_rand
     229             :  */
     230             : 
     231             : int
     232           0 : RAND_set_rand_engine(ENGINE *engine)
     233             : {
     234           0 :     const RAND_METHOD *meth, *old = selected_meth;
     235             : 
     236           0 :     if (engine) {
     237           0 :         ENGINE_up_ref(engine);
     238           0 :         meth = ENGINE_get_RAND(engine);
     239           0 :         if (meth == NULL) {
     240           0 :             ENGINE_finish(engine);
     241           0 :             return 0;
     242             :         }
     243             :     } else {
     244           0 :         meth = NULL;
     245             :     }
     246             : 
     247           0 :     if (old)
     248           0 :         (*old->cleanup)();
     249             : 
     250           0 :     if (selected_engine)
     251           0 :         ENGINE_finish(selected_engine);
     252             : 
     253           0 :     selected_engine = engine;
     254           0 :     selected_meth = meth;
     255             : 
     256           0 :     return 1;
     257             : }
     258             : 
     259             : #define RAND_FILE_SIZE 1024
     260             : 
     261             : /**
     262             :  * Load a a file and feed it into RAND_seed().
     263             :  *
     264             :  * @param filename name of file to read.
     265             :  * @param size minimum size to read.
     266             :  *
     267             :  * @return Returns the number of seed bytes loaded (0 indicates failure)
     268             :  *
     269             :  * @ingroup hcrypto_rand
     270             :  */
     271             : 
     272             : int
     273           0 : RAND_load_file(const char *filename, size_t size)
     274             : {
     275           0 :     unsigned char buf[128];
     276           0 :     size_t len;
     277           0 :     ssize_t slen;
     278           0 :     int fd;
     279             : 
     280           0 :     fd = open(filename, O_RDONLY | O_BINARY, 0600);
     281           0 :     if (fd < 0)
     282           0 :         return 0;
     283           0 :     rk_cloexec(fd);
     284           0 :     len = 0;
     285           0 :     while(len < size) {
     286           0 :         slen = read(fd, buf, sizeof(buf));
     287           0 :         if (slen <= 0)
     288           0 :             break;
     289           0 :         RAND_seed(buf, slen);
     290           0 :         len += slen;
     291             :     }
     292           0 :     close(fd);
     293             : 
     294           0 :     return len ? 1 : 0;
     295             : }
     296             : 
     297             : /**
     298             :  * Write of random numbers to a file to store for later initiation with RAND_load_file().
     299             :  *
     300             :  * @param filename name of file to write.
     301             :  *
     302             :  * @return 1 on success and non-one on failure.
     303             :  * @ingroup hcrypto_rand
     304             :  */
     305             : 
     306             : int
     307           0 : RAND_write_file(const char *filename)
     308             : {
     309           0 :     unsigned char buf[128];
     310           0 :     size_t len;
     311           0 :     int res = 0, fd;
     312             : 
     313           0 :     fd = open(filename, O_WRONLY | O_CREAT | O_BINARY, 0600);
     314           0 :     if (fd < 0)
     315           0 :         return 0;
     316           0 :     rk_cloexec(fd);
     317             : 
     318           0 :     len = 0;
     319           0 :     while(len < RAND_FILE_SIZE) {
     320           0 :         res = RAND_bytes(buf, sizeof(buf));
     321           0 :         if (res != 1)
     322           0 :             break;
     323           0 :         if (write(fd, buf, sizeof(buf)) != sizeof(buf)) {
     324           0 :             res = 0;
     325           0 :             break;
     326             :         }
     327           0 :         len += sizeof(buf);
     328             :     }
     329             : 
     330           0 :     close(fd);
     331             : 
     332           0 :     return res;
     333             : }
     334             : 
     335             : /**
     336             :  * Return the default random state filename for a user to use for
     337             :  * RAND_load_file(), and RAND_write_file().
     338             :  *
     339             :  * @param filename buffer to hold file name.
     340             :  * @param size size of buffer filename.
     341             :  *
     342             :  * @return the buffer filename or NULL on failure.
     343             :  *
     344             :  * @ingroup hcrypto_rand
     345             :  */
     346             : 
     347             : const char *
     348       33851 : RAND_file_name(char *filename, size_t size)
     349             : {
     350       33851 :     const char *e = NULL;
     351       33851 :     int pathp = 0, ret;
     352             : 
     353       33851 :     e = secure_getenv("RANDFILE");
     354       33851 :     if (e == NULL)
     355       33851 :         e = secure_getenv("HOME");
     356       33851 :     if (e)
     357       33851 :         pathp = 1;
     358             : 
     359             : #ifndef _WIN32
     360             :     /*
     361             :      * Here we really want to call getpwuid(getuid()) but this will
     362             :      * cause recursive lookups if the nss library uses
     363             :      * gssapi/krb5/hcrypto to authenticate to the ldap servers.
     364             :      *
     365             :      * So at least return the unix /dev/random if we have one
     366             :      */
     367       33851 :     if (e == NULL) {
     368           0 :         int fd;
     369             : 
     370           0 :         fd = _hc_unix_device_fd(O_RDONLY, &e);
     371           0 :         if (fd >= 0)
     372           0 :             close(fd);
     373             :     }
     374             : #else  /* Win32 */
     375             : 
     376             :     if (e == NULL) {
     377             :         char profile[MAX_PATH];
     378             : 
     379             :         if (SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL,
     380             :                             SHGFP_TYPE_CURRENT, profile) == S_OK) {
     381             :             ret = snprintf(filename, size, "%s\\.rnd", profile);
     382             : 
     383             :             if (ret > 0 && ret < size)
     384             :                 return filename;
     385             :         }
     386             :     }
     387             : 
     388             : #endif
     389             : 
     390       33851 :     if (e == NULL)
     391           0 :         return NULL;
     392             : 
     393       33851 :     if (pathp)
     394       33851 :         ret = snprintf(filename, size, "%s/.rnd", e);
     395             :     else
     396           0 :         ret = snprintf(filename, size, "%s", e);
     397             : 
     398       33851 :     if (ret <= 0 || ret >= size)
     399           0 :         return NULL;
     400             : 
     401       32582 :     return filename;
     402             : }

Generated by: LCOV version 1.14