/* Basic initialization which is required to initialize mutexes and such. It does not run a full initialization so that the filling of the random pool can be delayed until it is actually needed. We assume that this function is used before any concurrent access happens. */ static void initialize_basics(void) { static int initialized; int err; if (!initialized) { initialized = 1; err = ath_mutex_init (&pool_lock); if (err) log_fatal ("failed to create the pool lock: %s\n", strerror (err) ); err = ath_mutex_init (&nonce_buffer_lock); if (err) log_fatal ("failed to create the nonce buffer lock: %s\n", strerror (err) ); #ifdef USE_RANDOM_DAEMON _gcry_daemon_initialize_basics (); #endif /*USE_RANDOM_DAEMON*/ /* Make sure that we are still using the values we have traditionally used for the random levels. */ gcry_assert (GCRY_WEAK_RANDOM == 0 && GCRY_STRONG_RANDOM == 1 && GCRY_VERY_STRONG_RANDOM == 2); } }
/* 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) { static int nonce_initialized; int err; if (!nonce_initialized) { nonce_initialized = 1; err = ath_mutex_init (&nonce_buffer_lock); if (err) log_fatal ("failed to create the nonce buffer lock: %s\n", strerror (err) ); } if (fips_mode ()) _gcry_rngfips_initialize (full); else if (rng_types.standard) _gcry_rngcsprng_initialize (full); else if (rng_types.fips) _gcry_rngfips_initialize (full); else if (rng_types.system) _gcry_rngsystem_initialize (full); else _gcry_rngcsprng_initialize (full); }
/* Note, we assume that this function is used before any concurrent access happens. */ static void initialize_basics(void) { static int initialized; int err; if (!initialized) { initialized = 1; err = ath_mutex_init (&pool_lock); if (err) log_fatal ("failed to create the pool lock: %s\n", strerror (err) ); err = ath_mutex_init (&nonce_buffer_lock); if (err) log_fatal ("failed to create the nonce buffer lock: %s\n", strerror (err) ); } }
gcry_err_code_t _gcry_secmem_module_init () { int err; err = ath_mutex_init (&secmem_lock); if (err) log_fatal ("could not allocate secmem lock\n"); return 0; }
/* Explicitly initialize this module. */ gcry_err_code_t _gcry_cipher_init (void) { gcry_err_code_t err; err = ath_mutex_init (&ciphers_registered_lock); if (err) return gpg_err_code_from_errno (err); REGISTER_DEFAULT_CIPHERS; return err; }
/* Basic initialization is required to initialize mutexes and do a few checks on the implementation. */ static void basic_initialization (void) { static int initialized; int my_errno; if (initialized) return; initialized = 1; my_errno = ath_mutex_init (&system_rng_lock); if (my_errno) log_fatal ("failed to create the System RNG lock: %s\n", strerror (my_errno)); system_rng_is_locked = 0; /* Make sure that we are still using the values we traditionally used for the random levels. */ gcry_assert (GCRY_WEAK_RANDOM == 0 && GCRY_STRONG_RANDOM == 1 && GCRY_VERY_STRONG_RANDOM == 2); }
/* Check whether the OS is in FIPS mode and record that in a module local variable. If FORCE is passed as true, fips mode will be enabled anyway. Note: This function is not thread-safe and should be called before any threads are created. This function may only be called once. */ void _gcry_initialize_fips_mode (int force) { static int done; gpg_error_t err; /* Make sure we are not accidently called twice. */ if (done) { if ( fips_mode () ) { fips_new_state (STATE_FATALERROR); fips_noreturn (); } /* If not in fips mode an assert is sufficient. */ gcry_assert (!done); } done = 1; /* If the calling application explicitly requested fipsmode, do so. */ if (force) { gcry_assert (!no_fips_mode_required); goto leave; } /* For testing the system it is useful to override the system provided detection of the FIPS mode and force FIPS mode using a file. The filename is hardwired so that there won't be any confusion on whether /etc/gcrypt/ or /usr/local/etc/gcrypt/ is actually used. The file itself may be empty. */ if ( !access (FIPS_FORCE_FILE, F_OK) ) { gcry_assert (!no_fips_mode_required); goto leave; } /* Checking based on /proc file properties. */ { static const char procfname[] = "/proc/sys/crypto/fips_enabled"; FILE *fp; int saved_errno; fp = fopen (procfname, "r"); if (fp) { char line[256]; if (fgets (line, sizeof line, fp) && atoi (line)) { /* System is in fips mode. */ fclose (fp); gcry_assert (!no_fips_mode_required); goto leave; } fclose (fp); } else if ((saved_errno = errno) != ENOENT && saved_errno != EACCES && !access ("/proc/version", F_OK) ) { /* Problem reading the fips file despite that we have the proc file system. We better stop right away. */ log_info ("FATAL: error reading `%s' in libgcrypt: %s\n", procfname, strerror (saved_errno)); #ifdef HAVE_SYSLOG syslog (LOG_USER|LOG_ERR, "Libgcrypt error: " "reading `%s' failed: %s - abort", procfname, strerror (saved_errno)); #endif /*HAVE_SYSLOG*/ abort (); } } /* Fips not not requested, set flag. */ no_fips_mode_required = 1; leave: if (!no_fips_mode_required) { /* Yes, we are in FIPS mode. */ FILE *fp; /* Intitialize the lock to protect the FSM. */ err = ath_mutex_init (&fsm_lock); if (err) { /* If that fails we can't do anything but abort the process. We need to use log_info so that the FSM won't get involved. */ log_info ("FATAL: failed to create the FSM lock in libgcrypt: %s\n", strerror (err)); #ifdef HAVE_SYSLOG syslog (LOG_USER|LOG_ERR, "Libgcrypt error: " "creating FSM lock failed: %s - abort", strerror (err)); #endif /*HAVE_SYSLOG*/ abort (); } /* If the FIPS force files exists, is readable and has a number != 0 on its first line, we enable the enforced fips mode. */ fp = fopen (FIPS_FORCE_FILE, "r"); if (fp) { char line[256]; if (fgets (line, sizeof line, fp) && atoi (line)) enforced_fips_mode = 1; fclose (fp); } /* Now get us into the INIT state. */ fips_new_state (STATE_INIT); } return; }