diff options
author | Remko Tronçon <git@el-tramo.be> | 2013-04-27 15:30:27 (GMT) |
---|---|---|
committer | Remko Tronçon <git@el-tramo.be> | 2013-04-27 15:30:27 (GMT) |
commit | 87d5557ecba47f0cfd323e79f7d9284c484f825a (patch) | |
tree | 7af755e30a37dd388392e305b9c01637d8a039cb /Swiften | |
parent | 860d265a878ca444fca358f468a32df32a7f4444 (diff) | |
download | swift-87d5557ecba47f0cfd323e79f7d9284c484f825a.zip swift-87d5557ecba47f0cfd323e79f7d9284c484f825a.tar.bz2 |
Make HMACSHA1 not be a Hash.
Change-Id: I798d468614d2285c6f77640c365b51b19df2bf73
Diffstat (limited to 'Swiften')
-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; + }; +} |