Get true random number "Go" from the Linux kernel

Source: Internet
Author: User
Tags assert system log

Transferred from: http://www.cnblogs.com/bigship/archive/2010/04/04/1704228.html

Kernel random number generator

The Linux kernel implements a random number generator, which theoretically generates a true random number from the random number generator. Unlike the pseudo-random numbers produced by Rand (), Srand () in the standard C library, although pseudo-random numbers have certain random characteristics, they are not random numbers in statistical sense. That is, they are reproducible-the same pseudo-random sequence can be obtained whenever the same seed value is used. It is usually possible to change the seed by using the return value of time () to get a different sequence of pseudo-random numbers, but the result of the time () return value is not indeterminate (predictable), that is, there is still a lack of an indeterminate noise source. Pseudo-random numbers are not allowed for programs that require true random numbers.

In order to obtain a true random number, an external noise source is required. The Linux kernel has found a perfect source for noise generation-the person who uses the computer. When we use the computer to tap the time interval of the keyboard, moving the mouse distance and interval, the time interval of the specific interruption, and so on, these are non-deterministic and unpredictable for the computer. Although the behavior of the computer itself is entirely controlled by programming, there is a great deal of uncertainty about the operation of the peripheral hardware, which can be obtained through an interrupt processing routine (ISR) registered in the driver. The kernel maintains an entropy pool based on these non-deterministic device events, and the data in the pool is completely random. When a new device event arrives, the kernel estimates the randomness of the newly added data, and when we extract the data from the entropy pool, the kernel reduces the entropy estimate.

12345678910111213141516171819202122 asmlinkage int handle_IRQ_event(unsigned intirq, structpt_regs *regs,                             structirqaction *action){    intstatus = 1;    intretval = 0;        if(!(action->flags & SA_INTERRUPT))        local_irq_enable();    do    {        status |= action->flags;        retval |= action->handler(irq, action->dev_id, regs);        action = action->next;    }while(action);        if(status & SA_SAMPLE_RANDOM)        add_interrupt_randomness(irq);    local_irq_disable();    returnretval;}

The above code is a function on x86 to handle the ISR routines registered on an interrupt line. What we are interested in here is this: if the ISR specifies the SA_SAMPLE_RANDOM flag during registration, the function is also called add_interrupt_randomness () after the action has been processed. It uses the interrupt interval time to generate entropy for the kernel random number generator. This is where the kernel fills in the new data for the entropy pool.

What happens if we don't operate the computer at all? That is, as a source of noise, we do not touch the keyboard, mouse and other peripherals, do not let the entropy pool to obtain new data, this time if the entropy pool to take the data kernel how to react?

The kernel reduces the entropy estimate every time the data is taken from the entropy pool, and if the entropy estimate equals 0, the kernel can reject the user's request for random numbers at this time.

Get kernel random number

There are two ways to get the kernel random number from the entropy pool. One is the random number interface that is exported through the kernel, and the other is through special device files/dev/random and/dev/urandom. The following two methods are discussed separately.

Output interface of entropy
1 voidget_random_bytes(void *buf, intnbytes)

The function returns a buffer buf of length nbytes bytes, regardless of whether the entropy estimate is 0 returns the data. This function is used in kernel space. Let's write a small module to test it.

123456789101112131415161718192021222324252627282930 #include <linux/init.h>#include <linux/module.h>#include <linux/kernel.h>#define NUM 10voidget_random_bytes(void*buf, intnbytes);staticintget_random_number(void){    unsigned longrandNum[10];    inti = 0;    printk(KERN_ALERT "Get some real random number.\n");    for(i=0; i<NUM; i++)    {        get_random_bytes(&randNum[i], sizeof(unsigned long));        printk(KERN_ALERT "We get random number: %ld\n", randNum[i]);    }    return0;}staticvoidrandom_exit(void){    printk(KERN_ALERT "quit get_random_num.\n");}module_init(get_random_number);module_exit(random_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("Test");

Makefile as follows:

12345678910 obj-m = get_random_num.oKDIR = $(shell uname -r)PWD = $(shell pwd)all:    make -C /lib/modules/$(KDIR)/build M=$(PWD) modulesclean:    make -C /lib/modules/$(KDIR)/build M=$(PWD) clean#end#

After compiling the module to load, through the DMESG command output system log The latest information, you can see our small module output 10 from the kernel entropy pool of random numbers. Loading the module again can regain the new random number and observe the output, which is completely different from the random number previously obtained.

1234567891011121314151617181920212223 [37972.467955] Get some real random number.[37972.468392] We get random number: -82199505[37972.468580] We get random number: -276237802[37972.468586] We get random number: 411869317[37972.468590] We get random number: 1779353222[37972.468594] We get random number: 823507551[37972.468598] We get random number: 1061461415[37972.468602] We get random number: 1372137935[37972.468606] We get random number: 1460835009[37972.468610] We get random number: 2002191729[37972.468614] We get random number: -272204344[38059.349589] quit get_random_num.[38070.575433] Get some real random number.[38070.575462] We get random number: 1111808207[38070.575476] We get random number: -13789055[38070.575481] We get random number: 240443446[38070.575485] We get random number: -606998911[38070.575489] We get random number: 538794850[38070.575493] We get random number: -500786675[38070.575497] We get random number: -1240394927[38070.575501] We get random number: 1233931345[38070.575504] We get random number: 1488497117[38070.575508] We get random number: -177688514
/dev/random &/dev/urandom

Both of these special devices are character-based devices. We can get the random number by reading the two device files in the user space through the read system call. The difference between these two device files is that if the kernel entropy pool has an estimated value of 0 o'clock,

/dev/random will be blocked, and/dev/urandom will not have this limitation.

123456789101112131415161718192021222324252627282930313233343536373839 #include <assert.h>#include <sys/stat.h>#include <sys/types.h>#include <fcntl.h>#include <unistd.h>/* 从min和max中返回一个随机值 */intrandom_number(intmin, intmax){    staticintdev_random_fd = -1;    char*next_random_byte;    intbytes_to_read;    unsigned random_value;        assert(max > min);        if (dev_random_fd == -1)    {        dev_random_fd = open("/dev/random", O_RDONLY);        assert(dev_random_fd != -1);    }        next_random_byte = (char*)&random_value;    bytes_to_read = sizeof(random_value);        /* 因为是从/dev/random中读取,read可能会被阻塞,一次读取可能只能得到一个字节,     * 循环是为了让我们读取足够的字节数来填充random_value.     */    do    {        intbytes_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);        returnmin + (random_value % (max - min + 1));}

Similarly, you can use the DD command to get a random value of the specified number of bytes from the/dev/urandom and write to the file to save it-if you need to provide a random number in the form of a file.

DD If=/dev/urandom of = file Count = 1 bs = bytes

For a detailed introduction to the kernel random number generator, refer to the Linux kernel design and implementation of Appendix B of the second edition.

Get true random number "Go" from the Linux kernel

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.