Esempio n. 1
0
/****************
 * Resize the array of A to NLIMBS. The additional space is cleared
 * (set to 0).
 */
void
_gcry_mpi_resize (gcry_mpi_t a, unsigned nlimbs)
{
  size_t i;

  if (nlimbs <= a->alloced)
    {
      /* We only need to clear the new space (this is a nop if the
         limb space is already of the correct size. */
      for (i=a->nlimbs; i < a->alloced; i++)
        a->d[i] = 0;
      return;
    }

  /* Actually resize the limb space.  */
  if (a->d)
    {
      a->d = gcry_xrealloc (a->d, nlimbs * sizeof (mpi_limb_t));
      for (i=a->alloced; i < nlimbs; i++)
        a->d[i] = 0;
    }
  else
    {
      if (a->flags & 1)
	/* Secure memory is wanted.  */
	a->d = gcry_xcalloc_secure (nlimbs , sizeof (mpi_limb_t));
      else
	/* Standard memory.  */
	a->d = gcry_xcalloc (nlimbs , sizeof (mpi_limb_t));
    }
  a->alloced = nlimbs;
}
Esempio n. 2
0
static void
make_space ( struct make_space_ctx *c, size_t n )
{
    size_t used = c->pos - c->sexp->d;

    if ( used + n + sizeof(DATALEN) + 1 >= c->allocated ) {
	gcry_sexp_t newsexp;
	byte *newhead;

	c->allocated += 2*(n+sizeof(DATALEN)+1);
	newsexp = gcry_xrealloc ( c->sexp, sizeof *newsexp + c->allocated - 1 );
	newhead = newsexp->d;
	c->pos = newhead + used;
	c->sexp = newsexp;
    }
}
Esempio n. 3
0
/****************
 * Resize the array of A to NLIMBS. the additional space is cleared
 * (set to 0) [done by gcry_realloc()]
 */
void
_gcry_mpi_resize (gcry_mpi_t a, unsigned nlimbs)
{
  if (nlimbs <= a->alloced)
    return; /* no need to do it */

  if (a->d)
    a->d = gcry_xrealloc (a->d, nlimbs * sizeof (mpi_limb_t));
  else
    {
      if (a->flags & 1)
	/* Secure memory is wanted.  */
	a->d = gcry_xcalloc_secure (nlimbs , sizeof (mpi_limb_t));
      else
	/* Standard memory.  */
	a->d = gcry_xcalloc (nlimbs , sizeof (mpi_limb_t));
    }
  a->alloced = nlimbs;
}
Esempio n. 4
0
/* Fallback method using the registry to poll the statistics.  */
static void
registry_poll (void (*add)(const void*, size_t, enum random_origins),
               enum random_origins requester)
{
  static int cbPerfData = PERFORMANCE_BUFFER_SIZE;
  int iterations;
  DWORD dwSize, status;
  PERF_DATA_BLOCK *pPerfData;

  /* Get information from the system performance counters.  This can take a
     few seconds to do.  In some environments the call to RegQueryValueEx()
     can produce an access violation at some random time in the future, in
     some cases adding a short delay after the following code block makes
     the problem go away.  This problem is extremely difficult to
     reproduce, I haven't been able to get it to occur despite running it
     on a number of machines.  MS knowledge base article Q178887 covers
     this type of problem, it's typically caused by an external driver or
     other program that adds its own values under the
     HKEY_PERFORMANCE_DATA key.  The NT kernel, via Advapi32.dll, calls the
     required external module to map in the data inside an SEH try/except
     block, so problems in the module's collect function don't pop up until
     after it has finished, so the fault appears to occur in Advapi32.dll.
     There may be problems in the NT kernel as well though, a low-level
     memory checker indicated that ExpandEnvironmentStrings() in
     Kernel32.dll, called an interminable number of calls down inside
     RegQueryValueEx(), was overwriting memory (it wrote twice the
     allocated size of a buffer to a buffer allocated by the NT kernel).
     OTOH this could be coming from the external module calling back into
     the kernel, which eventually causes the problem described above.

     Possibly as an extension of the problem that the krnlWaitSemaphore()
     call above works around, running two instances of cryptlib (e.g. two
     applications that use it) under NT4 can result in one of them hanging
     in the RegQueryValueEx() call.  This happens only under NT4 and is
     hard to reproduce in any consistent manner.

     One workaround that helps a bit is to read the registry as a remote
     (rather than local) registry, it's possible that the use of a network
     RPC call isolates the calling app from the problem in that whatever
     service handles the RPC is taking the hit and not affecting the
     calling app.  Since this would require another round of extensive
     testing to verify and the NT native API call is working fine, we'll
     stick with the native API call for now.

     Some versions of NT4 had a problem where the amount of data returned
     was mis-reported and would never settle down, because of this the code
     below includes a safety-catch that bails out after 10 attempts have
     been made, this results in no data being returned but at does ensure
     that the thread will terminate.

     In addition to these problems the code in RegQueryValueEx() that
     estimates the amount of memory required to return the performance
     counter information isn't very accurate (it's much worse than the
     "slightly-inaccurate" level that the MS docs warn about, it's usually
     wildly off) since it always returns a worst-case estimate which is
     usually nowhere near the actual amount required.  For example it may
     report that 128K of memory is required, but only return 64K of data.

     Even worse than the registry-based performance counters is the
     performance data helper (PDH) shim that tries to make the counters
     look like the old Win16 API (which is also used by Win95).  Under NT
     this can consume tens of MB of memory and huge amounts of CPU time
     while it gathers its data, and even running once can still consume
     about 1/2MB of memory */
  if (getenv ("GNUPG_RNDW32_NOPERF"))
    {
      static int shown;

      if (!shown)
        {
          shown = 1;
          log_info ("note: get performance data has been disabled\n");
        }
    }
  else
    {
      pPerfData = gcry_xmalloc (cbPerfData);
      for (iterations=0; iterations < 10; iterations++)
        {
          dwSize = cbPerfData;
          if ( debug_me )
            log_debug ("rndw32#slow_gatherer_nt: get perf data\n" );

          status = RegQueryValueEx (HKEY_PERFORMANCE_DATA, "Global", NULL,
                                    NULL, (LPBYTE) pPerfData, &dwSize);
          if (status == ERROR_SUCCESS)
            {
              if (!memcmp (pPerfData->Signature, L"PERF", 8))
                (*add) ( pPerfData, dwSize, requester );
              else
                log_debug ("rndw32: no PERF signature\n");
              break;
            }
          else if (status == ERROR_MORE_DATA)
            {
              cbPerfData += PERFORMANCE_BUFFER_STEP;
              pPerfData = gcry_xrealloc (pPerfData, cbPerfData);
            }
          else
            {
              static int been_here;

              /* Silence the error message.  In particular under Wine (as
                 of 2008) we would get swamped with such diagnotiscs.  One
                 such diagnotiscs should be enough.  */
              if (been_here != status)
                {
                  been_here = status;
                  log_debug ("rndw32: get performance data problem: ec=%ld\n",
                             status);
                }
              break;
            }
        }
      gcry_free (pPerfData);
    }

  /* Although this isn't documented in the Win32 API docs, it's necessary
     to explicitly close the HKEY_PERFORMANCE_DATA key after use (it's
     implicitly opened on the first call to RegQueryValueEx()).  If this
     isn't done then any system components which provide performance data
     can't be removed or changed while the handle remains active.  */
  RegCloseKey (HKEY_PERFORMANCE_DATA);
}