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(ASN1_OBJECT *object)
40 return QByteArray(buf);
43QByteArray asn1ObjectName(ASN1_OBJECT *object)
52 return asn1ObjectId(object);
55QMultiMap<QByteArray, QString> mapFromX509Name(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);
150QVariant x509UnknownExtensionToValue(X509_EXTENSION *ext)
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
240QVariant x509ExtensionToValue(X509_EXTENSION *ext)
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) {
333 QByteArray keyid(
reinterpret_cast<
const char *>(auth_key->keyid->data),
334 auth_key->keyid->length);
335 result[
"keyid"_L1] = keyid.toHex();
342 if (auth_key->serial)
343 result[
"serial"_L1] = (qlonglong)q_ASN1_INTEGER_get(auth_key->serial);
360 using ErrorListPtr = QList<QSslErrorEntry> *;
361 ErrorListPtr errors =
nullptr;
386 qCWarning(lcTlsBackend,
"Neither X509_STORE, nor SSL contains error list, verification failed");
406bool X509CertificateOpenSSL::
isEqual(
const X509Certificate &rhs)
const
409 const auto &other =
static_cast<
const X509CertificateOpenSSL &>(rhs);
410 if (x509 && other.x509) {
411 const int ret = q_X509_cmp(x509, other.x509);
412 if (ret >= -1 && ret <= 1)
431 QMultiMap<QSsl::AlternativeNameEntryType, QString> result;
436 auto *altNames =
static_cast<STACK_OF(GENERAL_NAME) *>(
q_X509_get_ext_d2i(x509
, NID_subject_alt_name
,
441 auto altName = [](ASN1_IA5STRING *ia5,
int len) {
443 return QString::fromLatin1(altNameStr, len);
448 if (genName->type != GEN_DNS && genName->type != GEN_EMAIL && genName->type != GEN_IPADD)
452 if (len < 0 || len >= 8192) {
457 switch (genName->type) {
459 result.insert(QSsl::DnsEntry, altName(genName->d.ia5, len));
462 result.insert(QSsl::EmailEntry, altName(genName->d.ia5, len));
465 QHostAddress ipAddress;
468 ipAddress = QHostAddress(qFromBigEndian(*
reinterpret_cast<quint32 *>(genName->d.iPAddress->data)));
471 ipAddress = QHostAddress(
reinterpret_cast<quint8 *>(genName->d.iPAddress->data));
476 if (!ipAddress.isNull())
477 result.insert(QSsl::IpAddressEntry, ipAddress.toString());
503 return x509ToQByteArray(x509, QSsl::Pem);
511 return x509ToQByteArray(x509, QSsl::Der);
519 return x509ToText(x509);
524 return Qt::HANDLE(x509);
527size_t X509CertificateOpenSSL::
hash(size_t seed)
const noexcept
531 unsigned int len = 0;
532 unsigned char md[EVP_MAX_MD_SIZE];
534 return qHashBits(md, len, seed);
540QSslCertificate X509CertificateOpenSSL::certificateFromX509(X509 *x509)
542 QSslCertificate certificate;
544 auto *backend = QTlsBackend::backend<X509CertificateOpenSSL>(certificate);
545 if (!backend || !x509)
550 backend->notValidBefore = dateTimeFromASN1(nbef);
554 backend->notValidAfter = dateTimeFromASN1(naft);
556 backend->null =
false;
559 backend->issuerInfoEntries = mapFromX509Name(q_X509_get_issuer_name(x509));
560 backend->subjectInfoEntries = mapFromX509Name(q_X509_get_subject_name(x509));
561 backend->versionString = QByteArray::number(qlonglong(q_X509_get_version(x509)) + 1);
564 QByteArray hexString;
565 hexString.reserve(serialNumber->length * 3);
566 for (
int a = 0; a < serialNumber->length; ++a) {
567 hexString += QByteArray::number(serialNumber->data[a], 16).rightJustified(2,
'0');
571 backend->serialNumberString = hexString;
574 backend->parseExtensions();
579QList<QSslCertificate> X509CertificateOpenSSL::stackOfX509ToQSslCertificates(STACK_OF(X509) *x509)
584 QList<QSslCertificate> certificates;
587 certificates << certificateFromX509(entry);
600QList<QSslError> X509CertificateOpenSSL::verify(
const QList<QSslCertificate> &chain,
601 const QString &hostName)
604 auto roots = QSslConfiguration::defaultConfiguration().caCertificates();
610 if (QSslSocketPrivate::rootCertOnDemandLoadingSupported())
611 roots.append(QSslSocketPrivate::systemCaCertificates());
613 return verify(roots, chain, hostName);
616QList<QSslError> X509CertificateOpenSSL::verify(
const QList<QSslCertificate> &caCertificates,
617 const QList<QSslCertificate> &certificateChain,
618 const QString &hostName)
621 if (certificateChain.size() <= 0)
622 return {QSslError(QSslError::UnspecifiedError)};
624 QList<QSslError> errors;
627 qCWarning(lcTlsBackend) <<
"Unable to create certificate store";
628 errors << QSslError(QSslError::UnspecifiedError);
631 const std::unique_ptr<X509_STORE,
decltype(&q_X509_STORE_free)> storeGuard(certStore,
q_X509_STORE_free);
633 const QDateTime now = QDateTime::currentDateTimeUtc();
634 for (
const QSslCertificate &caCertificate : caCertificates) {
646 if (caCertificate.expiryDate() >= now) {
647 q_X509_STORE_add_cert(certStore,
reinterpret_cast<X509 *>(caCertificate.handle()));
651 QList<QSslErrorEntry> lastErrors;
652 if (!q_X509_STORE_set_ex_data(certStore, 0, &lastErrors)) {
653 qCWarning(lcTlsBackend) <<
"Unable to attach external data (error list) to a store";
654 errors << QSslError(QSslError::UnspecifiedError);
662 STACK_OF(X509) *intermediates =
nullptr;
663 if (certificateChain.size() > 1) {
666 if (!intermediates) {
667 errors << QSslError(QSslError::UnspecifiedError);
672 for (
const QSslCertificate &cert : certificateChain) {
678 q_OPENSSL_sk_push((OPENSSL_STACK *)intermediates,
reinterpret_cast<X509 *>(cert.handle()));
684 errors << QSslError(QSslError::UnspecifiedError);
687 std::unique_ptr<X509_STORE_CTX,
decltype(&q_X509_STORE_CTX_free)> ctxGuard(storeContext, q_X509_STORE_CTX_free);
690 errors << QSslError(QSslError::UnspecifiedError);
703 if (certificateChain[0].isBlacklisted())
704 errors << QSslError(QSslError::CertificateBlacklisted, certificateChain[0]);
707 if (!hostName.isEmpty() && !TlsCryptograph::isMatchingHostname(certificateChain[0], hostName)) {
709 QSslError error(QSslError::HostNameMismatch, certificateChain[0]);
714 errors.reserve(errors.size() + lastErrors.size());
715 for (
const auto &error : std::as_const(lastErrors))
716 errors << openSSLErrorToQSslError(error.code, certificateChain.value(error.depth));
721QList<QSslCertificate> X509CertificateOpenSSL::certificatesFromPem(
const QByteArray &pem,
int count)
723 QList<QSslCertificate> certificates;
726 while (count == -1 || certificates.size() < count) {
731 if (!matchLineFeed(pem, &startPos))
739 if (offset < pem.size() && !matchLineFeed(pem, &offset))
742 QByteArray decoded = QByteArray::fromBase64(
743 QByteArray::fromRawData(pem.data() + startPos, endPos - startPos));
744 const unsigned char *data = (
const unsigned char *)decoded.data();
746 if (X509 *x509 = q_d2i_X509(
nullptr, &data, decoded.size())) {
747 certificates << certificateFromX509(x509);
755QList<QSslCertificate> X509CertificateOpenSSL::certificatesFromDer(
const QByteArray &der,
int count)
757 QList<QSslCertificate> certificates;
759 const unsigned char *data = (
const unsigned char *)der.data();
760 int size = der.size();
762 while (size > 0 && (count == -1 || certificates.size() < count)) {
764 certificates << certificateFromX509(x509);
769 size -= ((
const char *)data - der.data());
775bool X509CertificateOpenSSL::importPkcs12(QIODevice *device, QSslKey *key, QSslCertificate *cert,
776 QList<QSslCertificate> *caCertificates,
777 const QByteArray &passPhrase)
785 QByteArray pkcs12data = device->readAll();
786 if (pkcs12data.size() == 0)
789 BIO *bio = q_BIO_new_mem_buf(
const_cast<
char *>(pkcs12data.constData()), pkcs12data.size());
791 qCWarning(lcTlsBackend,
"BIO_new_mem_buf returned null");
794 const auto bioRaii = qScopeGuard([bio]{
q_BIO_free(bio
);});
799 qCWarning(lcTlsBackend,
"Unable to read PKCS#12 structure, %s",
806 EVP_PKEY *pkey =
nullptr;
807 X509 *x509 =
nullptr;
808 STACK_OF(X509) *ca =
nullptr;
810 if (!q_PKCS12_parse(p12, passPhrase.constData(), &pkey, &x509, &ca)) {
811 qCWarning(lcTlsBackend,
"Unable to parse PKCS#12 structure, %s",
816 const auto x509Raii = qScopeGuard([x509]{
q_X509_free(x509
);});
818 const auto caRaii = qScopeGuard([ca] {
824 auto *tlsKey = QTlsBackend::backend<TlsKeyOpenSSL>(*key);
825 if (!tlsKey || !tlsKey->fromEVP_PKEY(pkey)) {
826 qCWarning(lcTlsBackend,
"Unable to convert private key");
830 *cert = certificateFromX509(x509);
833 *caCertificates = stackOfX509ToQSslCertificates(ca);
838QSslError X509CertificateOpenSSL::openSSLErrorToQSslError(
int errorCode,
const QSslCertificate &cert)
845 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
846 error = QSslError(QSslError::UnableToGetIssuerCertificate, cert);
break;
847 case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
848 error = QSslError(QSslError::UnableToDecryptCertificateSignature, cert);
break;
849 case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
850 error = QSslError(QSslError::UnableToDecodeIssuerPublicKey, cert);
break;
851 case X509_V_ERR_CERT_SIGNATURE_FAILURE:
852 error = QSslError(QSslError::CertificateSignatureFailed, cert);
break;
853 case X509_V_ERR_CERT_NOT_YET_VALID:
854 error = QSslError(QSslError::CertificateNotYetValid, cert);
break;
855 case X509_V_ERR_CERT_HAS_EXPIRED:
856 error = QSslError(QSslError::CertificateExpired, cert);
break;
857 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
858 error = QSslError(QSslError::InvalidNotBeforeField, cert);
break;
859 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
860 error = QSslError(QSslError::InvalidNotAfterField, cert);
break;
861 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
862 error = QSslError(QSslError::SelfSignedCertificate, cert);
break;
863 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
864 error = QSslError(QSslError::SelfSignedCertificateInChain, cert);
break;
865 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
866 error = QSslError(QSslError::UnableToGetLocalIssuerCertificate, cert);
break;
867 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
868 error = QSslError(QSslError::UnableToVerifyFirstCertificate, cert);
break;
869 case X509_V_ERR_CERT_REVOKED:
870 error = QSslError(QSslError::CertificateRevoked, cert);
break;
871 case X509_V_ERR_INVALID_CA:
872 error = QSslError(QSslError::InvalidCaCertificate, cert);
break;
873 case X509_V_ERR_PATH_LENGTH_EXCEEDED:
874 error = QSslError(QSslError::PathLengthExceeded, cert);
break;
875 case X509_V_ERR_INVALID_PURPOSE:
876 error = QSslError(QSslError::InvalidPurpose, cert);
break;
877 case X509_V_ERR_CERT_UNTRUSTED:
878 error = QSslError(QSslError::CertificateUntrusted, cert);
break;
879 case X509_V_ERR_CERT_REJECTED:
880 error = QSslError(QSslError::CertificateRejected, cert);
break;
882 error = QSslError(QSslError::UnspecifiedError, cert);
break;
887void X509CertificateOpenSSL::parseExtensions()
898 extensions.reserve(count);
900 for (
int i = 0; i < count; i++) {
903 qCWarning(lcTlsBackend) <<
"Invalid (nullptr) extension at index" << i;
907 extensions << convertExtension(ext);
924 result.oid = QString::fromUtf8(asn1ObjectId(obj));
925 result.name = QString::fromUtf8(asn1ObjectName(obj));
930 QVariant extensionValue = x509ExtensionToValue(ext);
931 if (extensionValue.isValid()) {
932 result.value = extensionValue;
937 extensionValue = x509UnknownExtensionToValue(ext);
938 if (extensionValue.isValid())
939 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
Namespace containing onternal types that TLS backends implement.
int qt_X509Callback(int ok, X509_STORE_CTX *ctx)
X509_STORE_CTX * q_X509_STORE_CTX_new()
int q_OBJ_obj2nid(const ASN1_OBJECT *a)
int q_ASN1_STRING_length(ASN1_STRING *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()
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)
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)
const unsigned char * q_ASN1_STRING_get0_data(const ASN1_STRING *x)
#define q_sk_X509_num(st)
const EVP_MD * q_EVP_sha1()
X509 * q_X509_dup(X509 *a)
PKCS12 * q_d2i_PKCS12_bio(BIO *bio, PKCS12 **pkcs12)
int q_X509_EXTENSION_get_critical(X509_EXTENSION *a)
#define q_BIO_get_mem_data(b, pp)
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)
void q_X509V3_conf_free(CONF_VALUE *val)
void * q_X509V3_EXT_d2i(X509_EXTENSION *a)
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)
ASN1_STRING * q_X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *a)
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)
int q_X509_check_issued(X509 *a, X509 *b)
const BIO_METHOD * q_BIO_s_mem()
int q_ASN1_STRING_to_UTF8(unsigned char **a, ASN1_STRING *b)
char * q_ERR_error_string(unsigned long a, char *b)
ASN1_OCTET_STRING * q_X509_EXTENSION_get_data(X509_EXTENSION *a)
int q_OBJ_obj2txt(char *buf, int buf_len, ASN1_OBJECT *obj, int no_name)
X509_NAME_ENTRY * q_X509_NAME_get_entry(X509_NAME *a, int 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)
void * q_X509_get_ext_d2i(X509 *a, int b, int *c, int *d)
const X509V3_EXT_METHOD * q_X509V3_EXT_get(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)
X509_EXTENSION * q_X509_get_ext(X509 *a, int b)
int q_ASN1_TIME_to_tm(const ASN1_TIME *s, struct tm *tm)
int q_X509_NAME_entry_count(X509_NAME *a)
#define q_SKM_sk_value(type, st, i)
ASN1_OBJECT * q_X509_EXTENSION_get_object(X509_EXTENSION *a)
#define q_OPENSSL_free(addr)
ASN1_TIME * q_X509_getm_notBefore(X509 *a)
#define q_sk_GENERAL_NAME_num(st)
int q_X509_STORE_CTX_get_error(X509_STORE_CTX *ctx)