Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qtlskey_schannel.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <QtNetwork/private/qssl_p.h>
5
8
10
11#include <QtNetwork/private/qtlsbackend_p.h>
12#include <QtNetwork/private/qsslkey_p.h>
13
14#include <QtNetwork/qsslkey.h>
15
16#include <QtCore/qscopeguard.h>
17#include <QtCore/qbytearray.h>
18#include <QtCore/qvarlengtharray.h>
19
21
22namespace {
23const wchar_t *getName(QSslKeyPrivate::Cipher cipher)
24{
25 switch (cipher) {
27 return BCRYPT_DES_ALGORITHM;
29 return BCRYPT_3DES_ALGORITHM;
31 return BCRYPT_RC2_ALGORITHM;
35 return BCRYPT_AES_ALGORITHM;
36 }
37 Q_UNREACHABLE();
38}
39
40BCRYPT_ALG_HANDLE getHandle(QSslKeyPrivate::Cipher cipher)
41{
42 BCRYPT_ALG_HANDLE handle;
43 NTSTATUS status = BCryptOpenAlgorithmProvider(
44 &handle, // phAlgorithm
45 getName(cipher), // pszAlgId
46 nullptr, // pszImplementation
47 0 // dwFlags
48 );
49 if (status < 0) {
50 qCWarning(lcTlsBackendSchannel, "Failed to open algorithm handle (%ld)!", status);
51 return nullptr;
52 }
53
54 return handle;
55}
56
57BCRYPT_KEY_HANDLE generateSymmetricKey(BCRYPT_ALG_HANDLE handle,
58 const QByteArray &key)
59{
60 BCRYPT_KEY_HANDLE keyHandle;
61 NTSTATUS status = BCryptGenerateSymmetricKey(
62 handle, // hAlgorithm
63 &keyHandle, // phKey
64 nullptr, // pbKeyObject (can ignore)
65 0, // cbKeyObject (also ignoring)
66 reinterpret_cast<unsigned char *>(const_cast<char *>(key.data())), // pbSecret
67 ULONG(key.length()), // cbSecret
68 0 // dwFlags
69 );
70 if (status < 0) {
71 qCWarning(lcTlsBackendSchannel, "Failed to generate symmetric key (%ld)!", status);
72 return nullptr;
73 }
74
75 status = BCryptSetProperty(
76 keyHandle, // hObject
77 BCRYPT_CHAINING_MODE, // pszProperty
78 reinterpret_cast<UCHAR *>(const_cast<wchar_t *>(BCRYPT_CHAIN_MODE_CBC)), // pbInput
79 ARRAYSIZE(BCRYPT_CHAIN_MODE_CBC), // cbInput
80 0 // dwFlags
81 );
82 if (status < 0) {
83 BCryptDestroyKey(keyHandle);
84 qCWarning(lcTlsBackendSchannel, "Failed to change the symmetric key's chaining mode (%ld)!",
85 status);
86 return nullptr;
87 }
88 return keyHandle;
89}
90
92 const QByteArray &iv, bool encrypt)
93{
94 BCRYPT_ALG_HANDLE handle = getHandle(cipher);
95 if (!handle)
96 return {};
97 auto handleDealloc = qScopeGuard([&handle]() {
98 BCryptCloseAlgorithmProvider(handle, 0);
99 });
100
101 BCRYPT_KEY_HANDLE keyHandle = generateSymmetricKey(handle, key);
102 if (!keyHandle)
103 return {};
104 auto keyHandleDealloc = qScopeGuard([&keyHandle]() {
105 BCryptDestroyKey(keyHandle);
106 });
107
108 QByteArray ivCopy = iv; // This gets modified, so we take a copy
109
110 ULONG sizeNeeded = 0;
111 QVarLengthArray<unsigned char> output;
112 auto cryptFunction = encrypt ? BCryptEncrypt : BCryptDecrypt;
113 for (int i = 0; i < 2; i++) {
114 output.resize(int(sizeNeeded));
115 auto input = reinterpret_cast<unsigned char *>(const_cast<char *>(data.data()));
116 // Need to call it twice because the first iteration lets us know the size needed.
117 NTSTATUS status = cryptFunction(
118 keyHandle, // hKey
119 input, // pbInput
120 ULONG(data.length()), // cbInput
121 nullptr, // pPaddingInfo
122 reinterpret_cast<unsigned char *>(ivCopy.data()), // pbIV
123 ULONG(ivCopy.length()), // cbIV
124 sizeNeeded ? output.data() : nullptr, // pbOutput
125 ULONG(output.length()), // cbOutput
126 &sizeNeeded, // pcbResult
127 BCRYPT_BLOCK_PADDING // dwFlags
128 );
129 if (status < 0) {
130 qCWarning(lcTlsBackendSchannel, "%s failed (%ld)!", encrypt ? "Encrypt" : "Decrypt",
131 status);
132 return {};
133 }
134 }
135
136 return QByteArray(reinterpret_cast<const char *>(output.constData()), int(sizeNeeded));
137}
138} // anonymous namespace
139
140namespace QTlsPrivate {
141
143 const QByteArray &iv) const
144{
145 return doCrypt(cipher, data, key, iv, false);
146}
147
149 const QByteArray &iv) const
150{
151 return doCrypt(cipher, data, key, iv, true);
152}
153
154} // namespace QTlsPrivate
155
157
\inmodule QtCore
Definition qbytearray.h:57
QByteArray decrypt(Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv) const override
QByteArray encrypt(Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv) const override
Combined button and popup list for selecting options.
const wchar_t * getName(QSslKeyPrivate::Cipher cipher)
BCRYPT_ALG_HANDLE getHandle(QSslKeyPrivate::Cipher cipher)
BCRYPT_KEY_HANDLE generateSymmetricKey(BCRYPT_ALG_HANDLE handle, const QByteArray &key)
Namespace containing onternal types that TLS backends implement.
QByteArray doCrypt(QSslKeyPrivate::Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv, bool enc)
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
#define qCWarning(category,...)
GLuint64 GLenum void * handle
GLuint64 key
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLenum GLenum input
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
Definition qscopeguard.h:60
QT_BEGIN_NAMESPACE typedef uchar * output