aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/license.txt2
-rw-r--r--doc/manual/rng.rst19
-rw-r--r--doc/news.rst2
-rw-r--r--src/lib/cert/x509/x509_ext.cpp20
-rw-r--r--src/lib/entropy/rdrand/rdrand.cpp2
-rw-r--r--src/lib/entropy/rdseed/rdseed.cpp2
-rw-r--r--src/lib/prov/tpm/tpm.cpp10
-rw-r--r--src/lib/prov/tpm/tpm.h30
-rw-r--r--src/lib/utils/os_utils.cpp51
-rw-r--r--src/tests/test_filters.cpp6
10 files changed, 112 insertions, 32 deletions
diff --git a/doc/license.txt b/doc/license.txt
index 873e55e37..ba4381c1b 100644
--- a/doc/license.txt
+++ b/doc/license.txt
@@ -26,7 +26,7 @@ Copyright (C) 1999-2013,2014,2015,2016 Jack Lloyd
2015 Simon Warta (Kullo GmbH)
2015 Matej Kenda (TopIT d.o.o.)
2015 René Korthaus
- 2015 Daniel Neus
+ 2015,2016 Daniel Neus
2015 Uri Blumenthal
All rights reserved.
diff --git a/doc/manual/rng.rst b/doc/manual/rng.rst
index 1ec37b52f..300570c3a 100644
--- a/doc/manual/rng.rst
+++ b/doc/manual/rng.rst
@@ -127,3 +127,22 @@ has been hashed by the ``RandomNumberGenerator`` that asked for the
entropy, thus any hashing you do will be wasteful of both CPU cycles
and entropy.
+Fork Safety
+---------------------------------
+
+On Unix platforms, the ``fork()`` and ``clone()`` system calls can
+be used to spawn a new child process. Fork safety ensures that the
+child process doesn't see the same output of random bytes as the
+parent process. Botan tries to ensure fork safety by feeding the
+process ID into the internal state of the random generator and by
+automatically reseeding the random generator if the process ID
+changed between two requests of random bytes. However, this does
+not protect against PID wrap around. The process ID is usually
+implemented as a 16 bit integer. In this scenario, a process will
+spawn a new child process, which exits the parent process and
+spawns a new child process himself. If the PID wrapped around, the
+second child process may get assigned the process ID of it's
+grandparent and the fork safety can not be ensured.
+
+Therefore, it is strongly recommended to explicitly reseed the
+random generator after forking a new process.
diff --git a/doc/news.rst b/doc/news.rst
index 72f5fa88b..d5698d23e 100644
--- a/doc/news.rst
+++ b/doc/news.rst
@@ -37,6 +37,8 @@ Version 1.11.29, Not Yet Released
* Small optimizations to Keccak hash
+* Support for locking allocator on Windows using VirtualLock/VirtualUnlock
+
Version 1.10.12, 2016-02-03
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/lib/cert/x509/x509_ext.cpp b/src/lib/cert/x509/x509_ext.cpp
index f8f9adb2b..f3a9a7f1c 100644
--- a/src/lib/cert/x509/x509_ext.cpp
+++ b/src/lib/cert/x509/x509_ext.cpp
@@ -379,7 +379,9 @@ void Alternative_Name::contents_to(Data_Store& subject_info,
* Alternative_Name Constructor
*/
Alternative_Name::Alternative_Name(const AlternativeName& alt_name,
- const std::string& oid_name_str) : m_alt_name(alt_name), m_oid_name_str(oid_name_str)
+ const std::string& oid_name_str) :
+ m_oid_name_str(oid_name_str),
+ m_alt_name(alt_name)
{}
/*
@@ -436,26 +438,28 @@ namespace {
class Policy_Information : public ASN1_Object
{
public:
- // public member variable:
- OID oid;
-
Policy_Information() {}
- explicit Policy_Information(const OID& oid) : oid(oid) {}
+ explicit Policy_Information(const OID& oid) : m_oid(oid) {}
+
+ const OID& oid() const { return m_oid; }
void encode_into(DER_Encoder& codec) const override
{
codec.start_cons(SEQUENCE)
- .encode(oid)
+ .encode(m_oid)
.end_cons();
}
void decode_from(BER_Decoder& codec) override
{
codec.start_cons(SEQUENCE)
- .decode(oid)
+ .decode(m_oid)
.discard_remaining()
.end_cons();
}
+
+ private:
+ OID m_oid;
};
}
@@ -488,7 +492,7 @@ void Certificate_Policies::decode_inner(const std::vector<byte>& in)
m_oids.clear();
for(size_t i = 0; i != policies.size(); ++i)
- m_oids.push_back(policies[i].oid);
+ m_oids.push_back(policies[i].oid());
}
/*
diff --git a/src/lib/entropy/rdrand/rdrand.cpp b/src/lib/entropy/rdrand/rdrand.cpp
index 13263bb63..89234b460 100644
--- a/src/lib/entropy/rdrand/rdrand.cpp
+++ b/src/lib/entropy/rdrand/rdrand.cpp
@@ -20,7 +20,7 @@ void Intel_Rdrand::poll(Entropy_Accumulator& accum) {
if(!CPUID::has_rdrand())
return;
- for(size_t i = 0; i != BOTAN_ENTROPY_INTEL_RNG_POLLS; ++i)
+ for(size_t p = 0; p != BOTAN_ENTROPY_INTEL_RNG_POLLS; ++p)
{
for(size_t i = 0; i != BOTAN_ENTROPY_RDRAND_RETRIES; ++i)
{
diff --git a/src/lib/entropy/rdseed/rdseed.cpp b/src/lib/entropy/rdseed/rdseed.cpp
index bcef9ad83..2ba2075cc 100644
--- a/src/lib/entropy/rdseed/rdseed.cpp
+++ b/src/lib/entropy/rdseed/rdseed.cpp
@@ -19,7 +19,7 @@ void Intel_Rdseed::poll(Entropy_Accumulator& accum) {
if(!CPUID::has_rdseed())
return;
- for(size_t i = 0; i != BOTAN_ENTROPY_INTEL_RNG_POLLS; ++i)
+ for(size_t p = 0; p != BOTAN_ENTROPY_INTEL_RNG_POLLS; ++p)
{
for(size_t i = 0; i != BOTAN_ENTROPY_RDSEED_RETRIES; ++i)
{
diff --git a/src/lib/prov/tpm/tpm.cpp b/src/lib/prov/tpm/tpm.cpp
index 9a29be395..c0b265b98 100644
--- a/src/lib/prov/tpm/tpm.cpp
+++ b/src/lib/prov/tpm/tpm.cpp
@@ -56,13 +56,14 @@ TSS_FLAG bit_flag(size_t bits)
}
}
+#if 0
bool is_srk_uuid(const UUID& uuid)
{
static const byte srk[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
const std::vector<uint8_t>& b = uuid.binary_value();
return (b.size() == 16 && same_mem(b.data(), srk, 16));
}
-
+#endif
#define TSPI_CHECK_SUCCESS(expr) do { \
TSS_RESULT res = expr; \
@@ -90,10 +91,11 @@ void set_policy_secret(TSS_HPOLICY policy, const char* secret)
{
if(secret)
{
+ BYTE* as_b = const_cast<BYTE*>(reinterpret_cast<const BYTE*>(secret));
TSPI_CHECK_SUCCESS(::Tspi_Policy_SetSecret(policy,
- TSS_SECRET_MODE_PLAIN,
- std::strlen(secret),
- (BYTE*)secret));
+ TSS_SECRET_MODE_PLAIN,
+ std::strlen(secret),
+ as_b));
}
else
{
diff --git a/src/lib/prov/tpm/tpm.h b/src/lib/prov/tpm/tpm.h
index 7df232be3..4a9dcd3c6 100644
--- a/src/lib/prov/tpm/tpm.h
+++ b/src/lib/prov/tpm/tpm.h
@@ -138,32 +138,36 @@ class BOTAN_DLL TPM_PrivateKey : public Private_Key
*/
std::string register_key(TPM_Storage_Type storage_type);
+ /**
+ * Returns a copy of the public key
+ */
+ std::unique_ptr<Public_Key> public_key() const;
+
+ std::vector<uint8_t> export_blob() const;
+
+ TPM_Context& ctx() const { return m_ctx; }
+
+ TSS_HKEY handle() const { return m_key; }
+
/*
* Returns the list of all keys (in URL format) registered with the system
*/
static std::vector<std::string> registered_keys(TPM_Context& ctx);
- size_t estimated_strength() const;
-
- size_t max_input_bits() const;
+ size_t estimated_strength() const override;
- AlgorithmIdentifier algorithm_identifier() const;
+ size_t max_input_bits() const override;
- std::vector<byte> x509_subject_public_key() const;
+ AlgorithmIdentifier algorithm_identifier() const override;
- secure_vector<byte> pkcs8_private_key() const; // not implemented
+ std::vector<byte> x509_subject_public_key() const override;
- std::unique_ptr<Public_Key> public_key() const;
+ secure_vector<byte> pkcs8_private_key() const override;
bool check_key(RandomNumberGenerator& rng, bool) const override;
- std::string algo_name() const { return "RSA"; } // ???
-
- std::vector<uint8_t> export_blob() const;
-
- TPM_Context& ctx() const { return m_ctx; }
+ std::string algo_name() const override { return "RSA"; } // ???
- TSS_HKEY handle() const { return m_key; }
private:
BigInt get_n() const;
BigInt get_e() const;
diff --git a/src/lib/utils/os_utils.cpp b/src/lib/utils/os_utils.cpp
index 5f9624532..86776bdd0 100644
--- a/src/lib/utils/os_utils.cpp
+++ b/src/lib/utils/os_utils.cpp
@@ -1,6 +1,7 @@
/*
* OS and machine specific utility functions
* (C) 2015,2016 Jack Lloyd
+* (C) 2016 Daniel Neus
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -50,7 +51,7 @@ uint64_t get_processor_timestamp()
#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
+ if(CPUID::has_rdtsc()) // not available on all x86 CPUs
{
uint32_t rtc_low = 0, rtc_high = 0;
asm volatile("rdtsc" : "=d" (rtc_high), "=a" (rtc_low));
@@ -140,6 +141,36 @@ size_t get_memory_locking_limit()
return std::min<size_t>(limits.rlim_cur, mlock_requested * 1024);
}
+#elif defined BOTAN_TARGET_OS_HAS_VIRTUAL_LOCK
+ SIZE_T working_min = 0, working_max = 0;
+ DWORD working_flags = 0;
+ if(!::GetProcessWorkingSetSizeEx(::GetCurrentProcess(), &working_min, &working_max, &working_flags))
+ {
+ return 0;
+ }
+
+ SYSTEM_INFO sSysInfo;
+ ::GetSystemInfo(&sSysInfo);
+
+ // According to Microsoft MSDN:
+ // The maximum number of pages that a process can lock is equal to the number of pages in its minimum working set minus a small overhead
+ // In the book "Windows Internals Part 2": the maximum lockable pages are minimum working set size - 8 pages
+ // But the information in the book seems to be inaccurate/outdated
+ // I've tested this on Windows 8.1 x64, Windows 10 x64 and Windows 7 x86
+ // On all three OS the value is 11 instead of 8
+ size_t overhead = sSysInfo.dwPageSize * 11ULL;
+ if(working_min > overhead)
+ {
+ size_t lockable_bytes = working_min - overhead;
+ if(lockable_bytes < (BOTAN_MLOCK_ALLOCATOR_MAX_LOCKED_KB * 1024ULL))
+ {
+ return lockable_bytes;
+ }
+ else
+ {
+ return BOTAN_MLOCK_ALLOCATOR_MAX_LOCKED_KB * 1024ULL;
+ }
+ }
#endif
return 0;
@@ -182,6 +213,20 @@ void* allocate_locked_pages(size_t length)
::memset(ptr, 0, length);
return ptr;
+#elif defined BOTAN_TARGET_OS_HAS_VIRTUAL_LOCK
+ LPVOID ptr = ::VirtualAlloc(nullptr, length, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
+ if(!ptr)
+ {
+ return nullptr;
+ }
+
+ if(::VirtualLock(ptr, length) == 0)
+ {
+ ::VirtualFree(ptr, 0, MEM_RELEASE);
+ return nullptr; // failed to lock
+ }
+
+ return ptr;
#else
return nullptr; /* not implemented */
#endif
@@ -196,6 +241,10 @@ void free_locked_pages(void* ptr, size_t length)
zero_mem(ptr, length);
::munlock(ptr, length);
::munmap(ptr, length);
+#elif defined BOTAN_TARGET_OS_HAS_VIRTUAL_LOCK
+ zero_mem(ptr, length);
+ ::VirtualUnlock(ptr, length);
+ ::VirtualFree(ptr, 0, MEM_RELEASE);
#else
// Invalid argument because no way this pointer was allocated by us
throw Invalid_Argument("Invalid ptr to free_locked_pages");
diff --git a/src/tests/test_filters.cpp b/src/tests/test_filters.cpp
index 35d578789..b6bbf05c3 100644
--- a/src/tests/test_filters.cpp
+++ b/src/tests/test_filters.cpp
@@ -32,11 +32,11 @@ class Filter_Tests : public Test
secqueue_result.test_eq("size of SecureQueue is correct", queue_a.size(), test_data.size());
secqueue_result.test_eq("0 bytes read so far from SecureQueue", queue_a.get_bytes_read(), 0);
- uint8_t byte;
- size_t bytes_read = queue_a.read_byte(byte);
+ uint8_t b;
+ size_t bytes_read = queue_a.read_byte(b);
secqueue_result.test_eq("1 byte read", bytes_read, 1);
- Botan::secure_vector<uint8_t> produced(byte);
+ Botan::secure_vector<uint8_t> produced(b);
Botan::secure_vector<uint8_t> expected(test_data.at(0));
secqueue_result.test_eq("byte read is correct", produced, expected);