Coverage Report

Created: 2026-02-26 07:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/qtbase/src/network/ssl/qssldiffiehellmanparameters.cpp
Line
Count
Source
1
// Copyright (C) 2015 Mikkel Krautz <mikkel@krautz.dk>
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
6
/*!
7
    \class QSslDiffieHellmanParameters
8
    \brief The QSslDiffieHellmanParameters class provides an interface for Diffie-Hellman parameters for servers.
9
    \since 5.8
10
11
    \reentrant
12
    \ingroup network
13
    \ingroup ssl
14
    \ingroup shared
15
    \inmodule QtNetwork
16
17
    QSslDiffieHellmanParameters provides an interface for setting Diffie-Hellman parameters to servers based on QSslSocket.
18
19
    \sa QSslSocket, QSslCipher, QSslConfiguration
20
*/
21
22
#include "qssldiffiehellmanparameters.h"
23
#include "qssldiffiehellmanparameters_p.h"
24
#include "qtlsbackend_p.h"
25
#include "qsslsocket.h"
26
#include "qsslsocket_p.h"
27
28
#include <QtCore/qcoreapplication.h>
29
#include <QtCore/qatomic.h>
30
#include <QtCore/qbytearray.h>
31
#include <QtCore/qbytearraymatcher.h>
32
#include <QtCore/qiodevice.h>
33
#include <QtCore/qdebug.h>
34
35
QT_BEGIN_NAMESPACE
36
37
// The 2048-bit MODP group from RFC 3526
38
Q_AUTOTEST_EXPORT extern const char qssl_dhparams_default_base64[] =
39
    "MIIBCAKCAQEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxObIlFKCHmO"
40
    "NATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjftawv/XLb0Brft7jhr"
41
    "+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXTmmkWP6j9JM9fg2VdI9yjrZYc"
42
    "YvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhghfDKQXkYuNs474553LBgOhgObJ4Oi7Aei"
43
    "j7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq5RXSJhiY+gUQFXKOWoqsqmj//////////wIBAg==";
44
45
/*!
46
    Returns the default QSslDiffieHellmanParameters used by QSslSocket.
47
48
    This is currently the 2048-bit MODP group from RFC 3526.
49
*/
50
QSslDiffieHellmanParameters QSslDiffieHellmanParameters::defaultParameters()
51
0
{
52
0
    QSslDiffieHellmanParameters def;
53
0
    def.d->derData = QByteArray::fromBase64(QByteArray(qssl_dhparams_default_base64));
54
0
    return def;
55
0
}
56
57
/*!
58
    Constructs an empty QSslDiffieHellmanParameters instance.
59
60
    If an empty QSslDiffieHellmanParameters instance is set on a
61
    QSslConfiguration object, Diffie-Hellman negotiation will
62
    be disabled.
63
64
    \sa isValid()
65
    \sa QSslConfiguration
66
*/
67
QSslDiffieHellmanParameters::QSslDiffieHellmanParameters()
68
0
    : d(new QSslDiffieHellmanParametersPrivate)
69
0
{
70
0
    d->ref.ref();
71
0
}
72
73
/*!
74
    Constructs a QSslDiffieHellmanParameters object using
75
    the byte array \a encoded in either PEM or DER form as specified by \a encoding.
76
77
    Use the isValid() method on the returned object to
78
    check whether the Diffie-Hellman parameters were valid and
79
    loaded correctly.
80
81
    \sa isValid()
82
    \sa QSslConfiguration
83
*/
84
QSslDiffieHellmanParameters QSslDiffieHellmanParameters::fromEncoded(const QByteArray &encoded, QSsl::EncodingFormat encoding)
85
0
{
86
0
    QSslDiffieHellmanParameters result;
87
0
    const auto *tlsBackend = QSslSocketPrivate::tlsBackendInUse();
88
0
    if (!tlsBackend)
89
0
        return result;
90
0
    switch (encoding) {
91
0
    case QSsl::Der:
92
0
        result.d->initFromDer(encoded);
93
0
        break;
94
0
    case QSsl::Pem:
95
0
        result.d->initFromPem(encoded);
96
0
        break;
97
0
    }
98
0
    return result;
99
0
}
100
101
/*!
102
    Constructs a QSslDiffieHellmanParameters object by
103
    reading from \a device in either PEM or DER form as specified by \a encoding.
104
105
    Use the isValid() method on the returned object
106
    to check whether the Diffie-Hellman parameters were valid
107
    and loaded correctly.
108
109
    In particular, if \a device is \nullptr or not open for reading, an invalid
110
    object will be returned.
111
112
    \sa isValid()
113
    \sa QSslConfiguration
114
*/
115
QSslDiffieHellmanParameters QSslDiffieHellmanParameters::fromEncoded(QIODevice *device, QSsl::EncodingFormat encoding)
116
0
{
117
0
    if (device)
118
0
        return fromEncoded(device->readAll(), encoding);
119
0
    else
120
0
        return QSslDiffieHellmanParameters();
121
0
}
122
123
/*!
124
    Constructs an identical copy of \a other.
125
*/
126
QSslDiffieHellmanParameters::QSslDiffieHellmanParameters(const QSslDiffieHellmanParameters &other)
127
0
    : d(other.d)
128
0
{
129
0
    if (d)
130
0
        d->ref.ref();
131
0
}
132
133
/*!
134
    \fn QSslDiffieHellmanParameters::QSslDiffieHellmanParameters(QSslDiffieHellmanParameters &&other)
135
136
    Move-constructs from \a other.
137
138
    \note The moved-from object \a other is placed in a partially-formed state, in which
139
    the only valid operations are destruction and assignment of a new value.
140
*/
141
142
/*!
143
    Destroys the QSslDiffieHellmanParameters object.
144
*/
145
QSslDiffieHellmanParameters::~QSslDiffieHellmanParameters()
146
0
{
147
0
    if (d && !d->ref.deref())
148
0
        delete d;
149
0
}
150
151
/*!
152
    Copies the contents of \a other into this QSslDiffieHellmanParameters, making the two QSslDiffieHellmanParameters
153
    identical.
154
155
    Returns a reference to this QSslDiffieHellmanParameters.
156
*/
157
QSslDiffieHellmanParameters &QSslDiffieHellmanParameters::operator=(const QSslDiffieHellmanParameters &other)
158
0
{
159
0
    QSslDiffieHellmanParameters copy(other);
160
0
    swap(copy);
161
0
    return *this;
162
0
}
163
164
/*!
165
    \fn QSslDiffieHellmanParameters &QSslDiffieHellmanParameters::operator=(QSslDiffieHellmanParameters &&other)
166
167
    Move-assigns \a other to this QSslDiffieHellmanParameters instance.
168
169
    \note The moved-from object \a other is placed in a partially-formed state, in which
170
    the only valid operations are destruction and assignment of a new value.
171
*/
172
173
/*!
174
    \fn void QSslDiffieHellmanParameters::swap(QSslDiffieHellmanParameters &other)
175
    \memberswap{QSslDiffieHellmanParameters}
176
*/
177
178
/*!
179
    Returns \c true if this is a an empty QSslDiffieHellmanParameters instance.
180
181
    Setting an empty QSslDiffieHellmanParameters instance on a QSslSocket-based
182
    server will disable Diffie-Hellman key exchange.
183
*/
184
bool QSslDiffieHellmanParameters::isEmpty() const noexcept
185
0
{
186
0
    return d->derData.isNull() && d->error == QSslDiffieHellmanParameters::NoError;
187
0
}
188
189
/*!
190
    Returns \c true if this is a valid QSslDiffieHellmanParameters; otherwise false.
191
192
    This method should be used after constructing a QSslDiffieHellmanParameters
193
    object to determine its validity.
194
195
    If a QSslDiffieHellmanParameters object is not valid, you can use the error()
196
    method to determine what error prevented the object from being constructed.
197
198
    \sa error()
199
*/
200
bool QSslDiffieHellmanParameters::isValid() const noexcept
201
0
{
202
0
    return d->error == QSslDiffieHellmanParameters::NoError;
203
0
}
204
205
/*!
206
    \enum QSslDiffieHellmanParameters::Error
207
208
    Describes a QSslDiffieHellmanParameters error.
209
210
    \value NoError               No error occurred.
211
212
    \value InvalidInputDataError The given input data could not be used to
213
                                 construct a QSslDiffieHellmanParameters
214
                                 object.
215
216
    \value UnsafeParametersError The Diffie-Hellman parameters are unsafe
217
                                 and should not be used.
218
*/
219
220
/*!
221
    Returns the error that caused the QSslDiffieHellmanParameters object
222
    to be invalid.
223
*/
224
QSslDiffieHellmanParameters::Error QSslDiffieHellmanParameters::error() const noexcept
225
0
{
226
0
    return d->error;
227
0
}
228
229
/*!
230
    Returns a human-readable description of the error that caused the
231
    QSslDiffieHellmanParameters object to be invalid.
232
*/
233
QString QSslDiffieHellmanParameters::errorString() const noexcept
234
0
{
235
0
    switch (d->error) {
236
0
    case QSslDiffieHellmanParameters::NoError:
237
0
        return QCoreApplication::translate("QSslDiffieHellmanParameter", "No error");
238
0
    case QSslDiffieHellmanParameters::InvalidInputDataError:
239
0
        return QCoreApplication::translate("QSslDiffieHellmanParameter", "Invalid input data");
240
0
    case QSslDiffieHellmanParameters::UnsafeParametersError:
241
0
        return QCoreApplication::translate("QSslDiffieHellmanParameter", "The given Diffie-Hellman parameters are deemed unsafe");
242
0
    }
243
244
0
    Q_UNREACHABLE_RETURN(QString());
245
0
}
246
247
/*!
248
    \fn bool QSslDiffieHellmanParameters::operator==(const QSslDiffieHellmanParameters &lhs, const QSslDiffieHellmanParameters &rhs) noexcept
249
    \since 5.8
250
251
    Returns \c true if \a lhs is equal to \a rhs; otherwise returns \c false.
252
*/
253
254
/*!
255
    \fn bool QSslDiffieHellmanParameters::operator!=(const QSslDiffieHellmanParameters &lhs, const QSslDiffieHellmanParameters &rhs) noexcept
256
    \since 5.8
257
258
    Returns \c true if \a lhs is not equal to \a rhs; otherwise returns \c false.
259
*/
260
261
/*!
262
    \internal
263
*/
264
bool QSslDiffieHellmanParameters::isEqual(const QSslDiffieHellmanParameters &other) const noexcept
265
0
{
266
0
    return d->derData == other.d->derData;
267
0
}
268
269
/*!
270
    \internal
271
*/
272
void QSslDiffieHellmanParametersPrivate::initFromDer(const QByteArray &der)
273
0
{
274
0
    if (const auto *tlsBackend = QSslSocketPrivate::tlsBackendInUse())
275
0
        error = QSslDiffieHellmanParameters::Error(tlsBackend->dhParametersFromDer(der, &derData));
276
0
}
277
278
/*!
279
    \internal
280
*/
281
void QSslDiffieHellmanParametersPrivate::initFromPem(const QByteArray &pem)
282
0
{
283
0
    if (const auto *tlsBackend = QSslSocketPrivate::tlsBackendInUse())
284
0
        error = QSslDiffieHellmanParameters::Error(tlsBackend->dhParametersFromPem(pem, &derData));
285
0
}
286
287
#ifndef QT_NO_DEBUG_STREAM
288
/*!
289
    \since 5.8
290
    \relates QSslDiffieHellmanParameters
291
292
    Writes the set of Diffie-Hellman parameters in \a dhparam into the debug object \a debug for
293
    debugging purposes.
294
295
    The Diffie-Hellman parameters will be represented in Base64-encoded DER form.
296
297
    \sa {Debugging Techniques}
298
*/
299
QDebug operator<<(QDebug debug, const QSslDiffieHellmanParameters &dhparam)
300
0
{
301
0
    QDebugStateSaver saver(debug);
302
0
    debug.resetFormat().nospace();
303
0
    debug << "QSslDiffieHellmanParameters(" << dhparam.d->derData.toBase64() << ')';
304
0
    return debug;
305
0
}
306
#endif
307
308
/*!
309
    \fn size_t qHash(const QSslDiffieHellmanParameters &key, size_t seed)
310
    \since 5.8
311
    \qhashold{QSslDiffieHellmanParameters}
312
*/
313
size_t qHash(const QSslDiffieHellmanParameters &dhparam, size_t seed) noexcept
314
0
{
315
0
    return qHash(dhparam.d->derData, seed);
316
0
}
317
318
QT_END_NAMESPACE