Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qssldiffiehellmanparameters_openssl.cpp
Go to the documentation of this file.
1// Copyright (C) 2015 Mikkel Krautz <mikkel@krautz.dk>
2// Copyright (C) 2016 Richard J. Moore <rich@kde.org>
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
7
8#include <QtNetwork/private/qsslsocket_p.h>
9
10#include <QtCore/qscopeguard.h>
11#include <QtCore/qbytearray.h>
12#include <QtCore/qiodevice.h>
13#include <QtCore/qdebug.h>
14
15#include <openssl/bn.h>
16#include <openssl/dh.h>
17
19
20#ifndef OPENSSL_NO_DEPRECATED_3_0
21
22namespace {
23
24bool isSafeDH(DH *dh)
25{
26 int status = 0;
27 int bad = 0;
28
29 // TLSTODO: check it's needed or if supportsSsl()
30 // is enough.
32
33 // From https://wiki.openssl.org/index.php/Diffie-Hellman_parameters:
34 //
35 // The additional call to BN_mod_word(dh->p, 24)
36 // (and unmasking of DH_NOT_SUITABLE_GENERATOR)
37 // is performed to ensure your program accepts
38 // IETF group parameters. OpenSSL checks the prime
39 // is congruent to 11 when g = 2; while the IETF's
40 // primes are congruent to 23 when g = 2.
41 // Without the test, the IETF parameters would
42 // fail validation. For details, see Diffie-Hellman
43 // Parameter Check (when g = 2, must p mod 24 == 11?).
44 // Mark p < 1024 bits as unsafe.
45 if (q_DH_bits(dh) < 1024)
46 return false;
47
48 if (q_DH_check(dh, &status) != 1)
49 return false;
50
51 const BIGNUM *p = nullptr;
52 const BIGNUM *q = nullptr;
53 const BIGNUM *g = nullptr;
54 q_DH_get0_pqg(dh, &p, &q, &g);
55
56 if (q_BN_is_word(const_cast<BIGNUM *>(g), DH_GENERATOR_2)) {
57 const unsigned long residue = q_BN_mod_word(p, 24);
58 if (residue == 11 || residue == 23)
59 status &= ~DH_NOT_SUITABLE_GENERATOR;
60 }
61
62 bad |= DH_CHECK_P_NOT_PRIME;
63 bad |= DH_CHECK_P_NOT_SAFE_PRIME;
64 bad |= DH_NOT_SUITABLE_GENERATOR;
65
66 return !(status & bad);
67}
68
69} // unnamed namespace
70
71#endif
72
74{
75#ifndef OPENSSL_NO_DEPRECATED_3_0
76 Q_ASSERT(derData);
77
78 if (der.isEmpty())
80
81 const unsigned char *data = reinterpret_cast<const unsigned char *>(der.data());
82 const int len = der.size();
83
84 // TLSTODO: check it's needed (loading ciphers and certs in
85 // addition to the library!)
87
88 DH *dh = q_d2i_DHparams(nullptr, &data, len);
89 if (dh) {
90 const auto dhRaii = qScopeGuard([dh] {q_DH_free(dh);});
91
92 if (isSafeDH(dh))
93 *derData = der;
94 else
96 } else {
98 }
99#else
100 Q_UNUSED(der);
101 Q_UNUSED(derData);
102 qCWarning(lcTlsBackend, "Diffie-Hellman parameters are not supported, because OpenSSL v3 was built with deprecated API removed");
103#endif
104 return DHParams::NoError;
105}
106
108{
109#ifndef OPENSSL_NO_DEPRECATED_3_0
110 Q_ASSERT(data);
111
112 if (pem.isEmpty())
114
115 // TLSTODO: check it was not a cargo-cult programming in case of
116 // DH ...
118
119 BIO *bio = q_BIO_new_mem_buf(const_cast<char *>(pem.data()), pem.size());
120 if (!bio)
122
123 const auto bioRaii = qScopeGuard([bio]
124 {
125 q_BIO_free(bio);
126 });
127
128 DH *dh = nullptr;
129 q_PEM_read_bio_DHparams(bio, &dh, nullptr, nullptr);
130
131 if (dh) {
132 const auto dhGuard = qScopeGuard([dh]
133 {
134 q_DH_free(dh);
135 });
136
137 if (isSafeDH(dh)) {
138 char *buf = nullptr;
139 const int len = q_i2d_DHparams(dh, reinterpret_cast<unsigned char **>(&buf));
140 const auto freeBuf = qScopeGuard([&] { q_OPENSSL_free(buf); });
141 if (len > 0)
142 data->assign({buf, len});
143 else
145 } else {
147 }
148 } else {
150 }
151#else
152 Q_UNUSED(pem);
153 Q_UNUSED(data);
154 qCWarning(lcTlsBackend, "Diffie-Hellman parameters are not supported, because OpenSSL v3 was built with deprecated API removed");
155#endif
156 return DHParams::NoError;
157}
158
\inmodule QtCore
Definition qbytearray.h:57
static void ensureInitialized()
int dhParametersFromDer(const QByteArray &derData, QByteArray *data) const override
int dhParametersFromPem(const QByteArray &pemData, QByteArray *data) const override
Combined button and popup list for selecting options.
#define qCWarning(category,...)
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLenum GLsizei const GLchar * buf
GLboolean GLboolean g
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLfloat GLfloat p
[1]
GLenum GLsizei len
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
Definition qscopeguard.h:60
DH * q_d2i_DHparams(DH **a, const unsigned char **pp, long length)
int q_DH_check(DH *dh, int *codes)
void q_DH_free(DH *dh)
BN_ULONG q_BN_mod_word(const BIGNUM *a, BN_ULONG w)
int q_i2d_DHparams(DH *a, unsigned char **p)
int q_DH_bits(DH *dh)
int q_BN_is_word(BIGNUM *a, BN_ULONG w)
DH * q_PEM_read_bio_DHparams(BIO *a, DH **b, pem_password_cb *c, void *d)
void q_DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
BIO * q_BIO_new_mem_buf(void *a, int b)
int q_BIO_free(BIO *a)
#define q_OPENSSL_free(addr)
#define Q_UNUSED(x)