diff options
Diffstat (limited to 'Swiften/Crypto/WindowsCryptoProvider.cpp')
-rw-r--r-- | Swiften/Crypto/WindowsCryptoProvider.cpp | 328 |
1 files changed, 164 insertions, 164 deletions
diff --git a/Swiften/Crypto/WindowsCryptoProvider.cpp b/Swiften/Crypto/WindowsCryptoProvider.cpp index db4b2bf..e0410c6 100644 --- a/Swiften/Crypto/WindowsCryptoProvider.cpp +++ b/Swiften/Crypto/WindowsCryptoProvider.cpp @@ -27,196 +27,196 @@ using namespace Swift; struct WindowsCryptoProvider::Private { - HCRYPTPROV context; + 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); - } - } - - virtual ~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; - }; + class WindowsHash : public Hash { + public: + WindowsHash(HCRYPTPROV context, ALG_ID algorithm) : hash(NULL) { + if (!CryptCreateHash(context, algorithm, 0, 0, &hash)) { + assert(false); + } + } + + virtual ~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; - }; + // 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); - } + // 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); - } + p = boost::make_shared<Private>(); + if (!CryptAcquireContext(&p->context, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { + assert(false); + } } WindowsCryptoProvider::~WindowsCryptoProvider() { - CryptReleaseContext(p->context, 0); + CryptReleaseContext(p->context, 0); } Hash* WindowsCryptoProvider::createSHA1() { - return new WindowsHash(p->context, CALG_SHA1); + return new WindowsHash(p->context, CALG_SHA1); } Hash* WindowsCryptoProvider::createMD5() { - return new WindowsHash(p->context, CALG_MD5); + return new WindowsHash(p->context, CALG_MD5); } bool WindowsCryptoProvider::isMD5AllowedForCrypto() const { - return !WindowsRegistry::isFIPSEnabled(); + return !WindowsRegistry::isFIPSEnabled(); } ByteArray WindowsCryptoProvider::getHMACSHA1(const SafeByteArray& key, const ByteArray& data) { - return getHMACSHA1Internal(key, data, this); + return getHMACSHA1Internal(key, data, this); } ByteArray WindowsCryptoProvider::getHMACSHA1(const ByteArray& key, const ByteArray& data) { - return getHMACSHA1Internal(key, data, this); + return getHMACSHA1Internal(key, data, this); } |