Botan
1.11.15
|
00001 /* 00002 * High Resolution Timestamp Entropy Source 00003 * (C) 1999-2009,2011,2014 Jack Lloyd 00004 * 00005 * Botan is released under the Simplified BSD License (see license.txt) 00006 */ 00007 00008 #include <botan/internal/hres_timer.h> 00009 #include <botan/cpuid.h> 00010 #include <chrono> 00011 00012 #if defined(BOTAN_TARGET_OS_HAS_QUERY_PERF_COUNTER) 00013 #include <windows.h> 00014 #undef min 00015 #undef max 00016 #endif 00017 00018 #if defined(BOTAN_TARGET_OS_HAS_CLOCK_GETTIME) 00019 #include <time.h> 00020 #endif 00021 00022 namespace Botan { 00023 00024 /* 00025 * Get the timestamp 00026 */ 00027 void High_Resolution_Timestamp::poll(Entropy_Accumulator& accum) 00028 { 00029 // Don't count any timestamps as contributing any entropy 00030 const double ESTIMATED_ENTROPY_PER_BYTE = 0.0; 00031 00032 #if defined(BOTAN_TARGET_OS_HAS_CLOCK_GETTIME) 00033 00034 #define CLOCK_GETTIME_POLL(src) \ 00035 do { \ 00036 struct timespec ts; \ 00037 ::clock_gettime(src, &ts); \ 00038 accum.add(&ts, sizeof(ts), ESTIMATED_ENTROPY_PER_BYTE); \ 00039 } while(0) 00040 00041 #if defined(CLOCK_REALTIME) 00042 CLOCK_GETTIME_POLL(CLOCK_REALTIME); 00043 #endif 00044 00045 #if defined(CLOCK_MONOTONIC) 00046 CLOCK_GETTIME_POLL(CLOCK_MONOTONIC); 00047 #endif 00048 00049 #if defined(CLOCK_MONOTONIC_RAW) 00050 CLOCK_GETTIME_POLL(CLOCK_MONOTONIC_RAW); 00051 #endif 00052 00053 #if defined(CLOCK_PROCESS_CPUTIME_ID) 00054 CLOCK_GETTIME_POLL(CLOCK_PROCESS_CPUTIME_ID); 00055 #endif 00056 00057 #if defined(CLOCK_THREAD_CPUTIME_ID) 00058 CLOCK_GETTIME_POLL(CLOCK_THREAD_CPUTIME_ID); 00059 #endif 00060 00061 #undef CLOCK_GETTIME_POLL 00062 00063 #else 00064 00065 #define STD_CHRONO_POLL(clock) \ 00066 do { \ 00067 auto timestamp = clock::now().time_since_epoch().count(); \ 00068 accum.add(timestamp, ESTIMATED_ENTROPY_PER_BYTE); \ 00069 } while(0) 00070 00071 STD_CHRONO_POLL(std::chrono::high_resolution_clock); 00072 STD_CHRONO_POLL(std::chrono::system_clock); 00073 00074 #undef STD_CHRONO_POLL 00075 00076 #endif 00077 00078 #if BOTAN_USE_GCC_INLINE_ASM 00079 00080 u64bit rtc = 0; 00081 00082 #if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY) 00083 if(CPUID::has_rdtsc()) // not availble on all x86 CPUs 00084 { 00085 u32bit rtc_low = 0, rtc_high = 0; 00086 asm volatile("rdtsc" : "=d" (rtc_high), "=a" (rtc_low)); 00087 rtc = (static_cast<u64bit>(rtc_high) << 32) | rtc_low; 00088 } 00089 00090 #elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY) 00091 u32bit rtc_low = 0, rtc_high = 0; 00092 asm volatile("mftbu %0; mftb %1" : "=r" (rtc_high), "=r" (rtc_low)); 00093 rtc = (static_cast<u64bit>(rtc_high) << 32) | rtc_low; 00094 00095 #elif defined(BOTAN_TARGET_ARCH_IS_ALPHA) 00096 asm volatile("rpcc %0" : "=r" (rtc)); 00097 00098 #elif defined(BOTAN_TARGET_ARCH_IS_SPARC64) && !defined(BOTAN_TARGET_OS_IS_OPENBSD) 00099 asm volatile("rd %%tick, %0" : "=r" (rtc)); 00100 00101 #elif defined(BOTAN_TARGET_ARCH_IS_IA64) 00102 asm volatile("mov %0=ar.itc" : "=r" (rtc)); 00103 00104 #elif defined(BOTAN_TARGET_ARCH_IS_S390X) 00105 asm volatile("stck 0(%0)" : : "a" (&rtc) : "memory", "cc"); 00106 00107 #elif defined(BOTAN_TARGET_ARCH_IS_HPPA) 00108 asm volatile("mfctl 16,%0" : "=r" (rtc)); // 64-bit only? 00109 00110 #endif 00111 00112 accum.add(rtc, ESTIMATED_ENTROPY_PER_BYTE); 00113 00114 #endif 00115 00116 #if defined(BOTAN_TARGET_OS_HAS_QUERY_PERF_COUNTER) 00117 { 00118 LARGE_INTEGER tv; 00119 ::QueryPerformanceCounter(&tv); 00120 accum.add(tv.QuadPart, ESTIMATED_ENTROPY_PER_BYTE); 00121 } 00122 #endif 00123 } 00124 00125 }