11#include <QtNetwork/private/qsslcertificate_p.h>
13#include <QtNetwork/qsslsocket.h>
14#include <QtNetwork/qhostaddress.h>
16#include <QtCore/qendian.h>
17#include <QtCore/qdatetime.h>
18#include <QtCore/qhash.h>
19#include <QtCore/qiodevice.h>
20#include <QtCore/qscopeguard.h>
21#include <QtCore/qtimezone.h>
22#include <QtCore/qvarlengtharray.h>
26using namespace Qt::StringLiterals;
32QByteArray asn1ObjectId(
const ASN1_OBJECT *object)
40 return QByteArray(buf);
43QByteArray asn1ObjectName(
const ASN1_OBJECT *object)
52 return asn1ObjectId(object);
55QMultiMap<QByteArray, QString> mapFromX509Name(
const X509_NAME *name)
60 QMultiMap<QByteArray, QString> info;
64 QByteArray name = asn1ObjectName(q_X509_NAME_ENTRY_get_object(e));
65 unsigned char *data =
nullptr;
67 info.insert(name, QString::fromUtf8((
char*)data, size));
74QDateTime dateTimeFromASN1(
const ASN1_TIME *aTime)
80 QDate resDate(lTime.tm_year + 1900, lTime.tm_mon + 1, lTime.tm_mday);
81 QTime resTime(lTime.tm_hour, lTime.tm_min, lTime.tm_sec);
82 result = QDateTime(resDate, resTime, QTimeZone::UTC);
89#define BEGINCERTSTRING "-----BEGIN CERTIFICATE-----"
90#define ENDCERTSTRING "-----END CERTIFICATE-----"
92QByteArray x509ToQByteArray(X509 *x509, QSsl::EncodingFormat format)
104 array.resize(length);
106 char *data = array.data();
107 char **dataP = &data;
108 unsigned char **dataPu = (
unsigned char **)dataP;
112 if (format == QSsl::Der)
116 array = array.toBase64();
118 for (
int i = 0; i <= array.size() - 64; i += 64) {
119 tmp += QByteArray::fromRawData(array.data() + i, 64);
122 if (
int remainder = array.size() % 64) {
123 tmp += QByteArray::fromRawData(array.data() + array.size() - remainder, remainder);
130QString x509ToText(X509 *x509)
138 const auto bioRaii = qScopeGuard([bio]{
q_BIO_free(bio
);});
142 QVarLengthArray<
char, 16384> data;
143 int count = q_BIO_read(bio, data.data(), 16384);
145 result = QByteArray( data.data(), count );
147 return QString::fromLatin1(result);
171 const auto extCleaner = qScopeGuard([meth, ext_internal]{
172 Q_ASSERT(ext_internal && meth);
176 else if (meth->ext_free)
177 meth->ext_free(ext_internal);
179 qCWarning(lcTlsBackend,
"No method to free an unknown extension, a potential memory leak?");
184 STACK_OF(CONF_VALUE) *val = meth->i2v(meth, ext_internal,
nullptr);
185 const auto stackCleaner = qScopeGuard([val]{
196 if (nval->name && nval->value) {
198 map[QString::fromUtf8(nval->name)] = QString::fromUtf8(nval->value);
199 }
else if (nval->name) {
200 list << QString::fromUtf8(nval->name);
201 }
else if (nval->value) {
202 list << QString::fromUtf8(nval->value);
210 }
else if (meth->i2s) {
211 const char *hexString = meth->i2s(meth, ext_internal);
212 QVariant result(hexString ? QString::fromUtf8(hexString) : QString{});
215 }
else if (meth->i2r) {
222 meth->i2r(meth, ext_internal, bio, 0);
226 result = QByteArray(bio_buffer, bio_size);
236
237
238
239
250 void *ext_internal =
nullptr;
251 const auto extCleaner = qScopeGuard([meth, &ext_internal]() {
252 if (!meth || !ext_internal)
257 else if (meth->ext_free)
258 meth->ext_free(ext_internal);
260 qCWarning(lcTlsBackend,
"Cannot free an extension, a potential memory leak?");
263 const char * hexString =
nullptr;
264 const auto hexStringCleaner = qScopeGuard([&hexString](){
270 case NID_basic_constraints:
272 BASIC_CONSTRAINTS *basic =
reinterpret_cast<BASIC_CONSTRAINTS *>(
q_X509V3_EXT_d2i(ext
));
276 result[
"ca"_L1] = basic->ca ?
true :
false;
278 result[
"pathLenConstraint"_L1] = (qlonglong)q_ASN1_INTEGER_get(basic->pathlen);
284 case NID_info_access:
286 AUTHORITY_INFO_ACCESS *info =
reinterpret_cast<AUTHORITY_INFO_ACCESS *>(
q_X509V3_EXT_d2i(ext
));
291 ACCESS_DESCRIPTION *ad =
q_SKM_sk_value(ACCESS_DESCRIPTION, info, i);
293 GENERAL_NAME *name = ad->location;
294 if (name->type == GEN_URI) {
296 if (len < 0 || len >= 8192) {
302 const QString uri = QString::fromUtf8(uriStr, len);
304 result[QString::fromUtf8(asn1ObjectName(ad->method))] = uri;
306 qCWarning(lcTlsBackend) <<
"Strange location type" << name->type;
314 case NID_subject_key_identifier:
320 hexString = meth->i2s(meth, ext_internal);
321 return QVariant(QString::fromUtf8(hexString));
324 case NID_authority_key_identifier:
326 AUTHORITY_KEYID *auth_key =
reinterpret_cast<AUTHORITY_KEYID *>(
q_X509V3_EXT_d2i(ext
));
332 if (auth_key->keyid) {
335 QByteArray keyid(
reinterpret_cast<
const char *>(data), length);
336 result[
"keyid"_L1] = keyid.toHex();
343 if (auth_key->serial)
344 result[
"serial"_L1] = (qlonglong)q_ASN1_INTEGER_get(auth_key->serial);
361 using ErrorListPtr = QList<QSslErrorEntry> *;
362 ErrorListPtr errors =
nullptr;
387 qCWarning(lcTlsBackend,
"Neither X509_STORE, nor SSL contains error list, verification failed");
407bool X509CertificateOpenSSL::
isEqual(
const X509Certificate &rhs)
const
410 const auto &other =
static_cast<
const X509CertificateOpenSSL &>(rhs);
411 if (x509 && other.x509) {
412 const int ret = q_X509_cmp(x509, other.x509);
413 if (ret >= -1 && ret <= 1)
432 QMultiMap<QSsl::AlternativeNameEntryType, QString> result;
437 auto *altNames =
static_cast<STACK_OF(GENERAL_NAME) *>(
q_X509_get_ext_d2i(x509
, NID_subject_alt_name
,
442 auto altName = [](ASN1_IA5STRING *ia5,
int len) {
444 return QString::fromLatin1(altNameStr, len);
449 if (genName->type != GEN_DNS && genName->type != GEN_EMAIL && genName->type != GEN_IPADD)
453 if (len < 0 || len >= 8192) {
458 switch (genName->type) {
460 result.insert(QSsl::DnsEntry, altName(genName->d.ia5, len));
463 result.insert(QSsl::EmailEntry, altName(genName->d.ia5, len));
466 QHostAddress ipAddress;
469 ipAddress = QHostAddress(qFromBigEndian(*
reinterpret_cast<
const quint32 *>(
q_ASN1_STRING_get0_data(genName->d.iPAddress
))));
477 if (!ipAddress.isNull())
478 result.insert(QSsl::IpAddressEntry, ipAddress.toString());
504 return x509ToQByteArray(x509, QSsl::Pem);
512 return x509ToQByteArray(x509, QSsl::Der);
520 return x509ToText(x509);
525 return Qt::HANDLE(x509);
528size_t X509CertificateOpenSSL::
hash(size_t seed)
const noexcept
532 unsigned int len = 0;
533 unsigned char md[EVP_MAX_MD_SIZE];
535 return qHashBits(md, len, seed);
541QSslCertificate X509CertificateOpenSSL::certificateFromX509(X509 *x509)
543 QSslCertificate certificate;
545 auto *backend = QTlsBackend::backend<X509CertificateOpenSSL>(certificate);
546 if (!backend || !x509)
551 backend->notValidBefore = dateTimeFromASN1(nbef);
555 backend->notValidAfter = dateTimeFromASN1(naft);
557 backend->null =
false;
560 backend->issuerInfoEntries = mapFromX509Name(q_X509_get_issuer_name(x509));
561 backend->subjectInfoEntries = mapFromX509Name(q_X509_get_subject_name(x509));
562 backend->versionString = QByteArray::number(qlonglong(q_X509_get_version(x509)) + 1);
565 QByteArray hexString;
568 hexString.reserve(qsizetype(serialNumberLength) * 3);
569 for (
int a = 0; a < serialNumberLength; ++a) {
570 hexString += QByteArray::number(serialNumberData[a], 16).rightJustified(2,
'0');
574 backend->serialNumberString = hexString;
577 backend->parseExtensions();
582QList<QSslCertificate> X509CertificateOpenSSL::stackOfX509ToQSslCertificates(STACK_OF(X509) *x509)
587 QList<QSslCertificate> certificates;
590 certificates << certificateFromX509(entry);
603QList<QSslError> X509CertificateOpenSSL::verify(
const QList<QSslCertificate> &chain,
604 const QString &hostName)
607 auto roots = QSslConfiguration::defaultConfiguration().caCertificates();
613 if (QSslSocketPrivate::rootCertOnDemandLoadingSupported())
614 roots.append(QSslSocketPrivate::systemCaCertificates());
616 return verify(roots, chain, hostName);
619QList<QSslError> X509CertificateOpenSSL::verify(
const QList<QSslCertificate> &caCertificates,
620 const QList<QSslCertificate> &certificateChain,
621 const QString &hostName)
624 if (certificateChain.size() <= 0)
625 return {QSslError(QSslError::UnspecifiedError)};
627 QList<QSslError> errors;
630 qCWarning(lcTlsBackend) <<
"Unable to create certificate store";
631 errors << QSslError(QSslError::UnspecifiedError);
634 const std::unique_ptr<X509_STORE,
decltype(&q_X509_STORE_free)> storeGuard(certStore,
q_X509_STORE_free);
636 const QDateTime now = QDateTime::currentDateTimeUtc();
637 for (
const QSslCertificate &caCertificate : caCertificates) {
649 if (caCertificate.expiryDate() >= now) {
650 q_X509_STORE_add_cert(certStore,
reinterpret_cast<X509 *>(caCertificate.handle()));
654 QList<QSslErrorEntry> lastErrors;
655 if (!q_X509_STORE_set_ex_data(certStore, 0, &lastErrors)) {
656 qCWarning(lcTlsBackend) <<
"Unable to attach external data (error list) to a store";
657 errors << QSslError(QSslError::UnspecifiedError);
665 STACK_OF(X509) *intermediates =
nullptr;
666 if (certificateChain.size() > 1) {
669 if (!intermediates) {
670 errors << QSslError(QSslError::UnspecifiedError);
675 for (
const QSslCertificate &cert : certificateChain) {
681 q_OPENSSL_sk_push((OPENSSL_STACK *)intermediates,
reinterpret_cast<X509 *>(cert.handle()));
687 errors << QSslError(QSslError::UnspecifiedError);
690 std::unique_ptr<X509_STORE_CTX,
decltype(&q_X509_STORE_CTX_free)> ctxGuard(storeContext, q_X509_STORE_CTX_free);
693 errors << QSslError(QSslError::UnspecifiedError);
706 if (certificateChain[0].isBlacklisted())
707 errors << QSslError(QSslError::CertificateBlacklisted, certificateChain[0]);
710 if (!hostName.isEmpty() && !TlsCryptograph::isMatchingHostname(certificateChain[0], hostName)) {
712 QSslError error(QSslError::HostNameMismatch, certificateChain[0]);
717 errors.reserve(errors.size() + lastErrors.size());
718 for (
const auto &error : std::as_const(lastErrors))
719 errors << openSSLErrorToQSslError(error.code, certificateChain.value(error.depth));
724QList<QSslCertificate> X509CertificateOpenSSL::certificatesFromPem(
const QByteArray &pem,
int count)
726 QList<QSslCertificate> certificates;
729 while (count == -1 || certificates.size() < count) {
734 if (!matchLineFeed(pem, &startPos))
742 if (offset < pem.size() && !matchLineFeed(pem, &offset))
745 QByteArray decoded = QByteArray::fromBase64(
746 QByteArray::fromRawData(pem.data() + startPos, endPos - startPos));
747 const unsigned char *data = (
const unsigned char *)decoded.data();
749 if (X509 *x509 = q_d2i_X509(
nullptr, &data, decoded.size())) {
750 certificates << certificateFromX509(x509);
758QList<QSslCertificate> X509CertificateOpenSSL::certificatesFromDer(
const QByteArray &der,
int count)
760 QList<QSslCertificate> certificates;
762 const unsigned char *data = (
const unsigned char *)der.data();
763 int size = der.size();
765 while (size > 0 && (count == -1 || certificates.size() < count)) {
767 certificates << certificateFromX509(x509);
772 size -= ((
const char *)data - der.data());
778bool X509CertificateOpenSSL::importPkcs12(QIODevice *device, QSslKey *key, QSslCertificate *cert,
779 QList<QSslCertificate> *caCertificates,
780 const QByteArray &passPhrase)
788 QByteArray pkcs12data = device->readAll();
789 if (pkcs12data.size() == 0)
792 BIO *bio = q_BIO_new_mem_buf(
const_cast<
char *>(pkcs12data.constData()), pkcs12data.size());
794 qCWarning(lcTlsBackend,
"BIO_new_mem_buf returned null");
797 const auto bioRaii = qScopeGuard([bio]{
q_BIO_free(bio
);});
802 qCWarning(lcTlsBackend,
"Unable to read PKCS#12 structure, %s",
809 EVP_PKEY *pkey =
nullptr;
810 X509 *x509 =
nullptr;
811 STACK_OF(X509) *ca =
nullptr;
813 if (!q_PKCS12_parse(p12, passPhrase.constData(), &pkey, &x509, &ca)) {
814 qCWarning(lcTlsBackend,
"Unable to parse PKCS#12 structure, %s",
819 const auto x509Raii = qScopeGuard([x509]{
q_X509_free(x509
);});
821 const auto caRaii = qScopeGuard([ca] {
827 auto *tlsKey = QTlsBackend::backend<TlsKeyOpenSSL>(*key);
828 if (!tlsKey || !tlsKey->fromEVP_PKEY(pkey)) {
829 qCWarning(lcTlsBackend,
"Unable to convert private key");
833 *cert = certificateFromX509(x509);
836 *caCertificates = stackOfX509ToQSslCertificates(ca);
841QSslError X509CertificateOpenSSL::openSSLErrorToQSslError(
int errorCode,
const QSslCertificate &cert)
848 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
849 error = QSslError(QSslError::UnableToGetIssuerCertificate, cert);
break;
850 case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
851 error = QSslError(QSslError::UnableToDecryptCertificateSignature, cert);
break;
852 case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
853 error = QSslError(QSslError::UnableToDecodeIssuerPublicKey, cert);
break;
854 case X509_V_ERR_CERT_SIGNATURE_FAILURE:
855 error = QSslError(QSslError::CertificateSignatureFailed, cert);
break;
856 case X509_V_ERR_CERT_NOT_YET_VALID:
857 error = QSslError(QSslError::CertificateNotYetValid, cert);
break;
858 case X509_V_ERR_CERT_HAS_EXPIRED:
859 error = QSslError(QSslError::CertificateExpired, cert);
break;
860 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
861 error = QSslError(QSslError::InvalidNotBeforeField, cert);
break;
862 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
863 error = QSslError(QSslError::InvalidNotAfterField, cert);
break;
864 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
865 error = QSslError(QSslError::SelfSignedCertificate, cert);
break;
866 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
867 error = QSslError(QSslError::SelfSignedCertificateInChain, cert);
break;
868 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
869 error = QSslError(QSslError::UnableToGetLocalIssuerCertificate, cert);
break;
870 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
871 error = QSslError(QSslError::UnableToVerifyFirstCertificate, cert);
break;
872 case X509_V_ERR_CERT_REVOKED:
873 error = QSslError(QSslError::CertificateRevoked, cert);
break;
874 case X509_V_ERR_INVALID_CA:
875 error = QSslError(QSslError::InvalidCaCertificate, cert);
break;
876 case X509_V_ERR_PATH_LENGTH_EXCEEDED:
877 error = QSslError(QSslError::PathLengthExceeded, cert);
break;
878 case X509_V_ERR_INVALID_PURPOSE:
879 error = QSslError(QSslError::InvalidPurpose, cert);
break;
880 case X509_V_ERR_CERT_UNTRUSTED:
881 error = QSslError(QSslError::CertificateUntrusted, cert);
break;
882 case X509_V_ERR_CERT_REJECTED:
883 error = QSslError(QSslError::CertificateRejected, cert);
break;
885 error = QSslError(QSslError::UnspecifiedError, cert);
break;
890void X509CertificateOpenSSL::parseExtensions()
901 extensions.reserve(count);
903 for (
int i = 0; i < count; i++) {
906 qCWarning(lcTlsBackend) <<
"Invalid (nullptr) extension at index" << i;
910 extensions << convertExtension(ext);
927 result.oid = QString::fromUtf8(asn1ObjectId(obj));
928 result.name = QString::fromUtf8(asn1ObjectName(obj));
933 QVariant extensionValue = x509ExtensionToValue(ext);
934 if (extensionValue.isValid()) {
935 result.value = extensionValue;
940 extensionValue = x509UnknownExtensionToValue(ext);
941 if (extensionValue.isValid())
942 result.value = extensionValue;
static void logAndClearErrorQueue()
static void clearErrorQueue()
static int s_indexForSSLExtraData
static TlsKeyOpenSSL * publicKeyFromX509(X509 *x)
static QSslErrorEntry errorEntryFromStoreContext(X509_STORE_CTX *ctx)
QByteArray toPem() const override
QByteArray toDer() const override
QString toText() const override
bool isSelfSigned() const override
TlsKey * publicKey() const override
size_t hash(size_t seed) const noexcept override
~X509CertificateOpenSSL()
bool isEqual(const X509Certificate &rhs) const override
Qt::HANDLE handle() const override
QMultiMap< QSsl::AlternativeNameEntryType, QString > subjectAlternativeNames() const override
Combined button and popup list for selecting options.
Namespace containing onternal types that TLS backends implement.
int qt_X509Callback(int ok, X509_STORE_CTX *ctx)
#define QT_OPENSSL4_CONST
X509_STORE_CTX * q_X509_STORE_CTX_new()
int q_OBJ_obj2nid(const ASN1_OBJECT *a)
void * q_X509_STORE_get_ex_data(X509_STORE *r, int idx)
OPENSSL_STACK * q_OPENSSL_sk_new_null()
int q_SSL_get_ex_data_X509_STORE_CTX_idx()
QT_OPENSSL4_CONST ASN1_OBJECT * q_X509_EXTENSION_get_object(QT_OPENSSL4_CONST X509_EXTENSION *a)
const char * q_OBJ_nid2sn(int a)
int q_X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, STACK_OF(X509) *chain)
void q_BASIC_CONSTRAINTS_free(BASIC_CONSTRAINTS *a)
QT_OPENSSL4_CONST X509_EXTENSION * q_X509_get_ext(X509 *a, int b)
int q_ASN1_STRING_to_UTF8(unsigned char **a, const ASN1_STRING *b)
unsigned long q_ERR_get_error()
int q_X509_digest(const X509 *x509, const EVP_MD *type, unsigned char *md, unsigned int *len)
#define q_sk_GENERAL_NAME_value(st, i)
QT_OPENSSL4_CONST ASN1_STRING * q_X509_NAME_ENTRY_get_data(const X509_NAME_ENTRY *a)
const unsigned char * q_ASN1_STRING_get0_data(const ASN1_STRING *x)
const X509V3_EXT_METHOD * q_X509V3_EXT_get(QT_OPENSSL4_CONST X509_EXTENSION *a)
#define q_sk_X509_num(st)
void * q_X509V3_EXT_d2i(QT_OPENSSL4_CONST X509_EXTENSION *a)
const EVP_MD * q_EVP_sha1()
X509 * q_X509_dup(X509 *a)
PKCS12 * q_d2i_PKCS12_bio(BIO *bio, PKCS12 **pkcs12)
#define q_BIO_get_mem_data(b, pp)
QT_OPENSSL4_CONST X509_NAME_ENTRY * q_X509_NAME_get_entry(const X509_NAME *a, int b)
void * q_X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx)
void q_X509_STORE_set_verify_cb(X509_STORE *ctx, X509_STORE_CTX_verify_cb verify_cb)
int q_ASN1_STRING_length(const ASN1_STRING *a)
void q_X509V3_conf_free(CONF_VALUE *val)
void q_OPENSSL_sk_free(OPENSSL_STACK *a)
void q_CRYPTO_free(void *str, const char *file, int line)
void q_EVP_PKEY_free(EVP_PKEY *a)
void q_AUTHORITY_KEYID_free(AUTHORITY_KEYID *a)
void q_X509_STORE_free(X509_STORE *store)
BIO * q_BIO_new(const BIO_METHOD *a)
int q_i2d_X509(X509 *a, unsigned char **b)
ASN1_TIME * q_X509_getm_notAfter(X509 *a)
X509_STORE * q_X509_STORE_new()
void q_PKCS12_free(PKCS12 *pkcs12)
void q_OPENSSL_sk_pop_free(OPENSSL_STACK *a, void(*b)(void *))
void * q_SSL_get_ex_data(const SSL *ssl, int idx)
void q_AUTHORITY_INFO_ACCESS_free(AUTHORITY_INFO_ACCESS *a)
ASN1_INTEGER * q_X509_get_serialNumber(X509 *a)
void q_ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it)
QT_OPENSSL4_CONST ASN1_OCTET_STRING * q_X509_EXTENSION_get_data(QT_OPENSSL4_CONST X509_EXTENSION *a)
int q_X509_check_issued(X509 *a, X509 *b)
const BIO_METHOD * q_BIO_s_mem()
char * q_ERR_error_string(unsigned long a, char *b)
void q_X509_print(BIO *a, X509 *b)
void q_X509_free(X509 *a)
int q_X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx)
int q_X509_NAME_entry_count(const X509_NAME *a)
void * q_X509_get_ext_d2i(X509 *a, int b, int *c, int *d)
int q_X509_EXTENSION_get_critical(const X509_EXTENSION *a)
#define q_sk_X509_value(st, i)
int q_X509_get_ext_count(X509 *a)
void q_GENERAL_NAME_free(GENERAL_NAME *a)
int q_X509_verify_cert(X509_STORE_CTX *ctx)
X509_STORE * q_X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx)
X509 * q_d2i_X509(X509 **a, const unsigned char **b, long c)
int q_ASN1_TIME_to_tm(const ASN1_TIME *s, struct tm *tm)
#define q_SKM_sk_value(type, st, i)
#define q_OPENSSL_free(addr)
ASN1_TIME * q_X509_getm_notBefore(X509 *a)
int q_OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *obj, int no_name)
#define q_sk_GENERAL_NAME_num(st)
int q_X509_STORE_CTX_get_error(X509_STORE_CTX *ctx)