The DRNG Library and Manual

Download

Download the static binary libraries, source code, and documentation:

This software is distributed under the Intel Sample Source Code license.

About

This is the DRNG Library, a project designed to bring the rdrand and rdseed instructions to customers who would traditionally not have access to them.

The "rdrand" and "rdseed" instructions are available at all privilege levels to any programmer, but tool chain support on some platforms is limited. One goal of this project is to provide access to these instructions via pre-compiled, static libraries. A second level goal is to provide a consistent, small, and very easy-to-use API to access the "rdrand" and "rdseed" instruction for various sizes of random data.

The source code and build system are provided for the entire library allowing the user to make any needed changes, or build dynamic versions, for incorporation into their own code.

Getting Started

For ease of use, this library is distributed with static libraries for Microsoft* Windows* and Microsoft* Visual Studio*, Linux Ubuntu* 14.10, and OS X* Yosemite*. The library can also be built from source, and requires the Visual Studio with the Intel(r) C++ Compiler or Visual Studio 2013 on Windows, or GNU* gcc* on Linux and OS X*. See the Building section for more details.

Once the static library is compiled, it is simply a matter of linking in the library with your code and including the header in the header search path to use the library. Linking the static library is beyond the scope of this documentation, but for demonstration, a simple Microsoft* Visual Studio* project is included, named test, as well as a simple project with Makefile for Linux or OS X. Source for the test is in main.c, and the test project on Linux can uses the top-level Makefile. The rdrand.sln solution includes the test project.

Rdrand is only supported on 3rd generation Intel(r) Core processors and beyond, and Rdseed is only supported on 5th generation Intel(r) Core processors and Core M processors and beyond. It makes sense to determine whether or not these instructions are supported by the CPU and this is done by examining the appropriate feature bits after calling cpuid. To ease use the library automatically handles this, and stores the results internally and transparently to the end user of the library. This result is stored in global data, and is thread-safe, given that if one thread of execution supports rdrand, they all will. Users may find it more practical, however, to call theRdRand_isSupported() and RdSeed_isSupported() functions when managing multiple potential code paths in an application.

The API was designed to be as simple and easy-to-use as possible, and consists of these functions:

int rdrand_16(uint16_t* x, int retry);
int rdrand_32(uint32_t* x, int retry);
int rdrand_64(uint64_t* x, int retry);

int rdseed_16(uint16_t* x, int retry_count);
int rdseed_32(uint32_t* x, int retry_count);
int rdseed_64(uint64_t* x, int retry_count);

int rdrand_get_n_64(unsigned int n, uint64_t* x);
int rdrand_get_n_32(unsigned int n, uint32_t* x);

int rdseed_get_n_64(unsigned int n, uint64_t* x, unsigned int skip, int max_retries);
int rdseed_get_n_32(unsigned int n, uint32_t* x, unsigned int skip, int max_retries);

int rdrand_get_bytes(unsigned int n, unsigned char *buffer);
int rdseed_get_bytes(unsigned int n, unsigned char *buffer, unsigned into skip, int max_retries);

Each function calls rdrand or rdseed internally for a specific data-size of random data to return to the caller.

The return of these functions states the hardware was not ready (if non-retry specified), success, or that the host hardware doesn't support the desired instruction at all. 

More detailed information about the library and its usage can be found in the companion article, Intel® Digital Random Number Generator (DRNG) Library Implementation and Uses.

Building

Building the Rdrand Library is supported under Microsoft* Visual Studio 2013*, Linux* and OS X*. Use of the Intel(r) C++ Compiler is optional unless you are using a version of Visual Studio earlier than 2013 on Microsoft Windows*.

To build the library, open the rdrand Microsoft Visual Studio solution (rdrand.sln), and build the project as normal from the build menu. Included are two projects, rdrand the actual library and test, the demonstration program.

On Linux and OS X the build is wrapped with GNU* autoconf*. To build:

$ ./configure
$ make

Release Notes

The DRNG Library is simple and as of this release is functionally complete. There are no known issues.

© 2015 Intel Corporation. All rights reserved.

For more complete information about compiler optimizations, see our Optimization Notice.
AttachmentSize
File libdrng-1.0.tar.gz970 KB
Package icon libdrng-1.0.zip276.46 KB

6 comments

Top
John M. (Intel)'s picture

The use of "=a"(*x) in libdrng is a side-effect of it being a macro definition. The C preprocessor is going to expand _rdrand32_step(x) to the inline expression that you see there, but when you invoke this function/macro in your code you are going to say _rdrand32_step(&var). When "x" gets expanded by the C preprocessor it will substitute "x" with "&var". Telling the asm call to pass the result to &var is not correct, so the macro definition needs to say *x so that you get *&var, or, just var.

The two libraries are doing the exact same thing in the end.

R H.'s picture

Thanks for your answer.

If we compare the code there are more differences. In libdrng "=a"(*x) is used and in the Botan library "=a" (r).

Can you explain what the advantages / disadvantages are when we compare these instructions ?

John M. (Intel)'s picture

I was able to get a look at the source code. It's an odd encoding, but it is the same outcome only much less efficient.

What it's doing is an add with carry (adcl) using two operands: the immediate value of 0, and the memory location for the variable cf (which is initialized to 0). If the carry flag is set, then it will result in a non-zero number in cf. Latencies are high on the adc instruction when the destination operand is a memory address.

The setc instruction is more direct and much faster. That's why we recommend that specific encoding.

Anyone using a modern version of gcc is going to get the intrinsic, though, so it's probably not a significant issue.

R H.'s picture

Thanks for the answer.

The code to which I refer in the Botan Library is: 

asm(".byte 0x0F, 0xC7, 0xF0; adcl $0,%1" : "=a" (r), "=r" (cf) : "0" (r), "1" (cf) : "cc");

If we compare the Botan asm code with the Intel Library asm code then it looks like this does not produce the same outcome, eg. the adcl compared with the setc instruction.

John M. (Intel)'s picture

For some reason I am not able to load the link you have provided, but the byte code you are referring to is the machine language encoding of "rdrand eax" if that helps.

R H.'s picture

In libdrng-1.0.zip we can find the following code in de file rdrand.c:

#  define _rdrand32_step(x) ({ unsigned char err; asm volatile(".byte 0x0f; .byte 0xc7; .byte 0xf0; setc %1":"=a"(*x), "=qm"(err)); err; })

In the botan library the code above is replaced with the code on http://botan.randombit.net/doxygen/rdrand_8cpp_source.html

Doed this give the same results ?

Add a Comment

Have a technical question? Visit our forums. Have site or software product issues? Contact support.