summaryrefslogtreecommitdiffstats
path: root/src/network/ssl/qsslkey_winrt.cpp
diff options
context:
space:
mode:
authorAndrew Knight <andrew.knight@digia.com>2014-08-12 12:21:57 +0300
committerAndrew Knight <andrew.knight@digia.com>2014-08-13 21:09:51 +0200
commit8c864ac49861b397a6d3e8b4a93c39b1ed373644 (patch)
treec82b95c1d52892397f59f50c3fc9be8f43b69d41 /src/network/ssl/qsslkey_winrt.cpp
parentcec893e4f0d6480a9b3e38af38c7b887a29f206d (diff)
winrt: Add partial SSL key support
This allows for opening of public key files. It does not, however, support opening private keys (or decrypting/encrypting them). This is due to limitations in the native API. Nearly all public key tests pass (the native API doesn't support the 40-bit key in the test set). The private key tests are expected to fail. Task-number: QTBUG-40688 Change-Id: Id8f2f1ae6526540736ceb2e5371f6a5d80c4ba7b Reviewed-by: Richard J. Moore <rich@kde.org> Reviewed-by: Oliver Wolff <oliver.wolff@digia.com>
Diffstat (limited to 'src/network/ssl/qsslkey_winrt.cpp')
-rw-r--r--src/network/ssl/qsslkey_winrt.cpp130
1 files changed, 121 insertions, 9 deletions
diff --git a/src/network/ssl/qsslkey_winrt.cpp b/src/network/ssl/qsslkey_winrt.cpp
index 1e416a8c09..1c625081a4 100644
--- a/src/network/ssl/qsslkey_winrt.cpp
+++ b/src/network/ssl/qsslkey_winrt.cpp
@@ -42,41 +42,153 @@
#include "qsslkey.h"
#include "qsslkey_p.h"
+#include <QtCore/qfunctions_winrt.h>
+
+#include <wrl.h>
+#include <windows.security.cryptography.h>
+#include <windows.security.cryptography.core.h>
+#include <windows.security.cryptography.certificates.h>
+#include <windows.storage.streams.h>
+#include <robuffer.h>
+
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Security::Cryptography;
+using namespace ABI::Windows::Security::Cryptography::Certificates;
+using namespace ABI::Windows::Security::Cryptography::Core;
+using namespace ABI::Windows::Storage::Streams;
+
QT_BEGIN_NAMESPACE
+struct SslKeyGlobal
+{
+ SslKeyGlobal()
+ {
+ HRESULT hr;
+ hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Security_Cryptography_CryptographicBuffer).Get(),
+ &bufferFactory);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ ComPtr<IAsymmetricKeyAlgorithmProviderStatics> keyProviderFactory;
+ hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Security_Cryptography_Core_AsymmetricKeyAlgorithmProvider).Get(),
+ &keyProviderFactory);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ ComPtr<IAsymmetricAlgorithmNamesStatics> algorithmNames;
+ hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Security_Cryptography_Core_AsymmetricAlgorithmNames).Get(),
+ &algorithmNames);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ HString algorithmName;
+ // The algorithm name doesn't matter for imports, so just use PKCS1
+ hr = algorithmNames->get_RsaPkcs1(algorithmName.GetAddressOf());
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = keyProviderFactory->OpenAlgorithm(algorithmName.Get(), &keyProvider);
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+
+ ComPtr<ICryptographicBufferStatics> bufferFactory;
+ ComPtr<IAsymmetricKeyAlgorithmProvider> keyProvider;
+};
+Q_GLOBAL_STATIC(SslKeyGlobal, g)
+
+// Use the opaque struct for key storage
+struct EVP_PKEY {
+ ComPtr<ICryptographicKey> key;
+};
+
void QSslKeyPrivate::clear(bool deep)
{
- Q_UNIMPLEMENTED();
+ isNull = true;
+
+ if (opaque) {
+ if (deep) {
+ delete opaque;
+ opaque = 0;
+ } else {
+ opaque->key.Reset();
+ }
+ }
}
void QSslKeyPrivate::decodeDer(const QByteArray &der, const QByteArray &passPhrase,
bool deepClear)
{
- Q_UNIMPLEMENTED();
+ Q_UNUSED(passPhrase);
+
+ clear(deepClear);
+
+ if (der.isEmpty())
+ return;
+
+ if (type != QSsl::PublicKey) {
+ qWarning("The WinRT SSL backend does not support importing private keys.");
+ return;
+ }
+
+ HRESULT hr;
+ ComPtr<IBuffer> buffer;
+ hr = g->bufferFactory->CreateFromByteArray(der.length(), (BYTE *)der.data(), &buffer);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ if (!opaque)
+ opaque = new EVP_PKEY;
+
+ hr = g->keyProvider->ImportDefaultPublicKeyBlob(buffer.Get(), &opaque->key);
+ RETURN_VOID_IF_FAILED("Failed to import public key");
+
+ isNull = false;
}
void QSslKeyPrivate::decodePem(const QByteArray &pem, const QByteArray &passPhrase,
bool deepClear)
{
- Q_UNIMPLEMENTED();
+ decodeDer(derFromPem(pem), passPhrase, deepClear);
}
int QSslKeyPrivate::length() const
{
- Q_UNIMPLEMENTED();
- return -1;
+ if (isNull)
+ return -1;
+
+ Q_ASSERT(opaque && opaque->key);
+ HRESULT hr;
+ UINT32 keySize;
+ hr = opaque->key->get_KeySize(&keySize);
+ Q_ASSERT_SUCCEEDED(hr);
+ return keySize;
}
QByteArray QSslKeyPrivate::toPem(const QByteArray &passPhrase) const
{
- Q_UNIMPLEMENTED();
- return QByteArray();
+ Q_UNUSED(passPhrase);
+ QByteArray result;
+ if (isNull)
+ return result;
+
+ Q_ASSERT(opaque && opaque->key);
+ HRESULT hr;
+ ComPtr<IBuffer> buffer;
+ hr = opaque->key->ExportDefaultPublicKeyBlobType(&buffer);
+ RETURN_IF_FAILED("Failed to export key", return result);
+
+ ComPtr<Windows::Storage::Streams::IBufferByteAccess> byteAccess;
+ hr = buffer.As(&byteAccess);
+ Q_ASSERT_SUCCEEDED(hr);
+ char *data;
+ hr = byteAccess->Buffer(reinterpret_cast<byte **>(&data));
+ Q_ASSERT_SUCCEEDED(hr);
+ UINT32 size;
+ hr = buffer->get_Length(&size);
+ Q_ASSERT_SUCCEEDED(hr);
+ result = pemFromDer(QByteArray::fromRawData(data, size));
+ return result;
}
Qt::HANDLE QSslKeyPrivate::handle() const
{
- Q_UNIMPLEMENTED();
- return 0;
+ return opaque ? opaque->key.Get() : 0;
}
QT_END_NAMESPACE