/* This is one of our accountants. */ static THREAD_RET_TYPE accountant_thread (void *arg) { gpg_err_code_t rc; int i; int acc1, acc2; int value; (void)arg; #ifdef _WIN32 srand (time(NULL)*getpid()); /* Windows needs it per thread. */ #endif for (i = 0; i < N_TRANSACTIONS; i++) { rc = gpgrt_lock_lock (&accounts_lock); if (rc) fail ("gpgrt_lock_lock failed at %d: %s", __LINE__, gpg_strerror (rc)); acc1 = pick_account (); acc2 = pick_account (); value = pick_value (); account[acc1] += value; account[acc2] -= value; rc = gpgrt_lock_unlock (&accounts_lock); if (rc) fail ("gpgrt_lock_unlock failed at %d: %s", __LINE__,gpg_strerror (rc)); if (i && !(i%8)) gpgrt_yield (); } return THREAD_RET_VALUE; }
/* Release the pool lock. */ static void unlock_pool (void) { int err; pool_is_locked = 0; err = gpgrt_lock_unlock (&pool_lock); if (err) log_fatal ("failed to release the pool lock: %s\n", gpg_strerror (err)); }
/* Release the system_rng_lock. */ static void unlock_rng (void) { gpg_err_code_t rc; system_rng_is_locked = 0; rc = gpgrt_lock_unlock (&system_rng_lock); if (rc) log_fatal ("failed to release the System RNG lock: %s\n", gpg_strerror (rc)); }
static void unlock_fsm (void) { gpg_error_t err; err = gpgrt_lock_unlock (&fsm_lock); if (err) { log_info ("FATAL: failed to release the FSM lock in libgrypt: %s\n", gpg_strerror (err)); #ifdef HAVE_SYSLOG syslog (LOG_USER|LOG_ERR, "Libgcrypt error: " "releasing FSM lock failed: %s - abort", gpg_strerror (err)); #endif /*HAVE_SYSLOG*/ abort (); } }
/* This is the revision department. */ static THREAD_RET_TYPE revision_thread (void *arg) { gpg_err_code_t rc; int i = 0; (void)arg; while (!stop_revision_thread) { rc = gpgrt_lock_lock (&accounts_lock); if (rc) fail ("gpgrt_lock_lock failed at %d: %s", __LINE__, gpg_strerror (rc)); check_accounts (); rc = gpgrt_lock_unlock (&accounts_lock); if (rc) fail ("gpgrt_lock_unlock failed at %d: %s", __LINE__,gpg_strerror (rc)); if (!(++i%7)) gpgrt_yield (); } return THREAD_RET_VALUE; }
/* Create an unpredicable nonce of LENGTH bytes in BUFFER. */ void _gcry_create_nonce (void *buffer, size_t length) { static unsigned char nonce_buffer[20+8]; static int nonce_buffer_initialized = 0; static volatile pid_t my_pid; /* The volatile is there to make sure the compiler does not optimize the code away in case the getpid function is badly attributed. */ volatile pid_t apid; unsigned char *p; size_t n; int err; /* First check whether we shall use the FIPS nonce generator. This is only done in FIPS mode, in all other modes, we use our own nonce generator which is seeded by the RNG actual in use. */ if (fips_mode ()) { _gcry_rngfips_create_nonce (buffer, length); return; } /* This is the nonce generator, which formerly lived in random-csprng.c. It is now used by all RNG types except when in FIPS mode (not that this means it is also used if the FIPS RNG has been selected but we are not in fips mode). */ /* Make sure we are initialized. */ _gcry_random_initialize (1); /* Acquire the nonce buffer lock. */ err = gpgrt_lock_lock (&nonce_buffer_lock); if (err) log_fatal ("failed to acquire the nonce buffer lock: %s\n", gpg_strerror (err)); apid = getpid (); /* The first time initialize our buffer. */ if (!nonce_buffer_initialized) { time_t atime = time (NULL); pid_t xpid = apid; my_pid = apid; if ((sizeof apid + sizeof atime) > sizeof nonce_buffer) BUG (); /* Initialize the first 20 bytes with a reasonable value so that a failure of gcry_randomize won't affect us too much. Don't care about the uninitialized remaining bytes. */ p = nonce_buffer; memcpy (p, &xpid, sizeof xpid); p += sizeof xpid; memcpy (p, &atime, sizeof atime); /* Initialize the never changing private part of 64 bits. */ _gcry_randomize (nonce_buffer+20, 8, GCRY_WEAK_RANDOM); nonce_buffer_initialized = 1; } else if ( my_pid != apid ) { /* We forked. Need to reseed the buffer - doing this for the private part should be sufficient. */ do_randomize (nonce_buffer+20, 8, GCRY_WEAK_RANDOM); /* Update the pid so that we won't run into here again and again. */ my_pid = apid; } /* Create the nonce by hashing the entire buffer, returning the hash and updating the first 20 bytes of the buffer with this hash. */ for (p = buffer; length > 0; length -= n, p += n) { _gcry_sha1_hash_buffer (nonce_buffer, nonce_buffer, sizeof nonce_buffer); n = length > 20? 20 : length; memcpy (p, nonce_buffer, n); } /* Release the nonce buffer lock. */ err = gpgrt_lock_unlock (&nonce_buffer_lock); if (err) log_fatal ("failed to release the nonce buffer lock: %s\n", gpg_strerror (err)); }