Before I mention the function that I have developed for the production of random numbers from the monolithic Linux kernel, I would first like to say something about the issue of random numbers.

The issue of producing truly random numbers is important and had even since the beginning puzzled computer scientists. In mathematics, it is very difficult to define the random and, generally, randomness is very difficult to prove with no assumptions. In the past, many scientists tried to develop mathematical models and algorithms to develop random number generators.

One of the greatest scientists of Computer Science, John von Neumann (the basic idea of the architecture of all computer systems today was his own design) jokingly said: ‘Anyone who considers arithmetical methods of producing random digits is, of course, in a state of sin.’.

However, this effort continues till today. The results of these efforts are quite good, however we can only speak of pseudorandom number generators. The “random” numbers are either repeating themselves producing in time patterns of numerical series, or can be guessed if we know the seed or initial values taken into account in these algorithms.

Today it is very difficult to design mathematical models to support the issue of truly random numbers. The PC itself is difficult to produce truly random numbers, so some collect enough seeds and initial values that will determine the initialization of the generator or collect the random numbers themselves from the external environment, the world that surrounds us.

The world we live in is analog and several physical quantities can be considered truly random numbers sources. For example, the sounds around us, light, temperature, etc. However, several features of nature can be repeated showing the problems mentioned above. Either way though, with the right sources of data (from our environment) and the right algorithms we can develop truly random number generators!

Let’s continue now with the function and the Linux kernel.

The Linux kernel has two pseudodevice files (random and urandom [with significant differences between them]) in the directory ‘dev’ of the root filesystem, which can be used as random number generators. More specifically, these pseudodevices can be used by the applications to obtain truly random numbers in encryption issues and not only. These random numbers are extracted from an entropy data structure of the kernel in which various random events concur such as system calls, software or hardware signals, hardware interrupts.

If you are a programmer of device drivers, you might know that each device has a number of interruption and a device interrupt service routine (and many more). If you want your routine to contribute to the entropy mentioned, you can use the following kernel call (this call is used to install the service routine of the interrupt of the device):

int request_irq (unsigned int irq,
                 irqreturn_t (* handler) (int, void *, struct pt_regs *),
                 unsigned long flags,
                 const char * dev_name,
                 void * dev_id);

Specifically, we have to deal with parameter ‘flags’ (discrete digits variable) to activate the setting ‘SA_SAMPLE_RANDOM’. In this way, the routine will participate in the entropy.

The function that communicates either with the pseudodevice file ‘random’ or the ‘urandom’ of the directory ‘dev’ to generate random numbers from the Linux kernel is the following:

/*
 *  random-number.c -- implements a function which returns
 *                     random number each time it's called.
 *
 *  Copyright (C) 2008  Efstathios Chatzikyriakidis (stathis.chatzikyriakidis@gmail.com)
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

/* include needed libraries' headers. */
#include <assert.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>

/* function prototype. */
int random_number (const int, const int, const char * const);

/* following function should use either `/dev/random' or
   `/dev/urandom' to fetch a random integer, it returns
   an integer, which is always between `min' and `max'. */
int
random_number (const min, const max, const char * const filename)
{
  /* store a file descriptor opened to `filename' in a static
     variable. that way, we don't need to open the file every
     time this function is called.  */
  static int dev_random_fd = -1;

  unsigned bytes_to_read, random_value;
  char *next_random_byte;

  /* make sure `max' is greater than `min'. */
  assert (max > min);

  /* if it is the first time this function is
     called, open a file descriptor to file.  */
  if (dev_random_fd == -1) {
    dev_random_fd = open (filename, O_RDONLY);
    assert (dev_random_fd != -1);
  }

  /* read enough random bytes to fill an integer variable.  */
  next_random_byte = (char *) &random_value;
  bytes_to_read = sizeof (random_value);

  /* loop until we've read enough bytes. since `filename' is
     filled from user-generated actions, the read may block,
     and may only return a single random byte at a time.  */
  do {
    register int bytes_read;
    bytes_read = read (dev_random_fd, next_random_byte, bytes_to_read);
    bytes_to_read -= bytes_read;
    next_random_byte += bytes_read;
  } while (bytes_to_read > 0);

  /* compute a random number in the correct range.  */
  return min + (random_value % (max - min + 1));
}