crdrand

Intel RDSEED 64 only giving 5 bytes of data


I'm trying to generate 8 bytes of random data using RDSEED (to seed SecureRandom in Java), by getting the 8 bytes from the 64-bit unsigned integer it generates. The problem is, while testing my code, I noticed that there are always 3 bytes that are zero, no matter how much I run the application.

#include <stdio.h>
#include <stdint.h>
#include <immintrin.h>

uint64_t rdseed64() {
    int retries = 0;
    uint64_t result;
    while (!_rdseed64_step(&result) || retries < 10) {
        retries++;
    }
    return result;
}

uint8_t* getBytes() {
    uint64_t x = rdseed64();
    uint8_t *p;
    p = (uint8_t *)&x;
    uint8_t buf[8];
    buf[0] = p[7];
    buf[1] = p[6];
    buf[2] = p[5];
    buf[3] = p[4];
    buf[4] = p[3];
    buf[5] = p[2];
    buf[6] = p[1];
    buf[7] = p[0];
    return buf;
}
int main(void) {
    uint8_t* bytes = getBytes();
    for (int i = 0; i < 8; i++) {
        uint8_t byte = bytes[i];
        printf("%x ", byte);
    }
    printf("\n");
    return 0;
}

Example output:
d4 0 0 0 fb 2c 5e 7e
7e 0 0 0 89 5e 76 a2
97 0 0 0 bd f 65 30


Solution

  • At least these problems:

    Code not compiled with all warnings enabled

    warning: function returns address of local variable [-Wreturn-local-addr]
    

    Save time.
    Try, if using gcc:

    -pedantic -Wall -Wextra -Wconversion
    

    Invalid pointer

    getBytes() returns a pointer to an object that is no longer in existence. Result : undefined behavior (UB).

    int8_t* getBytes() {
        ...
        uint8_t buf[8];
        ...
        return buf;
    }
    

    I recommend to instead pass into getBytes() a pointer to valid memory to store the 8 bytes. Rewrite getBytes() to accept that pointer.

    uint8_t bytes[8];
    getBytes(bytes);