diff options
| -rw-r--r-- | Swiften/Crypto/CommonCryptoCryptoProvider.cpp | 50 | ||||
| -rw-r--r-- | Swiften/Crypto/CommonCryptoCryptoProvider.h | 4 | ||||
| -rw-r--r-- | Swiften/Crypto/CryptoProvider.h | 75 | ||||
| -rw-r--r-- | Swiften/Crypto/OpenSSLCryptoProvider.cpp | 53 | ||||
| -rw-r--r-- | Swiften/Crypto/OpenSSLCryptoProvider.h | 6 | ||||
| -rw-r--r-- | Swiften/Crypto/WindowsCryptoProvider.cpp | 478 | ||||
| -rw-r--r-- | Swiften/Crypto/WindowsCryptoProvider.h | 60 | 
7 files changed, 312 insertions, 414 deletions
| diff --git a/Swiften/Crypto/CommonCryptoCryptoProvider.cpp b/Swiften/Crypto/CommonCryptoCryptoProvider.cpp index f1810ba..14f9284 100644 --- a/Swiften/Crypto/CommonCryptoCryptoProvider.cpp +++ b/Swiften/Crypto/CommonCryptoCryptoProvider.cpp @@ -100,42 +100,11 @@ namespace {  	};  	template<typename T> -	class HMACHash : public Hash { -		public: -			HMACHash(const T& key) : finalized(false) { -				CCHmacInit(&context, kCCHmacAlgSHA1, vecptr(key), key.size()); -			} - -			~HMACHash() { -			} - -			virtual Hash& update(const ByteArray& data) SWIFTEN_OVERRIDE { -				return updateInternal(data); -			} - -			virtual Hash& update(const SafeByteArray& data) SWIFTEN_OVERRIDE { -				return updateInternal(data); -			} - -			virtual std::vector<unsigned char> getHash() { -				assert(!finalized); -				std::vector<unsigned char> result(CC_SHA1_DIGEST_LENGTH); -				CCHmacFinal(&context, vecptr(result)); -				return result; -			} - -		private: -			template<typename ContainerType> -			Hash& updateInternal(const ContainerType& data) { -				assert(!finalized); -				CCHmacUpdate(&context, vecptr(data), boost::numeric_cast<CC_LONG>(data.size())); -				return *this; -			} - -		private: -			CCHmacContext context; -			bool finalized; -	}; +	ByteArray getHMACSHA1Internal(const T& key, const ByteArray& data) { +		std::vector<unsigned char> result(CC_SHA1_DIGEST_LENGTH); +		CCHmac(kCCHmacAlgSHA1, vecptr(key), key.size(), vecptr(data), boost::numeric_cast<CC_LONG>(data.size()), vecptr(result)); +		return result; +	}  }  CommonCryptoCryptoProvider::CommonCryptoCryptoProvider() { @@ -152,15 +121,14 @@ Hash* CommonCryptoCryptoProvider::createMD5() {  	return new MD5Hash();  } -Hash* CommonCryptoCryptoProvider::createHMACSHA1(const SafeByteArray& key) { -	return new HMACHash<SafeByteArray>(key); +ByteArray CommonCryptoCryptoProvider::getHMACSHA1(const SafeByteArray& key, const ByteArray& data) { +	return getHMACSHA1Internal(key, data);  } -Hash* CommonCryptoCryptoProvider::createHMACSHA1(const ByteArray& key) { -	return new HMACHash<ByteArray>(key); +ByteArray CommonCryptoCryptoProvider::getHMACSHA1(const ByteArray& key, const ByteArray& data) { +	return getHMACSHA1Internal(key, data);  } -  bool CommonCryptoCryptoProvider::isMD5AllowedForCrypto() const {  	return true;  } diff --git a/Swiften/Crypto/CommonCryptoCryptoProvider.h b/Swiften/Crypto/CommonCryptoCryptoProvider.h index 8072c0d..f921e17 100644 --- a/Swiften/Crypto/CommonCryptoCryptoProvider.h +++ b/Swiften/Crypto/CommonCryptoCryptoProvider.h @@ -17,8 +17,8 @@ namespace Swift {  			virtual Hash* createSHA1() SWIFTEN_OVERRIDE;  			virtual Hash* createMD5() SWIFTEN_OVERRIDE; -			virtual Hash* createHMACSHA1(const SafeByteArray& key) SWIFTEN_OVERRIDE; -			virtual Hash* createHMACSHA1(const ByteArray& key) SWIFTEN_OVERRIDE; +			virtual ByteArray getHMACSHA1(const SafeByteArray& key, const ByteArray& data) SWIFTEN_OVERRIDE; +			virtual ByteArray getHMACSHA1(const ByteArray& key, const ByteArray& data) SWIFTEN_OVERRIDE;  			virtual bool isMD5AllowedForCrypto() const SWIFTEN_OVERRIDE;  	};  } diff --git a/Swiften/Crypto/CryptoProvider.h b/Swiften/Crypto/CryptoProvider.h index afee8c4..c1e1eb9 100644 --- a/Swiften/Crypto/CryptoProvider.h +++ b/Swiften/Crypto/CryptoProvider.h @@ -1,39 +1,36 @@ -/*
 - * Copyright (c) 2013 Remko Tronçon
 - * Licensed under the GNU General Public License.
 - * See the COPYING file for more information.
 - */
 -
 -#pragma once
 -
 -#include <Swiften/Base/ByteArray.h>
 -#include <Swiften/Base/SafeByteArray.h>
 -#include <Swiften/Crypto/Hash.h>
 -
 -namespace Swift {
 -	class Hash;
 -
 -	class CryptoProvider {
 -		public:
 -			virtual ~CryptoProvider();
 -
 -			virtual Hash* createSHA1() = 0;
 -			virtual Hash* createMD5() = 0;
 -			virtual Hash* createHMACSHA1(const SafeByteArray& key) = 0;
 -			virtual Hash* createHMACSHA1(const ByteArray& key) = 0;
 -			virtual bool isMD5AllowedForCrypto() const = 0;
 -
 -			// Convenience
 -			template<typename T> ByteArray getSHA1Hash(const T& data) {
 -				return boost::shared_ptr<Hash>(createSHA1())->update(data).getHash();
 -			}
 -
 -			template<typename T> ByteArray getMD5Hash(const T& data) {
 -				return boost::shared_ptr<Hash>(createMD5())->update(data).getHash();
 -			}
 -
 -			template<typename T, typename U> ByteArray getHMACSHA1(const T& key, const U& data) {
 -				return boost::shared_ptr<Hash>(createHMACSHA1(key))->update(data).getHash();
 -			}
 -	};
 -}
 +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Base/API.h> +#include <Swiften/Base/ByteArray.h> +#include <Swiften/Base/SafeByteArray.h> +#include <Swiften/Crypto/Hash.h> + +namespace Swift { +	class Hash; + +	class SWIFTEN_API CryptoProvider { +		public: +			virtual ~CryptoProvider(); + +			virtual Hash* createSHA1() = 0; +			virtual Hash* createMD5() = 0; +			virtual ByteArray getHMACSHA1(const SafeByteArray& key, const ByteArray& data) = 0; +			virtual ByteArray getHMACSHA1(const ByteArray& key, const ByteArray& data) = 0; +			virtual bool isMD5AllowedForCrypto() const = 0; + +			// Convenience +			template<typename T> ByteArray getSHA1Hash(const T& data) { +				return boost::shared_ptr<Hash>(createSHA1())->update(data).getHash(); +			} + +			template<typename T> ByteArray getMD5Hash(const T& data) { +				return boost::shared_ptr<Hash>(createMD5())->update(data).getHash(); +			} +	}; +} diff --git a/Swiften/Crypto/OpenSSLCryptoProvider.cpp b/Swiften/Crypto/OpenSSLCryptoProvider.cpp index afe73aa..9b1d544 100644 --- a/Swiften/Crypto/OpenSSLCryptoProvider.cpp +++ b/Swiften/Crypto/OpenSSLCryptoProvider.cpp @@ -104,45 +104,12 @@ namespace {  	template<typename T> -	class HMACHash : public Hash { -		public: -			HMACHash(const T& key) : finalized(false) { -				HMAC_CTX_init(&context); -				HMAC_Init(&context, vecptr(key), boost::numeric_cast<int>(key.size()), EVP_sha1()); -			} - -			~HMACHash() { -				HMAC_CTX_cleanup(&context); -			} - -			virtual Hash& update(const ByteArray& data) SWIFTEN_OVERRIDE { -				return updateInternal(data); -			} - -			virtual Hash& update(const SafeByteArray& data) SWIFTEN_OVERRIDE { -				return updateInternal(data); -			} - -			virtual std::vector<unsigned char> getHash() { -				assert(!finalized); -				std::vector<unsigned char> result(SHA_DIGEST_LENGTH); -				unsigned int len = SHA_DIGEST_LENGTH; -				HMAC_Final(&context, vecptr(result), &len); -				return result; -			} - -		private: -			template<typename ContainerType> -			Hash& updateInternal(const ContainerType& data) { -				assert(!finalized); -				HMAC_Update(&context, vecptr(data), data.size()); -				return *this; -			} - -		private: -			HMAC_CTX context; -			bool finalized; -	}; +	ByteArray getHMACSHA1Internal(const T& key, const ByteArray& data) { +		unsigned int len = SHA_DIGEST_LENGTH; +		std::vector<unsigned char> result(len); +		HMAC(EVP_sha1(), vecptr(key), boost::numeric_cast<int>(key.size()), vecptr(data), data.size(), vecptr(result), &len); +		return result; +	}  }  OpenSSLCryptoProvider::OpenSSLCryptoProvider() { @@ -159,12 +126,12 @@ Hash* OpenSSLCryptoProvider::createMD5() {  	return new MD5Hash();  } -Hash* OpenSSLCryptoProvider::createHMACSHA1(const SafeByteArray& key) { -	return new HMACHash<SafeByteArray>(key); +ByteArray OpenSSLCryptoProvider::getHMACSHA1(const SafeByteArray& key, const ByteArray& data) { +	return getHMACSHA1Internal(key, data);  } -Hash* OpenSSLCryptoProvider::createHMACSHA1(const ByteArray& key) { -	return new HMACHash<ByteArray>(key); +ByteArray OpenSSLCryptoProvider::getHMACSHA1(const ByteArray& key, const ByteArray& data) { +	return getHMACSHA1Internal(key, data);  }  bool OpenSSLCryptoProvider::isMD5AllowedForCrypto() const { diff --git a/Swiften/Crypto/OpenSSLCryptoProvider.h b/Swiften/Crypto/OpenSSLCryptoProvider.h index e9ca37b..9440aee 100644 --- a/Swiften/Crypto/OpenSSLCryptoProvider.h +++ b/Swiften/Crypto/OpenSSLCryptoProvider.h @@ -1,5 +1,5 @@  /* - * Copyright (c) 2013  Remko Tronçon + * Copyright (c) 2013 Remko Tronçon   * Licensed under the GNU General Public License.   * See the COPYING file for more information.   */ @@ -17,8 +17,8 @@ namespace Swift {  			virtual Hash* createSHA1() SWIFTEN_OVERRIDE;  			virtual Hash* createMD5() SWIFTEN_OVERRIDE; -			virtual Hash* createHMACSHA1(const SafeByteArray& key) SWIFTEN_OVERRIDE; -			virtual Hash* createHMACSHA1(const ByteArray& key) SWIFTEN_OVERRIDE; +			virtual ByteArray getHMACSHA1(const SafeByteArray& key, const ByteArray& data) SWIFTEN_OVERRIDE; +			virtual ByteArray getHMACSHA1(const ByteArray& key, const ByteArray& data) SWIFTEN_OVERRIDE;  			virtual bool isMD5AllowedForCrypto() const SWIFTEN_OVERRIDE;  	};  } diff --git a/Swiften/Crypto/WindowsCryptoProvider.cpp b/Swiften/Crypto/WindowsCryptoProvider.cpp index 7cc6a46..9ca4c14 100644 --- a/Swiften/Crypto/WindowsCryptoProvider.cpp +++ b/Swiften/Crypto/WindowsCryptoProvider.cpp @@ -1,256 +1,222 @@ -/*
 - * Copyright (c) 2012 Kevin Smith
 - * Licensed under the GNU General Public License.
 - * See the COPYING file for more information.
 - */
 -
 -/*
 - * Copyright (c) 2013 Remko Tronçon
 - * Licensed under the GNU General Public License.
 - * See the COPYING file for more information.
 - */
 -
 -#include <Swiften/Crypto/WindowsCryptoProvider.h>
 -
 -#include <Windows.h>
 -#define SECURITY_WIN32
 -#include <security.h>
 -#include <Wincrypt.h>
 -#include <cassert>
 -#include <boost/smart_ptr/make_shared.hpp>
 -
 -#include <Swiften/Crypto/Hash.h>
 -#include <Swiften/Base/ByteArray.h>
 -#include <Swiften/Base/Algorithm.h>
 -#include <Swiften/Base/WindowsRegistry.h>
 -
 -using namespace Swift;
 -
 -struct WindowsCryptoProvider::Private {
 -	HCRYPTPROV context;
 -};
 -
 -namespace {
 -	class WindowsHash : public Hash {
 -		public:
 -			WindowsHash(HCRYPTPROV context, ALG_ID algorithm) : hash(NULL) {
 -				if (!CryptCreateHash(context, algorithm, 0, 0, &hash)) {
 -					assert(false);
 -				}
 -			}
 -
 -			~WindowsHash() {
 -				CryptDestroyHash(hash);
 -			}
 -
 -			virtual Hash& update(const ByteArray& data) SWIFTEN_OVERRIDE {
 -				return updateInternal(data);
 -			}
 -
 -			virtual Hash& update(const SafeByteArray& data) SWIFTEN_OVERRIDE {
 -				return updateInternal(data);
 -			}
 -
 -			virtual std::vector<unsigned char> getHash() {
 -				std::vector<unsigned char> result;
 -				DWORD hashLength = sizeof(DWORD);
 -				DWORD hashSize;
 -				CryptGetHashParam(hash, HP_HASHSIZE, reinterpret_cast<BYTE*>(&hashSize), &hashLength, 0);
 -				result.resize(static_cast<size_t>(hashSize));
 -				if (!CryptGetHashParam(hash, HP_HASHVAL, vecptr(result), &hashSize, 0)) {
 -					assert(false);
 -				}
 -				result.resize(static_cast<size_t>(hashSize));
 -				return result;
 -			}
 -
 -		private:
 -			template<typename ContainerType>
 -			Hash& updateInternal(const ContainerType& data) {
 -				if (!CryptHashData(hash, const_cast<BYTE*>(vecptr(data)), data.size(), 0)) {
 -					assert(false);
 -				}
 -				return *this;
 -			}
 -
 -		private:
 -			HCRYPTHASH hash;
 -	};
 -
 -#if 0
 -	// Haven't tested the code below properly yet, but figured out after writing
 -	// it that PLAINTEXTKEYBLOB doesn't work on XP or 2k, and the workaround is a
 -	// bit too ugly to try this now. So, using our own algorithm for now.  See
 -	// http://support.microsoft.com/kb/228786/en-us
 -	
 -	// MSDN describes this as PLAINTEXTKEYBLOB, but this struct doesn't exist,
 -	// and seems to even conflict with the PLAINTEXTKEYBLOB constant. Redefining
 -	// here.
 -	struct PlainTextKeyBlob {
 -		BLOBHEADER hdr;
 -		DWORD dwKeySize;
 -	};
 -
 -	class HMACHash : public Hash {
 -		public:
 -			template<typename T>
 -			HMACHash(HCRYPTPROV context, const T& rawKey) : hash(NULL) {
 -				// Import raw key
 -				T blobData(sizeof(PlainTextKeyBlob) + rawKey.size());
 -				PlainTextKeyBlob* blob = reinterpret_cast<PlainTextKeyBlob*>(vecptr(blobData));
 -				blob->hdr.bType = PLAINTEXTKEYBLOB;
 -				blob->hdr.bVersion = CUR_BLOB_VERSION;
 -				blob->hdr.reserved = 0;
 -				blob->hdr.aiKeyAlg = CALG_RC2;
 -				blob->dwKeySize = rawKey.size();
 -				std::copy(rawKey.begin(), rawKey.end(), blobData.begin() + sizeof(PlainTextKeyBlob));
 -				HCRYPTKEY key;
 -				if (!CryptImportKey(context, vecptr(blobData), blobData.size(), 0, CRYPT_IPSEC_HMAC_KEY, &key)) {
 -					assert(false);
 -					return;
 -				}
 -
 -				// Create hash
 -				if (!CryptCreateHash(context, CALG_HMAC, key, 0, &hash)) {
 -					assert(false);
 -					return;
 -				}
 -				ZeroMemory(&info, sizeof(info));
 -				info.HashAlgid = CALG_SHA1;
 -			}
 -
 -			~HMACHash() {
 -				CryptDestroyHash(hash);
 -			}
 -
 -			virtual Hash& update(const ByteArray& data) SWIFTEN_OVERRIDE {
 -				return updateInternal(data);
 -			}
 -
 -			virtual Hash& update(const SafeByteArray& data) SWIFTEN_OVERRIDE {
 -				return updateInternal(data);
 -			}
 -
 -			virtual std::vector<unsigned char> getHash() {
 -				std::vector<unsigned char> result;
 -				DWORD hashLength = sizeof(DWORD);
 -				DWORD hashSize;
 -				CryptGetHashParam(hash, HP_HASHSIZE, reinterpret_cast<BYTE*>(&hashSize), &hashLength, 0);
 -				result.resize(static_cast<size_t>(hashSize));
 -				if (!CryptGetHashParam(hash, HP_HASHVAL, vecptr(result), &hashSize, 0)) {
 -					assert(false);
 -				}
 -				result.resize(static_cast<size_t>(hashSize));
 -				return result;
 -			}
 -
 -		private:
 -			template<typename ContainerType>
 -			Hash& updateInternal(const ContainerType& data) {
 -				if (!CryptHashData(hash, const_cast<BYTE*>(vecptr(data)), data.size(), 0)) {
 -					assert(false);
 -				}
 -				return *this;
 -			}
 -
 -		private:
 -			HCRYPTHASH hash;
 -			HMAC_INFO info;
 -	};
 -#endif
 -
 -	// Simple implementation. You can only call 'update' once.
 -	template<typename T>
 -	class HMACHash : public Hash {
 -		public:
 -			HMACHash(const T& key, CryptoProvider* crypto) : crypto(crypto), finished(false) {
 -				if (key.size() <= BLOCK_SIZE) {
 -					paddedKey = key;
 -				}
 -				else {
 -					assign(paddedKey, crypto->getSHA1Hash(key));
 -				}
 -				paddedKey.resize(BLOCK_SIZE, 0x0);
 -			}
 -
 -			~HMACHash() {
 -			}
 -
 -			virtual Hash& update(const ByteArray& data) SWIFTEN_OVERRIDE {
 -				return updateInternal(data);
 -			}
 -
 -			virtual Hash& update(const SafeByteArray& data) SWIFTEN_OVERRIDE {
 -				return updateInternal(data);
 -			}
 -
 -			virtual std::vector<unsigned char> getHash() {
 -				return result;
 -			}
 -
 -		private:
 -			template<typename ContainerType>
 -			Hash& updateInternal(const ContainerType& data) {
 -				assert(!finished);
 -
 -				// Create the first value
 -				T x(paddedKey);
 -				for (unsigned int i = 0; i < x.size(); ++i) {
 -					x[i] ^= 0x36;
 -				}
 -				append(x, data);
 -
 -				// Create the second value
 -				T y(paddedKey);
 -				for (unsigned int i = 0; i < y.size(); ++i) {
 -					y[i] ^= 0x5c;
 -				}
 -				append(y, crypto->getSHA1Hash(x));
 -				result = crypto->getSHA1Hash(y);
 -
 -				finished = true;
 -				return *this;
 -			}
 -
 -		private:
 -			static const int BLOCK_SIZE = 64;
 -			CryptoProvider* crypto;
 -			T paddedKey;
 -			SafeByteArray data;
 -			bool finished;
 -			std::vector<unsigned char> result;
 -	};
 -
 -
 -}
 -
 -WindowsCryptoProvider::WindowsCryptoProvider() {
 -	p = boost::make_shared<Private>();
 -	if (!CryptAcquireContext(&p->context, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
 -		assert(false);
 -	}
 -}
 -
 -WindowsCryptoProvider::~WindowsCryptoProvider() {
 -	CryptReleaseContext(p->context, 0);
 -}
 -
 -Hash* WindowsCryptoProvider::createSHA1() {
 -	return new WindowsHash(p->context, CALG_SHA1);
 -}
 -
 -Hash* WindowsCryptoProvider::createMD5() {
 -	return new WindowsHash(p->context, CALG_MD5);
 -}
 -
 -bool WindowsCryptoProvider::isMD5AllowedForCrypto() const {
 -	return !WindowsRegistry::isFIPSEnabled();
 -}
 -
 -Hash* WindowsCryptoProvider::createHMACSHA1(const SafeByteArray& key) {
 -	return new HMACHash<SafeByteArray>(key, this);
 -}
 -
 -Hash* WindowsCryptoProvider::createHMACSHA1(const ByteArray& key) {
 -	return new HMACHash<ByteArray>(key, this);
 -}
 +/* + * Copyright (c) 2012 Kevin Smith + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +/* + * Copyright (c) 2013 Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#include <Swiften/Crypto/WindowsCryptoProvider.h> + +#include <Windows.h> +#define SECURITY_WIN32 +#include <security.h> +#include <Wincrypt.h> +#include <cassert> +#include <boost/smart_ptr/make_shared.hpp> + +#include <Swiften/Crypto/Hash.h> +#include <Swiften/Base/ByteArray.h> +#include <Swiften/Base/Algorithm.h> +#include <Swiften/Base/WindowsRegistry.h> + +using namespace Swift; + +struct WindowsCryptoProvider::Private { +	HCRYPTPROV context; +}; + +namespace { +	class WindowsHash : public Hash { +		public: +			WindowsHash(HCRYPTPROV context, ALG_ID algorithm) : hash(NULL) { +				if (!CryptCreateHash(context, algorithm, 0, 0, &hash)) { +					assert(false); +				} +			} + +			~WindowsHash() { +				CryptDestroyHash(hash); +			} + +			virtual Hash& update(const ByteArray& data) SWIFTEN_OVERRIDE { +				return updateInternal(data); +			} + +			virtual Hash& update(const SafeByteArray& data) SWIFTEN_OVERRIDE { +				return updateInternal(data); +			} + +			virtual std::vector<unsigned char> getHash() { +				std::vector<unsigned char> result; +				DWORD hashLength = sizeof(DWORD); +				DWORD hashSize; +				CryptGetHashParam(hash, HP_HASHSIZE, reinterpret_cast<BYTE*>(&hashSize), &hashLength, 0); +				result.resize(static_cast<size_t>(hashSize)); +				if (!CryptGetHashParam(hash, HP_HASHVAL, vecptr(result), &hashSize, 0)) { +					assert(false); +				} +				result.resize(static_cast<size_t>(hashSize)); +				return result; +			} + +		private: +			template<typename ContainerType> +			Hash& updateInternal(const ContainerType& data) { +				if (!CryptHashData(hash, const_cast<BYTE*>(vecptr(data)), data.size(), 0)) { +					assert(false); +				} +				return *this; +			} + +		private: +			HCRYPTHASH hash; +	}; + +#if 0 // NOT YET DONE +	// Haven't tested the code below properly yet, but figured out after writing +	// it that PLAINTEXTKEYBLOB doesn't work on XP or 2k, and the workaround is a +	// bit too ugly to try this now. So, using our own algorithm for now.  See +	// http://support.microsoft.com/kb/228786/en-us +	 +	// MSDN describes this as PLAINTEXTKEYBLOB, but this struct doesn't exist, +	// and seems to even conflict with the PLAINTEXTKEYBLOB constant. Redefining +	// here. +	struct PlainTextKeyBlob { +		BLOBHEADER hdr; +		DWORD dwKeySize; +	}; + +	class HMACHash : public Hash { +		public: +			template<typename T> +			HMACHash(HCRYPTPROV context, const T& rawKey) : hash(NULL) { +				// Import raw key +				T blobData(sizeof(PlainTextKeyBlob) + rawKey.size()); +				PlainTextKeyBlob* blob = reinterpret_cast<PlainTextKeyBlob*>(vecptr(blobData)); +				blob->hdr.bType = PLAINTEXTKEYBLOB; +				blob->hdr.bVersion = CUR_BLOB_VERSION; +				blob->hdr.reserved = 0; +				blob->hdr.aiKeyAlg = CALG_RC2; +				blob->dwKeySize = rawKey.size(); +				std::copy(rawKey.begin(), rawKey.end(), blobData.begin() + sizeof(PlainTextKeyBlob)); +				HCRYPTKEY key; +				if (!CryptImportKey(context, vecptr(blobData), blobData.size(), 0, CRYPT_IPSEC_HMAC_KEY, &key)) { +					assert(false); +					return; +				} + +				// Create hash +				if (!CryptCreateHash(context, CALG_HMAC, key, 0, &hash)) { +					assert(false); +					return; +				} +				ZeroMemory(&info, sizeof(info)); +				info.HashAlgid = CALG_SHA1; +			} + +			~HMACHash() { +				CryptDestroyHash(hash); +			} + +			virtual Hash& update(const ByteArray& data) SWIFTEN_OVERRIDE { +				return updateInternal(data); +			} + +			virtual Hash& update(const SafeByteArray& data) SWIFTEN_OVERRIDE { +				return updateInternal(data); +			} + +			virtual std::vector<unsigned char> getHash() { +				std::vector<unsigned char> result; +				DWORD hashLength = sizeof(DWORD); +				DWORD hashSize; +				CryptGetHashParam(hash, HP_HASHSIZE, reinterpret_cast<BYTE*>(&hashSize), &hashLength, 0); +				result.resize(static_cast<size_t>(hashSize)); +				if (!CryptGetHashParam(hash, HP_HASHVAL, vecptr(result), &hashSize, 0)) { +					assert(false); +				} +				result.resize(static_cast<size_t>(hashSize)); +				return result; +			} + +		private: +			template<typename ContainerType> +			Hash& updateInternal(const ContainerType& data) { +				if (!CryptHashData(hash, const_cast<BYTE*>(vecptr(data)), data.size(), 0)) { +					assert(false); +				} +				return *this; +			} + +		private: +			HCRYPTHASH hash; +			HMAC_INFO info; +	}; +#endif + +	// Simple implementation. +	template<typename T> +	ByteArray getHMACSHA1Internal(const T& key, const ByteArray& data, CryptoProvider* crypto) { +		static const int BLOCK_SIZE = 64; + +		T paddedKey; +		if (key.size() <= BLOCK_SIZE) { +			paddedKey = key; +		} +		else { +			assign(paddedKey, crypto->getSHA1Hash(key)); +		} +		paddedKey.resize(BLOCK_SIZE, 0x0); + +		// Create the first value +		T x(paddedKey); +		for (unsigned int i = 0; i < x.size(); ++i) { +			x[i] ^= 0x36; +		} +		append(x, data); + +		// Create the second value +		T y(paddedKey); +		for (unsigned int i = 0; i < y.size(); ++i) { +			y[i] ^= 0x5c; +		} +		append(y, crypto->getSHA1Hash(x)); +		return crypto->getSHA1Hash(y); +	} +} + +WindowsCryptoProvider::WindowsCryptoProvider() { +	p = boost::make_shared<Private>(); +	if (!CryptAcquireContext(&p->context, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { +		assert(false); +	} +} + +WindowsCryptoProvider::~WindowsCryptoProvider() { +	CryptReleaseContext(p->context, 0); +} + +Hash* WindowsCryptoProvider::createSHA1() { +	return new WindowsHash(p->context, CALG_SHA1); +} + +Hash* WindowsCryptoProvider::createMD5() { +	return new WindowsHash(p->context, CALG_MD5); +} + +bool WindowsCryptoProvider::isMD5AllowedForCrypto() const { +	return !WindowsRegistry::isFIPSEnabled(); +} + +ByteArray WindowsCryptoProvider::getHMACSHA1(const SafeByteArray& key, const ByteArray& data) { +	return getHMACSHA1Internal(key, data, this); +} + +ByteArray WindowsCryptoProvider::getHMACSHA1(const ByteArray& key, const ByteArray& data) { +	return getHMACSHA1Internal(key, data, this); +} diff --git a/Swiften/Crypto/WindowsCryptoProvider.h b/Swiften/Crypto/WindowsCryptoProvider.h index 242d4c2..9418fc0 100644 --- a/Swiften/Crypto/WindowsCryptoProvider.h +++ b/Swiften/Crypto/WindowsCryptoProvider.h @@ -1,30 +1,30 @@ -/*
 - * Copyright (c) 2013  Remko Tronçon
 - * Licensed under the GNU General Public License.
 - * See the COPYING file for more information.
 - */
 -
 -#pragma once
 -
 -#include <Swiften/Crypto/CryptoProvider.h>
 -#include <Swiften/Base/Override.h>
 -#include <boost/noncopyable.hpp>
 -#include <boost/shared_ptr.hpp>
 -
 -namespace Swift {
 -	class WindowsCryptoProvider : public CryptoProvider, public boost::noncopyable {
 -		public:
 -			WindowsCryptoProvider();
 -			~WindowsCryptoProvider();
 -
 -			virtual Hash* createSHA1() SWIFTEN_OVERRIDE;
 -			virtual Hash* createMD5() SWIFTEN_OVERRIDE;
 -			virtual Hash* createHMACSHA1(const SafeByteArray& key) SWIFTEN_OVERRIDE;
 -			virtual Hash* createHMACSHA1(const ByteArray& key) SWIFTEN_OVERRIDE;
 -			virtual bool isMD5AllowedForCrypto() const SWIFTEN_OVERRIDE;
 -
 -		private:
 -			struct Private;
 -			boost::shared_ptr<Private> p;
 -	};
 -}
 +/* + * Copyright (c) 2013  Remko Tronçon + * Licensed under the GNU General Public License. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/Base/Override.h> +#include <boost/noncopyable.hpp> +#include <boost/shared_ptr.hpp> + +namespace Swift { +	class WindowsCryptoProvider : public CryptoProvider, public boost::noncopyable { +		public: +			WindowsCryptoProvider(); +			~WindowsCryptoProvider(); + +			virtual Hash* createSHA1() SWIFTEN_OVERRIDE; +			virtual Hash* createMD5() SWIFTEN_OVERRIDE; +			virtual ByteArray getHMACSHA1(const SafeByteArray& key, const ByteArray& data) SWIFTEN_OVERRIDE; +			virtual ByteArray getHMACSHA1(const ByteArray& key, const ByteArray& data) SWIFTEN_OVERRIDE; +			virtual bool isMD5AllowedForCrypto() const SWIFTEN_OVERRIDE; + +		private: +			struct Private; +			boost::shared_ptr<Private> p; +	}; +} | 
 Swift
 Swift