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
qsslkeyingmaterial.cpp
Go to the documentation of this file.
1
// Copyright (C) 2026 Governikus GmbH & Co. KG.
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:significant reason:default
4
5
#
include
"qsslkeyingmaterial.h"
6
7
#
ifndef
QT_NO_DEBUG_STREAM
8
#
include
<
QtCore
/
qdebug
.
h
>
9
#
endif
10
#
include
<
QtCore
/
qhashfunctions
.
h
>
11
12
QT_BEGIN_NAMESPACE
13
14
/*!
15
\class QSslKeyingMaterial
16
\since 6.12
17
\preliminary
18
19
\brief Describes exported keying material derived from a TLS session.
20
21
\reentrant
22
\ingroup network
23
\ingroup ssl
24
\inmodule QtNetwork
25
\compares equality
26
27
QSslKeyingMaterial represents a request for keying material derived
28
from an established TLS connection using the TLS exporter mechanism.
29
30
The exporter mechanism is defined in RFC 5705 for TLS 1.2 and earlier
31
and in RFC 8446 for TLS 1.3. It allows applications to derive
32
cryptographically separate keying material from the TLS session
33
without exposing the session's traffic keys.
34
35
Each QSslKeyingMaterial object specifies:
36
\list
37
\li an exporter label identifying the purpose of the derived
38
keying material
39
\li an optional context value binding the keying material to
40
application-specific data
41
\li the desired size of the exported keying material
42
\endlist
43
44
The actual keying material is derived by the TLS backend after a
45
successful handshake and can be read with value().
46
47
QSslKeyingMaterial objects are typically configured via
48
QSslConfiguration::setKeyingMaterial() before initiating a TLS
49
connection.
50
51
Example: Deterministic export on client and server
52
\code
53
// Both client and server configure the same label and optional context
54
QSslKeyingMaterial keying("session-label", 32, "app-specific-context");
55
56
// After the TLS handshake completes get data from QSslConfiguration.
57
QByteArray derived = sslConfiguration().takeKeyingMaterial(keying)->value();
58
59
// Both client and server will obtain the same 'derived' bytes
60
// even though they each performed the derivation independently.
61
use(derived);
62
\endcode
63
64
\section1 Security Considerations
65
66
Exported keying material is a secret. QByteArray is a copy-on-write
67
container, so every QSslKeyingMaterial object holding a value shares one
68
buffer, and the secret remains in memory for as long as any of those
69
objects lives. An application that needs to guarantee it holds the only
70
remaining reference must release the Qt-internal ones explicitly.
71
72
After a successful handshake the value lives in exactly one place inside
73
Qt: the QSslKeyingMaterial entry in the socket's internal
74
QSslConfiguration. Each QSslConfiguration returned by
75
QSslSocket::sslConfiguration() is an independent copy of that
76
configuration, sharing the value's buffer with it.
77
78
Both QSslConfiguration::takeKeyingMaterial() overloads hand the values over
79
instead of sharing them: what they return holds the only reference to the
80
value, and the entries they leave behind in the configuration they were
81
called on are valueless \l{clone()}{clones}. Copy the value out of the
82
returned object with \l value() and let the object itself go out of scope,
83
then write the configuration back to the socket: that overwrites the
84
socket's entry with the valueless one, dropping the last reference Qt
85
holds.
86
87
\code
88
QSslConfiguration config = socket->sslConfiguration();
89
90
// Copy the value out of the temporary that owns it, and let it die:
91
QByteArray secret = config.takeKeyingMaterial(request)->value();
92
93
// Overwrite the socket's copy with the entry left behind, which has no value:
94
socket->setSslConfiguration(config);
95
\endcode
96
97
The following copies are outside the socket's control and must be dealt
98
with separately:
99
\list
100
\li Any other QSslConfiguration copy the application still holds,
101
including one stored in a QNetworkRequest or installed with
102
QSslConfiguration::setDefaultConfiguration(). Taking the value
103
from one copy does not affect the others.
104
\li A configuration that was never written back to the socket. Taking
105
the values out of a QSslConfiguration only strips that copy of the
106
configuration; the socket keeps its own until it is given the
107
valueless entries.
108
\li Any QSslKeyingMaterial copy the application made itself. Use
109
\l clone() when a copy of a request is needed without its value.
110
\endlist
111
112
The socket also drops the values when it starts a new handshake, because
113
its entries are reset to valueless clones then, and when it is destroyed.
114
Neither replaces the explicit step above for a socket that stays alive.
115
*/
116
117
/*!
118
Default-constructs an instance of QSslKeyingMaterial.
119
120
A default instance is never valid.
121
122
\sa isValid()
123
*/
124
125
QSslKeyingMaterial::QSslKeyingMaterial()
126
=
default
;
127
128
/*!
129
\fn explicit QSslKeyingMaterial::QSslKeyingMaterial(const QByteArray &label, qsizetype size)
130
\fn explicit QSslKeyingMaterial::QSslKeyingMaterial(const QByteArray &label, qsizetype size, const QByteArray &context)
131
132
Constructs a QSslKeyingMaterial object with the given exporter
133
\a label, output \a size, and optional \a context.
134
135
The \a label identifies the purpose of the exported keying material
136
and must be non-empty. The \a size specifies the number of bytes
137
to be derived from the TLS exporter.
138
139
The optional \a context is application-defined data that is mixed
140
into the key derivation process to provide domain separation.
141
142
The keying material itself is not generated until a TLS handshake
143
has completed successfully.
144
145
\note Under TLS 1.2 (RFC 5705), a null context and an empty (non-null)
146
context produce different keying material: the context length field is
147
omitted entirely when no context is present, yielding a different PRF
148
input. Under TLS 1.3 (RFC 8446), an absent context and an empty context
149
are defined to be equivalent and produce the same keying material.
150
Use \l{QByteArray::isNull()} to distinguish them.
151
152
\sa isValid(), label(), context(), value()
153
*/
154
155
QSslKeyingMaterial::QSslKeyingMaterial(
const
QByteArray &label, qsizetype size)
156
: m_label(label),
157
m_requestedSize(size)
158
{
159
}
160
161
QSslKeyingMaterial::QSslKeyingMaterial(
const
QByteArray &label, qsizetype size,
const
QByteArray &context)
162
: m_label(label),
163
m_context(context),
164
m_requestedSize(size)
165
{
166
}
167
168
QSslKeyingMaterial::QSslKeyingMaterial(
const
QSslKeyingMaterial &other)
169
=
default
;
170
171
QSslKeyingMaterial &QSslKeyingMaterial::operator=(
const
QSslKeyingMaterial &other)
172
=
default
;
173
174
QSslKeyingMaterial::~QSslKeyingMaterial()
175
=
default
;
176
177
/*!
178
Returns true if this QSslKeyingMaterial object describes a valid
179
exporter request.
180
181
A QSslKeyingMaterial object is considered valid if it has a
182
non-empty exporter label and a positive output size.
183
184
\sa label(), value()
185
*/
186
187
bool
QSslKeyingMaterial::isValid()
const
noexcept
188
{
189
return
!m_label.isEmpty() && requestedSize() > 0;
190
}
191
192
/*!
193
\fn QByteArray QSslKeyingMaterial::label() const
194
195
Returns the exporter label used for deriving the keying material.
196
197
The label identifies the purpose of the exported keying material
198
and is included verbatim in the TLS exporter derivation.
199
200
\sa context(), value()
201
*/
202
203
/*!
204
\fn QByteArray QSslKeyingMaterial::context() const
205
206
Returns the optional context value used for deriving the keying material.
207
208
The context value binds the exported keying material to
209
application-specific data and helps prevent accidental reuse of
210
identical keys across different purposes.
211
212
If no context was specified, a null/empty QByteArray is returned (see
213
\l{QSslKeyingMaterial::QSslKeyingMaterial()}).
214
215
\sa label(), value()
216
*/
217
218
/*!
219
Returns a copy of this keying material request, without its value().
220
221
The returned object carries the exporter label(), context() and
222
requestedSize(), so it can be used to request the same keying material
223
again, but its value() is empty. Use it to initialize a copy, or to
224
reset an entry, without carrying the value along.
225
226
\sa value()
227
*/
228
QSslKeyingMaterial QSslKeyingMaterial::clone()
const
229
{
230
return
QSslKeyingMaterial(m_label, m_requestedSize, m_context);
231
}
232
233
/*!
234
\fn QByteArray QSslKeyingMaterial::value() const
235
236
Returns the exported keying material.
237
238
The returned QByteArray contains the keying material derived from
239
the TLS session using the configured exporter label and context.
240
241
If the TLS handshake has not completed successfully or if the TLS
242
backend does not support key exporters, this function returns an
243
empty value.
244
245
\note The contents of the returned keying material are
246
security-sensitive and must be handled with care. See
247
\l{QSslKeyingMaterial#Security Considerations}{Security
248
Considerations} for how to keep the returned QByteArray the
249
only copy of it.
250
251
\sa label(), context(), requestedSize()
252
*/
253
254
/*!
255
\fn qsizetype QSslKeyingMaterial::requestedSize() const noexcept
256
257
The desired size of the keying material.
258
259
The desired size is the number of bytes the handshake protocol
260
is asked to generate for the purpose described by the \l label()
261
and \l context() of the requested keying material.
262
263
\sa value()
264
*/
265
266
/*!
267
\fn void QSslKeyingMaterial::swap(QSslKeyingMaterial &other) noexcept
268
\memberswap{keying material}
269
*/
270
271
/*!
272
\fn size_t qHash(const QSslKeyingMaterial &key) noexcept
273
\fn size_t qHash(const QSslKeyingMaterial &key, size_t seed) noexcept
274
\qhashold{QHash}
275
*/
276
size_t
qHash
(
const
QSslKeyingMaterial &material, size_t seed)
noexcept
277
{
278
return
qHashMulti(seed, material.m_label, material.m_context, material.m_value,
279
material.m_requestedSize);
280
}
281
282
// friend
283
bool
comparesEqual
(
const
QSslKeyingMaterial &lhs,
const
QSslKeyingMaterial &rhs)
noexcept
284
{
285
return
lhs.m_requestedSize == rhs.m_requestedSize
286
&& lhs.m_label == rhs.m_label
287
&& lhs.m_context.isNull() == rhs.m_context.isNull()
288
&& lhs.m_context == rhs.m_context
289
&& lhs.m_value == rhs.m_value;
290
}
291
292
#
ifndef
QT_NO_DEBUG_STREAM
293
/*!
294
\relates QSslKeyingMaterial
295
296
Writes a textual representation of the keying material \a keying
297
to the debug object \a debug.
298
299
\sa {Debugging Techniques}
300
*/
301
QDebug operator<<(QDebug debug,
const
QSslKeyingMaterial &keying)
302
{
303
QDebugStateSaver saver(debug);
304
debug.resetFormat().nospace();
305
debug <<
"QSslKeyingMaterial("
306
<< keying.label() <<
','
<< keying.context()
307
<<
", requested size: "
<< keying.requestedSize()
308
<<
", actual size: "
<< keying.value().size() <<
')'
;
309
return
debug;
310
}
311
#
endif
312
313
QT_END_NAMESPACE
comparesEqual
bool comparesEqual(const QFileInfo &lhs, const QFileInfo &rhs)
Definition
qfileinfo.cpp:469
qHash
constexpr size_t qHash(const QSize &s, size_t seed=0) noexcept
Definition
qsize.h:192
qtbase
src
network
ssl
qsslkeyingmaterial.cpp
Generated on
for Qt by
1.18.0