summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/network/ssl/qsslkey_winrt.cpp130
-rw-r--r--tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp27
2 files changed, 148 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
diff --git a/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp b/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp
index e735e463ee..f7b9bcba62 100644
--- a/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp
+++ b/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp
@@ -47,6 +47,14 @@
#include <QtNetwork/qhostaddress.h>
#include <QtNetwork/qnetworkproxy.h>
+#ifdef Q_OS_WINRT
+#define WINRT_EXPECT_FAILURES \
+ if (type == QSsl::PrivateKey) \
+ QEXPECT_FAIL("", "No support for private keys on WinRT: QTBUG-40688", Abort); \
+ if (strstr(QTest::currentDataTag(), "rsa-pub-40")) \
+ QEXPECT_FAIL("", "Weak public keys are not supported on WinRT", Abort);
+#endif
+
class tst_QSslKey : public QObject
{
Q_OBJECT
@@ -171,6 +179,10 @@ void tst_QSslKey::constructor()
QFETCH(QSsl::KeyType, type);
QFETCH(QSsl::EncodingFormat, format);
+#ifdef Q_OS_WINRT
+ WINRT_EXPECT_FAILURES
+#endif
+
QByteArray encoded = readFile(absFilePath);
QSslKey key(encoded, algorithm, format, type);
QVERIFY(!key.isNull());
@@ -232,6 +244,10 @@ void tst_QSslKey::length()
QFETCH(int, length);
QFETCH(QSsl::EncodingFormat, format);
+#ifdef Q_OS_WINRT
+ WINRT_EXPECT_FAILURES
+#endif
+
QByteArray encoded = readFile(absFilePath);
QSslKey key(encoded, algorithm, format, type);
QVERIFY(!key.isNull());
@@ -253,6 +269,10 @@ void tst_QSslKey::toPemOrDer()
QFETCH(QSsl::KeyType, type);
QFETCH(QSsl::EncodingFormat, format);
+#ifdef Q_OS_WINRT
+ WINRT_EXPECT_FAILURES
+#endif
+
QByteArray encoded = readFile(absFilePath);
QSslKey key(encoded, algorithm, format, type);
QVERIFY(!key.isNull());
@@ -297,6 +317,10 @@ void tst_QSslKey::toEncryptedPemOrDer()
QFETCH(QSsl::EncodingFormat, format);
QFETCH(QString, password);
+#ifdef Q_OS_WINRT
+ WINRT_EXPECT_FAILURES
+#endif
+
QByteArray plain = readFile(absFilePath);
QSslKey key(plain, algorithm, format, type);
QVERIFY(!key.isNull());
@@ -374,6 +398,9 @@ void tst_QSslKey::passphraseChecks()
QSslKey key(&keyFile,QSsl::Rsa,QSsl::Pem, QSsl::PrivateKey, "WRONG!");
QVERIFY(key.isNull()); // wrong passphrase => should not be able to decode key
}
+#ifdef Q_OS_WINRT
+ QEXPECT_FAIL("", "The WinRT backend does not support private key imports: QTBUG-40688", Abort);
+#endif
{
if (!keyFile.isOpen())
keyFile.open(QIODevice::ReadOnly);