QtBase  v6.3.1
qtlskey_openssl.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2021 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtNetwork module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
41 #include "qtlsbackend_openssl_p.h"
42 #include "qtlskey_openssl_p.h"
43 
44 #include <QtNetwork/private/qsslkey_p.h>
45 
46 #include <QtNetwork/qsslsocket.h>
47 
48 #include <QtCore/qscopeguard.h>
49 
51 
52 namespace QTlsPrivate {
53 
55  const QByteArray &passPhrase, bool deepClear)
56 {
57  if (der.isEmpty())
58  return;
59 
60  keyType = type;
62 
64  const auto pem = pemFromDer(der, headers);
65 
66  decodePem(type, algorithm, pem, passPhrase, deepClear);
67 }
68 
70  const QByteArray &passPhrase, bool deepClear)
71 {
72  if (pem.isEmpty())
73  return;
74 
75  keyType = type;
77 
78  clear(deepClear);
79 
80  BIO *bio = q_BIO_new_mem_buf(const_cast<char *>(pem.data()), pem.size());
81  if (!bio)
82  return;
83 
84  const auto bioRaii = qScopeGuard([bio]{q_BIO_free(bio);});
85 
86  void *phrase = const_cast<char *>(passPhrase.data());
87 
88 #ifdef OPENSSL_NO_DEPRECATED_3_0
89  if (type == QSsl::PublicKey)
90  genericKey = q_PEM_read_bio_PUBKEY(bio, nullptr, nullptr, phrase);
91  else
92  genericKey = q_PEM_read_bio_PrivateKey(bio, nullptr, nullptr, phrase);
94  if (keyIsNull)
96 #else
97 
98  if (algorithm == QSsl::Rsa) {
99  RSA *result = (type == QSsl::PublicKey)
100  ? q_PEM_read_bio_RSA_PUBKEY(bio, &rsa, nullptr, phrase)
101  : q_PEM_read_bio_RSAPrivateKey(bio, &rsa, nullptr, phrase);
102  if (rsa && rsa == result)
103  keyIsNull = false;
104  } else if (algorithm == QSsl::Dsa) {
105  DSA *result = (type == QSsl::PublicKey)
106  ? q_PEM_read_bio_DSA_PUBKEY(bio, &dsa, nullptr, phrase)
107  : q_PEM_read_bio_DSAPrivateKey(bio, &dsa, nullptr, phrase);
108  if (dsa && dsa == result)
109  keyIsNull = false;
110  } else if (algorithm == QSsl::Dh) {
111  EVP_PKEY *result = (type == QSsl::PublicKey)
112  ? q_PEM_read_bio_PUBKEY(bio, nullptr, nullptr, phrase)
113  : q_PEM_read_bio_PrivateKey(bio, nullptr, nullptr, phrase);
114  if (result)
116  if (dh)
117  keyIsNull = false;
119 #ifndef OPENSSL_NO_EC
120  } else if (algorithm == QSsl::Ec) {
121  EC_KEY *result = (type == QSsl::PublicKey)
122  ? q_PEM_read_bio_EC_PUBKEY(bio, &ec, nullptr, phrase)
123  : q_PEM_read_bio_ECPrivateKey(bio, &ec, nullptr, phrase);
124  if (ec && ec == result)
125  keyIsNull = false;
126 #endif // OPENSSL_NO_EC
127  }
128 
129 #endif // OPENSSL_NO_DEPRECATED_3_0
130 }
131 
133 {
136 
137  QByteArray der(pem);
138 
139  int headerIndex = der.indexOf(header);
140  int footerIndex = der.indexOf(footer, headerIndex + header.length());
141  if (type() != QSsl::PublicKey) {
142  if (headerIndex == -1 || footerIndex == -1) {
143  header = pkcs8Header(true);
144  footer = pkcs8Footer(true);
145  headerIndex = der.indexOf(header);
146  footerIndex = der.indexOf(footer, headerIndex + header.length());
147  }
148  if (headerIndex == -1 || footerIndex == -1) {
149  header = pkcs8Header(false);
150  footer = pkcs8Footer(false);
151  headerIndex = der.indexOf(header);
152  footerIndex = der.indexOf(footer, headerIndex + header.length());
153  }
154  }
155  if (headerIndex == -1 || footerIndex == -1)
156  return QByteArray();
157 
158  der = der.mid(headerIndex + header.size(), footerIndex - (headerIndex + header.size()));
159 
160  if (der.contains("Proc-Type:")) {
161  // taken from QHttpNetworkReplyPrivate::parseHeader
162  int i = 0;
163  while (i < der.count()) {
164  int j = der.indexOf(':', i); // field-name
165  if (j == -1)
166  break;
167  const QByteArray field = der.mid(i, j - i).trimmed();
168  j++;
169  // any number of LWS is allowed before and after the value
171  do {
172  i = der.indexOf('\n', j);
173  if (i == -1)
174  break;
175  if (!value.isEmpty())
176  value += ' ';
177  // check if we have CRLF or only LF
178  bool hasCR = (i && der[i-1] == '\r');
179  int length = i -(hasCR ? 1: 0) - j;
180  value += der.mid(j, length).trimmed();
181  j = ++i;
182  } while (i < der.count() && (der.at(i) == ' ' || der.at(i) == '\t'));
183  if (i == -1)
184  break; // something is wrong
185 
186  headers->insert(field, value);
187  }
188  der = der.mid(i);
189  }
190 
191  return QByteArray::fromBase64(der); // ignores newlines
192 }
193 
194 void TlsKeyOpenSSL::clear(bool deep)
195 {
196  keyIsNull = true;
197 
198 #ifndef OPENSSL_NO_DEPRECATED_3_0
199  if (algorithm() == QSsl::Rsa && rsa) {
200  if (deep)
201  q_RSA_free(rsa);
202  rsa = nullptr;
203  }
204  if (algorithm() == QSsl::Dsa && dsa) {
205  if (deep)
206  q_DSA_free(dsa);
207  dsa = nullptr;
208  }
209  if (algorithm() == QSsl::Dh && dh) {
210  if (deep)
211  q_DH_free(dh);
212  dh = nullptr;
213  }
214 #ifndef OPENSSL_NO_EC
215  if (algorithm() == QSsl::Ec && ec) {
216  if (deep)
217  q_EC_KEY_free(ec);
218  ec = nullptr;
219  }
220 #endif
221 #endif // OPENSSL_NO_DEPRECATED_3_0
222 
223  if (algorithm() == QSsl::Opaque && opaque) {
224  if (deep)
226  opaque = nullptr;
227  }
228 
229  if (genericKey) {
230  // None of the above cleared it. genericKey is either
231  // initialised by PEM read operation, or from X509, and
232  // we are the owners and not sharing. So we free it.
234  genericKey = nullptr;
235  }
236 }
237 
239 {
240  if (keyAlgorithm == QSsl::Opaque)
241  return Qt::HANDLE(opaque);
242 
243 #ifndef OPENSSL_NO_DEPRECATED_3_0
244  switch (keyAlgorithm) {
245  case QSsl::Rsa:
246  return Qt::HANDLE(rsa);
247  case QSsl::Dsa:
248  return Qt::HANDLE(dsa);
249  case QSsl::Dh:
250  return Qt::HANDLE(dh);
251 #ifndef OPENSSL_NO_EC
252  case QSsl::Ec:
253  return Qt::HANDLE(ec);
254 #endif
255  default:
256  return Qt::HANDLE(nullptr);
257  }
258 #else
259  qCWarning(lcTlsBackend,
260  "This version of OpenSSL disabled direct manipulation with RSA/DSA/DH/EC_KEY structures, consider using QSsl::Opaque instead.");
261  return Qt::HANDLE(nullptr);
262 #endif
263 }
264 
266 {
267  if (isNull() || algorithm() == QSsl::Opaque)
268  return -1;
269 
270 #ifndef OPENSSL_NO_DEPRECATED_3_0
271  switch (algorithm()) {
272  case QSsl::Rsa:
273  return q_RSA_bits(rsa);
274  case QSsl::Dsa:
275  return q_DSA_bits(dsa);
276  case QSsl::Dh:
277  return q_DH_bits(dh);
278 #ifndef OPENSSL_NO_EC
279  case QSsl::Ec:
281 #endif
282  default:
283  return -1;
284  }
285 #else // OPENSSL_NO_DEPRECATED_3_0
287  return q_EVP_PKEY_get_bits(genericKey);
288 #endif // OPENSSL_NO_DEPRECATED_3_0
289 }
290 
292 {
294  return {};
295 
296  const EVP_CIPHER *cipher = nullptr;
297  if (type() == QSsl::PrivateKey && !passPhrase.isEmpty()) {
298 #ifndef OPENSSL_NO_DES
299  cipher = q_EVP_des_ede3_cbc();
300 #else
301  return {};
302 #endif
303  }
304 
305  BIO *bio = q_BIO_new(q_BIO_s_mem());
306  if (!bio)
307  return {};
308 
309  const auto bioRaii = qScopeGuard([bio]{q_BIO_free(bio);});
310 
311 #ifndef OPENSSL_NO_DEPRECATED_3_0
312 
313 #define write_pubkey(alg, key) q_PEM_write_bio_##alg##_PUBKEY(bio, key)
314 #define write_privatekey(alg, key) \
315  q_PEM_write_bio_##alg##PrivateKey(bio, key, cipher, (uchar *)passPhrase.data(), \
316  passPhrase.size(), nullptr, nullptr)
317 
318 #else
319 
320 #define write_pubkey(alg, key) q_PEM_write_bio_PUBKEY(bio, genericKey)
321 #define write_privatekey(alg, key) \
322  q_PEM_write_bio_PrivateKey_traditional(bio, genericKey, cipher, (uchar *)passPhrase.data(), passPhrase.size(), nullptr, nullptr)
323 
324 #endif // OPENSSL_NO_DEPRECATED_3_0
325 
326  bool fail = false;
327  if (algorithm() == QSsl::Rsa) {
328  if (type() == QSsl::PublicKey) {
329  if (!write_pubkey(RSA, rsa))
330  fail = true;
331  } else if (!write_privatekey(RSA, rsa)) {
332  fail = true;
333  }
334  } else if (algorithm() == QSsl::Dsa) {
335  if (type() == QSsl::PublicKey) {
336  if (!write_pubkey(DSA, dsa))
337  fail = true;
338  } else if (!write_privatekey(DSA, dsa)) {
339  fail = true;
340  }
341  } else if (algorithm() == QSsl::Dh) {
342 #ifdef OPENSSL_NO_DEPRECATED_3_0
343  EVP_PKEY *result = genericKey;
344 #else
345  EVP_PKEY *result = q_EVP_PKEY_new();
346  const auto guard = qScopeGuard([result]{if (result) q_EVP_PKEY_free(result);});
347  if (!result || !q_EVP_PKEY_set1_DH(result, dh)) {
348  fail = true;
349  } else
350 #endif
351  if (type() == QSsl::PublicKey) {
352  if (!q_PEM_write_bio_PUBKEY(bio, result))
353  fail = true;
354  } else if (!q_PEM_write_bio_PrivateKey(bio, result, cipher, (uchar *)passPhrase.data(),
355  passPhrase.size(), nullptr, nullptr)) {
356  fail = true;
357  }
358 #ifndef OPENSSL_NO_EC
359  } else if (algorithm() == QSsl::Ec) {
360  if (type() == QSsl::PublicKey) {
361  if (!write_pubkey(EC, ec))
362  fail = true;
363  } else {
364  if (!write_privatekey(EC, ec))
365  fail = true;
366  }
367 #endif
368  } else {
369  fail = true;
370  }
371 
372  QByteArray pem;
373  if (!fail) {
374  char *data = nullptr;
375  const long size = q_BIO_get_mem_data(bio, &data);
376  if (size > 0 && data)
377  pem = QByteArray(data, size);
378  } else {
380  }
381 
382  return pem;
383 }
384 
386 {
387  EVP_PKEY *evpKey = reinterpret_cast<EVP_PKEY *>(handle);
388  if (!evpKey || !fromEVP_PKEY(evpKey)) {
389  opaque = evpKey;
391  } else {
392  q_EVP_PKEY_free(evpKey);
393  }
394 
395  keyType = expectedType;
396  keyIsNull = !opaque;
397 }
398 
399 bool TlsKeyOpenSSL::fromEVP_PKEY(EVP_PKEY *pkey)
400 {
401  if (!pkey)
402  return false;
403 
404 #ifndef OPENSSL_NO_DEPRECATED_3_0
405 #define get_key(key, alg) key = q_EVP_PKEY_get1_##alg(pkey)
406 #else
407 #define get_key(key, alg) q_EVP_PKEY_up_ref(pkey); genericKey = pkey;
408 #endif
409 
410  switch (q_EVP_PKEY_type(q_EVP_PKEY_base_id(pkey))) {
411  case EVP_PKEY_RSA:
412  keyIsNull = false;
415  get_key(rsa, RSA);
416  return true;
417  case EVP_PKEY_DSA:
418  keyIsNull = false;
421  get_key(dsa, DSA);
422  return true;
423  case EVP_PKEY_DH:
424  keyIsNull = false;
427  get_key(dh, DH);
428  return true;
429 #ifndef OPENSSL_NO_EC
430  case EVP_PKEY_EC:
431  keyIsNull = false;
434  get_key(ec, EC_KEY);
435  return true;
436 #endif
437  default:;
438  // Unknown key type. This could be handled as opaque, but then
439  // we'd eventually leak memory since we wouldn't be able to free
440  // the underlying EVP_PKEY structure. For now, we won't support
441  // this.
442  }
443 
444  return false;
445 }
446 
448  const QByteArray &key, const QByteArray &iv, bool enc)
449 {
450  const EVP_CIPHER *type = nullptr;
451  int i = 0, len = 0;
452 
453  switch (cipher) {
454  case Cipher::DesCbc:
455 #ifndef OPENSSL_NO_DES
456  type = q_EVP_des_cbc();
457 #endif
458  break;
459  case Cipher::DesEde3Cbc:
460 #ifndef OPENSSL_NO_DES
462 #endif
463  break;
464  case Cipher::Rc2Cbc:
465 #ifndef OPENSSL_NO_RC2
466  type = q_EVP_rc2_cbc();
467 #endif
468  break;
469  case Cipher::Aes128Cbc:
471  break;
472  case Cipher::Aes192Cbc:
474  break;
475  case Cipher::Aes256Cbc:
477  break;
478  }
479 
480  if (type == nullptr)
481  return {};
482 
483  QByteArray output;
484  output.resize(data.size() + EVP_MAX_BLOCK_LENGTH);
485 
486  EVP_CIPHER_CTX *ctx = q_EVP_CIPHER_CTX_new();
488  if (q_EVP_CipherInit(ctx, type, nullptr, nullptr, enc) != 1) {
491  return {};
492  }
493 
495  if (cipher == Cipher::Rc2Cbc)
496  q_EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC2_KEY_BITS, 8 * key.size(), nullptr);
497 
498  q_EVP_CipherInit_ex(ctx, nullptr, nullptr,
499  reinterpret_cast<const unsigned char *>(key.constData()),
500  reinterpret_cast<const unsigned char *>(iv.constData()),
501  enc);
502  q_EVP_CipherUpdate(ctx,
503  reinterpret_cast<unsigned char *>(output.data()), &len,
504  reinterpret_cast<const unsigned char *>(data.constData()), data.size());
505  q_EVP_CipherFinal(ctx,
506  reinterpret_cast<unsigned char *>(output.data()) + len, &i);
507  len += i;
508 
511 
512  return output.left(len);
513 }
514 
516  const QByteArray &key, const QByteArray &iv) const
517 {
518  return doCrypt(cipher, data, key, iv, false);
519 }
520 
522  const QByteArray &key, const QByteArray &iv) const
523 {
524  return doCrypt(cipher, data, key, iv, true);
525 }
526 
528 {
529  TlsKeyOpenSSL *tlsKey = new TlsKeyOpenSSL;
530  std::unique_ptr<TlsKeyOpenSSL> keyRaii(tlsKey);
531 
532  tlsKey->keyType = QSsl::PublicKey;
533 
534 #ifndef OPENSSL_NO_DEPRECATED_3_0
535 
536 #define get_pubkey(keyName, alg) tlsKey->keyName = q_EVP_PKEY_get1_##alg(pkey)
537 
538 #else
539 
540 #define get_pubkey(a, b) tlsKey->genericKey = pkey
541 
542 #endif
543 
544  EVP_PKEY *pkey = q_X509_get_pubkey(x);
545  Q_ASSERT(pkey);
546  const int keyType = q_EVP_PKEY_type(q_EVP_PKEY_base_id(pkey));
547 
548  if (keyType == EVP_PKEY_RSA) {
549  get_pubkey(rsa, RSA);
550  tlsKey->keyAlgorithm = QSsl::Rsa;
551  tlsKey->keyIsNull = false;
552  } else if (keyType == EVP_PKEY_DSA) {
553  get_pubkey(dsa, DSA);
554  tlsKey->keyAlgorithm = QSsl::Dsa;
555  tlsKey->keyIsNull = false;
556 #ifndef OPENSSL_NO_EC
557  } else if (keyType == EVP_PKEY_EC) {
558  get_pubkey(ec, EC_KEY);
559  tlsKey->keyAlgorithm = QSsl::Ec;
560  tlsKey->keyIsNull = false;
561 #endif
562  } else if (keyType == EVP_PKEY_DH) {
563  // DH unsupported (key is null)
564  } else {
565  // error? (key is null)
566  }
567 
568 #ifndef OPENSSL_NO_DEPRECATED_3_0
569  q_EVP_PKEY_free(pkey);
570 #endif
571 
572  return keyRaii.release();
573 }
574 
575 } // namespace QTlsPrivate
576 
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
#define value
[5]
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:85
QByteArray trimmed() const &
Definition: qbytearray.h:220
char * data()
Definition: qbytearray.h:516
qsizetype size() const noexcept
Definition: qbytearray.h:470
const char * constData() const noexcept
Definition: qbytearray.h:144
qsizetype indexOf(char c, qsizetype from=0) const
static QByteArray fromBase64(const QByteArray &base64, Base64Options options=Base64Encoding)
char at(qsizetype i) const
Definition: qbytearray.h:505
bool contains(char c) const
Definition: qbytearray.h:565
bool isEmpty() const noexcept
Definition: qbytearray.h:129
QByteArray left(qsizetype len) const
void resize(qsizetype size)
qsizetype count(char c) const
QByteArray mid(qsizetype index, qsizetype len=-1) const
iterator insert(const Key &key, const T &value)
Definition: qmap.h:719
static bool supportsSsl()
static void logAndClearErrorQueue()
KeyType type() const override
QByteArray pemFromDer(const QByteArray &der, const QMap< QByteArray, QByteArray > &headers) const override
KeyAlgorithm algorithm() const override
static QByteArray pkcs8Footer(bool encrypted)
static QByteArray pkcs8Header(bool encrypted)
bool isNull() const override
QByteArray pemHeader() const
QByteArray pemFooter() const
void decodePem(KeyType type, KeyAlgorithm algorithm, const QByteArray &pem, const QByteArray &passPhrase, bool deepClear) override
void fromHandle(Qt::HANDLE opaque, KeyType expectedType) override
void clear(bool deep) override
bool fromEVP_PKEY(EVP_PKEY *pkey)
QByteArray derFromPem(const QByteArray &pem, QMap< QByteArray, QByteArray > *headers) const override
void decodeDer(KeyType type, KeyAlgorithm algorithm, const QByteArray &der, const QByteArray &passPhrase, bool deepClear) override
QByteArray decrypt(Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv) const override
QByteArray toPem(const QByteArray &passPhrase) const override
int length() const override
Qt::HANDLE handle() const override
QByteArray encrypt(Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv) const override
static TlsKeyOpenSSL * publicKeyFromX509(X509 *x)
KeyType
Definition: qssl.h:51
@ PublicKey
Definition: qssl.h:53
@ PrivateKey
Definition: qssl.h:52
KeyAlgorithm
Definition: qssl.h:61
@ Rsa
Definition: qssl.h:63
@ Ec
Definition: qssl.h:65
@ Opaque
Definition: qssl.h:62
@ Dsa
Definition: qssl.h:64
@ Dh
Definition: qssl.h:66
QByteArray doCrypt(QSslKeyPrivate::Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv, bool enc)
void * HANDLE
Definition: qnamespace.h:1561
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLOutputLayerEXT EGLint EGLAttrib value
QT_BEGIN_INCLUDE_NAMESPACE typedef unsigned char uchar
Definition: qglobal.h:332
#define qCWarning(category,...)
GLenum GLuint GLenum GLsizei length
Definition: qopengl.h:270
GLenum type
Definition: qopengl.h:270
GLuint64 GLenum void * handle
GLint GLint GLint GLint GLint x
[0]
GLuint64 key
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLsizei len
Definition: qopenglext.h:3292
GLuint64EXT * result
[6]
Definition: qopenglext.h:10932
#define Q_ASSERT(cond)
Definition: qrandom.cpp:84
QScopeGuard< typename std::decay< F >::type > qScopeGuard(F &&f)
[qScopeGuard]
Definition: qscopeguard.h:93
int q_EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *c)
const EVP_CIPHER * q_EVP_aes_128_cbc()
const EVP_CIPHER * q_EVP_des_cbc()
DH * q_EVP_PKEY_get1_DH(EVP_PKEY *a)
EC_KEY * q_PEM_read_bio_EC_PUBKEY(BIO *a, EC_KEY **b, pem_password_cb *c, void *d)
int q_EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, const unsigned char *key, const unsigned char *iv, int enc)
EVP_PKEY * q_PEM_read_bio_PrivateKey(BIO *a, EVP_PKEY **b, pem_password_cb *c, void *d)
int q_EVP_PKEY_base_id(EVP_PKEY *a)
const EVP_CIPHER * q_EVP_rc2_cbc()
EC_KEY * q_PEM_read_bio_ECPrivateKey(BIO *a, EC_KEY **b, pem_password_cb *c, void *d)
void q_DH_free(DH *dh)
const EVP_CIPHER * q_EVP_des_ede3_cbc()
int q_EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl)
DSA * q_PEM_read_bio_DSA_PUBKEY(BIO *a, DSA **b, pem_password_cb *c, void *d)
void q_DSA_free(DSA *a)
int q_DSA_bits(DSA *a)
#define q_BIO_get_mem_data(b, pp)
void q_EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *a)
int q_EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen)
int q_DH_bits(DH *dh)
RSA * q_PEM_read_bio_RSA_PUBKEY(BIO *a, RSA **b, pem_password_cb *c, void *d)
EVP_CIPHER_CTX * q_EVP_CIPHER_CTX_new()
void q_EVP_PKEY_free(EVP_PKEY *a)
DSA * q_PEM_read_bio_DSAPrivateKey(BIO *a, DSA **b, pem_password_cb *c, void *d)
void q_EC_KEY_free(EC_KEY *ecdh)
EVP_PKEY * q_X509_get_pubkey(X509 *a)
int q_EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
int q_EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *impl, const unsigned char *key, const unsigned char *iv, int enc)
int q_PEM_write_bio_PUBKEY(BIO *a, EVP_PKEY *b)
int q_EVP_PKEY_set1_DH(EVP_PKEY *a, DH *b)
const EC_GROUP * q_EC_KEY_get0_group(const EC_KEY *k)
int q_EC_GROUP_get_degree(const EC_GROUP *g)
int q_RSA_bits(RSA *a)
RSA * q_PEM_read_bio_RSAPrivateKey(BIO *a, RSA **b, pem_password_cb *c, void *d)
EVP_PKEY * q_EVP_PKEY_new()
int q_PEM_write_bio_PrivateKey(BIO *a, EVP_PKEY *b, const EVP_CIPHER *c, unsigned char *d, int e, pem_password_cb *f, void *g)
const EVP_CIPHER * q_EVP_aes_256_cbc()
EVP_PKEY * q_PEM_read_bio_PUBKEY(BIO *a, EVP_PKEY **b, pem_password_cb *c, void *d)
BIO * q_BIO_new(const BIO_METHOD *a)
int q_EVP_PKEY_type(int a)
const EVP_CIPHER * q_EVP_aes_192_cbc()
int q_BIO_free(BIO *a)
const BIO_METHOD * q_BIO_s_mem()
int q_EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
void q_RSA_free(RSA *a)
BIO * q_BIO_new_mem_buf(void *a, int b)
#define write_pubkey(alg, key)
#define write_privatekey(alg, key)
#define get_key(key, alg)
#define get_pubkey(keyName, alg)
QHttpRequestHeader header("GET", QUrl::toPercentEncoding("/index.html"))
[1]