aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2016-01-29 17:18:38 -0500
committerJack Lloyd <[email protected]>2016-02-07 03:00:53 -0500
commit9379336ba62e273601623bf28ece112946aec1e1 (patch)
treeaf57abfbe639d4f2662ed0830db0a262610cbdd5 /src/lib
parente23cfdeb6d079a2c8d147142f31934d2c8b3a881 (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.cpp74
-rw-r--r--src/lib/entropy/win32_stats/es_win32.cpp4
-rw-r--r--src/lib/rng/hmac_rng/hmac_rng.cpp12
-rw-r--r--src/lib/rng/hmac_rng/hmac_rng.h1
-rw-r--r--src/lib/utils/os_utils.cpp84
-rw-r--r--src/lib/utils/os_utils.h28
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);