void gcry_create_nonce (void *buffer, size_t length) { if (!fips_is_operational ()) { (void)fips_not_operational (); fips_signal_fatal_error ("called in non-operational state"); fips_noreturn (); } _gcry_create_nonce (buffer, length); }
void gcry_randomize (void *buffer, size_t length, enum gcry_random_level level) { if (!fips_is_operational ()) { (void)fips_not_operational (); fips_signal_fatal_error ("called in non-operational state"); fips_noreturn (); } _gcry_randomize (buffer, length, level); }
void * gcry_random_bytes_secure (size_t nbytes, enum gcry_random_level level) { if (!fips_is_operational ()) { (void)fips_not_operational (); fips_signal_fatal_error ("called in non-operational state"); fips_noreturn (); } return _gcry_random_bytes_secure (nbytes, level); }
/* Perform a state transition to NEW_STATE. If this is an invalid transition, the module will go into a fatal error state. */ static void fips_new_state (enum module_states new_state) { int ok = 0; enum module_states last_state; lock_fsm (); last_state = current_state; switch (current_state) { case STATE_POWERON: if (new_state == STATE_INIT || new_state == STATE_ERROR || new_state == STATE_FATALERROR) ok = 1; break; case STATE_INIT: if (new_state == STATE_SELFTEST || new_state == STATE_ERROR || new_state == STATE_FATALERROR) ok = 1; break; case STATE_SELFTEST: if (new_state == STATE_OPERATIONAL || new_state == STATE_ERROR || new_state == STATE_FATALERROR) ok = 1; break; case STATE_OPERATIONAL: if (new_state == STATE_SHUTDOWN || new_state == STATE_SELFTEST || new_state == STATE_ERROR || new_state == STATE_FATALERROR) ok = 1; break; case STATE_ERROR: if (new_state == STATE_SHUTDOWN || new_state == STATE_ERROR || new_state == STATE_FATALERROR || new_state == STATE_SELFTEST) ok = 1; break; case STATE_FATALERROR: if (new_state == STATE_SHUTDOWN ) ok = 1; break; case STATE_SHUTDOWN: /* We won't see any transition *from* Shutdown because the only allowed new state is Power-Off and that one can't be represented. */ break; } if (ok) { current_state = new_state; } unlock_fsm (); if (!ok || _gcry_log_verbosity (2)) log_info ("libgcrypt state transition %s => %s %s\n", state2str (last_state), state2str (new_state), ok? "granted":"denied"); if (!ok) { /* Invalid state transition. Halting library. */ #ifdef HAVE_SYSLOG syslog (LOG_USER|LOG_ERR, "Libgcrypt error: invalid state transition %s => %s", state2str (last_state), state2str (new_state)); #endif /*HAVE_SYSLOG*/ fips_noreturn (); } else if (new_state == STATE_ERROR || new_state == STATE_FATALERROR) { #ifdef HAVE_SYSLOG syslog (LOG_USER|LOG_WARNING, "Libgcrypt notice: state transition %s => %s", state2str (last_state), state2str (new_state)); #endif /*HAVE_SYSLOG*/ } }
/* 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 accidentally 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 = gpgrt_lock_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", gpg_strerror (err)); #ifdef HAVE_SYSLOG syslog (LOG_USER|LOG_ERR, "Libgcrypt error: " "creating FSM lock failed: %s - abort", gpg_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; }