8#include <QtCore/private/qsystemerror_p.h>
9#include <QtNetwork/private/qsslcertificate_p.h>
21 if (certificateContext)
22 CertFreeCertificateContext(certificateContext);
42 certificateContext->cbCertEncoded);
45 auto *certBackend = QTlsBackend::backend<X509CertificateSchannel>(certificate);
47 certBackend->certificateContext = CertDuplicateCertificateContext(certificateContext);
61 if (pkcs12data.
size() == 0)
64 CRYPT_DATA_BLOB dataBlob;
65 dataBlob.cbData = pkcs12data.
size();
66 dataBlob.pbData =
reinterpret_cast<BYTE*
>(pkcs12data.
data());
70 const DWORD
flags = (CRYPT_EXPORTABLE | PKCS12_NO_PERSIST_KEY | PKCS12_PREFER_CNG_KSP);
73 reinterpret_cast<LPCWSTR
>(password.utf16()),
77 qCWarning(lcTlsBackendSchannel,
"Failed to import PFX data: %s",
87 CERT_FIND_HAS_PRIVATE_KEY,
91 qCWarning(lcTlsBackendSchannel,
"Failed to find certificate in PFX store: %s",
99 NCRYPT_KEY_HANDLE keyHandle = {};
100 DWORD keyHandleSize =
sizeof(keyHandle);
101 if (!CertGetCertificateContextProperty(certContext.get(), CERT_NCRYPT_KEY_HANDLE_PROP_ID,
102 &keyHandle, &keyHandleSize)) {
103 qCWarning(lcTlsBackendSchannel,
"Failed to find private key handle in certificate context: %s",
108 SECURITY_STATUS securityStatus = ERROR_SUCCESS;
111 DWORD
policy = (NCRYPT_ALLOW_EXPORT_FLAG | NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG);
112 DWORD policySize =
sizeof(
policy);
114 securityStatus = NCryptSetProperty(keyHandle, NCRYPT_EXPORT_POLICY_PROPERTY,
115 reinterpret_cast<BYTE*
>(&
policy), policySize, 0);
116 if (securityStatus != ERROR_SUCCESS) {
117 qCWarning(lcTlsBackendSchannel,
"Failed to update export policy of private key: 0x%x",
118 static_cast<unsigned int>(securityStatus));
123 securityStatus = NCryptExportKey(keyHandle, {}, BCRYPT_RSAFULLPRIVATE_BLOB,
124 nullptr,
nullptr, 0, &blobSize, 0);
125 if (securityStatus != ERROR_SUCCESS) {
126 qCWarning(lcTlsBackendSchannel,
"Failed to retrieve private key size: 0x%x",
127 static_cast<unsigned int>(securityStatus));
131 std::vector<BYTE> blob(blobSize);
132 securityStatus = NCryptExportKey(keyHandle, {}, BCRYPT_RSAFULLPRIVATE_BLOB,
133 nullptr, blob.data(), blobSize, &blobSize, 0);
134 if (securityStatus != ERROR_SUCCESS) {
135 qCWarning(lcTlsBackendSchannel,
"Failed to retrieve private key from certificate: 0x%x",
136 static_cast<unsigned int>(securityStatus));
140 DWORD privateKeySize = {};
142 if (!CryptEncodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, CNG_RSA_PRIVATE_KEY_BLOB,
143 blob.data(),
nullptr, &privateKeySize)) {
144 qCWarning(lcTlsBackendSchannel,
"Failed to encode private key to key info: %s",
149 std::vector<BYTE> privateKeyData(privateKeySize);
151 CRYPT_PRIVATE_KEY_INFO privateKeyInfo = {};
152 privateKeyInfo.Algorithm.pszObjId =
const_cast<PSTR
>(szOID_RSA_RSA);
153 privateKeyInfo.PrivateKey.cbData = privateKeySize;
154 privateKeyInfo.PrivateKey.pbData = privateKeyData.data();
156 if (!CryptEncodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
157 CNG_RSA_PRIVATE_KEY_BLOB, blob.data(),
158 privateKeyInfo.PrivateKey.pbData, &privateKeyInfo.PrivateKey.cbData)) {
159 qCWarning(lcTlsBackendSchannel,
"Failed to encode private key to key info: %s",
167 if (!CryptEncodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_PRIVATE_KEY_INFO,
168 &privateKeyInfo,
nullptr, &derSize)) {
169 qCWarning(lcTlsBackendSchannel,
"Failed to encode key info to DER format: %s",
177 if (!CryptEncodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_PRIVATE_KEY_INFO,
178 &privateKeyInfo,
reinterpret_cast<BYTE*
>(
derData.
data()), &derSize)) {
179 qCWarning(lcTlsBackendSchannel,
"Failed to encode key info to DER format: %s",
187 qCWarning(lcTlsBackendSchannel,
"Failed to parse private key from DER format");
192 if (caCertificates) {
193 PCCERT_CONTEXT caCertContext =
nullptr;
194 while ((caCertContext = CertFindCertificateInStore(certStore.get(),
195 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
196 0, CERT_FIND_ANY,
nullptr, caCertContext))) {
197 if (CertCompareCertificate(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
198 certContext->pCertInfo, caCertContext->pCertInfo))
203 caCertificates->
append(caCertificate);
IOBluetoothDevice * device
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
\inmodule QtCore \reentrant
void append(parameter_type t)
The QSslCertificate class provides a convenient API for an X509 certificate.
The QSslKey class provides an interface for private and public keys.
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
TlsKey is an abstract class, that allows a TLS plugin to provide an underlying implementation for the...
QByteArray publicKeyDerData
QSsl::KeyAlgorithm publicKeyAlgorithm
TlsKey * publicKey() const override
Qt::HANDLE handle() const override
static bool importPkcs12(QIODevice *device, QSslKey *key, QSslCertificate *cert, QList< QSslCertificate > *caCertificates, const QByteArray &passPhrase)
X509CertificateSchannel()
~X509CertificateSchannel()
static QSslCertificate QSslCertificate_from_CERT_CONTEXT(const CERT_CONTEXT *certificateContext)
Combined button and popup list for selecting options.
Namespace containing onternal types that TLS backends implement.
constexpr Initialization Uninitialized
#define qCWarning(category,...)
#define qPrintable(string)
std::unique_ptr< const CERT_CONTEXT, QPCCertContextDeleter > QPCCertContextPointer
std::unique_ptr< void, QHCertStoreDeleter > QHCertStorePointer
QList< QSslCertificate > cert
[0]