-
-
Save randomoracle/7ea224739e5b98fa392e to your computer and use it in GitHub Desktop.
Check for and use RDRAND instruction on Intel/AMD CPUs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Compile and run via: | |
// g++ -o randcheck randcheck.c && ./randcheck | |
#include <stdlib.h> | |
#include <stdio.h> | |
typedef unsigned long long quadword; | |
quadword check_cpu_features(int leaf_ID) { | |
quadword cpu_features = 0; | |
asm("xorq %%rcx, %%rcx;" | |
"xorq %%rdx, %%rdx;" | |
"mov %1, %%eax;" | |
"cpuid;" | |
// Combine EDX:ECX together, with EDX making up upper 32-bits | |
"shlq $32, %%rdx;" | |
"orq %%rcx, %%rdx;" | |
"movq %%rdx, %0;" | |
: "=r" (cpu_features) | |
: "r" (leaf_ID) | |
: "%rax", "%rcx", "%rdx" | |
); | |
return cpu_features; | |
} | |
void sample_rng(int amount) { | |
printf("Actually trying RDRAND instruction now...\n"); | |
for (int total = 0; total < amount; total += 8) { | |
quadword value; | |
asm("rdrand %%rax;" | |
"movq %%rax, %0;" | |
: "=r" (value) | |
: | |
: "%rax" | |
); | |
printf("%016llx\n", value); | |
} | |
} | |
int check_for_bit(quadword value, int index) { | |
return ((1LL << index) & value) != 0; | |
} | |
int main(int argc, char **argv) { | |
quadword features = check_cpu_features(1); | |
printf("Advertised CPU features: %016llx\n", features); | |
int on_hypervisor = check_for_bit(features,31); | |
printf("Running on hypervisor: %s\n", on_hypervisor ? "YES" : "NO"); | |
int has_rdrand = check_for_bit(features, 30); | |
if (has_rdrand) { | |
printf("CPUID advertises support for RNG.\n"); | |
sample_rng(64); | |
} else { | |
printf("This processor does not have a hardware RNG.\n"); | |
} | |
return !has_rdrand; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment