10#include <QtNetwork/private/qsslcertificate_p.h>
12#include <QtNetwork/qsslsocket.h>
13#include <QtNetwork/qhostaddress.h>
15#include <QtCore/qendian.h>
16#include <QtCore/qdatetime.h>
17#include <QtCore/qhash.h>
18#include <QtCore/qiodevice.h>
19#include <QtCore/qscopeguard.h>
20#include <QtCore/qtimezone.h>
21#include <QtCore/qvarlengtharray.h>
25using namespace Qt::StringLiterals;
31QByteArray asn1ObjectId(ASN1_OBJECT *object)
39 return QByteArray(buf);
42QByteArray asn1ObjectName(ASN1_OBJECT *object)
51 return asn1ObjectId(object);
54QMultiMap<QByteArray, QString> mapFromX509Name(X509_NAME *name)
59 QMultiMap<QByteArray, QString> info;
63 QByteArray name = asn1ObjectName(q_X509_NAME_ENTRY_get_object(e));
64 unsigned char *data =
nullptr;
66 info.insert(name, QString::fromUtf8((
char*)data, size));
73QDateTime dateTimeFromASN1(
const ASN1_TIME *aTime)
79 QDate resDate(lTime.tm_year + 1900, lTime.tm_mon + 1, lTime.tm_mday);
80 QTime resTime(lTime.tm_hour, lTime.tm_min, lTime.tm_sec);
81 result = QDateTime(resDate, resTime, QTimeZone::UTC);
88#define BEGINCERTSTRING "-----BEGIN CERTIFICATE-----"
89#define ENDCERTSTRING "-----END CERTIFICATE-----"
91QByteArray x509ToQByteArray(X509 *x509, QSsl::EncodingFormat format)
103 array.resize(length);
105 char *data = array.data();
106 char **dataP = &data;
107 unsigned char **dataPu = (
unsigned char **)dataP;
111 if (format == QSsl::Der)
115 array = array.toBase64();
117 for (
int i = 0; i <= array.size() - 64; i += 64) {
118 tmp += QByteArray::fromRawData(array.data() + i, 64);
121 if (
int remainder = array.size() % 64) {
122 tmp += QByteArray::fromRawData(array.data() + array.size() - remainder, remainder);
129QString x509ToText(X509 *x509)
137 const auto bioRaii = qScopeGuard([bio]{
q_BIO_free(bio
);});
141 QVarLengthArray<
char, 16384> data;
142 int count = q_BIO_read(bio, data.data(), 16384);
144 result = QByteArray( data.data(), count );
146 return QString::fromLatin1(result);
149QVariant x509UnknownExtensionToValue(X509_EXTENSION *ext)
170 const auto extCleaner = qScopeGuard([meth, ext_internal]{
171 Q_ASSERT(ext_internal && meth);
175 else if (meth->ext_free)
176 meth->ext_free(ext_internal);
178 qCWarning(lcTlsBackend,
"No method to free an unknown extension, a potential memory leak?");
183 STACK_OF(CONF_VALUE) *val = meth->i2v(meth, ext_internal,
nullptr);
184 const auto stackCleaner = qScopeGuard([val]{
195 if (nval->name && nval->value) {
197 map[QString::fromUtf8(nval->name)] = QString::fromUtf8(nval->value);
198 }
else if (nval->name) {
199 list << QString::fromUtf8(nval->name);
200 }
else if (nval->value) {
201 list << QString::fromUtf8(nval->value);
209 }
else if (meth->i2s) {
210 const char *hexString = meth->i2s(meth, ext_internal);
211 QVariant result(hexString ? QString::fromUtf8(hexString) : QString{});
214 }
else if (meth->i2r) {
221 meth->i2r(meth, ext_internal, bio, 0);
225 result = QByteArray(bio_buffer, bio_size);
235
236
237
238
239QVariant x509ExtensionToValue(X509_EXTENSION *ext)
249 void *ext_internal =
nullptr;
250 const auto extCleaner = qScopeGuard([meth, &ext_internal]() {
251 if (!meth || !ext_internal)
256 else if (meth->ext_free)
257 meth->ext_free(ext_internal);
259 qCWarning(lcTlsBackend,
"Cannot free an extension, a potential memory leak?");
262 const char * hexString =
nullptr;
263 const auto hexStringCleaner = qScopeGuard([&hexString](){
269 case NID_basic_constraints:
271 BASIC_CONSTRAINTS *basic =
reinterpret_cast<BASIC_CONSTRAINTS *>(
q_X509V3_EXT_d2i(ext
));
275 result[
"ca"_L1] = basic->ca ?
true :
false;
277 result[
"pathLenConstraint"_L1] = (qlonglong)q_ASN1_INTEGER_get(basic->pathlen);
283 case NID_info_access:
285 AUTHORITY_INFO_ACCESS *info =
reinterpret_cast<AUTHORITY_INFO_ACCESS *>(
q_X509V3_EXT_d2i(ext
));
290 ACCESS_DESCRIPTION *ad =
q_SKM_sk_value(ACCESS_DESCRIPTION, info, i);
292 GENERAL_NAME *name = ad->location;
293 if (name->type == GEN_URI) {
295 if (len < 0 || len >= 8192) {
301 const QString uri = QString::fromUtf8(uriStr, len);
303 result[QString::fromUtf8(asn1ObjectName(ad->method))] = uri;
305 qCWarning(lcTlsBackend) <<
"Strange location type" << name->type;
313 case NID_subject_key_identifier:
319 hexString = meth->i2s(meth, ext_internal);
320 return QVariant(QString::fromUtf8(hexString));
323 case NID_authority_key_identifier:
325 AUTHORITY_KEYID *auth_key =
reinterpret_cast<AUTHORITY_KEYID *>(
q_X509V3_EXT_d2i(ext
));
331 if (auth_key->keyid) {
332 QByteArray keyid(
reinterpret_cast<
const char *>(auth_key->keyid->data),
333 auth_key->keyid->length);
334 result[
"keyid"_L1] = keyid.toHex();
341 if (auth_key->serial)
342 result[
"serial"_L1] = (qlonglong)q_ASN1_INTEGER_get(auth_key->serial);
359 using ErrorListPtr = QList<QSslErrorEntry> *;
360 ErrorListPtr errors =
nullptr;
385 qCWarning(lcTlsBackend,
"Neither X509_STORE, nor SSL contains error list, verification failed");
405bool X509CertificateOpenSSL::
isEqual(
const X509Certificate &rhs)
const
408 const auto &other =
static_cast<
const X509CertificateOpenSSL &>(rhs);
409 if (x509 && other.x509) {
410 const int ret = q_X509_cmp(x509, other.x509);
411 if (ret >= -1 && ret <= 1)
430 QMultiMap<QSsl::AlternativeNameEntryType, QString> result;
435 auto *altNames =
static_cast<STACK_OF(GENERAL_NAME) *>(
q_X509_get_ext_d2i(x509
, NID_subject_alt_name
,
440 auto altName = [](ASN1_IA5STRING *ia5,
int len) {
442 return QString::fromLatin1(altNameStr, len);
447 if (genName->type != GEN_DNS && genName->type != GEN_EMAIL && genName->type != GEN_IPADD)
451 if (len < 0 || len >= 8192) {
456 switch (genName->type) {
458 result.insert(QSsl::DnsEntry, altName(genName->d.ia5, len));
461 result.insert(QSsl::EmailEntry, altName(genName->d.ia5, len));
464 QHostAddress ipAddress;
467 ipAddress = QHostAddress(qFromBigEndian(*
reinterpret_cast<quint32 *>(genName->d.iPAddress->data)));
470 ipAddress = QHostAddress(
reinterpret_cast<quint8 *>(genName->d.iPAddress->data));
475 if (!ipAddress.isNull())
476 result.insert(QSsl::IpAddressEntry, ipAddress.toString());
502 return x509ToQByteArray(x509, QSsl::Pem);
510 return x509ToQByteArray(x509, QSsl::Der);
518 return x509ToText(x509);
523 return Qt::HANDLE(x509);
526size_t X509CertificateOpenSSL::
hash(size_t seed)
const noexcept
530 unsigned int len = 0;
531 unsigned char md[EVP_MAX_MD_SIZE];
533 return qHashBits(md, len, seed);
539QSslCertificate X509CertificateOpenSSL::certificateFromX509(X509 *x509)
541 QSslCertificate certificate;
543 auto *backend = QTlsBackend::backend<X509CertificateOpenSSL>(certificate);
544 if (!backend || !x509)
549 backend->notValidBefore = dateTimeFromASN1(nbef);
553 backend->notValidAfter = dateTimeFromASN1(naft);
555 backend->null =
false;
558 backend->issuerInfoEntries = mapFromX509Name(q_X509_get_issuer_name(x509));
559 backend->subjectInfoEntries = mapFromX509Name(q_X509_get_subject_name(x509));
560 backend->versionString = QByteArray::number(qlonglong(q_X509_get_version(x509)) + 1);
563 QByteArray hexString;
564 hexString.reserve(serialNumber->length * 3);
565 for (
int a = 0; a < serialNumber->length; ++a) {
566 hexString += QByteArray::number(serialNumber->data[a], 16).rightJustified(2,
'0');
570 backend->serialNumberString = hexString;
573 backend->parseExtensions();
578QList<QSslCertificate> X509CertificateOpenSSL::stackOfX509ToQSslCertificates(STACK_OF(X509) *x509)
583 QList<QSslCertificate> certificates;
586 certificates << certificateFromX509(entry);
599QList<QSslError> X509CertificateOpenSSL::verify(
const QList<QSslCertificate> &chain,
600 const QString &hostName)
603 auto roots = QSslConfiguration::defaultConfiguration().caCertificates();
609 if (QSslSocketPrivate::rootCertOnDemandLoadingSupported())
610 roots.append(QSslSocketPrivate::systemCaCertificates());
612 return verify(roots, chain, hostName);
615QList<QSslError> X509CertificateOpenSSL::verify(
const QList<QSslCertificate> &caCertificates,
616 const QList<QSslCertificate> &certificateChain,
617 const QString &hostName)
620 if (certificateChain.size() <= 0)
621 return {QSslError(QSslError::UnspecifiedError)};
623 QList<QSslError> errors;
626 qCWarning(lcTlsBackend) <<
"Unable to create certificate store";
627 errors << QSslError(QSslError::UnspecifiedError);
630 const std::unique_ptr<X509_STORE,
decltype(&q_X509_STORE_free)> storeGuard(certStore,
q_X509_STORE_free);
632 const QDateTime now = QDateTime::currentDateTimeUtc();
633 for (
const QSslCertificate &caCertificate : caCertificates) {
645 if (caCertificate.expiryDate() >= now) {
646 q_X509_STORE_add_cert(certStore,
reinterpret_cast<X509 *>(caCertificate.handle()));
650 QList<QSslErrorEntry> lastErrors;
651 if (!q_X509_STORE_set_ex_data(certStore, 0, &lastErrors)) {
652 qCWarning(lcTlsBackend) <<
"Unable to attach external data (error list) to a store";
653 errors << QSslError(QSslError::UnspecifiedError);
661 STACK_OF(X509) *intermediates =
nullptr;
662 if (certificateChain.size() > 1) {
665 if (!intermediates) {
666 errors << QSslError(QSslError::UnspecifiedError);
671 for (
const QSslCertificate &cert : certificateChain) {
677 q_OPENSSL_sk_push((OPENSSL_STACK *)intermediates,
reinterpret_cast<X509 *>(cert.handle()));
683 errors << QSslError(QSslError::UnspecifiedError);
686 std::unique_ptr<X509_STORE_CTX,
decltype(&q_X509_STORE_CTX_free)> ctxGuard(storeContext, q_X509_STORE_CTX_free);
689 errors << QSslError(QSslError::UnspecifiedError);
702 if (certificateChain[0].isBlacklisted())
703 errors << QSslError(QSslError::CertificateBlacklisted, certificateChain[0]);
706 if (!hostName.isEmpty() && !TlsCryptograph::isMatchingHostname(certificateChain[0], hostName)) {
708 QSslError error(QSslError::HostNameMismatch, certificateChain[0]);
713 errors.reserve(errors.size() + lastErrors.size());
714 for (
const auto &error : std::as_const(lastErrors))
715 errors << openSSLErrorToQSslError(error.code, certificateChain.value(error.depth));
720QList<QSslCertificate> X509CertificateOpenSSL::certificatesFromPem(
const QByteArray &pem,
int count)
722 QList<QSslCertificate> certificates;
725 while (count == -1 || certificates.size() < count) {
730 if (!matchLineFeed(pem, &startPos))
738 if (offset < pem.size() && !matchLineFeed(pem, &offset))
741 QByteArray decoded = QByteArray::fromBase64(
742 QByteArray::fromRawData(pem.data() + startPos, endPos - startPos));
743 const unsigned char *data = (
const unsigned char *)decoded.data();
745 if (X509 *x509 = q_d2i_X509(
nullptr, &data, decoded.size())) {
746 certificates << certificateFromX509(x509);
754QList<QSslCertificate> X509CertificateOpenSSL::certificatesFromDer(
const QByteArray &der,
int count)
756 QList<QSslCertificate> certificates;
758 const unsigned char *data = (
const unsigned char *)der.data();
759 int size = der.size();
761 while (size > 0 && (count == -1 || certificates.size() < count)) {
763 certificates << certificateFromX509(x509);
768 size -= ((
const char *)data - der.data());
774bool X509CertificateOpenSSL::importPkcs12(QIODevice *device, QSslKey *key, QSslCertificate *cert,
775 QList<QSslCertificate> *caCertificates,
776 const QByteArray &passPhrase)
784 QByteArray pkcs12data = device->readAll();
785 if (pkcs12data.size() == 0)
788 BIO *bio = q_BIO_new_mem_buf(
const_cast<
char *>(pkcs12data.constData()), pkcs12data.size());
790 qCWarning(lcTlsBackend,
"BIO_new_mem_buf returned null");
793 const auto bioRaii = qScopeGuard([bio]{
q_BIO_free(bio
);});
798 qCWarning(lcTlsBackend,
"Unable to read PKCS#12 structure, %s",
805 EVP_PKEY *pkey =
nullptr;
806 X509 *x509 =
nullptr;
807 STACK_OF(X509) *ca =
nullptr;
809 if (!q_PKCS12_parse(p12, passPhrase.constData(), &pkey, &x509, &ca)) {
810 qCWarning(lcTlsBackend,
"Unable to parse PKCS#12 structure, %s",
815 const auto x509Raii = qScopeGuard([x509]{
q_X509_free(x509
);});
817 const auto caRaii = qScopeGuard([ca] {
823 auto *tlsKey = QTlsBackend::backend<TlsKeyOpenSSL>(*key);
824 if (!tlsKey || !tlsKey->fromEVP_PKEY(pkey)) {
825 qCWarning(lcTlsBackend,
"Unable to convert private key");
829 *cert = certificateFromX509(x509);
832 *caCertificates = stackOfX509ToQSslCertificates(ca);
837QSslError X509CertificateOpenSSL::openSSLErrorToQSslError(
int errorCode,
const QSslCertificate &cert)
844 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
845 error = QSslError(QSslError::UnableToGetIssuerCertificate, cert);
break;
846 case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
847 error = QSslError(QSslError::UnableToDecryptCertificateSignature, cert);
break;
848 case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
849 error = QSslError(QSslError::UnableToDecodeIssuerPublicKey, cert);
break;
850 case X509_V_ERR_CERT_SIGNATURE_FAILURE:
851 error = QSslError(QSslError::CertificateSignatureFailed, cert);
break;
852 case X509_V_ERR_CERT_NOT_YET_VALID:
853 error = QSslError(QSslError::CertificateNotYetValid, cert);
break;
854 case X509_V_ERR_CERT_HAS_EXPIRED:
855 error = QSslError(QSslError::CertificateExpired, cert);
break;
856 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
857 error = QSslError(QSslError::InvalidNotBeforeField, cert);
break;
858 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
859 error = QSslError(QSslError::InvalidNotAfterField, cert);
break;
860 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
861 error = QSslError(QSslError::SelfSignedCertificate, cert);
break;
862 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
863 error = QSslError(QSslError::SelfSignedCertificateInChain, cert);
break;
864 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
865 error = QSslError(QSslError::UnableToGetLocalIssuerCertificate, cert);
break;
866 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
867 error = QSslError(QSslError::UnableToVerifyFirstCertificate, cert);
break;
868 case X509_V_ERR_CERT_REVOKED:
869 error = QSslError(QSslError::CertificateRevoked, cert);
break;
870 case X509_V_ERR_INVALID_CA:
871 error = QSslError(QSslError::InvalidCaCertificate, cert);
break;
872 case X509_V_ERR_PATH_LENGTH_EXCEEDED:
873 error = QSslError(QSslError::PathLengthExceeded, cert);
break;
874 case X509_V_ERR_INVALID_PURPOSE:
875 error = QSslError(QSslError::InvalidPurpose, cert);
break;
876 case X509_V_ERR_CERT_UNTRUSTED:
877 error = QSslError(QSslError::CertificateUntrusted, cert);
break;
878 case X509_V_ERR_CERT_REJECTED:
879 error = QSslError(QSslError::CertificateRejected, cert);
break;
881 error = QSslError(QSslError::UnspecifiedError, cert);
break;
886void X509CertificateOpenSSL::parseExtensions()
897 extensions.reserve(count);
899 for (
int i = 0; i < count; i++) {
902 qCWarning(lcTlsBackend) <<
"Invalid (nullptr) extension at index" << i;
906 extensions << convertExtension(ext);
923 result.oid = QString::fromUtf8(asn1ObjectId(obj));
924 result.name = QString::fromUtf8(asn1ObjectName(obj));
929 QVariant extensionValue = x509ExtensionToValue(ext);
930 if (extensionValue.isValid()) {
931 result.value = extensionValue;
936 extensionValue = x509UnknownExtensionToValue(ext);
937 if (extensionValue.isValid())
938 result.value = extensionValue;
static void logAndClearErrorQueue()
static void clearErrorQueue()
static int s_indexForSSLExtraData
static QString getErrorsFromOpenSsl()
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)
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)