support CryptoAPI on windows, for SHA-1 hashing (#882)

support CryptoAPI on windows, for SHA-1 hashing. don't always use openssl in test build configurations
This commit is contained in:
Arvid Norberg 2016-07-05 08:40:09 -04:00 committed by GitHub
parent cbb6f47f36
commit 3ec48ec5b4
8 changed files with 165 additions and 54 deletions

View File

@ -3,7 +3,7 @@ language: cpp
matrix:
include:
- env: variant=test_release coverage=1 toolset=gcc-coverage
- env: variant=test_debug sim=1 toolset=gcc
- env: variant=test_debug sim=1 ssl=openssl crypto=libcrypto toolset=gcc
- env: variant=test_barebones toolset=gcc
- env: analyze=1 autotools=1 toolset=gcc
- os: osx
@ -11,7 +11,7 @@ matrix:
env: variant=test_release docs=1 toolset=darwin
- os: osx
osx_image: xcode6.4
env: variant=test_debug toolset=darwin
env: variant=test_debug ssl=openssl crypto=libcrypto toolset=darwin
- os: osx
osx_image: xcode6.4
env: variant=test_barebones toolset=darwin
@ -52,6 +52,8 @@ addons:
before_install:
- git submodule update --init --recursive
- 'if [[ $ssl == "" ]]; then export ssl=off; fi'
- 'if [[ $crypto == "" ]]; then export crypto=built-in; fi'
- 'if [[ $TRAVIS_OS_NAME == "osx" && "$variant" != "" ]]; then brew update > /dev/null && brew install --quiet ccache boost-build boost-python; fi'
- 'if [ "$docs" = "1" ]; then
brew install --quiet https://raw.githubusercontent.com/catap/homebrew/docutils/Library/Formula/docutils.rb;
@ -120,7 +122,7 @@ script:
# libtorrent is the name of the test suite target
- cd test
- 'if [ "$variant" != "" ]; then
bjam -j3 warnings-as-errors=on variant=$variant -l900 $toolset libtorrent test_natpmp enum_if &&
bjam -j3 warnings-as-errors=on ssl=$ssl crypto=$crypto variant=$variant -l900 $toolset libtorrent test_natpmp enum_if &&
if [ "$coverage" == "1" ]; then
codecov --root .. --gcov-exec gcov-5;
fi;
@ -128,13 +130,13 @@ script:
- cd ../examples
- 'if [ "$variant" != "" ]; then
bjam -j3 warnings-as-errors=on variant=$variant picker-debugging=on $toolset link=shared;
bjam -j3 warnings-as-errors=on ssl=$ssl crypto=$crypto variant=$variant picker-debugging=on $toolset link=shared;
fi'
- cd ..
- cd tools
- 'if [ "$variant" != "" ]; then
bjam -j3 warnings-as-errors=on variant=$variant picker-debugging=on $toolset link=shared;
bjam -j3 warnings-as-errors=on ssl=$ssl crypto=$crypto variant=$variant picker-debugging=on $toolset link=shared;
fi'
- cd ..
@ -143,12 +145,12 @@ script:
# as the main library, so we cannot stage them to the same directory
# here we specify the temporary lib dir as a path to look for the main library
- 'if [ "$variant" != "" ]; then
bjam -j3 warnings-as-errors=on picker-debugging=on link=shared variant=$variant $toolset install location=./lib;
bjam -j3 warnings-as-errors=on ssl=$ssl crypto=$crypto picker-debugging=on link=shared variant=$variant $toolset install location=./lib;
fi'
- cd bindings/python
- 'if [ "$variant" != "" ]; then
bjam -j3 warnings-as-errors=on variant=$variant picker-debugging=on $toolset stage_module libtorrent-link=shared install-type=LIB dll-path=../../lib &&
bjam -j3 warnings-as-errors=on ssl=$ssl crypto=$crypto variant=$variant picker-debugging=on $toolset stage_module libtorrent-link=shared install-type=LIB dll-path=../../lib &&
LD_LIBRARY_PATH=../../lib DYLD_LIBRARY_PATH=../../lib python test.py;
fi'
- cd ../..;
@ -156,7 +158,7 @@ script:
# simulation
- cd simulation
- 'if [[ "$variant" != "" && "$sim" == "1" ]]; then
bjam -j2 crypto=built-in warnings-as-errors=on $toolset;
bjam -j2 crypto=built-in ssl=off warnings-as-errors=on $toolset;
fi'
- cd ..
@ -195,6 +197,6 @@ script:
- cd test
- 'if [ $arch == "arm" ];
then
bjam arm-tests warnings-as-errors=on variant=test_arm $toolset target-os=linux link=static testing.launcher="sudo cp -R bin rootfs/; sudo chroot rootfs";
bjam arm-tests warnings-as-errors=on ssl=$ssl crypto=$crypto variant=test_arm $toolset target-os=linux link=static testing.launcher="sudo cp -R bin rootfs/; sudo chroot rootfs";
fi'
- cd ..

View File

@ -1,3 +1,4 @@
* support windows' CryptoAPI for SHA-1
* separated ssl and crypto options in build
* remove lazy-bitfield feature
* simplified suggest-read-cache feature to not depend on disk threads

View File

@ -512,7 +512,7 @@ variant test_release : release
<inlining>off
;
variant test_debug : debug
: <ssl>openssl <crypto>libcrypto <logging>on <disk-stats>on
: <logging>on <disk-stats>on
<allocator>debug
<invariant-checks>full <boost-link>shared
<export-extra>on <debug-iterators>on <threading>multi <asserts>on

View File

@ -12,36 +12,34 @@ environment:
compiler: msvc-14.0
model: 64
sim: 1
linkflags: '"/LIBPATH:C:\\openssl-1.0.1p-vs2015\\lib64"'
include: '"c:\\openssl-1.0.1p-vs2015\\include"'
- variant: test_debug
compiler: msvc-14.0
model: 32
linkflags: '"/LIBPATH:C:\\openssl-1.0.1p-vs2015\\lib"'
include: '"c:\\openssl-1.0.1p-vs2015\\include"'
- variant: test_release
compiler: msvc-14.0
model: 64
python: 1
linkflags: '"/LIBPATH:C:\\openssl-1.0.1p-vs2015\\lib64"'
include: '"c:\\openssl-1.0.1p-vs2015\\include"'
ssl: openssl
crypto: libcrypto
linkflags: 'linkflags="/LIBPATH:C:\\openssl-1.0.1p-vs2015\\lib64"'
include: 'include="c:\\openssl-1.0.1p-vs2015\\include"'
- variant: test_debug
compiler: gcc
model: 32
linkflags: '"-LC:\\OpenSSL-Win32\\lib"'
include: '"c:\\OpenSSL-Win32\\include"'
ssl: openssl
crypto: libcrypto
linkflags: 'linkflags="-LC:\\OpenSSL-Win32\\lib"'
include: 'include="c:\\OpenSSL-Win32\\include"'
install:
- if defined sim ( git submodule update --init --recursive )
- set ROOT_DIRECTORY=%CD%
- cd %ROOT_DIRECTORY%
- if %compiler% == msvc-14.0 (
if not exist openssl-1.0.1p-vs2015.7z (
echo downloading openssl-2015
& appveyor DownloadFile "http://www.npcglib.org/~stathis/downloads/openssl-1.0.1p-vs2015.7z"
)
- if %compiler% == msvc-14.0 if defined ssl if not exist openssl-1.0.1p-vs2015.7z (
echo downloading openssl-2015
& appveyor DownloadFile "http://www.npcglib.org/~stathis/downloads/openssl-1.0.1p-vs2015.7z"
)
- if %compiler% == msvc-14.0 (
- if %compiler% == msvc-14.0 if defined ssl (
echo extracting openssl-2015
& 7z x -oc:\ -aoa openssl-1.0.1p-vs2015.7z > nul
& copy c:\openssl-1.0.1p-vs2015\lib64\ssleay32MT.lib c:\openssl-1.0.1p-vs2015\lib64\ssleay32.lib
@ -49,6 +47,10 @@ install:
& copy c:\openssl-1.0.1p-vs2015\lib\ssleay32MT.lib c:\openssl-1.0.1p-vs2015\lib\ssleay32.lib
& copy c:\openssl-1.0.1p-vs2015\lib\libeay32MT.lib c:\openssl-1.0.1p-vs2015\lib\libeay32.lib
)
- if not defined ssl ( set ssl=off )
- if not defined crypto ( set crypto=built-in )
- if not defined linkflags ( set linkflags="" )
- if not defined include ( set include="" )
- cd %ROOT_DIRECTORY%
- set BOOST_ROOT=c:\Libraries\boost_1_59_0
- set BOOST_BUILD_PATH=%BOOST_ROOT%\tools\build
@ -72,34 +74,34 @@ cache:
build_script:
# examples
- cd %ROOT_DIRECTORY%\examples
- b2.exe --hash warnings-as-errors=on -j2 %compiler% address-model=%model% variant=%variant% picker-debugging=on linkflags=%linkflags% include=%include% link=shared
- b2.exe --hash warnings-as-errors=on -j2 %compiler% ssl=%ssl% crypto=%crypto% address-model=%model% variant=%variant% picker-debugging=on %linkflags% %include% link=shared
# tools
- cd %ROOT_DIRECTORY%\tools
- b2.exe --hash warnings-as-errors=on -j2 %compiler% address-model=%model% variant=%variant% picker-debugging=on linkflags=%linkflags% include=%include% link=shared
- b2.exe --hash warnings-as-errors=on -j2 %compiler% ssl=%ssl% crypto=%crypto% address-model=%model% variant=%variant% picker-debugging=on %linkflags% %include% link=shared
# test
- cd %ROOT_DIRECTORY%\test
- b2.exe --hash warnings-as-errors=on -j2 address-model=%model% win-tests test_upnp test_natpmp %compiler% variant=%variant% picker-debugging=on link=shared linkflags=%linkflags% include=%include% testing.execute=off
- b2.exe --hash warnings-as-errors=on -j2 %compiler% ssl=%ssl% crypto=%crypto% address-model=%model% win-tests test_upnp test_natpmp variant=%variant% picker-debugging=on link=shared %linkflags% %include% testing.execute=off
# python binding
- cd %ROOT_DIRECTORY%\bindings\python
# we use 64 bit python builds
- if defined python ( b2.exe --hash warnings-as-errors=on -j2 %compiler% address-model=%model% stage_module install-dependencies=on variant=%variant% picker-debugging=on libtorrent-link=shared linkflags=%linkflags% include=%include% )
- if defined python ( b2.exe --hash warnings-as-errors=on -j2 %compiler% ssl=%ssl% crypto=%crypto% address-model=%model% stage_module install-dependencies=on variant=%variant% picker-debugging=on libtorrent-link=shared %linkflags% %include% )
# simulations
- if defined sim (
cd %ROOT_DIRECTORY%\simulation
& b2.exe --hash warnings-as-errors=on -j2 link=shared crypto=built-in %compiler% address-model=%model% testing.execute=off
& b2.exe --hash warnings-as-errors=on -j2 link=shared %compiler% ssl=%ssl% crypto=%crypto% address-model=%model% testing.execute=off
)
test_script:
- cd %ROOT_DIRECTORY%\test
# mingw tests crash currently. needs resolving
- if not %compiler% == gcc ( b2.exe --hash warnings-as-errors=on -j2 address-model=%model% win-tests %compiler% variant=%variant% picker-debugging=on link=shared linkflags=%linkflags% include=%include% )
- if not %compiler% == gcc ( b2.exe --hash warnings-as-errors=on -j2 ssl=%ssl% crypto=%crypto% address-model=%model% win-tests %compiler% variant=%variant% picker-debugging=on link=shared %linkflags% %include% )
- cd %ROOT_DIRECTORY%\bindings\python
# we use 64 bit python build
- if defined python ( c:\Python35-x64\python.exe test.py )
- cd %ROOT_DIRECTORY%\simulation
- if defined sim ( b2.exe --hash warnings-as-errors=on -j2 link=shared crypto=built-in %compiler% address-model=%model% )
- if defined sim ( b2.exe --hash warnings-as-errors=on -j2 ssl=%ssl% crypto=%crypto% link=shared crypto=built-in %compiler% address-model=%model% )

View File

@ -235,6 +235,13 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef TORRENT_USE_GETIPFORWARDTABLE
# define TORRENT_USE_GETIPFORWARDTABLE 1
#endif
# if !defined TORRENT_USE_LIBCRYPTO && !defined TORRENT_USE_LIBGCRYPT
// unless some other crypto library has been specified, default to the native
// windows CryptoAPI
#define TORRENT_USE_CRYPTOAPI 1
#endif
#define TORRENT_USE_GETADAPTERSADDRESSES 1
#define TORRENT_HAS_SALEN 0
// windows has its own functions to convert
@ -390,6 +397,10 @@ POSSIBILITY OF SUCH DAMAGE.
#define TORRENT_USE_COMMONCRYPTO 0
#endif
#ifndef TORRENT_USE_CRYPTOAPI
#define TORRENT_USE_CRYPTOAPI 0
#endif
#ifndef TORRENT_HAVE_MMAP
#define TORRENT_HAVE_MMAP 0
#endif

View File

@ -33,6 +33,7 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef TORRENT_HASHER_HPP_INCLUDED
#define TORRENT_HASHER_HPP_INCLUDED
#include "libtorrent/config.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
@ -43,13 +44,14 @@ POSSIBILITY OF SUCH DAMAGE.
#include <gcrypt.h>
#elif TORRENT_USE_COMMONCRYPTO
#include <CommonCrypto/CommonDigest.h>
#elif TORRENT_USE_CRYPTOAPI
#include <Wincrypt.h>
#elif defined TORRENT_USE_LIBCRYPTO
extern "C"
{
extern "C" {
#include <openssl/sha.h>
}
@ -83,12 +85,10 @@ namespace libtorrent
// this is the same as default constructing followed by a call to
// ``update(data, len)``.
hasher(const char* data, int len);
hasher(char const* data, int len);
#ifdef TORRENT_USE_LIBGCRYPT
hasher(hasher const& h);
hasher& operator=(hasher const& h);
#endif
hasher(hasher const&);
hasher& operator=(hasher const&);
// append the following bytes to what is being hashed
hasher& update(std::string const& data) { update(data.c_str(), int(data.size())); return *this; }
@ -97,6 +97,7 @@ namespace libtorrent
// returns the SHA-1 digest of the buffers previously passed to
// update() and the hasher constructor.
sha1_hash final();
// restore the hasher state to be as if the hasher has just been
// default constructed.
void reset();
@ -109,6 +110,8 @@ namespace libtorrent
gcry_md_hd_t m_context;
#elif TORRENT_USE_COMMONCRYPTO
CC_SHA1_CTX m_context;
#elif TORRENT_USE_CRYPTOAPI
HCRYPTHASH m_context;
#elif defined TORRENT_USE_LIBCRYPTO
SHA_CTX m_context;
#else

View File

@ -17,6 +17,7 @@ project
<source>create_torrent.cpp
<source>utils.cpp
<toolset>msvc:<cflags>/wd4275
<toolset>msvc:<cflags>/wd4005
: default-build
<threading>multi
<invariant-checks>full

View File

@ -31,6 +31,35 @@ POSSIBILITY OF SUCH DAMAGE.
*/
#include "libtorrent/hasher.hpp"
#include "libtorrent/error_code.hpp"
#if TORRENT_USE_CRYPTOAPI
namespace
{
HCRYPTPROV make_crypt_provider()
{
using namespace libtorrent;
HCRYPTPROV ret;
if (CryptAcquireContext(&ret, nullptr, nullptr, PROV_RSA_FULL
, CRYPT_VERIFYCONTEXT) == false)
{
#ifndef BOOST_NO_EXCEPTIONS
throw system_error(error_code(GetLastError(), system_category()));
#else
std::terminate();
#endif
}
return ret;
}
HCRYPTPROV get_crypt_provider()
{
static HCRYPTPROV prov = make_crypt_provider();
return prov;
}
}
#endif
namespace libtorrent
{
@ -40,6 +69,15 @@ namespace libtorrent
gcry_md_open(&m_context, GCRY_MD_SHA1, 0);
#elif TORRENT_USE_COMMONCRYPTO
CC_SHA1_Init(&m_context);
#elif TORRENT_USE_CRYPTOAPI
if (CryptCreateHash(get_crypt_provider(), CALG_SHA1, 0, 0, &m_context) == false)
{
#ifndef BOOST_NO_EXCEPTIONS
throw system_error(error_code(GetLastError(), system_category()));
#else
std::terminate();
#endif
}
#elif defined TORRENT_USE_LIBCRYPTO
SHA1_Init(&m_context);
#else
@ -48,22 +86,11 @@ namespace libtorrent
}
hasher::hasher(const char* data, int len)
: hasher()
{
TORRENT_ASSERT(data != 0);
TORRENT_ASSERT(len > 0);
#ifdef TORRENT_USE_LIBGCRYPT
gcry_md_open(&m_context, GCRY_MD_SHA1, 0);
gcry_md_write(m_context, data, len);
#elif TORRENT_USE_COMMONCRYPTO
CC_SHA1_Init(&m_context);
CC_SHA1_Update(&m_context, reinterpret_cast<unsigned char const*>(data), len);
#elif defined TORRENT_USE_LIBCRYPTO
SHA1_Init(&m_context);
SHA1_Update(&m_context, reinterpret_cast<unsigned char const*>(data), len);
#else
SHA1_init(&m_context);
SHA1_update(&m_context, reinterpret_cast<unsigned char const*>(data), len);
#endif
update(data, len);
}
#ifdef TORRENT_USE_LIBGCRYPT
@ -74,10 +101,41 @@ namespace libtorrent
hasher& hasher::operator=(hasher const& h)
{
if (this == &h) return;
gcry_md_close(m_context);
gcry_md_copy(&m_context, h.m_context);
return *this;
}
#elif TORRENT_USE_CRYPTOAPI
hasher::hasher(hasher const& h)
{
if (CryptDuplicateHash(h.m_context, 0, 0, &m_context) == false)
{
#ifndef BOOST_NO_EXCEPTIONS
throw system_error(error_code(GetLastError(), system_category()));
#else
std::terminate();
#endif
}
}
hasher& hasher::operator=(hasher const& h)
{
if (this == &h) return *this;
CryptDestroyHash(m_context);
if (CryptDuplicateHash(h.m_context, 0, 0, &m_context) == false)
{
#ifndef BOOST_NO_EXCEPTIONS
throw system_error(error_code(GetLastError(), system_category()));
#else
std::terminate();
#endif
}
return *this;
}
#else
hasher::hasher(hasher const&) = default;
hasher& hasher::operator=(hasher const&) = default;
#endif
hasher& hasher::update(const char* data, int len)
@ -88,6 +146,15 @@ namespace libtorrent
gcry_md_write(m_context, data, len);
#elif TORRENT_USE_COMMONCRYPTO
CC_SHA1_Update(&m_context, reinterpret_cast<unsigned char const*>(data), len);
#elif TORRENT_USE_CRYPTOAPI
if (CryptHashData(m_context, reinterpret_cast<BYTE const*>(data), len, 0) == false)
{
#ifndef BOOST_NO_EXCEPTIONS
throw system_error(error_code(GetLastError(), system_category()));
#else
std::terminate();
#endif
}
#elif defined TORRENT_USE_LIBCRYPTO
SHA1_Update(&m_context, reinterpret_cast<unsigned char const*>(data), len);
#else
@ -104,6 +171,19 @@ namespace libtorrent
digest.assign((const char*)gcry_md_read(m_context, 0));
#elif TORRENT_USE_COMMONCRYPTO
CC_SHA1_Final(digest.begin(), &m_context);
#elif TORRENT_USE_CRYPTOAPI
DWORD size = sha1_hash::size;
if (CryptGetHashParam(m_context, HP_HASHVAL
, reinterpret_cast<BYTE*>(digest.data()), &size, 0) == false)
{
#ifndef BOOST_NO_EXCEPTIONS
throw system_error(error_code(GetLastError(), system_category()));
#else
std::terminate();
#endif
}
TORRENT_ASSERT(size == sha1_hash::size);
#elif defined TORRENT_USE_LIBCRYPTO
SHA1_Final(digest.begin(), &m_context);
#else
@ -118,6 +198,16 @@ namespace libtorrent
gcry_md_reset(m_context);
#elif TORRENT_USE_COMMONCRYPTO
CC_SHA1_Init(&m_context);
#elif TORRENT_USE_CRYPTOAPI
CryptDestroyHash(m_context);
if (CryptCreateHash(get_crypt_provider(), CALG_SHA1, 0, 0, &m_context) == false)
{
#ifndef BOOST_NO_EXCEPTIONS
throw system_error(error_code(GetLastError(), system_category()));
#else
std::terminate();
#endif
}
#elif defined TORRENT_USE_LIBCRYPTO
SHA1_Init(&m_context);
#else
@ -127,10 +217,11 @@ namespace libtorrent
hasher::~hasher()
{
#ifdef TORRENT_USE_LIBGCRYPT
#if TORRENT_USE_CRYPTOAPI
CryptDestroyHash(m_context);
#elif defined TORRENT_USE_LIBGCRYPT
gcry_md_close(m_context);
#endif
}
}