/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 |