Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
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
// Qt-Security score:critical reason:cryptography
4
5
#
include
<
QtNetwork
/
private
/
qssl_p
.
h
>
6
7
#
include
"qtlsbackend_schannel_p.h"
8
#
include
"qtlskey_schannel_p.h"
9
10
#
include
"../shared/qwincrypt_p.h"
11
12
#
include
<
QtNetwork
/
private
/
qtlsbackend_p
.
h
>
13
#
include
<
QtNetwork
/
private
/
qsslkey_p
.
h
>
14
15
#
include
<
QtNetwork
/
qsslkey
.
h
>
16
17
#
include
<
QtCore
/
qscopeguard
.
h
>
18
#
include
<
QtCore
/
qbytearray
.
h
>
19
#
include
<
QtCore
/
qvarlengtharray
.
h
>
20
21
QT_BEGIN_NAMESPACE
22
23
namespace
{
24
const
wchar_t
*
getName
(QSslKeyPrivate::Cipher cipher)
25
{
26
switch
(cipher) {
27
case
QTlsPrivate::Cipher::DesCbc:
28
return
BCRYPT_DES_ALGORITHM;
29
case
QTlsPrivate::Cipher::DesEde3Cbc:
30
return
BCRYPT_3DES_ALGORITHM;
31
case
QTlsPrivate::Cipher::Rc2Cbc:
32
return
BCRYPT_RC2_ALGORITHM;
33
case
QTlsPrivate::Cipher::Aes128Cbc:
34
case
QTlsPrivate::Cipher::Aes192Cbc:
35
case
QTlsPrivate::Cipher::Aes256Cbc:
36
return
BCRYPT_AES_ALGORITHM;
37
}
38
Q_UNREACHABLE();
39
}
40
41
BCRYPT_ALG_HANDLE
getHandle
(QSslKeyPrivate::Cipher cipher)
42
{
43
BCRYPT_ALG_HANDLE handle;
44
NTSTATUS status = BCryptOpenAlgorithmProvider(
45
&handle,
// phAlgorithm
46
getName(cipher),
// pszAlgId
47
nullptr
,
// pszImplementation
48
0
// dwFlags
49
);
50
if
(status < 0) {
51
qCWarning(lcTlsBackendSchannel,
"Failed to open algorithm handle (%ld)!"
, status);
52
return
nullptr
;
53
}
54
55
return
handle;
56
}
57
58
BCRYPT_KEY_HANDLE
generateSymmetricKey
(BCRYPT_ALG_HANDLE handle,
59
const
QByteArray &key)
60
{
61
BCRYPT_KEY_HANDLE keyHandle;
62
NTSTATUS status = BCryptGenerateSymmetricKey(
63
handle,
// hAlgorithm
64
&keyHandle,
// phKey
65
nullptr
,
// pbKeyObject (can ignore)
66
0,
// cbKeyObject (also ignoring)
67
reinterpret_cast
<
unsigned
char
*>(
const_cast
<
char
*>(key.data())),
// pbSecret
68
ULONG(key.length()),
// cbSecret
69
0
// dwFlags
70
);
71
if
(status < 0) {
72
qCWarning(lcTlsBackendSchannel,
"Failed to generate symmetric key (%ld)!"
, status);
73
return
nullptr
;
74
}
75
76
status = BCryptSetProperty(
77
keyHandle,
// hObject
78
BCRYPT_CHAINING_MODE,
// pszProperty
79
reinterpret_cast
<UCHAR *>(
const_cast
<
wchar_t
*>(BCRYPT_CHAIN_MODE_CBC)),
// pbInput
80
ARRAYSIZE(BCRYPT_CHAIN_MODE_CBC),
// cbInput
81
0
// dwFlags
82
);
83
if
(status < 0) {
84
BCryptDestroyKey(keyHandle);
85
qCWarning(lcTlsBackendSchannel,
"Failed to change the symmetric key's chaining mode (%ld)!"
,
86
status);
87
return
nullptr
;
88
}
89
return
keyHandle;
90
}
91
92
QByteArray
doCrypt
(QSslKeyPrivate::Cipher cipher,
const
QByteArray &data,
const
QByteArray &key,
93
const
QByteArray &iv,
bool
encrypt)
94
{
95
BCRYPT_ALG_HANDLE handle = getHandle(cipher);
96
if
(!handle)
97
return
{};
98
auto
handleDealloc = qScopeGuard([&handle]() {
99
BCryptCloseAlgorithmProvider(handle, 0);
100
});
101
102
BCRYPT_KEY_HANDLE keyHandle = generateSymmetricKey(handle, key);
103
if
(!keyHandle)
104
return
{};
105
auto
keyHandleDealloc = qScopeGuard([&keyHandle]() {
106
BCryptDestroyKey(keyHandle);
107
});
108
109
QByteArray ivCopy = iv;
// This gets modified, so we take a copy
110
111
ULONG sizeNeeded = 0;
112
QVarLengthArray<
unsigned
char
> output;
113
auto
cryptFunction = encrypt ? BCryptEncrypt : BCryptDecrypt;
114
for
(
int
i = 0; i < 2; i++) {
115
output.resize(
int
(sizeNeeded));
116
auto
input =
reinterpret_cast
<
unsigned
char
*>(
const_cast
<
char
*>(data.data()));
117
// Need to call it twice because the first iteration lets us know the size needed.
118
NTSTATUS status = cryptFunction(
119
keyHandle,
// hKey
120
input,
// pbInput
121
ULONG(data.length()),
// cbInput
122
nullptr
,
// pPaddingInfo
123
reinterpret_cast
<
unsigned
char
*>(ivCopy.data()),
// pbIV
124
ULONG(ivCopy.length()),
// cbIV
125
sizeNeeded ? output.data() :
nullptr
,
// pbOutput
126
ULONG(output.length()),
// cbOutput
127
&sizeNeeded,
// pcbResult
128
BCRYPT_BLOCK_PADDING
// dwFlags
129
);
130
if
(status < 0) {
131
qCWarning(lcTlsBackendSchannel,
"%s failed (%ld)!"
, encrypt ?
"Encrypt"
:
"Decrypt"
,
132
status);
133
return
{};
134
}
135
}
136
137
return
QByteArray(
reinterpret_cast
<
const
char
*>(output.constData()),
int
(sizeNeeded));
138
}
139
}
// anonymous namespace
140
141
namespace
QTlsPrivate
{
142
143
QByteArray
TlsKeySchannel::
decrypt
(Cipher cipher,
const
QByteArray &data,
const
QByteArray &key,
144
const
QByteArray &iv)
const
145
{
146
return
doCrypt(cipher, data, key, iv,
false
);
147
}
148
149
QByteArray
TlsKeySchannel::
encrypt
(Cipher cipher,
const
QByteArray &data,
const
QByteArray &key,
150
const
QByteArray &iv)
const
151
{
152
return
doCrypt(cipher, data, key, iv,
true
);
153
}
154
155
}
// namespace QTlsPrivate
156
157
QT_END_NAMESPACE
QTlsPrivate::TlsKeySchannel::decrypt
QByteArray decrypt(Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv) const override
Definition
qtlskey_schannel.cpp:143
QTlsPrivate::TlsKeySchannel::encrypt
QByteArray encrypt(Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv) const override
Definition
qtlskey_schannel.cpp:149
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
QT_BEGIN_NAMESPACE::doCrypt
QByteArray doCrypt(QSslKeyPrivate::Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv, bool encrypt)
Definition
qtlskey_schannel.cpp:92
QT_BEGIN_NAMESPACE::getName
const wchar_t * getName(QSslKeyPrivate::Cipher cipher)
Definition
qtlskey_schannel.cpp:24
QT_BEGIN_NAMESPACE::getHandle
BCRYPT_ALG_HANDLE getHandle(QSslKeyPrivate::Cipher cipher)
Definition
qtlskey_schannel.cpp:41
QT_BEGIN_NAMESPACE::generateSymmetricKey
BCRYPT_KEY_HANDLE generateSymmetricKey(BCRYPT_ALG_HANDLE handle, const QByteArray &key)
Definition
qtlskey_schannel.cpp:58
QTlsPrivate
Namespace containing onternal types that TLS backends implement.
Definition
qocspresponse.h:41
qtbase
src
plugins
tls
schannel
qtlskey_schannel.cpp
Generated on
for Qt by
1.18.0