summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRemko Tronçon <git@el-tramo.be>2013-04-27 15:30:27 (GMT)
committerRemko Tronçon <git@el-tramo.be>2013-04-27 15:30:27 (GMT)
commit87d5557ecba47f0cfd323e79f7d9284c484f825a (patch)
tree7af755e30a37dd388392e305b9c01637d8a039cb /Swiften/Crypto
parent860d265a878ca444fca358f468a32df32a7f4444 (diff)
downloadswift-87d5557ecba47f0cfd323e79f7d9284c484f825a.zip
swift-87d5557ecba47f0cfd323e79f7d9284c484f825a.tar.bz2
Make HMACSHA1 not be a Hash.
Change-Id: I798d468614d2285c6f77640c365b51b19df2bf73
Diffstat (limited to 'Swiften/Crypto')
-rw-r--r--Swiften/Crypto/CommonCryptoCryptoProvider.cpp50
-rw-r--r--Swiften/Crypto/CommonCryptoCryptoProvider.h4
-rw-r--r--Swiften/Crypto/CryptoProvider.h75
-rw-r--r--Swiften/Crypto/OpenSSLCryptoProvider.cpp53
-rw-r--r--Swiften/Crypto/OpenSSLCryptoProvider.h6
-rw-r--r--Swiften/Crypto/WindowsCryptoProvider.cpp478
-rw-r--r--Swiften/Crypto/WindowsCryptoProvider.h60
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;
+ };
+}