Botan
1.11.15
|
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 }