Botan  1.11.15
src/lib/entropy/rdrand/rdrand.cpp
Go to the documentation of this file.
00001 /*
00002 * Entropy Source Using Intel's rdrand instruction
00003 * (C) 2012 Jack Lloyd
00004 *
00005 * Botan is released under the Simplified BSD License (see license.txt)
00006 */
00007 
00008 #include <botan/internal/rdrand.h>
00009 #include <botan/cpuid.h>
00010 
00011 #if !defined(BOTAN_USE_GCC_INLINE_ASM)
00012   #include <immintrin.h>
00013 #endif
00014 
00015 namespace Botan {
00016 
00017 /*
00018 * Get the timestamp
00019 */
00020 void Intel_Rdrand::poll(Entropy_Accumulator& accum)
00021    {
00022    if(!CPUID::has_rdrand())
00023       return;
00024 
00025    /*
00026    * Put an upper bound on the total entropy we're willing to claim
00027    * for any one polling of rdrand to prevent it from swamping our
00028    * poll. Internally, the rdrand system is a DRGB that reseeds at a
00029    * somewhat unpredictable rate (the current conditions are
00030    * documented, but that might not be true for different
00031    * implementations, eg on Haswell or a future AMD chip, so I don't
00032    * want to assume). This limit ensures we're going to poll at least
00033    * one other source so we have some diversity in our inputs.
00034    */
00035 
00036    const size_t POLL_UPPER_BOUND = 96;
00037    const size_t RDRAND_POLLS = 32;
00038    const double ENTROPY_PER_POLL =
00039       static_cast<double>(POLL_UPPER_BOUND) / (RDRAND_POLLS * 4);
00040 
00041    for(size_t i = 0; i != RDRAND_POLLS; ++i)
00042       {
00043       unsigned int r = 0;
00044 
00045 #if BOTAN_USE_GCC_INLINE_ASM
00046       int cf = 0;
00047 
00048       // Encoding of rdrand %eax
00049       asm(".byte 0x0F, 0xC7, 0xF0; adcl $0,%1" :
00050           "=a" (r), "=r" (cf) : "0" (r), "1" (cf) : "cc");
00051 #else
00052       int cf = _rdrand32_step(&r);
00053 #endif
00054 
00055       if(cf == 1)
00056          accum.add(r, ENTROPY_PER_POLL);
00057       }
00058    }
00059 
00060 }