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

source code of qtbase/src/network/ssl/qssldiffiehellmanparameters.cpp