diff options
author | René Schümann <white06tiger@gmail.com> | 2015-03-14 19:56:55 +0000 |
---|---|---|
committer | René Schümann <white06tiger@gmail.com> | 2015-03-14 19:56:55 +0000 |
commit | c60aed5432e9cda277b9351de51e82dfb8e02475 (patch) | |
tree | 97ccd1ea8e2544f6a9673ee7d04c18b714877a35 /plugins/MirOTR/libgcrypt-1.4.6/src/fips.c | |
parent | d2b26b1f86326362f56540b5185fa09ab5f2779c (diff) |
MirOTR: part one of many file/folder structure changes
git-svn-id: http://svn.miranda-ng.org/main/trunk@12402 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/MirOTR/libgcrypt-1.4.6/src/fips.c')
-rw-r--r-- | plugins/MirOTR/libgcrypt-1.4.6/src/fips.c | 852 |
1 files changed, 0 insertions, 852 deletions
diff --git a/plugins/MirOTR/libgcrypt-1.4.6/src/fips.c b/plugins/MirOTR/libgcrypt-1.4.6/src/fips.c deleted file mode 100644 index 8709dae96d..0000000000 --- a/plugins/MirOTR/libgcrypt-1.4.6/src/fips.c +++ /dev/null @@ -1,852 +0,0 @@ -/* fips.c - FIPS mode management - * 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/>. - */ - -#include <config.h> -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <unistd.h> -#include <string.h> -#ifdef ENABLE_HMAC_BINARY_CHECK -# include <dlfcn.h> -#endif -#ifdef HAVE_SYSLOG -# include <syslog.h> -#endif /*HAVE_SYSLOG*/ - -#include "g10lib.h" -#include "ath.h" -#include "cipher-proto.h" -#include "hmac256.h" - - -/* The name of the file used to foce libgcrypt into fips mode. */ -#define FIPS_FORCE_FILE "/etc/gcrypt/fips_enabled" - - -/* The states of the finite state machine used in fips mode. */ -enum module_states - { - /* POWEROFF cannot be represented. */ - STATE_POWERON = 0, - STATE_INIT, - STATE_SELFTEST, - STATE_OPERATIONAL, - STATE_ERROR, - STATE_FATALERROR, - STATE_SHUTDOWN - }; - - -/* Flag telling whether we are in fips mode. It uses inverse logic so - that fips mode is the default unless changed by the intialization - code. To check whether fips mode is enabled, use the function - fips_mode()! */ -static int no_fips_mode_required; - -/* Flag to indicate that we are in the enforced FIPS mode. */ -static int enforced_fips_mode; - -/* If this flag is set, the application may no longer assume that the - process is running in FIPS mode. This flag is protected by the - FSM_LOCK. */ -static int inactive_fips_mode; - -/* This is the lock we use to protect the FSM. */ -static ath_mutex_t fsm_lock = ATH_MUTEX_INITIALIZER; - -/* The current state of the FSM. The whole state machinery is only - used while in fips mode. Change this only while holding fsm_lock. */ -static enum module_states current_state; - - - - - -static void fips_new_state (enum module_states new_state); - - - -/* Convert lowercase hex digits; assumes valid hex digits. */ -#define loxtoi_1(p) (*(p) <= '9'? (*(p)- '0'): (*(p)-'a'+10)) -#define loxtoi_2(p) ((loxtoi_1(p) * 16) + loxtoi_1((p)+1)) - -/* Returns true if P points to a lowercase hex digit. */ -#define loxdigit_p(p) !!strchr ("01234567890abcdef", *(p)) - - - -/* 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; -} - -static void -lock_fsm (void) -{ - gpg_error_t err; - - err = ath_mutex_lock (&fsm_lock); - if (err) - { - log_info ("FATAL: failed to acquire the FSM lock in libgrypt: %s\n", - strerror (err)); -#ifdef HAVE_SYSLOG - syslog (LOG_USER|LOG_ERR, "Libgcrypt error: " - "acquiring FSM lock failed: %s - abort", - strerror (err)); -#endif /*HAVE_SYSLOG*/ - abort (); - } -} - -static void -unlock_fsm (void) -{ - gpg_error_t err; - - err = ath_mutex_unlock (&fsm_lock); - if (err) - { - log_info ("FATAL: failed to release the FSM lock in libgrypt: %s\n", - strerror (err)); -#ifdef HAVE_SYSLOG - syslog (LOG_USER|LOG_ERR, "Libgcrypt error: " - "releasing FSM lock failed: %s - abort", - strerror (err)); -#endif /*HAVE_SYSLOG*/ - abort (); - } -} - - -/* This function returns true if fips mode is enabled. This is - independent of the fips required finite state machine and only used - to enable fips specific code. Please use the fips_mode macro - instead of calling this function directly. */ -int -_gcry_fips_mode (void) -{ - /* No locking is required because we have the requirement that this - variable is only initialized once with no other threads - existing. */ - return !no_fips_mode_required; -} - - -/* Return a flag telling whether we are in the enforced fips mode. */ -int -_gcry_enforced_fips_mode (void) -{ - return enforced_fips_mode; -} - - -/* If we do not want to enforce the fips mode, we can set a flag so - that the application may check whether it is still in fips mode. - TEXT will be printed as part of a syslog message. This function - may only be be called if in fips mode. */ -void -_gcry_inactivate_fips_mode (const char *text) -{ - gcry_assert (_gcry_fips_mode ()); - - if (_gcry_enforced_fips_mode () ) - { - /* Get us into the error state. */ - fips_signal_error (text); - return; - } - - lock_fsm (); - if (!inactive_fips_mode) - { - inactive_fips_mode = 1; - unlock_fsm (); -#ifdef HAVE_SYSLOG - syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: " - "%s - FIPS mode inactivated", text); -#endif /*HAVE_SYSLOG*/ - } - else - unlock_fsm (); -} - - -/* Return the FIPS mode inactive flag. If it is true the FIPS mode is - not anymore active. */ -int -_gcry_is_fips_mode_inactive (void) -{ - int flag; - - if (!_gcry_fips_mode ()) - return 0; - lock_fsm (); - flag = inactive_fips_mode; - unlock_fsm (); - return flag; -} - - - -static const char * -state2str (enum module_states state) -{ - const char *s; - - switch (state) - { - case STATE_POWERON: s = "Power-On"; break; - case STATE_INIT: s = "Init"; break; - case STATE_SELFTEST: s = "Self-Test"; break; - case STATE_OPERATIONAL: s = "Operational"; break; - case STATE_ERROR: s = "Error"; break; - case STATE_FATALERROR: s = "Fatal-Error"; break; - case STATE_SHUTDOWN: s = "Shutdown"; break; - default: s = "?"; break; - } - return s; -} - - -/* Return true if the library is in the operational state. */ -int -_gcry_fips_is_operational (void) -{ - int result; - - if (!fips_mode ()) - result = 1; - else - { - lock_fsm (); - if (current_state == STATE_INIT) - { - /* If we are still in the INIT state, we need to run the - selftests so that the FSM can eventually get into - operational state. Given that we would need a 2-phase - initialization of libgcrypt, but that has traditionally - not been enforced, we use this on demand self-test - checking. Note that Proper applications would do the - application specific libgcrypt initialization between a - gcry_check_version() and gcry_control - (GCRYCTL_INITIALIZATION_FINISHED) where the latter will - run the selftests. The drawback of these on-demand - self-tests are a small chance that self-tests are - performed by severeal threads; that is no problem because - our FSM make sure that we won't oversee any error. */ - unlock_fsm (); - _gcry_fips_run_selftests (0); - lock_fsm (); - } - - result = (current_state == STATE_OPERATIONAL); - unlock_fsm (); - } - return result; -} - - -/* This is test on wether the library is in the operational state. In - contrast to _gcry_fips_is_operational this function won't do a - state transition on the fly. */ -int -_gcry_fips_test_operational (void) -{ - int result; - - if (!fips_mode ()) - result = 1; - else - { - lock_fsm (); - result = (current_state == STATE_OPERATIONAL); - unlock_fsm (); - } - return result; -} - - -/* This is a test on whether the library is in the error or - operational state. */ -int -_gcry_fips_test_error_or_operational (void) -{ - int result; - - if (!fips_mode ()) - result = 1; - else - { - lock_fsm (); - result = (current_state == STATE_OPERATIONAL - || current_state == STATE_ERROR); - unlock_fsm (); - } - return result; -} - - -static void -reporter (const char *domain, int algo, const char *what, const char *errtxt) -{ - if (!errtxt && !_gcry_log_verbosity (2)) - return; - - log_info ("libgcrypt selftest: %s %s%s (%d): %s%s%s%s\n", - !strcmp (domain, "hmac")? "digest":domain, - !strcmp (domain, "hmac")? "HMAC-":"", - !strcmp (domain, "cipher")? _gcry_cipher_algo_name (algo) : - !strcmp (domain, "digest")? _gcry_md_algo_name (algo) : - !strcmp (domain, "hmac")? _gcry_md_algo_name (algo) : - !strcmp (domain, "pubkey")? _gcry_pk_algo_name (algo) : "", - algo, errtxt? errtxt:"Okay", - what?" (":"", what? what:"", what?")":""); -} - -/* Run self-tests for all required cipher algorithms. Return 0 on - success. */ -static int -run_cipher_selftests (int extended) -{ - static int algos[] = - { - GCRY_CIPHER_3DES, - GCRY_CIPHER_AES128, - GCRY_CIPHER_AES192, - GCRY_CIPHER_AES256, - 0 - }; - int idx; - gpg_error_t err; - int anyerr = 0; - - for (idx=0; algos[idx]; idx++) - { - err = _gcry_cipher_selftest (algos[idx], extended, reporter); - reporter ("cipher", algos[idx], NULL, - err? gpg_strerror (err):NULL); - if (err) - anyerr = 1; - } - return anyerr; -} - - -/* Run self-tests for all required hash algorithms. Return 0 on - success. */ -static int -run_digest_selftests (int extended) -{ - static int algos[] = - { - GCRY_MD_SHA1, - GCRY_MD_SHA224, - GCRY_MD_SHA256, - GCRY_MD_SHA384, - GCRY_MD_SHA512, - 0 - }; - int idx; - gpg_error_t err; - int anyerr = 0; - - for (idx=0; algos[idx]; idx++) - { - err = _gcry_md_selftest (algos[idx], extended, reporter); - reporter ("digest", algos[idx], NULL, - err? gpg_strerror (err):NULL); - if (err) - anyerr = 1; - } - return anyerr; -} - - -/* Run self-tests for all HMAC algorithms. Return 0 on success. */ -static int -run_hmac_selftests (int extended) -{ - static int algos[] = - { - GCRY_MD_SHA1, - GCRY_MD_SHA224, - GCRY_MD_SHA256, - GCRY_MD_SHA384, - GCRY_MD_SHA512, - 0 - }; - int idx; - gpg_error_t err; - int anyerr = 0; - - for (idx=0; algos[idx]; idx++) - { - err = _gcry_hmac_selftest (algos[idx], extended, reporter); - reporter ("hmac", algos[idx], NULL, - err? gpg_strerror (err):NULL); - if (err) - anyerr = 1; - } - return anyerr; -} - - -/* Run self-tests for all required public key algorithms. Return 0 on - success. */ -static int -run_pubkey_selftests (int extended) -{ - static int algos[] = - { - GCRY_PK_RSA, - GCRY_PK_DSA, - /* GCRY_PK_ECDSA is not enabled in fips mode. */ - 0 - }; - int idx; - gpg_error_t err; - int anyerr = 0; - - for (idx=0; algos[idx]; idx++) - { - err = _gcry_pk_selftest (algos[idx], extended, reporter); - reporter ("pubkey", algos[idx], NULL, - err? gpg_strerror (err):NULL); - if (err) - anyerr = 1; - } - return anyerr; -} - - -/* Run self-tests for the random number generator. Returns 0 on - success. */ -static int -run_random_selftests (void) -{ - gpg_error_t err; - - err = _gcry_random_selftest (reporter); - reporter ("random", 0, NULL, err? gpg_strerror (err):NULL); - - return !!err; -} - -/* Run an integrity check on the binary. Returns 0 on success. */ -static int -check_binary_integrity (void) -{ -#ifdef ENABLE_HMAC_BINARY_CHECK - gpg_error_t err; - Dl_info info; - unsigned char digest[32]; - int dlen; - char *fname = NULL; - const char key[] = "What am I, a doctor or a moonshuttle conductor?"; - - if (!dladdr ("gcry_check_version", &info)) - err = gpg_error_from_syserror (); - else - { - dlen = _gcry_hmac256_file (digest, sizeof digest, info.dli_fname, - key, strlen (key)); - if (dlen < 0) - err = gpg_error_from_syserror (); - else if (dlen != 32) - err = gpg_error (GPG_ERR_INTERNAL); - else - { - fname = gcry_malloc (strlen (info.dli_fname) + 1 + 5 + 1 ); - if (!fname) - err = gpg_error_from_syserror (); - else - { - FILE *fp; - char *p; - - /* Prefix the basename with a dot. */ - strcpy (fname, info.dli_fname); - p = strrchr (fname, '/'); - if (p) - p++; - else - p = fname; - memmove (p+1, p, strlen (p)+1); - *p = '.'; - strcat (fname, ".hmac"); - - /* Open the file. */ - fp = fopen (fname, "r"); - if (!fp) - err = gpg_error_from_syserror (); - else - { - /* A buffer of 64 bytes plus one for a LF and one to - detect garbage. */ - unsigned char buffer[64+1+1]; - const unsigned char *s; - int n; - - /* The HMAC files consists of lowercase hex digits - only with an optional trailing linefeed. Fail if - there is any garbage. */ - err = gpg_error (GPG_ERR_SELFTEST_FAILED); - n = fread (buffer, 1, sizeof buffer, fp); - if (n == 64 || (n == 65 && buffer[64] == '\n')) - { - buffer[64] = 0; - for (n=0, s= buffer; - n < 32 && loxdigit_p (s) && loxdigit_p (s+1); - n++, s += 2) - buffer[n] = loxtoi_2 (s); - if ( n == 32 && !memcmp (digest, buffer, 32) ) - err = 0; - } - fclose (fp); - } - } - } - } - reporter ("binary", 0, fname, err? gpg_strerror (err):NULL); -#ifdef HAVE_SYSLOG - if (err) - syslog (LOG_USER|LOG_ERR, "Libgcrypt error: " - "integrity check using `%s' failed: %s", - fname? fname:"[?]", gpg_strerror (err)); -#endif /*HAVE_SYSLOG*/ - gcry_free (fname); - return !!err; -#else - return 0; -#endif -} - - -/* Run the self-tests. If EXTENDED is true, extended versions of the - selftest are run, that is more tests than required by FIPS. */ -gpg_err_code_t -_gcry_fips_run_selftests (int extended) -{ - enum module_states result = STATE_ERROR; - gcry_err_code_t ec = GPG_ERR_SELFTEST_FAILED; - - if (fips_mode ()) - fips_new_state (STATE_SELFTEST); - - if (run_cipher_selftests (extended)) - goto leave; - - if (run_digest_selftests (extended)) - goto leave; - - if (run_hmac_selftests (extended)) - goto leave; - - /* Run random tests before the pubkey tests because the latter - require random. */ - if (run_random_selftests ()) - goto leave; - - if (run_pubkey_selftests (extended)) - goto leave; - - /* Now check the integrity of the binary. We do this this after - having checked the HMAC code. */ - if (check_binary_integrity ()) - goto leave; - - /* All selftests passed. */ - result = STATE_OPERATIONAL; - ec = 0; - - leave: - if (fips_mode ()) - fips_new_state (result); - - return ec; -} - - -/* This function is used to tell the FSM about errors in the library. - The FSM will be put into an error state. This function should not - be called directly but by one of the macros - - fips_signal_error (description) - fips_signal_fatal_error (description) - - where DESCRIPTION is a string describing the error. */ -void -_gcry_fips_signal_error (const char *srcfile, int srcline, const char *srcfunc, - int is_fatal, const char *description) -{ - if (!fips_mode ()) - return; /* Not required. */ - - /* Set new state before printing an error. */ - fips_new_state (is_fatal? STATE_FATALERROR : STATE_ERROR); - - /* Print error. */ - log_info ("%serror in libgcrypt, file %s, line %d%s%s: %s\n", - is_fatal? "fatal ":"", - srcfile, srcline, - srcfunc? ", function ":"", srcfunc? srcfunc:"", - description? description : "no description available"); -#ifdef HAVE_SYSLOG - syslog (LOG_USER|LOG_ERR, "Libgcrypt error: " - "%serror in file %s, line %d%s%s: %s", - is_fatal? "fatal ":"", - srcfile, srcline, - srcfunc? ", function ":"", srcfunc? srcfunc:"", - description? description : "no description available"); -#endif /*HAVE_SYSLOG*/ -} - - -/* 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*/ - } -} - - - - -/* This function should be called to ensure that the execution shall - not continue. */ -void -_gcry_fips_noreturn (void) -{ -#ifdef HAVE_SYSLOG - syslog (LOG_USER|LOG_ERR, "Libgcrypt terminated the application"); -#endif /*HAVE_SYSLOG*/ - fflush (NULL); - abort (); - /*NOTREACHED*/ -} |