diff options
author | Jack Lloyd <[email protected]> | 2016-01-29 17:18:38 -0500 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2016-02-07 03:00:53 -0500 |
commit | 9379336ba62e273601623bf28ece112946aec1e1 (patch) | |
tree | af57abfbe639d4f2662ed0830db0a262610cbdd5 /src/lib | |
parent | e23cfdeb6d079a2c8d147142f31934d2c8b3a881 (diff) |
Add explicit fork check to HMAC_RNG
Add OS functions get_process_id, get_processor_timestamp, and
get_system_timestamp_ns. HMAC_RNG uses the pid call to detect forks to
initiate a reseed. It also adds the output of all three functions (the
pid, the CPU cycle counter, and the system timestamp) into the PRF input.
Calls the new OS timer functions from hres_timer entropy source.
Removes the call to QPC in es_win32 which is mostly redundant with the
one in hres_timer.
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/entropy/hres_timer/hres_timer.cpp | 74 | ||||
-rw-r--r-- | src/lib/entropy/win32_stats/es_win32.cpp | 4 | ||||
-rw-r--r-- | src/lib/rng/hmac_rng/hmac_rng.cpp | 12 | ||||
-rw-r--r-- | src/lib/rng/hmac_rng/hmac_rng.h | 1 | ||||
-rw-r--r-- | src/lib/utils/os_utils.cpp | 84 | ||||
-rw-r--r-- | src/lib/utils/os_utils.h | 28 |
6 files changed, 118 insertions, 85 deletions
diff --git a/src/lib/entropy/hres_timer/hres_timer.cpp b/src/lib/entropy/hres_timer/hres_timer.cpp index 0b39c935a..e2a5ddbef 100644 --- a/src/lib/entropy/hres_timer/hres_timer.cpp +++ b/src/lib/entropy/hres_timer/hres_timer.cpp @@ -1,19 +1,12 @@ /* * High Resolution Timestamp Entropy Source -* (C) 1999-2009,2011,2014 Jack Lloyd +* (C) 1999-2009,2011,2014,2016 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ #include <botan/internal/hres_timer.h> -#include <botan/cpuid.h> -#include <chrono> - -#if defined(BOTAN_TARGET_OS_HAS_QUERY_PERF_COUNTER) - #include <windows.h> - #undef min - #undef max -#endif +#include <botan/internal/os_utils.h> #if defined(BOTAN_TARGET_OS_HAS_CLOCK_GETTIME) #include <time.h> @@ -26,6 +19,10 @@ namespace Botan { */ void High_Resolution_Timestamp::poll(Entropy_Accumulator& accum) { + accum.add(OS::get_processor_timestamp(), BOTAN_ENTROPY_ESTIMATE_TIMESTAMPS); + + accum.add(OS::get_system_timestamp_ns(), BOTAN_ENTROPY_ESTIMATE_TIMESTAMPS); + #if defined(BOTAN_TARGET_OS_HAS_CLOCK_GETTIME) #define CLOCK_GETTIME_POLL(src) \ @@ -57,65 +54,6 @@ void High_Resolution_Timestamp::poll(Entropy_Accumulator& accum) #undef CLOCK_GETTIME_POLL -#else - -#define STD_CHRONO_POLL(clock) \ - do { \ - auto timestamp = clock::now().time_since_epoch().count(); \ - accum.add(timestamp, BOTAN_ENTROPY_ESTIMATE_TIMESTAMPS); \ - } while(0) - - STD_CHRONO_POLL(std::chrono::high_resolution_clock); - STD_CHRONO_POLL(std::chrono::system_clock); - -#undef STD_CHRONO_POLL - -#endif - -#if defined(BOTAN_USE_GCC_INLINE_ASM) - - u64bit rtc = 0; - -#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY) - if(CPUID::has_rdtsc()) // not availble on all x86 CPUs - { - u32bit rtc_low = 0, rtc_high = 0; - asm volatile("rdtsc" : "=d" (rtc_high), "=a" (rtc_low)); - rtc = (static_cast<u64bit>(rtc_high) << 32) | rtc_low; - } - -#elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY) - u32bit rtc_low = 0, rtc_high = 0; - asm volatile("mftbu %0; mftb %1" : "=r" (rtc_high), "=r" (rtc_low)); - rtc = (static_cast<u64bit>(rtc_high) << 32) | rtc_low; - -#elif defined(BOTAN_TARGET_ARCH_IS_ALPHA) - asm volatile("rpcc %0" : "=r" (rtc)); - -#elif defined(BOTAN_TARGET_ARCH_IS_SPARC64) && !defined(BOTAN_TARGET_OS_IS_OPENBSD) - asm volatile("rd %%tick, %0" : "=r" (rtc)); - -#elif defined(BOTAN_TARGET_ARCH_IS_IA64) - asm volatile("mov %0=ar.itc" : "=r" (rtc)); - -#elif defined(BOTAN_TARGET_ARCH_IS_S390X) - asm volatile("stck 0(%0)" : : "a" (&rtc) : "memory", "cc"); - -#elif defined(BOTAN_TARGET_ARCH_IS_HPPA) - asm volatile("mfctl 16,%0" : "=r" (rtc)); // 64-bit only? - -#endif - - accum.add(rtc, BOTAN_ENTROPY_ESTIMATE_TIMESTAMPS); - -#endif - -#if defined(BOTAN_TARGET_OS_HAS_QUERY_PERF_COUNTER) - { - LARGE_INTEGER tv; - ::QueryPerformanceCounter(&tv); - accum.add(tv.QuadPart, BOTAN_ENTROPY_ESTIMATE_TIMESTAMPS); - } #endif } diff --git a/src/lib/entropy/win32_stats/es_win32.cpp b/src/lib/entropy/win32_stats/es_win32.cpp index 52bb24136..909db093c 100644 --- a/src/lib/entropy/win32_stats/es_win32.cpp +++ b/src/lib/entropy/win32_stats/es_win32.cpp @@ -43,10 +43,6 @@ void Win32_EntropySource::poll(Entropy_Accumulator& accum) GetCaretPos(&point); accum.add(point, BOTAN_ENTROPY_ESTIMATE_SYSTEM_DATA); - LARGE_INTEGER perf_counter; - QueryPerformanceCounter(&perf_counter); - accum.add(perf_counter, BOTAN_ENTROPY_ESTIMATE_TIMESTAMPS); - /* Now use the Tooltip library to iterate throug various objects on the system, including processes, threads, and heap objects. diff --git a/src/lib/rng/hmac_rng/hmac_rng.cpp b/src/lib/rng/hmac_rng/hmac_rng.cpp index f5a782526..0b80de7bd 100644 --- a/src/lib/rng/hmac_rng/hmac_rng.cpp +++ b/src/lib/rng/hmac_rng/hmac_rng.cpp @@ -1,12 +1,13 @@ /* * HMAC_RNG -* (C) 2008,2009,2013,2015 Jack Lloyd +* (C) 2008,2009,2013,2015,2016 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ #include <botan/hmac_rng.h> #include <botan/entropy_src.h> +#include <botan/internal/os_utils.h> #include <algorithm> #include <chrono> @@ -69,10 +70,10 @@ void HMAC_RNG::clear() void HMAC_RNG::new_K_value(byte label) { - typedef std::chrono::high_resolution_clock clock; - m_prf->update(m_K); - m_prf->update_be(clock::now().time_since_epoch().count()); + m_prf->update_be(m_pid); + m_prf->update_be(OS::get_processor_timestamp()); + m_prf->update_be(OS::get_system_timestamp_ns()); m_prf->update_be(m_counter++); m_prf->update(label); m_prf->final(m_K.data()); @@ -83,7 +84,7 @@ void HMAC_RNG::new_K_value(byte label) */ void HMAC_RNG::randomize(byte out[], size_t length) { - if(!is_seeded()) + if(!is_seeded() || m_pid != OS::get_process_id()) { reseed(256); if(!is_seeded()) @@ -168,6 +169,7 @@ size_t HMAC_RNG::reseed_with_sources(Entropy_Sources& srcs, m_extractor->output_length() * 8); m_output_since_reseed = 0; + m_pid = OS::get_process_id(); return static_cast<size_t>(bits_collected); } diff --git a/src/lib/rng/hmac_rng/hmac_rng.h b/src/lib/rng/hmac_rng/hmac_rng.h index 1e38daa08..95ae25e39 100644 --- a/src/lib/rng/hmac_rng/hmac_rng.h +++ b/src/lib/rng/hmac_rng/hmac_rng.h @@ -60,6 +60,7 @@ class BOTAN_DLL HMAC_RNG : public RandomNumberGenerator secure_vector<byte> m_K; u32bit m_counter = 0; + u32bit m_pid = 0; }; } diff --git a/src/lib/utils/os_utils.cpp b/src/lib/utils/os_utils.cpp index ae93d58d7..bd87ca2ed 100644 --- a/src/lib/utils/os_utils.cpp +++ b/src/lib/utils/os_utils.cpp @@ -1,27 +1,103 @@ /* * OS and machine specific utility functions -* (C) 2015 Jack Lloyd +* (C) 2015,2016 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ #include <botan/internal/os_utils.h> +#include <botan/cpuid.h> #include <botan/exceptn.h> #include <botan/mem_ops.h> +#include <chrono> -//TODO: defined(BOTAN_TARGET_OS_TYPE_IS_POSIX) - -#if defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK) +#if defined(BOTAN_TARGET_OS_TYPE_IS_UNIX) #include <sys/types.h> #include <sys/mman.h> #include <sys/resource.h> #include <unistd.h> #endif +#if defined(BOTAN_TARGET_OS_TYPE_IS_WINDOWS) + #include <windows.h> +#endif + namespace Botan { namespace OS { +uint32_t get_process_id() + { +#if defined(BOTAN_TARGET_OS_IS_UNIX) + return ::getpid(); +#elif defined(BOTAN_TARGET_OS_IS_WIDOWS) + return ::GetProcessId(); +#else + return 0; +#endif + } + +uint64_t get_processor_timestamp() + { + uint64_t rtc = 0; + +#if defined(BOTAN_TARGET_OS_HAS_QUERY_PERF_COUNTER) + LARGE_INTEGER tv; + ::QueryPerformanceCounter(&tv); + rtc = tv.QuadPart; +#endif + +#if defined(BOTAN_USE_GCC_INLINE_ASM) + +#if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY) + if(CPUID::has_rdtsc()) // not availble on all x86 CPUs + { + uint32_t rtc_low = 0, rtc_high = 0; + asm volatile("rdtsc" : "=d" (rtc_high), "=a" (rtc_low)); + rtc = (static_cast<u64bit>(rtc_high) << 32) | rtc_low; + } + +#elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY) + uint32_t rtc_low = 0, rtc_high = 0; + asm volatile("mftbu %0; mftb %1" : "=r" (rtc_high), "=r" (rtc_low)); + rtc = (static_cast<u64bit>(rtc_high) << 32) | rtc_low; + +#elif defined(BOTAN_TARGET_ARCH_IS_ALPHA) + asm volatile("rpcc %0" : "=r" (rtc)); + +#elif defined(BOTAN_TARGET_ARCH_IS_SPARC64) && !defined(BOTAN_TARGET_OS_IS_OPENBSD) + // OpenBSD does not trap access to the %tick register + asm volatile("rd %%tick, %0" : "=r" (rtc)); + +#elif defined(BOTAN_TARGET_ARCH_IS_IA64) + asm volatile("mov %0=ar.itc" : "=r" (rtc)); + +#elif defined(BOTAN_TARGET_ARCH_IS_S390X) + asm volatile("stck 0(%0)" : : "a" (&rtc) : "memory", "cc"); + +#elif defined(BOTAN_TARGET_ARCH_IS_HPPA) + asm volatile("mfctl 16,%0" : "=r" (rtc)); // 64-bit only? +#endif + +#endif + + return rtc; + } + +uint64_t get_system_timestamp_ns() + { +#if defined(BOTAN_TARGET_OS_HAS_CLOCK_GETTIME) + struct timespec ts; + if(::clock_gettime(CLOCK_REALTIME, &ts) == 0) + { + return (static_cast<uint64_t>(ts.tv_sec) * 1000000000) + static_cast<uint64_t>(ts.tv_nsec); + } +#endif + + auto now = std::chrono::high_resolution_clock::now().time_since_epoch(); + return std::chrono::duration_cast<std::chrono::nanoseconds>(now).count(); + } + size_t get_memory_locking_limit() { #if defined(BOTAN_TARGET_OS_HAS_POSIX_MLOCK) diff --git a/src/lib/utils/os_utils.h b/src/lib/utils/os_utils.h index 0030f88c9..3335463f7 100644 --- a/src/lib/utils/os_utils.h +++ b/src/lib/utils/os_utils.h @@ -1,6 +1,6 @@ /* * OS specific utility functions -* (C) 2015 Jack Lloyd +* (C) 2015,2016 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -14,6 +14,26 @@ namespace Botan { namespace OS { +/** +* Returns the OS assigned process ID, if available. Otherwise returns 0. +*/ +uint32_t get_process_id(); + +/** +* Returns the value of the hardware cycle counter, if available. +* Returns 0 if not available. On Windows uses QueryPerformanceCounter. +* On other platforms reads the native cycle counter directly. +* The epoch and update rate are arbitrary and may not be constant +* (depending on the hardware). +*/ +uint64_t get_processor_timestamp(); + +/** +* Returns the value of the system clock with best resolution available, +* normalized to nanoseconds resolution. +*/ +uint64_t get_system_timestamp_ns(); + /* * Returns the maximum amount of memory (in bytes) we could/should * hyptothetically allocate. Reads "BOTAN_MLOCK_POOL_SIZE" from @@ -22,9 +42,9 @@ namespace OS { size_t get_memory_locking_limit(); /* -* Request so many bytes of page-aligned RAM locked into memory OS -* calls (mlock, VirtualLock, or similar). Returns null on failure. The -* memory returned is zeroed. Free it with free_locked_pages. +* Request so many bytes of page-aligned RAM locked into memory using +* mlock, VirtualLock, or similar. Returns null on failure. The memory +* returned is zeroed. Free it with free_locked_pages. */ void* allocate_locked_pages(size_t length); |