From d294b4290b997f174ade322a9638db2f1e15ed41 Mon Sep 17 00:00:00 2001 From: Jeffrey Walton Date: Tue, 3 May 2016 00:23:05 -0400 Subject: [PATCH] Add changes for Windows Sotre that went missing with my clumsy Git skills --- config.h | 88 ++++++++++++++++++++++++++++++------- fipstest.cpp | 13 ++++++ hrtimer.cpp | 55 +++++++++++++++++------ hrtimer.h | 16 ++++--- misc.h | 34 ++++++++++++++- network.cpp | 9 ++-- network.h | 9 ++-- osrng.cpp | 120 ++++++++++++++++++++++++++++++++++++++++++--------- osrng.h | 45 +++++++++++-------- socketft.cpp | 41 +++++++++++++----- socketft.h | 8 ++-- stdcpp.h | 4 ++ test.cpp | 3 ++ trap.h | 6 +++ trdlocal.cpp | 7 +-- trdlocal.h | 6 +-- validat1.cpp | 2 +- wait.cpp | 36 ++++++++++++++-- wait.h | 5 ++- winpipes.cpp | 28 ++++++++---- winpipes.h | 16 ++++--- 21 files changed, 428 insertions(+), 123 deletions(-) diff --git a/config.h b/config.h index 2e71bcb8..71068eb6 100644 --- a/config.h +++ b/config.h @@ -33,9 +33,26 @@ // #define NO_OS_DEPENDENCE // Define this to use features provided by Microsoft's CryptoAPI. -// Currently the only feature used is random number generation. +// Currently the only feature used is Windows random number generation. // This macro will be ignored if NO_OS_DEPENDENCE is defined. -#define USE_MS_CRYPTOAPI +// #define USE_MS_CRYPTOAPI + +// Define this to use features provided by Microsoft's CryptoNG API. +// CryptoNG API is available in Vista and above and its cross platform, +// including desktop apps and store apps. Currently the only feature +// used is Windows random number generation. +// This macro will be ignored if NO_OS_DEPENDENCE is defined. +// #define USE_MS_CNGAPI + +// If the user did not make a choice, then select CryptoNG if either +// Visual Studio 2015 is available, or Windows 10 or above is available. +#if !defined(USE_MS_CRYPTOAPI) && !defined(USE_MS_CNGAPI) +# if (_MSC_VER >= 1900) || ((WINVER >= 0x0A00 /*_WIN32_WINNT_WIN10*/) || (_WIN32_WINNT >= 0x0A00 /*_WIN32_WINNT_WIN10*/)) +# define USE_MS_CNGAPI +# else +# define USE_MS_CRYPTOAPI +# endif +#endif // Define this to ensure C/C++ standard compliance and respect for GCC aliasing rules and other alignment fodder. If you // experience a break with GCC at -O3, you should try this first. Guard it in case its set on the command line (and it differs). @@ -531,33 +548,43 @@ NAMESPACE_END # define HIGHRES_TIMER_AVAILABLE #endif +#ifdef CRYPTOPP_WIN32_AVAILABLE +# if !defined(WINAPI_FAMILY) +# define THREAD_TIMER_AVAILABLE +# elif defined(WINAPI_FAMILY) && defined(WINAPI_FAMILY_PARTITION) +# if (WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)) +# define THREAD_TIMER_AVAILABLE +# endif +# endif +#endif + #ifdef CRYPTOPP_UNIX_AVAILABLE # define HAS_BERKELEY_STYLE_SOCKETS -#endif - -#ifdef CRYPTOPP_WIN32_AVAILABLE -# define HAS_WINDOWS_STYLE_SOCKETS -#endif - -#if defined(HIGHRES_TIMER_AVAILABLE) && (defined(HAS_BERKELEY_STYLE_SOCKETS) || defined(HAS_WINDOWS_STYLE_SOCKETS)) # define SOCKETS_AVAILABLE #endif +// Sockets are only available under Windows Runtime desktop partition apps (despite the MSDN literature) +#ifdef CRYPTOPP_WIN32_AVAILABLE +# define HAS_WINDOWS_STYLE_SOCKETS +# if !defined(WINAPI_FAMILY) +# define SOCKETS_AVAILABLE +# elif defined(WINAPI_FAMILY) && defined(WINAPI_FAMILY_PARTITION) +# if (WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)) +# define SOCKETS_AVAILABLE +# endif +# endif +#endif + #if defined(HAS_WINDOWS_STYLE_SOCKETS) && (!defined(HAS_BERKELEY_STYLE_SOCKETS) || defined(PREFER_WINDOWS_STYLE_SOCKETS)) # define USE_WINDOWS_STYLE_SOCKETS #else # define USE_BERKELEY_STYLE_SOCKETS #endif -#if defined(HIGHRES_TIMER_AVAILABLE) && defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(USE_BERKELEY_STYLE_SOCKETS) +#if defined(CRYPTOPP_WIN32_AVAILABLE) && defined(SOCKETS_AVAILABLE) && !defined(USE_BERKELEY_STYLE_SOCKETS) # define WINDOWS_PIPES_AVAILABLE #endif -#if defined(CRYPTOPP_WIN32_AVAILABLE) && defined(USE_MS_CRYPTOAPI) -# define NONBLOCKING_RNG_AVAILABLE -# define OS_RNG_AVAILABLE -#endif - #if defined(CRYPTOPP_UNIX_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING) # define NONBLOCKING_RNG_AVAILABLE # define BLOCKING_RNG_AVAILABLE @@ -567,8 +594,24 @@ NAMESPACE_END #endif #ifdef CRYPTOPP_WIN32_AVAILABLE +# if !defined(WINAPI_FAMILY) # define HAS_WINTHREADS # define THREADS_AVAILABLE +# define NONBLOCKING_RNG_AVAILABLE +# define OS_RNG_AVAILABLE +# elif defined(WINAPI_FAMILY) && defined(WINAPI_FAMILY_PARTITION) +# if (WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)) +# define HAS_WINTHREADS +# define THREADS_AVAILABLE +# define NONBLOCKING_RNG_AVAILABLE +# define OS_RNG_AVAILABLE +# elif !(WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)) +# if ((WINVER >= 0x0A00 /*_WIN32_WINNT_WIN10*/) || (_WIN32_WINNT >= 0x0A00 /*_WIN32_WINNT_WIN10*/)) +# define NONBLOCKING_RNG_AVAILABLE +# define OS_RNG_AVAILABLE +# endif +# endif +# endif #endif #endif // NO_OS_DEPENDENCE @@ -664,6 +707,19 @@ NAMESPACE_END // C++11 or C++14 is available #if defined(CRYPTOPP_CXX11) +// 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 @@ -693,7 +749,7 @@ NAMESPACE_END #elif (CRYPTOPP_GCC_VERSION >= 40600) # define CRYPTOPP_CXX11_NOEXCEPT 1 #endif // noexcept compilers - + // variadic templates: MS at VS2013 (18.00); GCC at 4.3; Clang at 2.9; and Intel 12.1. #if (CRYPTOPP_MSC_VERSION >= 1800) # define CRYPTOPP_CXX11_VARIADIC_TEMPLATES 1 diff --git a/fipstest.cpp b/fipstest.cpp index 08d752e7..46af6dd1 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) && defined(WINAPI_FAMILY_PARTITION) +# 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..4aa464ce 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) +inline 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}; @@ -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 d9f98cad..21d00e25 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 @@ -1070,6 +1070,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 +1888,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..4c7333fc 100644 --- a/network.cpp +++ b/network.cpp @@ -3,14 +3,15 @@ #include "pch.h" #include "network.h" + +#ifdef 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..b97f4f3e 100644 --- a/network.h +++ b/network.h @@ -3,12 +3,11 @@ #include "config.h" -#ifdef HIGHRES_TIMER_AVAILABLE +#ifdef 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/validat1.cpp b/validat1.cpp index 8e214607..72d68214 100644 --- a/validat1.cpp +++ b/validat1.cpp @@ -906,7 +906,7 @@ bool TestOS_RNG() return pass; } -#ifdef NO_OS_DEPENDENCE +#if defined(NO_OS_DEPENDENCE) || !defined(OS_RNG_AVAILABLE) bool TestAutoSeeded() { return true; 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: