50 QList<QSslCertificate> *caCertificates,
51 const QByteArray &passPhrase)
58 QByteArray pkcs12data = device->readAll();
59 if (pkcs12data.size() == 0)
62 CRYPT_DATA_BLOB dataBlob;
63 dataBlob.cbData = pkcs12data.size();
64 dataBlob.pbData =
reinterpret_cast<BYTE*>(pkcs12data.data());
66 const auto password = QString::fromUtf8(passPhrase);
68 const DWORD flags = (CRYPT_EXPORTABLE | PKCS12_NO_PERSIST_KEY | PKCS12_ALWAYS_CNG_KSP);
71 reinterpret_cast<LPCWSTR>(password.utf16()),
75 qCWarning(lcTlsBackendSchannel,
"Failed to import PFX data: %s",
76 qPrintable(QSystemError::windowsString()));
81 const auto certContext = QPCCertContextPointer(CertFindCertificateInStore(certStore.get(),
85 CERT_FIND_HAS_PRIVATE_KEY,
89 qCWarning(lcTlsBackendSchannel,
"Failed to find certificate in PFX store: %s",
90 qPrintable(QSystemError::windowsString()));
94 *cert = QSslCertificate_from_CERT_CONTEXT(certContext.get());
97 NCRYPT_KEY_HANDLE keyHandle = {};
98 DWORD keyHandleSize =
sizeof(keyHandle);
99 if (!CertGetCertificateContextProperty(certContext.get(), CERT_NCRYPT_KEY_HANDLE_PROP_ID,
100 &keyHandle, &keyHandleSize)) {
101 qCWarning(lcTlsBackendSchannel,
"Failed to find private key handle in certificate context: %s",
102 qPrintable(QSystemError::windowsString()));
106 SECURITY_STATUS securityStatus = ERROR_SUCCESS;
109 DWORD policy = (NCRYPT_ALLOW_EXPORT_FLAG | NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG);
110 DWORD policySize =
sizeof(policy);
112 securityStatus = NCryptSetProperty(keyHandle, NCRYPT_EXPORT_POLICY_PROPERTY,
113 reinterpret_cast<BYTE*>(&policy), policySize, 0);
114 if (securityStatus != ERROR_SUCCESS) {
115 qCWarning(lcTlsBackendSchannel,
"Failed to update export policy of private key: 0x%x",
116 static_cast<
unsigned int>(securityStatus));
121 securityStatus = NCryptExportKey(keyHandle, {}, BCRYPT_RSAFULLPRIVATE_BLOB,
122 nullptr,
nullptr, 0, &blobSize, 0);
123 if (securityStatus != ERROR_SUCCESS) {
124 qCWarning(lcTlsBackendSchannel,
"Failed to retrieve private key size: 0x%x",
125 static_cast<
unsigned int>(securityStatus));
129 std::vector<BYTE> blob(blobSize);
130 securityStatus = NCryptExportKey(keyHandle, {}, BCRYPT_RSAFULLPRIVATE_BLOB,
131 nullptr, blob.data(), blobSize, &blobSize, 0);
132 if (securityStatus != ERROR_SUCCESS) {
133 qCWarning(lcTlsBackendSchannel,
"Failed to retrieve private key from certificate: 0x%x",
134 static_cast<
unsigned int>(securityStatus));
138 DWORD privateKeySize = {};
140 if (!CryptEncodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, CNG_RSA_PRIVATE_KEY_BLOB,
141 blob.data(),
nullptr, &privateKeySize)) {
142 qCWarning(lcTlsBackendSchannel,
"Failed to encode private key to key info: %s",
143 qPrintable(QSystemError::windowsString()));
147 std::vector<BYTE> privateKeyData(privateKeySize);
149 CRYPT_PRIVATE_KEY_INFO privateKeyInfo = {};
150 privateKeyInfo.Algorithm.pszObjId =
const_cast<PSTR>(szOID_RSA_RSA);
151 privateKeyInfo.PrivateKey.cbData = privateKeySize;
152 privateKeyInfo.PrivateKey.pbData = privateKeyData.data();
154 if (!CryptEncodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
155 CNG_RSA_PRIVATE_KEY_BLOB, blob.data(),
156 privateKeyInfo.PrivateKey.pbData, &privateKeyInfo.PrivateKey.cbData)) {
157 qCWarning(lcTlsBackendSchannel,
"Failed to encode private key to key info: %s",
158 qPrintable(QSystemError::windowsString()));
165 if (!CryptEncodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_PRIVATE_KEY_INFO,
166 &privateKeyInfo,
nullptr, &derSize)) {
167 qCWarning(lcTlsBackendSchannel,
"Failed to encode key info to DER format: %s",
168 qPrintable(QSystemError::windowsString()));
173 QByteArray derData(derSize, Qt::Uninitialized);
175 if (!CryptEncodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_PRIVATE_KEY_INFO,
176 &privateKeyInfo,
reinterpret_cast<BYTE*>(derData.data()), &derSize)) {
177 qCWarning(lcTlsBackendSchannel,
"Failed to encode key info to DER format: %s",
178 qPrintable(QSystemError::windowsString()));
183 *key = QSslKey(derData, QSsl::Rsa, QSsl::Der, QSsl::PrivateKey);
185 qCWarning(lcTlsBackendSchannel,
"Failed to parse private key from DER format");
190 if (caCertificates) {
191 PCCERT_CONTEXT caCertContext =
nullptr;
192 while ((caCertContext = CertFindCertificateInStore(certStore.get(),
193 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
194 0, CERT_FIND_ANY,
nullptr, caCertContext))) {
195 if (CertCompareCertificate(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
196 certContext->pCertInfo, caCertContext->pCertInfo))
199 auto caCertificate = QSslCertificate_from_CERT_CONTEXT(caCertContext);
201 caCertificates->append(caCertificate);