diff options
author | Jeremy Lainé <jeremy.laine@m4x.org> | 2014-08-31 14:55:06 +0300 |
---|---|---|
committer | Richard J. Moore <rich@kde.org> | 2014-09-02 23:16:25 +0200 |
commit | cd3dece750aa30b15091f211a72b6fcf67d49853 (patch) | |
tree | 36594c8282b07fde103d893da48a94201d67a8c5 /src/network/ssl/qsslkey_winrt.cpp | |
parent | b17365cda91a6ecc8d12e995d83f4ff479c59b5f (diff) |
ssl: common key parser support for encrypted keys
This adds the infrastructure for reading and writing encrypted private keys
when using non-OpenSSL backends. Each platform must provide its cryptographic
encrypt / decrypt functions.
As WinRT already uses the common parser, this commit includes an
implementation for that platform.
Done-with: Andrew Knight <andrew.knight@digia.com>
Task-number: QTBUG-40688
Change-Id: I0d153425ce63601ff03b784a111e13962061025f
Reviewed-by: Richard J. Moore <rich@kde.org>
Diffstat (limited to 'src/network/ssl/qsslkey_winrt.cpp')
-rw-r--r-- | src/network/ssl/qsslkey_winrt.cpp | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/src/network/ssl/qsslkey_winrt.cpp b/src/network/ssl/qsslkey_winrt.cpp index 2c83069694..c5b4146ee9 100644 --- a/src/network/ssl/qsslkey_winrt.cpp +++ b/src/network/ssl/qsslkey_winrt.cpp @@ -61,3 +61,101 @@ using namespace ABI::Windows::Security::Cryptography::Core; using namespace ABI::Windows::Storage::Streams; QT_USE_NAMESPACE + +struct SslKeyGlobal +{ + SslKeyGlobal() + { + HRESULT hr; + hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Security_Cryptography_Core_CryptographicEngine).Get(), + &engine); + Q_ASSERT_SUCCEEDED(hr); + + ComPtr<ISymmetricKeyAlgorithmProviderStatics> keyProviderFactory; + hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Security_Cryptography_Core_SymmetricKeyAlgorithmProvider).Get(), + &keyProviderFactory); + Q_ASSERT_SUCCEEDED(hr); + hr = keyProviderFactory->OpenAlgorithm(HString::MakeReference(L"DES_CBC").Get(), + &keyProviders[QSslKeyPrivate::DesCbc]); + Q_ASSERT_SUCCEEDED(hr); + hr = keyProviderFactory->OpenAlgorithm(HString::MakeReference(L"3DES_CBC").Get(), + &keyProviders[QSslKeyPrivate::DesEde3Cbc]); + Q_ASSERT_SUCCEEDED(hr); + hr = keyProviderFactory->OpenAlgorithm(HString::MakeReference(L"RC2_CBC").Get(), + &keyProviders[QSslKeyPrivate::Rc2Cbc]); + Q_ASSERT_SUCCEEDED(hr); + + hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Security_Cryptography_CryptographicBuffer).Get(), + &bufferFactory); + Q_ASSERT_SUCCEEDED(hr); + } + + ComPtr<ICryptographicEngineStatics> engine; + QHash<QSslKeyPrivate::Cipher, ComPtr<ISymmetricKeyAlgorithmProvider>> keyProviders; + ComPtr<ICryptographicBufferStatics> bufferFactory; +}; +Q_GLOBAL_STATIC(SslKeyGlobal, g) + +static QByteArray doCrypt(QSslKeyPrivate::Cipher cipher, QByteArray data, const QByteArray &key, const QByteArray &iv, bool encrypt) +{ + HRESULT hr; + + ISymmetricKeyAlgorithmProvider *keyProvider = g->keyProviders[cipher].Get(); + Q_ASSERT(keyProvider); + + ComPtr<IBuffer> keyBuffer; + hr = g->bufferFactory->CreateFromByteArray(key.length(), (BYTE *)key.data(), &keyBuffer); + Q_ASSERT_SUCCEEDED(hr); + ComPtr<ICryptographicKey> cryptographicKey; + hr = keyProvider->CreateSymmetricKey(keyBuffer.Get(), &cryptographicKey); + Q_ASSERT_SUCCEEDED(hr); + + UINT32 blockLength; + hr = keyProvider->get_BlockLength(&blockLength); + Q_ASSERT_SUCCEEDED(hr); + if (encrypt) { // Add padding + const char padding = blockLength - data.length() % blockLength; + data += QByteArray(padding, padding); + } + + ComPtr<IBuffer> dataBuffer; + hr = g->bufferFactory->CreateFromByteArray(data.length(), (BYTE *)data.data(), &dataBuffer); + Q_ASSERT_SUCCEEDED(hr); + ComPtr<IBuffer> ivBuffer; + hr = g->bufferFactory->CreateFromByteArray(iv.length(), (BYTE *)iv.data(), &ivBuffer); + Q_ASSERT_SUCCEEDED(hr); + ComPtr<IBuffer> resultBuffer; + hr = encrypt ? g->engine->Encrypt(cryptographicKey.Get(), dataBuffer.Get(), ivBuffer.Get(), &resultBuffer) + : g->engine->Decrypt(cryptographicKey.Get(), dataBuffer.Get(), ivBuffer.Get(), &resultBuffer); + Q_ASSERT_SUCCEEDED(hr); + + UINT32 resultLength; + hr = resultBuffer->get_Length(&resultLength); + Q_ASSERT_SUCCEEDED(hr); + ComPtr<Windows::Storage::Streams::IBufferByteAccess> bufferAccess; + hr = resultBuffer.As(&bufferAccess); + Q_ASSERT_SUCCEEDED(hr); + byte *resultData; + hr = bufferAccess->Buffer(&resultData); + Q_ASSERT_SUCCEEDED(hr); + + if (!encrypt) { // Remove padding + const uchar padding = resultData[resultLength - 1]; + if (padding > 0 && padding <= blockLength) + resultLength -= padding; + else + qWarning("Invalid padding length of %u; decryption likely failed.", padding); + } + + return QByteArray(reinterpret_cast<const char *>(resultData), resultLength); +} + +QByteArray QSslKeyPrivate::decrypt(Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv) +{ + return doCrypt(cipher, data, key, iv, false); +} + +QByteArray QSslKeyPrivate::encrypt(Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv) +{ + return doCrypt(cipher, data, key, iv, true); +} |