|  | /* random.c - Random number switch | 
|  | * Copyright (C) 2008  Free Software Foundation, Inc. | 
|  | * | 
|  | * This file is part of Libgcrypt. | 
|  | * | 
|  | * Libgcrypt is free software; you can redistribute it and/or modify | 
|  | * it under the terms of the GNU Lesser General Public License as | 
|  | * published by the Free Software Foundation; either version 2.1 of | 
|  | * the License, or (at your option) any later version. | 
|  | * | 
|  | * Libgcrypt is distributed in the hope that it will be useful, | 
|  | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | * GNU Lesser General Public License for more details. | 
|  | * | 
|  | * You should have received a copy of the GNU Lesser General Public | 
|  | * License along with this program; if not, see <http://www.gnu.org/licenses/>. | 
|  | */ | 
|  |  | 
|  | /* | 
|  | This module switches between different implementations of random | 
|  | number generators and provides a few help functions. | 
|  | */ | 
|  |  | 
|  | #include <config.h> | 
|  | #include <stdio.h> | 
|  | #include <stdlib.h> | 
|  | #include <errno.h> | 
|  |  | 
|  | #include "g10lib.h" | 
|  | #include "random.h" | 
|  | #include "rand-internal.h" | 
|  | #include "ath.h" | 
|  |  | 
|  |  | 
|  | /* If not NULL a progress function called from certain places and the | 
|  | opaque value passed along.  Registred by | 
|  | _gcry_register_random_progress (). */ | 
|  | static void (*progress_cb) (void *,const char*,int,int, int ); | 
|  | static void *progress_cb_data; | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  | /* ---  Functions  --- */ | 
|  |  | 
|  |  | 
|  | /* Used to register a progress callback.  This needs to be called | 
|  | before any threads are created. */ | 
|  | void | 
|  | _gcry_register_random_progress (void (*cb)(void *,const char*,int,int,int), | 
|  | void *cb_data ) | 
|  | { | 
|  | progress_cb = cb; | 
|  | progress_cb_data = cb_data; | 
|  | } | 
|  |  | 
|  |  | 
|  | /* This progress function is currently used by the random modules to | 
|  | give hints on how much more entropy is required. */ | 
|  | void | 
|  | _gcry_random_progress (const char *what, int printchar, int current, int total) | 
|  | { | 
|  | if (progress_cb) | 
|  | progress_cb (progress_cb_data, what, printchar, current, total); | 
|  | } | 
|  |  | 
|  |  | 
|  |  | 
|  | /* Initialize this random subsystem.  If FULL is false, this function | 
|  | merely calls the basic initialization of the module and does not do | 
|  | anything more.  Doing this is not really required but when running | 
|  | in a threaded environment we might get a race condition | 
|  | otherwise. */ | 
|  | void | 
|  | _gcry_random_initialize (int full) | 
|  | { | 
|  | if (fips_mode ()) | 
|  | _gcry_rngfips_initialize (full); | 
|  | else | 
|  | _gcry_rngcsprng_initialize (full); | 
|  | } | 
|  |  | 
|  |  | 
|  | void | 
|  | _gcry_random_dump_stats (void) | 
|  | { | 
|  | if (fips_mode ()) | 
|  | _gcry_rngfips_dump_stats (); | 
|  | else | 
|  | _gcry_rngcsprng_dump_stats (); | 
|  | } | 
|  |  | 
|  |  | 
|  | /* This function should be called during initialization and beore | 
|  | intialization of this module to place the random pools into secure | 
|  | memory.  */ | 
|  | void | 
|  | _gcry_secure_random_alloc (void) | 
|  | { | 
|  | if (fips_mode ()) | 
|  | ;  /* Not used; the fips rng is allows in secure mode.  */ | 
|  | else | 
|  | _gcry_rngcsprng_secure_alloc (); | 
|  | } | 
|  |  | 
|  |  | 
|  | /* This may be called before full initialization to degrade the | 
|  | quality of the RNG for the sake of a faster running test suite.  */ | 
|  | void | 
|  | _gcry_enable_quick_random_gen (void) | 
|  | { | 
|  | if (fips_mode ()) | 
|  | ;  /* Not used.  */ | 
|  | else | 
|  | _gcry_rngcsprng_enable_quick_gen (); | 
|  | } | 
|  |  | 
|  |  | 
|  | void | 
|  | _gcry_set_random_daemon_socket (const char *socketname) | 
|  | { | 
|  | if (fips_mode ()) | 
|  | ;  /* Not used.  */ | 
|  | else | 
|  | _gcry_rngcsprng_set_daemon_socket (socketname); | 
|  | } | 
|  |  | 
|  | /* With ONOFF set to 1, enable the use of the daemon.  With ONOFF set | 
|  | to 0, disable the use of the daemon.  With ONOF set to -1, return | 
|  | whether the daemon has been enabled. */ | 
|  | int | 
|  | _gcry_use_random_daemon (int onoff) | 
|  | { | 
|  | if (fips_mode ()) | 
|  | return 0; /* Never enabled in fips mode.  */ | 
|  | else | 
|  | return _gcry_rngcsprng_use_daemon (onoff); | 
|  | } | 
|  |  | 
|  |  | 
|  | /* This function returns true if no real RNG is available or the | 
|  | quality of the RNG has been degraded for test purposes.  */ | 
|  | int | 
|  | _gcry_random_is_faked (void) | 
|  | { | 
|  | if (fips_mode ()) | 
|  | return _gcry_rngfips_is_faked (); | 
|  | else | 
|  | return _gcry_rngcsprng_is_faked (); | 
|  | } | 
|  |  | 
|  |  | 
|  | /* Add BUFLEN bytes from BUF to the internal random pool.  QUALITY | 
|  | should be in the range of 0..100 to indicate the goodness of the | 
|  | entropy added, or -1 for goodness not known.  */ | 
|  | gcry_error_t | 
|  | gcry_random_add_bytes (const void *buf, size_t buflen, int quality) | 
|  | { | 
|  | if (fips_mode ()) | 
|  | return 0; /* No need for this in fips mode.  */ | 
|  | else | 
|  | return _gcry_rngcsprng_add_bytes (buf, buflen, quality); | 
|  | } | 
|  |  | 
|  |  | 
|  | /* Helper function.  */ | 
|  | static void | 
|  | do_randomize (void *buffer, size_t length, enum gcry_random_level level) | 
|  | { | 
|  | if (fips_mode ()) | 
|  | _gcry_rngfips_randomize (buffer, length, level); | 
|  | else | 
|  | _gcry_rngcsprng_randomize (buffer, length, level); | 
|  | } | 
|  |  | 
|  | /* The public function to return random data of the quality LEVEL. | 
|  | Returns a pointer to a newly allocated and randomized buffer of | 
|  | LEVEL and NBYTES length.  Caller must free the buffer.  */ | 
|  | void * | 
|  | gcry_random_bytes (size_t nbytes, enum gcry_random_level level) | 
|  | { | 
|  | void *buffer; | 
|  |  | 
|  | buffer = gcry_xmalloc (nbytes); | 
|  | do_randomize (buffer, nbytes, level); | 
|  | return buffer; | 
|  | } | 
|  |  | 
|  |  | 
|  | /* The public function to return random data of the quality LEVEL; | 
|  | this version of the function returns the random in a buffer allocated | 
|  | in secure memory.  Caller must free the buffer. */ | 
|  | void * | 
|  | gcry_random_bytes_secure (size_t nbytes, enum gcry_random_level level) | 
|  | { | 
|  | void *buffer; | 
|  |  | 
|  | /* Historical note (1.3.0--1.4.1): The buffer was only allocated | 
|  | in secure memory if the pool in random-csprng.c was also set to | 
|  | use secure memory.  */ | 
|  | buffer = gcry_xmalloc_secure (nbytes); | 
|  | do_randomize (buffer, nbytes, level); | 
|  | return buffer; | 
|  | } | 
|  |  | 
|  |  | 
|  | /* Public function to fill the buffer with LENGTH bytes of | 
|  | cryptographically strong random bytes.  Level GCRY_WEAK_RANDOM is | 
|  | not very strong, GCRY_STRONG_RANDOM is strong enough for most | 
|  | usage, GCRY_VERY_STRONG_RANDOM is good for key generation stuff but | 
|  | may be very slow.  */ | 
|  | void | 
|  | gcry_randomize (void *buffer, size_t length, enum gcry_random_level level) | 
|  | { | 
|  | do_randomize (buffer, length, level); | 
|  | } | 
|  |  | 
|  |  | 
|  | /* This function may be used to specify the file to be used as a seed | 
|  | file for the PRNG.  This fucntion should be called prior to the | 
|  | initialization of the random module.  NAME may not be NULL.  */ | 
|  | void | 
|  | _gcry_set_random_seed_file (const char *name) | 
|  | { | 
|  | if (fips_mode ()) | 
|  | ; /* No need for this in fips mode.  */ | 
|  | else | 
|  | _gcry_rngcsprng_set_seed_file (name); | 
|  | } | 
|  |  | 
|  |  | 
|  | /* If a seed file has been setup, this function may be used to write | 
|  | back the random numbers entropy pool.  */ | 
|  | void | 
|  | _gcry_update_random_seed_file (void) | 
|  | { | 
|  | if (fips_mode ()) | 
|  | ; /* No need for this in fips mode.  */ | 
|  | else | 
|  | _gcry_rngcsprng_update_seed_file (); | 
|  | } | 
|  |  | 
|  |  | 
|  |  | 
|  | /* The fast random pool function as called at some places in | 
|  | libgcrypt.  This is merely a wrapper to make sure that this module | 
|  | is initalized and to lock the pool.  Note, that this function is a | 
|  | NOP unless a random function has been used or _gcry_initialize (1) | 
|  | has been used.  We use this hack so that the internal use of this | 
|  | function in cipher_open and md_open won't start filling up the | 
|  | random pool, even if no random will be required by the process. */ | 
|  | void | 
|  | _gcry_fast_random_poll (void) | 
|  | { | 
|  | if (fips_mode ()) | 
|  | ; /* No need for this in fips mode.  */ | 
|  | else | 
|  | _gcry_rngcsprng_fast_poll (); | 
|  | } | 
|  |  | 
|  |  | 
|  |  | 
|  | /* Create an unpredicable nonce of LENGTH bytes in BUFFER. */ | 
|  | void | 
|  | gcry_create_nonce (void *buffer, size_t length) | 
|  | { | 
|  | if (fips_mode ()) | 
|  | _gcry_rngfips_create_nonce (buffer, length); | 
|  | else | 
|  | _gcry_rngcsprng_create_nonce (buffer, length); | 
|  | } | 
|  |  | 
|  |  | 
|  | /* Run the self-tests for the RNG.  This is currently only implemented | 
|  | for the FIPS generator.  */ | 
|  | gpg_error_t | 
|  | _gcry_random_selftest (selftest_report_func_t report) | 
|  | { | 
|  | if (fips_mode ()) | 
|  | return _gcry_rngfips_selftest (report); | 
|  | else | 
|  | return 0; /* No selftests yet.  */ | 
|  | } | 
|  |  | 
|  |  | 
|  | /* Create a new test context for an external RNG test driver.  On | 
|  | success the test context is stored at R_CONTEXT; on failure NULL is | 
|  | stored at R_CONTEXT and an error code is returned.  */ | 
|  | gcry_err_code_t | 
|  | _gcry_random_init_external_test (void **r_context, | 
|  | unsigned int flags, | 
|  | const void *key, size_t keylen, | 
|  | const void *seed, size_t seedlen, | 
|  | const void *dt, size_t dtlen) | 
|  | { | 
|  | (void)flags; | 
|  | if (fips_mode ()) | 
|  | return _gcry_rngfips_init_external_test (r_context, flags, key, keylen, | 
|  | seed, seedlen, | 
|  | dt, dtlen); | 
|  | else | 
|  | return GPG_ERR_NOT_SUPPORTED; | 
|  | } | 
|  |  | 
|  | /* Get BUFLEN bytes from the RNG using the test CONTEXT and store them | 
|  | at BUFFER.  Return 0 on success or an error code.  */ | 
|  | gcry_err_code_t | 
|  | _gcry_random_run_external_test (void *context, char *buffer, size_t buflen) | 
|  | { | 
|  | if (fips_mode ()) | 
|  | return _gcry_rngfips_run_external_test (context, buffer, buflen); | 
|  | else | 
|  | return GPG_ERR_NOT_SUPPORTED; | 
|  | } | 
|  |  | 
|  | /* Release the test CONTEXT.  */ | 
|  | void | 
|  | _gcry_random_deinit_external_test (void *context) | 
|  | { | 
|  | if (fips_mode ()) | 
|  | _gcry_rngfips_deinit_external_test (context); | 
|  | } |