diff --git a/CMakeLists.txt b/CMakeLists.txt index 95fdca67..416835cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,6 +51,12 @@ if(NOT CRYPTOPP_DATA_DIR STREQUAL "") add_definitions(-DCRYPTOPP_DATA_DIR="${CRYPTOPP_DATA_DIR}") endif() +if(WINDOWS_STORE OR WINDOWS_PHONE) + if("${CMAKE_SYSTEM_VERSION}" MATCHES "10\\.0.*") + SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D\"_WIN32_WINNT=0x0A00\"" ) + endif() + SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /FI\"winapifamily.h\"" ) +endif() #============================================================================ # Sources & headers #============================================================================ @@ -83,19 +89,24 @@ if(MINGW OR WIN32) endif() if(MSVC AND NOT DISABLE_ASM) - if(CMAKE_CL_64) - list(APPEND cryptopp_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/x64dll.asm) - list(APPEND cryptopp_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/x64masm.asm) - set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/x64dll.asm PROPERTIES COMPILE_FLAGS "/D_M_X64") - set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/x64masm.asm PROPERTIES COMPILE_FLAGS "/D_M_X64") - set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/rdrand.asm PROPERTIES COMPILE_FLAGS "/D_M_X64") - else() - set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/x64dll.asm PROPERTIES COMPILE_FLAGS "/D_M_X86 /safeseh") - set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/x64masm.asm PROPERTIES COMPILE_FLAGS "/D_M_X86 /safeseh") - set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/rdrand.asm PROPERTIES COMPILE_FLAGS "/D_M_X86 /safeseh") - endif() - list(APPEND cryptopp_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/rdrand.asm) - enable_language(ASM_MASM) + if(${CMAKE_GENERATOR} MATCHES ".*ARM") + message(STATUS "Disabling ASM because ARM is specified as target platform.") + add_definitions(-DCRYPTOPP_DISABLE_ASM) + else() + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + list(APPEND cryptopp_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/x64dll.asm) + list(APPEND cryptopp_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/x64masm.asm) + set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/x64dll.asm PROPERTIES COMPILE_FLAGS "/D_M_X64") + set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/x64masm.asm PROPERTIES COMPILE_FLAGS "/D_M_X64") + set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/rdrand.asm PROPERTIES COMPILE_FLAGS "/D_M_X64") + else() + set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/x64dll.asm PROPERTIES COMPILE_FLAGS "/D_M_X86 /safeseh") + set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/x64masm.asm PROPERTIES COMPILE_FLAGS "/D_M_X86 /safeseh") + set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/rdrand.asm PROPERTIES COMPILE_FLAGS "/D_M_X86 /safeseh") + endif() + list(APPEND cryptopp_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/rdrand.asm) + enable_language(ASM_MASM) + endif() endif() #============================================================================ @@ -207,4 +218,5 @@ endif() # Documentation if(BUILD_DOCUMENTATION) install(DIRECTORY "${out_source_DOCS_DIR}" DESTINATION ${CMAKE_INSTALL_DOCDIR}) -endif() \ No newline at end of file +endif() + diff --git a/config.h b/config.h index d2f87085..35e3e324 100644 --- a/config.h +++ b/config.h @@ -763,6 +763,19 @@ NAMESPACE_END # define CRYPTOPP_CXX11_ATOMICS 1 #endif // atomics +// atomics: MS at VS2012 (17.00); GCC at 4.4; Clang at 3.1/3.2; and Intel 13.0. +#if (CRYPTOPP_MSC_VERSION >= 1700) +# define CRYPTOPP_CXX11_ATOMICS 1 +#elif defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1300) +# define CRYPTOPP_CXX11_ATOMICS 1 +#elif defined(__clang__) +# if __has_feature(cxx_atomic) +# define CRYPTOPP_CXX11_ATOMICS 1 +# endif +#elif (CRYPTOPP_GCC_VERSION >= 40400) +# define CRYPTOPP_CXX11_ATOMICS 1 +#endif // atomics + // alignof/alignas: MS at VS2013 (19.00); GCC at 4.8; Clang at 3.3; and Intel 15.0. #if (CRYPTOPP_MSC_VERSION >= 1900) # define CRYPTOPP_CXX11_ALIGNAS 1 diff --git a/config.recommend b/config.recommend index 0208747a..c12f4c04 100644 --- a/config.recommend +++ b/config.recommend @@ -763,6 +763,19 @@ NAMESPACE_END # define CRYPTOPP_CXX11_ATOMICS 1 #endif // atomics +// atomics: MS at VS2012 (17.00); GCC at 4.4; Clang at 3.1/3.2; and Intel 13.0. +#if (CRYPTOPP_MSC_VERSION >= 1700) +# define CRYPTOPP_CXX11_ATOMICS 1 +#elif defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1300) +# define CRYPTOPP_CXX11_ATOMICS 1 +#elif defined(__clang__) +# if __has_feature(cxx_atomic) +# define CRYPTOPP_CXX11_ATOMICS 1 +# endif +#elif (CRYPTOPP_GCC_VERSION >= 40400) +# define CRYPTOPP_CXX11_ATOMICS 1 +#endif // atomics + // alignof/alignas: MS at VS2013 (19.00); GCC at 4.8; Clang at 3.3; and Intel 15.0. #if (CRYPTOPP_MSC_VERSION >= 1900) # define CRYPTOPP_CXX11_ALIGNAS 1 diff --git a/fipstest.cpp b/fipstest.cpp index 08d752e7..1050892f 100644 --- a/fipstest.cpp +++ b/fipstest.cpp @@ -1,6 +1,7 @@ // fipstest.cpp - written and placed in the public domain by Wei Dai #include "pch.h" +#include "config.h" #ifndef CRYPTOPP_IMPORTS @@ -11,8 +12,20 @@ #include "smartptr.h" #include "misc.h" +// Simply disable CRYPTOPP_WIN32_AVAILABLE for Windows Phone and Windows Store apps #ifdef CRYPTOPP_WIN32_AVAILABLE +# if defined(WINAPI_FAMILY) +# if !(WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)) +# undef CRYPTOPP_WIN32_AVAILABLE +# endif +# endif +#endif + +#ifdef CRYPTOPP_WIN32_AVAILABLE +#ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0400 +#endif + #include #if defined(_MSC_VER) && _MSC_VER >= 1400 diff --git a/hrtimer.cpp b/hrtimer.cpp index caf2fa6c..babd1fb7 100644 --- a/hrtimer.cpp +++ b/hrtimer.cpp @@ -3,13 +3,24 @@ #include "pch.h" #include "hrtimer.h" #include "misc.h" + #include // for NULL #include #if defined(CRYPTOPP_WIN32_AVAILABLE) #define WIN32_LEAN_AND_MEAN #include -#elif defined(CRYPTOPP_UNIX_AVAILABLE) +# if ((WINVER >= 0x0602 /*_WIN32_WINNT_WIN8*/) || (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)) +# include +# if defined(WINAPI_FAMILY) +# if (WINAPI_FAMILY_PARTITION(WINAPI_FAMILY_PHONE_APP)) +# include +# endif +# endif +#endif +#endif + +#if defined(CRYPTOPP_UNIX_AVAILABLE) #include #include #include @@ -21,6 +32,22 @@ NAMESPACE_BEGIN(CryptoPP) #ifndef CRYPTOPP_IMPORTS +#if defined(CRYPTOPP_WIN32_AVAILABLE) +static TimerWord InitializePerformanceCounterFrequency() +{ + LARGE_INTEGER freq = {0,0}; + if (!QueryPerformanceFrequency(&freq)) + throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceFrequency failed with error " + IntToString(GetLastError())); + return freq.QuadPart; +} + +inline TimerWord PerformanceCounterFrequency() +{ + static const word64 freq = InitializePerformanceCounterFrequency(); + return freq; +} +#endif + double TimerBase::ConvertTo(TimerWord t, Unit unit) { static unsigned long unitsPerSecondTable[] = {1, 1000, 1000*1000, 1000*1000*1000}; @@ -56,7 +83,7 @@ double TimerBase::ElapsedTimeAsDouble() unsigned long TimerBase::ElapsedTime() { double elapsed = ElapsedTimeAsDouble(); - assert(elapsed <= ULONG_MAX); + assert(elapsed <= (double)ULONG_MAX); return (unsigned long)elapsed; } @@ -81,14 +108,7 @@ TimerWord Timer::GetCurrentTimerValue() TimerWord Timer::TicksPerSecond() { #if defined(CRYPTOPP_WIN32_AVAILABLE) - // Use the second union member to avoid an uninitialized warning - static LARGE_INTEGER freq = {0,0}; - if (freq.QuadPart == 0) - { - if (!QueryPerformanceFrequency(&freq)) - throw Exception(Exception::OTHER_ERROR, "Timer: QueryPerformanceFrequency failed with error " + IntToString(GetLastError())); - } - return freq.QuadPart; + return PerformanceCounterFrequency(); #elif defined(CRYPTOPP_UNIX_AVAILABLE) return 1000000; #else @@ -100,14 +120,14 @@ TimerWord Timer::TicksPerSecond() TimerWord ThreadUserTimer::GetCurrentTimerValue() { -#if defined(CRYPTOPP_WIN32_AVAILABLE) +#if defined(CRYPTOPP_WIN32_AVAILABLE) && defined(THREAD_TIMER_AVAILABLE) static bool getCurrentThreadImplemented = true; if (getCurrentThreadImplemented) { FILETIME now, ignored; if (!GetThreadTimes(GetCurrentThread(), &ignored, &ignored, &ignored, &now)) { - DWORD lastError = GetLastError(); + const DWORD lastError = GetLastError(); if (lastError == ERROR_CALL_NOT_IMPLEMENTED) { getCurrentThreadImplemented = false; @@ -119,6 +139,14 @@ TimerWord ThreadUserTimer::GetCurrentTimerValue() } GetCurrentThreadNotImplemented: return (TimerWord)clock() * (10*1000*1000 / CLOCKS_PER_SEC); +#elif defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(THREAD_TIMER_AVAILABLE) + LARGE_INTEGER now; + if (!QueryPerformanceCounter(&now)) + { + const DWORD lastError = GetLastError(); + throw Exception(Exception::OTHER_ERROR, "ThreadUserTimer: QueryPerformanceCounter failed with error " + IntToString(lastError)); + } + return now.QuadPart; #elif defined(CRYPTOPP_UNIX_AVAILABLE) tms now; times(&now); @@ -130,8 +158,11 @@ GetCurrentThreadNotImplemented: TimerWord ThreadUserTimer::TicksPerSecond() { -#if defined(CRYPTOPP_WIN32_AVAILABLE) +#if defined(CRYPTOPP_WIN32_AVAILABLE) && defined(THREAD_TIMER_AVAILABLE) return 10*1000*1000; +#elif defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(THREAD_TIMER_AVAILABLE) + static const TimerWord ticksPerSecond = PerformanceCounterFrequency(); + return ticksPerSecond; #elif defined(CRYPTOPP_UNIX_AVAILABLE) static const long ticksPerSecond = sysconf(_SC_CLK_TCK); return ticksPerSecond; diff --git a/hrtimer.h b/hrtimer.h index c184c01b..88c2e538 100644 --- a/hrtimer.h +++ b/hrtimer.h @@ -2,7 +2,8 @@ #define CRYPTOPP_HRTIMER_H #include "config.h" -#ifndef HIGHRES_TIMER_AVAILABLE + +#if !defined(HIGHRES_TIMER_AVAILABLE) || (defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(THREAD_TIMER_AVAILABLE)) #include #endif @@ -14,7 +15,8 @@ NAMESPACE_BEGIN(CryptoPP) typedef clock_t TimerWord; #endif -//! _ +//! \class TimerBase +//! \brief Base class for timers class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE TimerBase { public: @@ -38,13 +40,15 @@ private: TimerWord m_start, m_last; }; -//! measure CPU time spent executing instructions of this thread (if supported by OS) -/*! /note This only works correctly on Windows NT or later. On Unix it reports process time, and others wall clock time. -*/ +//! \class ThreadUserTimer +//! \brief Measure CPU time spent executing instructions of this thread (if supported by OS) +//! \note ThreadUserTimer only works correctly on Windows NT or later desktops and servers. +//! On Unix-based it reports process time. On Windows Phone and Windows Store it reports wall +//! clock time with performance counter precision. On all others it reports wall clock time. class ThreadUserTimer : public TimerBase { public: - ThreadUserTimer(Unit unit = TimerBase::SECONDS, bool stuckAtZero = false) : TimerBase(unit, stuckAtZero) {} + ThreadUserTimer(Unit unit = TimerBase::SECONDS, bool stuckAtZero = false) : TimerBase(unit, stuckAtZero) {} TimerWord GetCurrentTimerValue(); TimerWord TicksPerSecond(); }; diff --git a/misc.h b/misc.h index e540da0d..9e33688e 100644 --- a/misc.h +++ b/misc.h @@ -12,7 +12,7 @@ #if CRYPTOPP_MSC_VERSION # pragma warning(push) -# pragma warning(disable: 4146) +# pragma warning(disable: 4146 4514) # if (CRYPTOPP_MSC_VERSION >= 1400) # pragma warning(disable: 6326) # endif @@ -218,7 +218,9 @@ struct NewObject //! _ReadWriteBarrier() or __asm__("" ::: "memory"). #define MEMORY_BARRIER ... #else -#if (_MSC_VER >= 1400) +#if defined(CRYPTOPP_CXX11_ATOMICS) +# define MEMORY_BARRIER() std::atomic_thread_fence(std::memory_order_acq_rel) +#elif (_MSC_VER >= 1400) # pragma intrinsic(_ReadWriteBarrier) # define MEMORY_BARRIER() _ReadWriteBarrier() #elif defined(__INTEL_COMPILER) @@ -254,6 +256,33 @@ private: //! \brief Return a reference to the inner Singleton object //! \details Ref() is used to create the object using the object factory. The //! object is only created once with the limitations discussed in the class documentation. +#if defined(CRYPTOPP_CXX11_ATOMICS) +template + const T & Singleton::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const +{ + static volatile simple_ptr s_pObject; + T *p = s_pObject.m_p; + std::atomic_thread_fence(std::memory_order_acquire); + + if (p) + return *p; + + T *newObject = m_objectFactory(); + p = s_pObject.m_p; + std::atomic_thread_fence(std::memory_order_acquire); + + if (p) + { + delete newObject; + return *p; + } + + s_pObject.m_p = newObject; + std::atomic_thread_fence(std::memory_order_release); + + return *newObject; +} +#else template const T & Singleton::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const { @@ -279,6 +308,7 @@ const T & Singleton::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const return *newObject; } +#endif // ************** misc functions *************** @@ -1070,6 +1100,36 @@ template<> inline void SecureWipeBuffer(word64 *buf, size_t n) #endif // #if (_MSC_VER >= 1400 || defined(__GNUC__)) && (CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86) +#if (_MSC_VER >= 1700) && defined(_M_ARM) +template<> inline void SecureWipeBuffer(byte *buf, size_t n) +{ + char *p = reinterpret_cast(buf+n); + while (n--) + __iso_volatile_store8(--p, 0); +} + +template<> inline void SecureWipeBuffer(word16 *buf, size_t n) +{ + short *p = reinterpret_cast(buf+n); + while (n--) + __iso_volatile_store16(--p, 0); +} + +template<> inline void SecureWipeBuffer(word32 *buf, size_t n) +{ + int *p = reinterpret_cast(buf+n); + while (n--) + __iso_volatile_store32(--p, 0); +} + +template<> inline void SecureWipeBuffer(word64 *buf, size_t n) +{ + __int64 *p = reinterpret_cast<__int64*>(buf+n); + while (n--) + __iso_volatile_store64(--p, 0); +} +#endif + //! \brief Sets each element of an array to 0 //! \param buf an array of elements //! \param n the number of elements in the array @@ -1858,7 +1918,7 @@ inline word64 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, co inline void UnalignedbyteNonTemplate(ByteOrder order, byte *block, byte value, const byte *xorBlock) { CRYPTOPP_UNUSED(order); - block[0] = xorBlock ? (value ^ xorBlock[0]) : value; + block[0] = (byte)(xorBlock ? (value ^ xorBlock[0]) : value); } inline void UnalignedbyteNonTemplate(ByteOrder order, byte *block, word16 value, const byte *xorBlock) diff --git a/network.cpp b/network.cpp index c77748e3..118f6b27 100644 --- a/network.cpp +++ b/network.cpp @@ -3,14 +3,15 @@ #include "pch.h" #include "network.h" + +#if !defined(NO_OS_DEPENDENCE) && defined(SOCKETS_AVAILABLE) + #include "wait.h" #define CRYPTOPP_TRACE_NETWORK 0 NAMESPACE_BEGIN(CryptoPP) -#ifdef HIGHRES_TIMER_AVAILABLE - lword LimitedBandwidth::ComputeCurrentTransceiveLimit() { if (!m_maxBytesPerSecond) @@ -548,6 +549,6 @@ lword NetworkSink::DoFlush(unsigned long maxTime, size_t targetSize) return totalFlushSize; } -#endif // #ifdef HIGHRES_TIMER_AVAILABLE - NAMESPACE_END + +#endif // #ifdef SOCKETS_AVAILABLE diff --git a/network.h b/network.h index d9b3c66e..fa13b526 100644 --- a/network.h +++ b/network.h @@ -3,12 +3,11 @@ #include "config.h" -#ifdef HIGHRES_TIMER_AVAILABLE +#if !defined(NO_OS_DEPENDENCE) && defined(SOCKETS_AVAILABLE) #include "filters.h" #include "hrtimer.h" - -#include +#include "stdcpp.h" NAMESPACE_BEGIN(CryptoPP) @@ -230,6 +229,6 @@ private: NAMESPACE_END -#endif // #ifdef HIGHRES_TIMER_AVAILABLE +#endif // SOCKETS_AVAILABLE -#endif +#endif // CRYPTOPP_NETWORK_H diff --git a/osrng.cpp b/osrng.cpp index f9181ec2..eaec1532 100644 --- a/osrng.cpp +++ b/osrng.cpp @@ -3,21 +3,49 @@ // Thanks to Leonard Janke for the suggestion for AutoSeededRandomPool. #include "pch.h" +#include "config.h" #ifndef CRYPTOPP_IMPORTS +// Win32 has CryptoAPI and . Windows 10 and Windows Store 10 have CNG and . +// There's a hole for Windows Phone 8 and Windows Store 8. There is no userland crypto available. +// Also see http://stackoverflow.com/questions/36974545/random-numbers-for-windows-phone-8-and-windows-store-8 +#if defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(OS_RNG_AVAILABLE) +# pragma message("WARNING: Compiling for Windows but an OS RNG is not available. This is likely a Windows Phone 8 or Windows Store 8 app.") +#endif + +#if !defined(OS_NO_DEPENDENCE) && defined(OS_RNG_AVAILABLE) + #include "osrng.h" - -#ifdef OS_RNG_AVAILABLE - #include "rng.h" #ifdef CRYPTOPP_WIN32_AVAILABLE -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x0400 -#endif +//#ifndef _WIN32_WINNT +//#define _WIN32_WINNT 0x0400 +//#endif +#define WIN32_LEAN_AND_MEAN #include +#if defined(USE_MS_CRYPTOAPI) #include +#ifndef CRYPT_NEWKEYSET +# define CRYPT_NEWKEYSET 0x00000008 +#endif +#ifndef CRYPT_MACHINE_KEYSET +# define CRYPT_MACHINE_KEYSET 0x00000020 +#endif +#elif defined(USE_MS_CNGAPI) +//#include +#include +#ifndef BCRYPT_SUCCESS +# define BCRYPT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) +#endif +#ifndef STATUS_INVALID_PARAMETER +# define STATUS_INVALID_PARAMETER 0xC000000D +#endif +#ifndef STATUS_INVALID_HANDLE +# define STATUS_INVALID_HANDLE 0xC0000008 +#endif +#endif #endif #ifdef CRYPTOPP_UNIX_AVAILABLE @@ -45,18 +73,62 @@ OS_RNG_Err::OS_RNG_Err(const std::string &operation) #ifdef CRYPTOPP_WIN32_AVAILABLE -MicrosoftCryptoProvider::MicrosoftCryptoProvider() +#if defined(USE_MS_CNGAPI) +inline DWORD NtStatusToErrorCode(NTSTATUS status) { + if (status == STATUS_INVALID_PARAMETER) + return ERROR_INVALID_PARAMETER; + else if (status == STATUS_INVALID_HANDLE) + return ERROR_INVALID_HANDLE; + else + return (DWORD)status; +} +#endif + +#if defined(UNICODE) || defined(_UNICODE) +# define CRYPTOPP_CONTAINER L"Crypto++ RNG" +#else +# define CRYPTOPP_CONTAINER "Crypto++ RNG" +#endif + +MicrosoftCryptoProvider::MicrosoftCryptoProvider() : m_hProvider(0) +{ +#if defined(USE_MS_CRYPTOAPI) + // See http://support.microsoft.com/en-us/kb/238187 for CRYPT_NEWKEYSET fallback strategy if (!CryptAcquireContext(&m_hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) - throw OS_RNG_Err("CryptAcquireContext"); + { + const DWORD firstErr = GetLastError(); + if (!CryptAcquireContext(&m_hProvider, CRYPTOPP_CONTAINER, 0, PROV_RSA_FULL, CRYPT_NEWKEYSET /*user*/) && + !CryptAcquireContext(&m_hProvider, CRYPTOPP_CONTAINER, 0, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET|CRYPT_NEWKEYSET)) + { + // Set original error with original code + SetLastError(firstErr); + throw OS_RNG_Err("CryptAcquireContext"); + } + } +#elif defined(USE_MS_CNGAPI) + NTSTATUS ret = BCryptOpenAlgorithmProvider(&m_hProvider, BCRYPT_RNG_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0); + if (!(BCRYPT_SUCCESS(ret))) + { + // Hack... OS_RNG_Err calls GetLastError() + SetLastError(NtStatusToErrorCode(ret)); + throw OS_RNG_Err("BCryptOpenAlgorithmProvider"); + } +#endif } MicrosoftCryptoProvider::~MicrosoftCryptoProvider() { - CryptReleaseContext(m_hProvider, 0); +#if defined(USE_MS_CRYPTOAPI) + if (m_hProvider) + CryptReleaseContext(m_hProvider, 0); +#elif defined(USE_MS_CNGAPI) + if (m_hProvider) + BCryptCloseAlgorithmProvider(m_hProvider, 0); +#endif } -#endif +#endif // CRYPTOPP_WIN32_AVAILABLE NonblockingRng::NonblockingRng() { @@ -77,16 +149,24 @@ NonblockingRng::~NonblockingRng() void NonblockingRng::GenerateBlock(byte *output, size_t size) { #ifdef CRYPTOPP_WIN32_AVAILABLE -# ifdef WORKAROUND_MS_BUG_Q258000 - const MicrosoftCryptoProvider &m_Provider = Singleton().Ref(); -# endif - if (!CryptGenRandom(m_Provider.GetProviderHandle(), (DWORD)size, output)) + // Acquiring a provider is expensive. Do it once and retain the reference. + static const MicrosoftCryptoProvider &hProvider = Singleton().Ref(); +# if defined(USE_MS_CRYPTOAPI) + if (!CryptGenRandom(hProvider.GetProviderHandle(), (DWORD)size, output)) throw OS_RNG_Err("CryptGenRandom"); +# elif defined(USE_MS_CNGAPI) + NTSTATUS ret = BCryptGenRandom(hProvider.GetProviderHandle(), output, (ULONG)size, 0); + if (!(BCRYPT_SUCCESS(ret))) + { + // Hack... OS_RNG_Err calls GetLastError() + SetLastError(NtStatusToErrorCode(ret)); + throw OS_RNG_Err("BCryptGenRandom"); + } +# endif #else while (size) { ssize_t len = read(m_fd, output, size); - if (len < 0) { // /dev/urandom reads CAN give EAGAIN errors! (maybe EINTR as well) @@ -99,10 +179,10 @@ void NonblockingRng::GenerateBlock(byte *output, size_t size) output += len; size -= len; } -#endif +#endif // CRYPTOPP_WIN32_AVAILABLE } -#endif +#endif // NONBLOCKING_RNG_AVAILABLE // ************************************************************* @@ -151,7 +231,7 @@ void BlockingRng::GenerateBlock(byte *output, size_t size) } } -#endif +#endif // BLOCKING_RNG_AVAILABLE // ************************************************************* @@ -187,6 +267,6 @@ void AutoSeededRandomPool::Reseed(bool blocking, unsigned int seedSize) NAMESPACE_END -#endif +#endif // OS_RNG_AVAILABLE -#endif +#endif // CRYPTOPP_IMPORTS diff --git a/osrng.h b/osrng.h index dd53112e..92dfa312 100644 --- a/osrng.h +++ b/osrng.h @@ -1,7 +1,6 @@ // osrng.h - written and placed in the public domain by Wei Dai -//! \file -//! \headerfile osrng.h +//! \file osrng.h //! \brief Classes for access to the operating system's random number generators #ifndef CRYPTOPP_OSRNG_H @@ -9,7 +8,7 @@ #include "config.h" -#ifdef OS_RNG_AVAILABLE +#if !defined(OS_NO_DEPENDENCE) && defined(OS_RNG_AVAILABLE) #include "cryptlib.h" #include "randpool.h" @@ -36,7 +35,7 @@ public: #ifdef CRYPTOPP_WIN32_AVAILABLE //! \class MicrosoftCryptoProvider //! \brief Wrapper for Microsoft crypto service provider -//! \sa \def USE_MS_CRYPTOAPI, \def WORKAROUND_MS_BUG_Q258000 +//! \sa \def USE_MS_CRYPTOAPI, \def USE_MS_CNGAPI, \def WORKAROUND_MS_BUG_Q258000 class CRYPTOPP_DLL MicrosoftCryptoProvider { public: @@ -44,34 +43,47 @@ public: MicrosoftCryptoProvider(); ~MicrosoftCryptoProvider(); -// type HCRYPTPROV, avoid #include -#if defined(__CYGWIN__) && defined(__x86_64__) +// type HCRYPTPROV and BCRYPT_ALG_HANDLE, avoid #include +#if defined(USE_MS_CRYPTOAPI) +# if defined(__CYGWIN__) && defined(__x86_64__) typedef unsigned long long ProviderHandle; -#elif defined(WIN64) || defined(_WIN64) +# elif defined(WIN64) || defined(_WIN64) typedef unsigned __int64 ProviderHandle; -#else +# else typedef unsigned long ProviderHandle; -#endif +# endif +#elif defined(USE_MS_CNGAPI) + typedef void *PVOID; + typedef PVOID ProviderHandle; +#endif // USE_MS_CRYPTOAPI or USE_MS_CNGAPI - //! \brief Retrieves the CryptoAPI provider handle + //! \brief Retrieves the provider handle //! \returns CryptoAPI provider handle - //! \details The handle is acquired by a call to CryptAcquireContext(). - //! CryptReleaseContext() is called upon destruction. + //! \details If USE_MS_CRYPTOAPI is in effect, then CryptAcquireContext() + //! acquires then handle and CryptReleaseContext() releases the handle + //! upon destruction. If USE_MS_CNGAPI is in effect, then + //! BCryptOpenAlgorithmProvider() acquires then handle and + //! BCryptCloseAlgorithmProvider() releases the handle upon destruction. ProviderHandle GetProviderHandle() const {return m_hProvider;} private: ProviderHandle m_hProvider; }; -#if defined(_MSC_VER) +#if defined(_MSC_VER) && defined(USE_MS_CRYPTOAPI) # pragma comment(lib, "advapi32.lib") #endif +#if defined(_MSC_VER) && defined(USE_MS_CNGAPI) +# pragma comment(lib, "bcrypt.lib") +#endif + #endif //CRYPTOPP_WIN32_AVAILABLE //! \class NonblockingRng //! \brief Wrapper class for /dev/random and /dev/srandom -//! \details Encapsulates CryptoAPI's CryptGenRandom() on Windows, or /dev/urandom on Unix and compatibles. +//! \details Encapsulates CryptoAPI's CryptGenRandom() or CryptoNG's BCryptGenRandom() +//! on Windows, or /dev/urandom on Unix and compatibles. class CRYPTOPP_DLL NonblockingRng : public RandomNumberGenerator { public: @@ -87,9 +99,7 @@ public: protected: #ifdef CRYPTOPP_WIN32_AVAILABLE -# ifndef WORKAROUND_MS_BUG_Q258000 - MicrosoftCryptoProvider m_Provider; -# endif + MicrosoftCryptoProvider m_Provider; #else int m_fd; #endif @@ -137,6 +147,7 @@ CRYPTOPP_DLL void CRYPTOPP_API OS_GenerateRandomBlock(bool blocking, byte *outpu //! \class AutoSeededRandomPool //! \brief Automatically Seeded Randomness Pool //! \details This class seeds itself using an operating system provided RNG. +//! AutoSeededRandomPool was suggested by Leonard Janke. class CRYPTOPP_DLL AutoSeededRandomPool : public RandomPool { public: diff --git a/socketft.cpp b/socketft.cpp index ad31f68a..ef66ba00 100644 --- a/socketft.cpp +++ b/socketft.cpp @@ -1,19 +1,21 @@ // socketft.cpp - written and placed in the public domain by Wei Dai #include "pch.h" +#include "config.h" + +#if !defined(NO_OS_DEPENDENCE) && defined(SOCKETS_AVAILABLE) // TODO: http://github.com/weidai11/cryptopp/issues/19 #define _WINSOCK_DEPRECATED_NO_WARNINGS #include "socketft.h" - -#ifdef SOCKETS_AVAILABLE - #include "wait.h" -// Windows 8, Windows Server 2012, and Windows Phone 8.1 need +// Windows 8, Windows Server 2012, and Windows Phone 8.1 need and #if defined(CRYPTOPP_WIN32_AVAILABLE) -# if defined(_WIN32_WINNT_WIN8) && ((WINVER >= _WIN32_WINNT_WIN8) || (_WIN32_WINNT >= _WIN32_WINNT_WIN8)) +# if ((WINVER >= 0x0602 /*_WIN32_WINNT_WIN8*/) || (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)) # include +# include +# define USE_WINDOWS8_API # endif #endif @@ -103,8 +105,15 @@ void Socket::CloseSocket() if (m_s != INVALID_SOCKET) { #ifdef USE_WINDOWS_STYLE_SOCKETS - CancelIo((HANDLE) m_s); +# if defined(USE_WINDOWS8_API) + BOOL result = CancelIoEx((HANDLE) m_s, NULL); + assert(result || (!result && GetLastError() == ERROR_NOT_FOUND)); CheckAndHandleError_int("closesocket", closesocket(m_s)); +# else + BOOL result = CancelIo((HANDLE) m_s); + assert(result || (!result && GetLastError() == ERROR_NOT_FOUND)); + CheckAndHandleError_int("closesocket", closesocket(m_s)); +# endif #else CheckAndHandleError_int("close", close(m_s)); #endif @@ -356,7 +365,13 @@ SocketReceiver::SocketReceiver(Socket &s) SocketReceiver::~SocketReceiver() { #ifdef USE_WINDOWS_STYLE_SOCKETS - CancelIo((HANDLE) m_s.GetSocket()); +# if defined(USE_WINDOWS8_API) + BOOL result = CancelIoEx((HANDLE) m_s.GetSocket(), NULL); + assert(result || (!result && GetLastError() == ERROR_NOT_FOUND)); +# else + BOOL result = CancelIo((HANDLE) m_s.GetSocket()); + assert(result || (!result && GetLastError() == ERROR_NOT_FOUND)); +# endif #endif } @@ -438,7 +453,13 @@ SocketSender::SocketSender(Socket &s) SocketSender::~SocketSender() { #ifdef USE_WINDOWS_STYLE_SOCKETS - CancelIo((HANDLE) m_s.GetSocket()); +# if defined(USE_WINDOWS8_API) + BOOL result = CancelIoEx((HANDLE) m_s.GetSocket(), NULL); + assert(result || (!result && GetLastError() == ERROR_NOT_FOUND)); +# else + BOOL result = CancelIo((HANDLE) m_s.GetSocket()); + assert(result || (!result && GetLastError() == ERROR_NOT_FOUND)); +# endif #endif } @@ -559,8 +580,8 @@ void SocketSender::GetWaitObjects(WaitObjectContainer &container, CallStack cons container.AddWriteFd(m_s, CallStack("SocketSender::GetWaitObjects()", &callStack)); } -#endif +#endif // USE_BERKELEY_STYLE_SOCKETS NAMESPACE_END -#endif // #ifdef SOCKETS_AVAILABLE +#endif // SOCKETS_AVAILABLE diff --git a/socketft.h b/socketft.h index 03f325c3..61592834 100644 --- a/socketft.h +++ b/socketft.h @@ -1,7 +1,9 @@ #ifndef CRYPTOPP_SOCKETFT_H #define CRYPTOPP_SOCKETFT_H -#ifdef SOCKETS_AVAILABLE +#include "config.h" + +#if !defined(NO_OS_DEPENDENCE) && defined(SOCKETS_AVAILABLE) #include "cryptlib.h" #include "network.h" @@ -218,6 +220,6 @@ private: NAMESPACE_END -#endif // #ifdef SOCKETS_AVAILABLE +#endif // SOCKETS_AVAILABLE -#endif +#endif // CRYPTOPP_SOCKETFT_H diff --git a/stdcpp.h b/stdcpp.h index 66efc203..22cee7a2 100644 --- a/stdcpp.h +++ b/stdcpp.h @@ -32,6 +32,10 @@ namespace std { #include #endif +#if defined(CRYPTOPP_CXX11_ATOMICS) +#include +#endif + #include #include #include diff --git a/test.cpp b/test.cpp index a920db7d..509d3848 100644 --- a/test.cpp +++ b/test.cpp @@ -802,6 +802,9 @@ void HexDecode(const char *in, const char *out) void ForwardTcpPort(const char *sourcePortName, const char *destinationHost, const char *destinationPortName) { + // Quiet warnings for Windows Phone and Windows Store builds + CRYPTOPP_UNUSED(sourcePortName), CRYPTOPP_UNUSED(destinationHost), CRYPTOPP_UNUSED(destinationPortName); + #ifdef SOCKETS_AVAILABLE SocketsInitializer sockInit; diff --git a/trap.h b/trap.h index 4627079a..63985840 100644 --- a/trap.h +++ b/trap.h @@ -18,7 +18,11 @@ # include # if defined(CRYPTOPP_WIN32_AVAILABLE) # pragma push_macro("WIN32_LEAN_AND_MEAN") +# pragma push_macro("_WIN32_WINNT") +# pragma push_macro("NOMINMAX") # define WIN32_LEAN_AND_MEAN +# define _WIN32_WINNT 0x0400 +# define NOMINMAX # include # elif defined(CRYPTOPP_BSD_AVAILABLE) || defined(CRYPTOPP_UNIX_AVAILABLE) # include @@ -60,6 +64,8 @@ #if defined(CRYPTOPP_DEBUG) && defined(CRYPTOPP_WIN32_AVAILABLE) # pragma pop_macro("WIN32_LEAN_AND_MEAN") +# pragma pop_macro("_WIN32_WINNT") +# pragma pop_macro("NOMINMAX") #endif #endif // CRYPTOPP_TRAP_H diff --git a/trdlocal.cpp b/trdlocal.cpp index ecc7d7b0..12386abe 100644 --- a/trdlocal.cpp +++ b/trdlocal.cpp @@ -9,7 +9,8 @@ #endif #ifndef CRYPTOPP_IMPORTS -#ifdef THREADS_AVAILABLE + +#if !defined(NO_OS_DEPENDENCE) && defined(THREADS_AVAILABLE) #include "trdlocal.h" @@ -101,5 +102,5 @@ void *ThreadLocalStorage::GetValue() const NAMESPACE_END -#endif // #ifdef THREADS_AVAILABLE -#endif +#endif // THREADS_AVAILABLE +#endif // CRYPTOPP_IMPORTS diff --git a/trdlocal.h b/trdlocal.h index 05216679..a3eb0431 100644 --- a/trdlocal.h +++ b/trdlocal.h @@ -3,7 +3,7 @@ #include "config.h" -#ifdef THREADS_AVAILABLE +#if !defined(NO_OS_DEPENDENCE) && defined(THREADS_AVAILABLE) #include "misc.h" @@ -39,6 +39,6 @@ private: NAMESPACE_END -#endif // #ifdef THREADS_AVAILABLE +#endif // THREADS_AVAILABLE -#endif +#endif // CRYPTOPP_TRDLOCAL_H diff --git a/wait.cpp b/wait.cpp index 5db5cf39..fa4fd7fc 100644 --- a/wait.cpp +++ b/wait.cpp @@ -7,16 +7,18 @@ # pragma warning(disable: 4189) #endif +#if !defined(NO_OS_DEPENDENCE) && (defined(SOCKETS_AVAILABLE) || defined(WINDOWS_PIPES_AVAILABLE)) + #include "wait.h" #include "misc.h" #include "smartptr.h" -#ifdef SOCKETS_AVAILABLE - -// Windows 8, Windows Server 2012, and Windows Phone 8.1 need +// Windows 8, Windows Server 2012, and Windows Phone 8.1 need and #if defined(CRYPTOPP_WIN32_AVAILABLE) -# if defined(_WIN32_WINNT_WIN8) && ((WINVER >= _WIN32_WINNT_WIN8) || (_WIN32_WINNT >= _WIN32_WINNT_WIN8)) +# if ((WINVER >= 0x0602 /*_WIN32_WINNT_WIN8*/) || (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)) # include +# include +# define USE_WINDOWS8_API # endif #endif @@ -153,8 +155,13 @@ WaitObjectContainer::~WaitObjectContainer() assert(bResult != 0); CRYPTOPP_UNUSED(bResult); // Enterprise Analysis warning +#if defined(USE_WINDOWS8_API) + DWORD dwResult = ::WaitForMultipleObjectsEx((DWORD)m_threads.size(), threadHandles, TRUE, INFINITE, FALSE); + assert((dwResult >= WAIT_OBJECT_0) && (dwResult < (DWORD)m_threads.size())); +#else DWORD dwResult = ::WaitForMultipleObjects((DWORD)m_threads.size(), threadHandles, TRUE, INFINITE); assert((dwResult >= WAIT_OBJECT_0) && (dwResult < (DWORD)m_threads.size())); +#endif for (i=0; i 0) { diff --git a/wait.h b/wait.h index 298ca684..13e6ba33 100644 --- a/wait.h +++ b/wait.h @@ -4,12 +4,13 @@ #define CRYPTOPP_WAIT_H #include "config.h" + +#if !defined(NO_OS_DEPENDENCE) && (defined(SOCKETS_AVAILABLE) || defined(WINDOWS_PIPES_AVAILABLE)) + #include "cryptlib.h" #include "misc.h" #include "stdcpp.h" -#ifdef SOCKETS_AVAILABLE - #ifdef USE_WINDOWS_STYLE_SOCKETS #include #else diff --git a/winpipes.cpp b/winpipes.cpp index 66725a2f..0b4846d0 100644 --- a/winpipes.cpp +++ b/winpipes.cpp @@ -1,16 +1,19 @@ // winpipes.cpp - written and placed in the public domain by Wei Dai #include "pch.h" +#include "config.h" + +#if !defined(NO_OS_DEPENDENCE) && defined(WINDOWS_PIPES_AVAILABLE) + #include "winpipes.h" - -#ifdef WINDOWS_PIPES_AVAILABLE - #include "wait.h" -// Windows 8, Windows Server 2012, and Windows Phone 8.1 need +// Windows 8, Windows Server 2012, and Windows Phone 8.1 need and #if defined(CRYPTOPP_WIN32_AVAILABLE) -# if defined(_WIN32_WINNT_WIN8) && ((WINVER >= _WIN32_WINNT_WIN8) || (_WIN32_WINNT >= _WIN32_WINNT_WIN8)) +# if ((WINVER >= 0x0602 /*_WIN32_WINNT_WIN8*/) || (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/)) # include +# include +# define USE_WINDOWS8_API # endif #endif @@ -135,8 +138,12 @@ unsigned int WindowsPipeReceiver::GetReceiveResult() { if (m_resultPending) { - const HANDLE h = GetHandle(); - if (GetOverlappedResult(h, &m_overlapped, &m_lastResult, false)) +#if defined(USE_WINDOWS8_API) + BOOL result = GetOverlappedResultEx(GetHandle(), &m_overlapped, &m_lastResult, INFINITE, FALSE); +#else + BOOL result = GetOverlappedResult(GetHandle(), &m_overlapped, &m_lastResult, FALSE); +#endif + if (result) { if (m_lastResult == 0) m_eofReceived = true; @@ -201,8 +208,13 @@ unsigned int WindowsPipeSender::GetSendResult() if (m_resultPending) { const HANDLE h = GetHandle(); - BOOL result = GetOverlappedResult(h, &m_overlapped, &m_lastResult, false); +#if defined(USE_WINDOWS8_API) + BOOL result = GetOverlappedResultEx(h, &m_overlapped, &m_lastResult, INFINITE, FALSE); + CheckAndHandleError("GetOverlappedResultEx", result); +#else + BOOL result = GetOverlappedResult(h, &m_overlapped, &m_lastResult, FALSE); CheckAndHandleError("GetOverlappedResult", result); +#endif m_resultPending = false; } return m_lastResult; diff --git a/winpipes.h b/winpipes.h index 9019d2fe..246fb91b 100644 --- a/winpipes.h +++ b/winpipes.h @@ -1,7 +1,9 @@ #ifndef CRYPTOPP_WINPIPES_H #define CRYPTOPP_WINPIPES_H -#ifdef WINDOWS_PIPES_AVAILABLE +#include "config.h" + +#if !defined(NO_OS_DEPENDENCE) && defined(WINDOWS_PIPES_AVAILABLE) #include "cryptlib.h" #include "network.h" @@ -10,7 +12,7 @@ NAMESPACE_BEGIN(CryptoPP) -//! Windows Handle +//! \brief Windows Handle class WindowsHandle { public: @@ -35,7 +37,7 @@ protected: bool m_own; }; -//! Windows Pipe +//! \brief Windows Pipe class WindowsPipe { public: @@ -56,7 +58,7 @@ protected: {assert(result==TRUE || result==FALSE); if (!result) HandleError(operation);} }; -//! pipe-based implementation of NetworkReceiver +//! \brief Pipe-based implementation of NetworkReceiver class WindowsPipeReceiver : public WindowsPipe, public NetworkReceiver { public: @@ -79,7 +81,7 @@ private: bool m_eofReceived; }; -//! pipe-based implementation of NetworkSender +//! \brief Pipe-based implementation of NetworkSender class WindowsPipeSender : public WindowsPipe, public NetworkSender { public: @@ -102,7 +104,7 @@ private: DWORD m_lastResult; }; -//! Windows Pipe Source +//! \brief Windows Pipe Source class WindowsPipeSource : public WindowsHandle, public NetworkSource, public WindowsPipeReceiver { public: @@ -121,7 +123,7 @@ private: NetworkReceiver & AccessReceiver() {return *this;} }; -//! Windows Pipe Sink +//! \brief Windows Pipe Sink class WindowsPipeSink : public WindowsHandle, public NetworkSink, public WindowsPipeSender { public: