diff options
-rw-r--r-- | doc/license.txt | 2 | ||||
-rw-r--r-- | doc/manual/rng.rst | 19 | ||||
-rw-r--r-- | doc/news.rst | 2 | ||||
-rw-r--r-- | src/lib/cert/x509/x509_ext.cpp | 20 | ||||
-rw-r--r-- | src/lib/entropy/rdrand/rdrand.cpp | 2 | ||||
-rw-r--r-- | src/lib/entropy/rdseed/rdseed.cpp | 2 | ||||
-rw-r--r-- | src/lib/prov/tpm/tpm.cpp | 10 | ||||
-rw-r--r-- | src/lib/prov/tpm/tpm.h | 30 | ||||
-rw-r--r-- | src/lib/utils/os_utils.cpp | 51 | ||||
-rw-r--r-- | src/tests/test_filters.cpp | 6 |
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); |