Ejemplo n.º 1
0
/* ----------------------------------------------------------------------
 * allocate an object from the pool.  if there are free objects in
 * the pool, the allocation will happen immediately.  otherwise, we
 * will sleep for up to 'timeout' microseconds waiting for an object
 * to be released.
 *
 * timeout of 0xffffffff means 'wait forever';  0 means 'do not wait'.
 *
 * returns (opaque) pointer to the newly allocated object, or NULL on
 * failure (ie. even after 'timeout' there were still no free objects)
 *
 * a newly allocated object will have its reference count initialised
 * to 1.
 * -------------------------------------------------------------------- */
VC_POOL_OBJECT_T *
vc_pool_alloc( VC_POOL_T *pool, size_t size, uint32_t timeout )
{
   VC_POOL_OBJECT_T *object;
   vcos_assert( pool->magic == POOL_MAGIC );

   // wait for an object to become free
   for (;;) {
      lock_pool( pool );
      object = alloc_object( pool, size );
      unlock_pool( pool );

      if ( object )
         break;

      if ( wait_event(pool,timeout) )
      {
         pool->alloc_fails++;
         return NULL; // timed out
      }
   }

   pool_object_logging( __FUNCTION__, object );
   return object;
}
Ejemplo n.º 2
0
/* Full initialization of this module. */
static void
initialize(void)
{
  /* Although the basic initialization should have happened already,
     we call it here to make sure that all prerequisites are met.  */
  initialize_basics ();

  /* Now we can look the pool and complete the initialization if
     necessary.  */
  lock_pool ();
  if (!rndpool)
    {
      /* The data buffer is allocated somewhat larger, so that we can
         use this extra space (which is allocated in secure memory) as
         a temporary hash buffer */
      rndpool = (secure_alloc
                 ? xcalloc_secure (1, POOLSIZE + BLOCKLEN)
                 : xcalloc (1, POOLSIZE + BLOCKLEN));
      keypool = (secure_alloc
                 ? xcalloc_secure (1, POOLSIZE + BLOCKLEN)
                 : xcalloc (1, POOLSIZE + BLOCKLEN));

      /* Setup the slow entropy gathering function.  The code requires
         that this function exists. */
      slow_gather_fnc = getfnc_gather_random ();

      /* Setup the fast entropy gathering function.  */
      fast_gather_fnc = getfnc_fast_random_poll ();

    }
  unlock_pool ();
}
Ejemplo n.º 3
0
/* ----------------------------------------------------------------------
 * increase the refcount of a pool object
 *
 * return the new refcount
 * -------------------------------------------------------------------- */
int
vc_pool_acquire( VC_POOL_OBJECT_T *object )
{
   vcos_assert( object->magic == OBJECT_MAGIC );
   lock_pool( object->pool );
   int refcount = ++object->refcount;
   pool_object_logging( __FUNCTION__, object );
   unlock_pool( object->pool );
   return refcount;
}
Ejemplo n.º 4
0
/* Try to close the FDs of the random gather module.  This is
   currently only implemented for rndlinux. */
void
_gcry_rngcsprng_close_fds (void)
{
  lock_pool ();
#if USE_RNDLINUX
  _gcry_rndlinux_gather_random (NULL, 0, 0, 0);
  pool_filled = 0; /* Force re-open on next use.  */
#endif
  unlock_pool ();
}
Ejemplo n.º 5
0
/* Public function to fill the buffer with LENGTH bytes of
   cryptographically strong random bytes.  Level GCRY_WEAK_RANDOM is
   not very strong, GCRY_STRONG_RANDOM is strong enough for most
   usage, GCRY_VERY_STRONG_RANDOM is good for key generation stuff but
   may be very slow.  */
void
_gcry_rngcsprng_randomize (void *buffer, size_t length,
						   enum gcry_random_level level)
{
  unsigned char *p;

  /* Make sure we are initialized. */
  initialize ();

  /* Handle our hack used for regression tests of Libgcrypt. */
  if ( quick_test && level > GCRY_STRONG_RANDOM )
	level = GCRY_STRONG_RANDOM;

  /* Make sure the level is okay. */
  level &= 3;

#ifdef USE_RANDOM_DAEMON
  if (allow_daemon
	  && !_gcry_daemon_randomize (daemon_socket_name, buffer, length, level))
	return; /* The daemon succeeded. */
  allow_daemon = 0; /* Daemon failed - switch off. */
#endif /*USE_RANDOM_DAEMON*/

  /* Acquire the pool lock. */
  lock_pool ();

  /* Update the statistics. */
  if (level >= GCRY_VERY_STRONG_RANDOM)
	{
	  rndstats.getbytes2 += length;
	  rndstats.ngetbytes2++;
	}
  else
	{
	  rndstats.getbytes1 += length;
	  rndstats.ngetbytes1++;
	}

  /* Read the random into the provided buffer. */
  for (p = buffer; length > 0;)
	{
	  size_t n;

	  n = length > POOLSIZE? POOLSIZE : length;
	  read_pool (p, n, level);
	  length -= n;
	  p += n;
	}

  /* Release the pool lock. */
  unlock_pool ();
}
Ejemplo n.º 6
0
/* The fast random pool function as called at some places in
   libgcrypt.  This is merely a wrapper to make sure that this module
   is initalized and to look the pool.  Note, that this function is a
   NOP unless a random function has been used or _gcry_initialize (1)
   has been used.  We use this hack so that the internal use of this
   function in cipher_open and md_open won't start filling up the
   random pool, even if no random will be required by the process. */
void
_gcry_rngcsprng_fast_poll (void)
{
  initialize_basics ();

  lock_pool ();
  if (rndpool)
	{
	  /* Yes, we are fully initialized. */
	  do_fast_random_poll ();
	}
  unlock_pool ();
}
Ejemplo n.º 7
0
/**
 * Delete a queue.
 *
 * Free a whole queue.
 * @param queue - The queue to free.
 */
void queue_delete(T_QUEUE queue, OS_ERR_TYPE* err)
{
    OS_ERR_TYPE _err;
    queue_impl_t * q = (queue_impl_t*) queue;
    T_EXEC_LEVEL execLvl = _getExecLevel();
    uint32_t data;
    T_QUEUE_MESSAGE p_msg = &data;

    /* check execution level */
    if ((E_EXEC_LVL_FIBER == execLvl) || (E_EXEC_LVL_TASK == execLvl))
    {
        lock_pool();
        if (queue_used(q) && q->sema != NULL)
        {

            /* first empty the queue before to delete it to free all the elements */
            do{
                queue_get_message(q, &p_msg, OS_NO_WAIT, &_err);
            }while(_err == E_OS_OK);

            if(_err == E_OS_ERR_EMPTY)
            {
                semaphore_delete(q->sema, &_err);
                q->sema = NULL;
                if( _err == E_OS_OK)
                {
                    queue_free(q);
                    error_management (err, E_OS_OK);
                }
                else
                {
                    panic(E_OS_ERR_UNKNOWN);    // Panic because we should never reach this point.
                }
            }
            else
            {
                error_management (err, E_OS_ERR);
            }
        }
        else
        {
            error_management (err, E_OS_ERR);
        }
        unlock_pool();
    }
    else
    {
        error_management (err, E_OS_ERR_NOT_ALLOWED);
    }
    return;
}
Ejemplo n.º 8
0
/* ----------------------------------------------------------------------
 * decrease the refcount of a pool object.  if the refcount hits 0,
 * the object is treated as being returned to the pool as free; update
 * pool struct accordingly (and potentially wakeup any sleepers)
 *
 * return the new refcount
 * -------------------------------------------------------------------- */
int
vc_pool_release( VC_POOL_OBJECT_T *object )
{
   vcos_assert( object->magic == OBJECT_MAGIC );
   lock_pool( object->pool );
   int refcount = --object->refcount;
   pool_object_logging( __FUNCTION__, object );
   if ( refcount == 0 ) {
      free_object( object );
      signal_event( object->pool );
   }
   unlock_pool( object->pool );
   return refcount;
}
Ejemplo n.º 9
0
/**
 * @brief Get a buffer from the pool
 *
 * @param bphp Pointer to buffer pool handle structure.
 * @return Pointer to a buffer reference structure.
 *
 */
BPCF_BUFFER_REF* mmpool_getbuff(BPOOL_HANDLE* bphp) {
	BPCF_BUFFER_REF* buff_refp = NULL;
	BPOOL_INDEX bpx;
	lock_pool(bphp);
	if (!dq_rtd(&bphp->bpmf_recp->dq_inpool, &bpx)) {
		// Get reference to the buffer
		buff_refp = mmpool_buffx2refp(bphp, bpx);
		// Add the buffer to the out of pool deque
		dq_abd(&bphp->bpmf_recp->dq_outpool, &bpx);
		bphp->bpmf_recp->stats.remaining--;
	}
	unlock_pool(bphp);
	return buff_refp;
}
Ejemplo n.º 10
0
/* ----------------------------------------------------------------------
 * destroy a pool of objects.  if none of the pool objects are in use,
 * the destroy will happen immediately.  otherwise, we will sleep for
 * up to 'timeout' microseconds waiting for the objects to be released.
 *
 * timeout of 0xffffffff means 'wait forever';  0 means 'do not wait'.
 *
 * returns 0 on success, -1 on error (ie. even after 'timeout' there
 * were still objects in use)
 * -------------------------------------------------------------------- */
int32_t
vc_pool_destroy( VC_POOL_T *pool, uint32_t timeout )
{
   int i;
   vcos_assert( pool->magic == POOL_MAGIC );

   // wait for all objects to become free
   for (;;) {
      lock_pool( pool );
      if ( pool->allocated == 0 )
         break;
      unlock_pool( pool );
      if ( wait_event(pool,timeout) )
         return -1; // timed out
   }

   if ( pool->mem != MEM_INVALID_HANDLE ) {

      // just a single memory object to free
      mem_release( pool->mem );

   } else {

      // release individual pool entries back to mempool
      for (i=0; i<pool->nobjects; i++)
         mem_release( pool->object[i].mem );

   }

   // remove from the global list
   rtos_latch_get(&pool_list_latch);
   VC_POOL_T **pp = &vc_pool_list;
   while (*pp != pool)
   {
      pp = &((*pp)->next);
   }
   vcos_assert(*pp);
   *pp = pool->next;
   rtos_latch_put(&pool_list_latch);


   // kill the pool struct
   pool->magic = 0;
   destroy_event( pool );
   rtos_priorityfree( pool );
   return 0;
}
Ejemplo n.º 11
0
/**
 * @brief Return a buffer to the pool.
 *
 * @param bphp Pointer to buffer pool handle structure.
 * @param buffp Pointer to buffer reference structure of buffer to return
 * @return Pointer to a buffer reference structure.
 * @return 0 if successful, non-zero error code otherwise.
 */
int mmpool_putbuff(BPOOL_HANDLE* bphp, BPCF_BUFFER_REF* buffp) {
	int error = 0;
	lock_pool(bphp);
	/*
	 * Search the out of pool deque for the item. 
	 */
	if (search_deque(&bphp->bpmf_recp->dq_outpool, buffp->bpindex)) {
		// Found a match ...  do the deallocation.
		dq_abd(&bphp->bpmf_recp->dq_inpool, &buffp->bpindex);
		bphp->bpmf_recp->stats.remaining++;
	} else {
		// The buffer pool index of the passed reference is NOT
		// in use ... this is an error condition
		error = 1;
	}
	unlock_pool(bphp);
	return error;
}
Ejemplo n.º 12
0
/**
 * Create a message queue.
 *
 *     Create a message queue.
 *     This service may panic if err parameter is NULL and:
 *     -# no queue is available, or
 *     -# when called from an ISR.
 *
 *     Authorized execution levels:  task, fiber.
 *
 *     As for semaphores and mutexes, queues are picked from a pool of
 *     statically-allocated objects.
 *
 * @param maxSize: maximum number of  messages in the queue.
 *     (Rationale: queues only contain pointer to messages)
 *
 * @param err (out): execution status:
 *          -# E_OS_OK : queue was created
 *          -# E_OS_ERR: all queues from the pool are already being used
 *          -# E_OS_ERR_NOT_ALLOWED: service cannot be executed from ISR context.
 *
 * @return Handler on the created queue.
 *     NULL if all allocated queues are already being used.
 */
T_QUEUE queue_create(uint32_t max_size, OS_ERR_TYPE* err)
{
    queue_impl_t * q = NULL;
    T_EXEC_LEVEL execLvl = _getExecLevel();
    OS_ERR_TYPE _err;


    if(max_size==0 || max_size>QUEUE_ELEMENT_POOL_SIZE)
    {
        error_management (err, E_OS_ERR);
        return NULL;
    }

    /* check execution level */
    if ((E_EXEC_LVL_FIBER == execLvl) || (E_EXEC_LVL_TASK == execLvl))
    {
        /* Block concurrent accesses to the pool of queue_list */
        lock_pool();
        q = queue_alloc();
        unlock_pool();

        if (q != NULL)
        {
           list_init(&q->_list);  // replace the following commented code
           q->current_size = 0;
           q->max_size = max_size;
           q->sema = semaphore_create(0, &_err);
           error_management (err, _err);
        }
        else
        {
            error_management (err, E_OS_ERR);
        }
    }
    else
    {
        error_management (err, E_OS_ERR_NOT_ALLOWED);
    }

    return (T_QUEUE)q;
}
Ejemplo n.º 13
0
/* Add BUFLEN bytes from BUF to the internal random pool.  QUALITY
   should be in the range of 0..100 to indicate the goodness of the
   entropy added, or -1 for goodness not known.  */
gcry_error_t
_gcry_rngcsprng_add_bytes (const void *buf, size_t buflen, int quality)
{
  size_t nbytes;
  const char *bufptr;

  if (quality == -1)
	quality = 35;
  else if (quality > 100)
	quality = 100;
  else if (quality < 0)
	quality = 0;
	  
  if (!buf)
	return gpg_error (GPG_ERR_INV_ARG);

  if (!buflen || quality < 10)
	return 0; /* Take a shortcut. */

  /* Because we don't increment the entropy estimation with FASTPOLL,
	 we don't need to take lock that estimation while adding from an
	 external source.  This limited entropy estimation also means that
	 we can't take QUALITY into account.  */
  initialize_basics ();
  bufptr = buf;
  while (buflen)
	{
	  nbytes = buflen > POOLSIZE? POOLSIZE : buflen;
	  lock_pool ();
	  if (rndpool)
		add_randomness (bufptr, nbytes, RANDOM_ORIGIN_EXTERNAL);
	  unlock_pool ();
	  bufptr += nbytes;
	  buflen -= nbytes;
	}
  return 0;
}   
Ejemplo n.º 14
0
void
_gcry_rngcsprng_update_seed_file (void)
{
  unsigned long *sp, *dp;
  int fd, i;

  /* We do only a basic initialization so that we can lock the pool.
	 This is required to cope with the case that this function is
	 called by some cleanup code at a point where the RNG has never
	 been initialized.  */
  initialize_basics ();
  lock_pool ();

  if ( !seed_file_name || !rndpool || !pool_filled )
	{
	  unlock_pool ();
	  return;
	}
  if ( !allow_seed_file_update )
	{
	  unlock_pool ();
	  log_info(_("note: random_seed file not updated\n"));
	  return;
	}

  /* At this point we know that there is something in the pool and
	 thus we can conclude that the pool has been fully initialized.  */


  /* Copy the entropy pool to a scratch pool and mix both of them. */
  for (i=0,dp=(unsigned long*)keypool, sp=(unsigned long*)rndpool;
	   i < POOLWORDS; i++, dp++, sp++ ) 
	{
	  *dp = *sp + ADD_VALUE;
	}
  mix_pool(rndpool); rndstats.mixrnd++;
  mix_pool(keypool); rndstats.mixkey++;

#if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__)
  fd = open (seed_file_name, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,
			 S_IRUSR|S_IWUSR );
#else
# if LOCK_SEED_FILE
	fd = open (seed_file_name, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR );
# else
	fd = open (seed_file_name, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR );
# endif
#endif

  if (fd == -1 )
	log_info (_("can't create `%s': %s\n"), seed_file_name, strerror(errno) );
  else if (lock_seed_file (fd, seed_file_name, 1))
	{
	  close (fd);
	}
#if LOCK_SEED_FILE
  else if (ftruncate (fd, 0))
	{
	  log_info(_("can't write `%s': %s\n"), seed_file_name, strerror(errno));
	  close (fd);
	}
#endif /*LOCK_SEED_FILE*/
  else 
	{
	  do
		{
		  i = write (fd, keypool, POOLSIZE );
		} 
	  while (i == -1 && errno == EINTR);
	  if (i != POOLSIZE) 
		log_info (_("can't write `%s': %s\n"),seed_file_name, strerror(errno));
	  if (close(fd))
		log_info (_("can't close `%s': %s\n"),seed_file_name, strerror(errno));
	}
  
  unlock_pool ();
}