summaryrefslogtreecommitdiffstats
path: root/src/winrtrunner
diff options
context:
space:
mode:
Diffstat (limited to 'src/winrtrunner')
-rw-r--r--src/winrtrunner/appxengine.cpp332
-rw-r--r--src/winrtrunner/appxengine.h1
-rw-r--r--src/winrtrunner/appxengine_p.h1
-rw-r--r--src/winrtrunner/appxphoneengine.cpp12
-rw-r--r--src/winrtrunner/winrtrunner.pro3
5 files changed, 349 insertions, 0 deletions
diff --git a/src/winrtrunner/appxengine.cpp b/src/winrtrunner/appxengine.cpp
index eacf52db9..c74f7c4b4 100644
--- a/src/winrtrunner/appxengine.cpp
+++ b/src/winrtrunner/appxengine.cpp
@@ -52,6 +52,9 @@
#include <wrl.h>
#include <windows.applicationmodel.h>
#include <windows.management.deployment.h>
+#if _MSC_VER >= 1900
+#include <wincrypt.h>
+#endif
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
@@ -62,6 +65,240 @@ using namespace ABI::Windows::System;
QT_USE_NAMESPACE
+#if _MSC_VER >= 1900
+// *********** Taken from MSDN Example code
+// https://msdn.microsoft.com/en-us/library/windows/desktop/jj835834%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
+
+#define SIGNER_SUBJECT_FILE 0x01
+#define SIGNER_NO_ATTR 0x00
+#define SIGNER_CERT_POLICY_CHAIN_NO_ROOT 0x08
+#define SIGNER_CERT_STORE 0x02
+
+typedef struct _SIGNER_FILE_INFO
+{
+ DWORD cbSize;
+ LPCWSTR pwszFileName;
+ HANDLE hFile;
+} SIGNER_FILE_INFO;
+
+typedef struct _SIGNER_BLOB_INFO
+{
+ DWORD cbSize;
+ GUID *pGuidSubject;
+ DWORD cbBlob;
+ BYTE *pbBlob;
+ LPCWSTR pwszDisplayName;
+} SIGNER_BLOB_INFO;
+
+typedef struct _SIGNER_SUBJECT_INFO
+{
+ DWORD cbSize;
+ DWORD *pdwIndex;
+ DWORD dwSubjectChoice;
+ union
+ {
+ SIGNER_FILE_INFO *pSignerFileInfo;
+ SIGNER_BLOB_INFO *pSignerBlobInfo;
+ };
+} SIGNER_SUBJECT_INFO, *PSIGNER_SUBJECT_INFO;
+
+typedef struct _SIGNER_ATTR_AUTHCODE
+{
+ DWORD cbSize;
+ BOOL fCommercial;
+ BOOL fIndividual;
+ LPCWSTR pwszName;
+ LPCWSTR pwszInfo;
+} SIGNER_ATTR_AUTHCODE;
+
+typedef struct _SIGNER_SIGNATURE_INFO
+{
+ DWORD cbSize;
+ ALG_ID algidHash;
+ DWORD dwAttrChoice;
+ union
+ {
+ SIGNER_ATTR_AUTHCODE *pAttrAuthcode;
+ };
+ PCRYPT_ATTRIBUTES psAuthenticated;
+ PCRYPT_ATTRIBUTES psUnauthenticated;
+} SIGNER_SIGNATURE_INFO, *PSIGNER_SIGNATURE_INFO;
+
+typedef struct _SIGNER_PROVIDER_INFO
+{
+ DWORD cbSize;
+ LPCWSTR pwszProviderName;
+ DWORD dwProviderType;
+ DWORD dwKeySpec;
+ DWORD dwPvkChoice;
+ union
+ {
+ LPWSTR pwszPvkFileName;
+ LPWSTR pwszKeyContainer;
+ };
+} SIGNER_PROVIDER_INFO, *PSIGNER_PROVIDER_INFO;
+
+typedef struct _SIGNER_SPC_CHAIN_INFO
+{
+ DWORD cbSize;
+ LPCWSTR pwszSpcFile;
+ DWORD dwCertPolicy;
+ HCERTSTORE hCertStore;
+} SIGNER_SPC_CHAIN_INFO;
+
+typedef struct _SIGNER_CERT_STORE_INFO
+{
+ DWORD cbSize;
+ PCCERT_CONTEXT pSigningCert;
+ DWORD dwCertPolicy;
+ HCERTSTORE hCertStore;
+} SIGNER_CERT_STORE_INFO;
+
+typedef struct _SIGNER_CERT
+{
+ DWORD cbSize;
+ DWORD dwCertChoice;
+ union
+ {
+ LPCWSTR pwszSpcFile;
+ SIGNER_CERT_STORE_INFO *pCertStoreInfo;
+ SIGNER_SPC_CHAIN_INFO *pSpcChainInfo;
+ };
+ HWND hwnd;
+} SIGNER_CERT, *PSIGNER_CERT;
+
+typedef struct _SIGNER_CONTEXT
+{
+ DWORD cbSize;
+ DWORD cbBlob;
+ BYTE *pbBlob;
+} SIGNER_CONTEXT, *PSIGNER_CONTEXT;
+
+typedef struct _SIGNER_SIGN_EX2_PARAMS
+{
+ DWORD dwFlags;
+ PSIGNER_SUBJECT_INFO pSubjectInfo;
+ PSIGNER_CERT pSigningCert;
+ PSIGNER_SIGNATURE_INFO pSignatureInfo;
+ PSIGNER_PROVIDER_INFO pProviderInfo;
+ DWORD dwTimestampFlags;
+ PCSTR pszAlgorithmOid;
+ PCWSTR pwszTimestampURL;
+ PCRYPT_ATTRIBUTES pCryptAttrs;
+ PVOID pSipData;
+ PSIGNER_CONTEXT *pSignerContext;
+ PVOID pCryptoPolicy;
+ PVOID pReserved;
+} SIGNER_SIGN_EX2_PARAMS, *PSIGNER_SIGN_EX2_PARAMS;
+
+typedef struct _APPX_SIP_CLIENT_DATA
+{
+ PSIGNER_SIGN_EX2_PARAMS pSignerParams;
+ IUnknown* pAppxSipState;
+} APPX_SIP_CLIENT_DATA, *PAPPX_SIP_CLIENT_DATA;
+
+bool signAppxPackage(PCCERT_CONTEXT signingCertContext, LPCWSTR packageFilePath)
+{
+ HRESULT hr = S_OK;
+
+ DWORD signerIndex = 0;
+
+ SIGNER_FILE_INFO fileInfo = {};
+ fileInfo.cbSize = sizeof(SIGNER_FILE_INFO);
+ fileInfo.pwszFileName = packageFilePath;
+
+ SIGNER_SUBJECT_INFO subjectInfo = {};
+ subjectInfo.cbSize = sizeof(SIGNER_SUBJECT_INFO);
+ subjectInfo.pdwIndex = &signerIndex;
+ subjectInfo.dwSubjectChoice = SIGNER_SUBJECT_FILE;
+ subjectInfo.pSignerFileInfo = &fileInfo;
+
+ SIGNER_CERT_STORE_INFO certStoreInfo = {};
+ certStoreInfo.cbSize = sizeof(SIGNER_CERT_STORE_INFO);
+ certStoreInfo.dwCertPolicy = SIGNER_CERT_POLICY_CHAIN_NO_ROOT;
+ certStoreInfo.pSigningCert = signingCertContext;
+
+ SIGNER_CERT cert = {};
+ cert.cbSize = sizeof(SIGNER_CERT);
+ cert.dwCertChoice = SIGNER_CERT_STORE;
+ cert.pCertStoreInfo = &certStoreInfo;
+
+ // The algidHash of the signature to be created must match the
+ // hash algorithm used to create the app package
+ SIGNER_SIGNATURE_INFO signatureInfo = {};
+ signatureInfo.cbSize = sizeof(SIGNER_SIGNATURE_INFO);
+ signatureInfo.algidHash = CALG_SHA_512;
+ signatureInfo.dwAttrChoice = SIGNER_NO_ATTR;
+
+ SIGNER_SIGN_EX2_PARAMS signerParams = {};
+ signerParams.pSubjectInfo = &subjectInfo;
+ signerParams.pSigningCert = &cert;
+ signerParams.pSignatureInfo = &signatureInfo;
+
+ APPX_SIP_CLIENT_DATA sipClientData = {};
+ sipClientData.pSignerParams = &signerParams;
+ signerParams.pSipData = &sipClientData;
+
+ // Type definition for invoking SignerSignEx2 via GetProcAddress
+ typedef HRESULT (WINAPI *SignerSignEx2Function)(
+ DWORD,
+ PSIGNER_SUBJECT_INFO,
+ PSIGNER_CERT,
+ PSIGNER_SIGNATURE_INFO,
+ PSIGNER_PROVIDER_INFO,
+ DWORD,
+ PCSTR,
+ PCWSTR,
+ PCRYPT_ATTRIBUTES,
+ PVOID,
+ PSIGNER_CONTEXT *,
+ PVOID,
+ PVOID);
+
+ // Load the SignerSignEx2 function from MSSign32.dll
+ HMODULE msSignModule = LoadLibraryEx(
+ L"MSSign32.dll",
+ NULL,
+ LOAD_LIBRARY_SEARCH_SYSTEM32);
+
+ if (!msSignModule) {
+ qCWarning(lcWinRtRunner) << "LoadLibraryEx failed to load MSSign32.dll.";
+ return false;
+ }
+
+ SignerSignEx2Function SignerSignEx2 = reinterpret_cast<SignerSignEx2Function>(
+ GetProcAddress(msSignModule, "SignerSignEx2"));
+ if (!SignerSignEx2) {
+ qCWarning(lcWinRtRunner) << "Could not resolve SignerSignEx2";
+ FreeLibrary(msSignModule);
+ return false;
+ }
+ hr = SignerSignEx2(signerParams.dwFlags,
+ signerParams.pSubjectInfo,
+ signerParams.pSigningCert,
+ signerParams.pSignatureInfo,
+ signerParams.pProviderInfo,
+ signerParams.dwTimestampFlags,
+ signerParams.pszAlgorithmOid,
+ signerParams.pwszTimestampURL,
+ signerParams.pCryptAttrs,
+ signerParams.pSipData,
+ signerParams.pSignerContext,
+ signerParams.pCryptoPolicy,
+ signerParams.pReserved);
+
+ FreeLibrary(msSignModule);
+
+ RETURN_FALSE_IF_FAILED("Could not sign package.");
+
+ if (sipClientData.pAppxSipState)
+ sipClientData.pAppxSipState->Release();
+
+ return true;
+}
+// ************ MSDN
+#endif // MSC_VER >= 1900
+
bool AppxEngine::getManifestFile(const QString &fileName, QString *manifest)
{
if (!QFile::exists(fileName)) {
@@ -194,6 +431,14 @@ AppxEngine::AppxEngine(Runner *runner, AppxEnginePrivate *dd)
d->packageFamilyName = QString::fromWCharArray(packageFamilyName);
CoTaskMemFree(packageFamilyName);
+#if _MSC_VER >= 1900
+ LPWSTR publisher;
+ packageId->GetPublisher(&publisher);
+ CHECK_RESULT_FATAL("Failed to retrieve publisher name from package.", return);
+ d->publisherName = QString::fromWCharArray(publisher);
+ CoTaskMemFree(publisher);
+#endif // _MSC_VER >= 1900
+
ComPtr<IAppxManifestApplicationsEnumerator> applications;
hr = manifestReader->GetApplications(&applications);
CHECK_RESULT_FATAL("Failed to get a list of applications from the manifest.", return);
@@ -441,3 +686,90 @@ bool AppxEngine::createPackage(const QString &packageFileName)
return true;
}
+
+bool AppxEngine::sign(const QString &fileName)
+{
+#if _MSC_VER >= 1900
+ Q_D(const AppxEngine);
+ BYTE buffer[256];
+ DWORD bufferSize = 256;
+
+ if (!CertStrToName(X509_ASN_ENCODING, wchar(d->publisherName), CERT_X500_NAME_STR, 0, buffer, &bufferSize, 0)) {
+ qCWarning(lcWinRtRunner) << "CertStrToName failed";
+ return false;
+ }
+ CERT_NAME_BLOB certBlob;
+ certBlob.cbData = bufferSize;
+ certBlob.pbData = buffer;
+
+ CRYPT_ALGORITHM_IDENTIFIER identifier;
+ identifier.pszObjId = strdup(szOID_RSA_SHA256RSA);
+ identifier.Parameters.cbData = 0;
+ identifier.Parameters.pbData = NULL;
+
+ CERT_EXTENSIONS extensions;
+ extensions.cExtension = 2;
+ extensions.rgExtension = new CERT_EXTENSION[2];
+
+ // Basic Constraints
+ CERT_BASIC_CONSTRAINTS2_INFO constraintsInfo;
+ constraintsInfo.fCA = FALSE;
+ constraintsInfo.fPathLenConstraint = FALSE;
+ constraintsInfo.dwPathLenConstraint = 0;
+
+ BYTE *constraintsEncoded = NULL;
+ DWORD encodedSize = 0;
+ CryptEncodeObject(X509_ASN_ENCODING, X509_BASIC_CONSTRAINTS2, &constraintsInfo,
+ constraintsEncoded, &encodedSize);
+ constraintsEncoded = new BYTE[encodedSize];
+ if (!CryptEncodeObject(X509_ASN_ENCODING, X509_BASIC_CONSTRAINTS2, &constraintsInfo,
+ constraintsEncoded, &encodedSize)) {
+ qCWarning(lcWinRtRunner) << "Could not encode basic constraints.";
+ delete [] constraintsEncoded;
+ return false;
+ }
+
+ extensions.rgExtension[0].pszObjId = strdup(szOID_BASIC_CONSTRAINTS2);
+ extensions.rgExtension[0].fCritical = TRUE;
+ extensions.rgExtension[0].Value.cbData = encodedSize;
+ extensions.rgExtension[0].Value.pbData = constraintsEncoded;
+
+ // Code Signing
+ char *codeSign = strdup(szOID_PKIX_KP_CODE_SIGNING);
+ CERT_ENHKEY_USAGE enhancedUsage;
+ enhancedUsage.cUsageIdentifier = 1;
+ enhancedUsage.rgpszUsageIdentifier = &codeSign;
+
+ BYTE *enhancedKeyEncoded = 0;
+ encodedSize = 0;
+ CryptEncodeObject(X509_ASN_ENCODING, X509_ENHANCED_KEY_USAGE, &enhancedUsage,
+ enhancedKeyEncoded, &encodedSize);
+ enhancedKeyEncoded = new BYTE[encodedSize];
+ if (!CryptEncodeObject(X509_ASN_ENCODING, X509_ENHANCED_KEY_USAGE, &enhancedUsage,
+ enhancedKeyEncoded, &encodedSize)) {
+ qCWarning(lcWinRtRunner) << "Could not encode enhanced key usage.";
+ delete [] constraintsEncoded;
+ return false;
+ }
+
+ extensions.rgExtension[1].pszObjId = strdup(szOID_ENHANCED_KEY_USAGE);
+ extensions.rgExtension[1].fCritical = TRUE;
+ extensions.rgExtension[1].Value.cbData = encodedSize;
+ extensions.rgExtension[1].Value.pbData = enhancedKeyEncoded;
+
+ PCCERT_CONTEXT context = CertCreateSelfSignCertificate(NULL, &certBlob, NULL, NULL,
+ &identifier, NULL, NULL, &extensions);
+
+ delete [] constraintsEncoded;
+
+ if (!context) {
+ qCWarning(lcWinRtRunner) << "Failed to create self sign certificate:" << GetLastError();
+ return false;
+ }
+
+ return signAppxPackage(context, wchar(fileName));
+#else // _MSC_VER < 1900
+ Q_UNUSED(fileName);
+ return true;
+#endif // _MSC_VER < 1900
+}
diff --git a/src/winrtrunner/appxengine.h b/src/winrtrunner/appxengine.h
index 30b03fe07..4aec67588 100644
--- a/src/winrtrunner/appxengine.h
+++ b/src/winrtrunner/appxengine.h
@@ -63,6 +63,7 @@ protected:
bool installDependencies();
bool createPackage(const QString &packageFileName);
+ bool sign(const QString &fileName);
static bool getManifestFile(const QString &fileName, QString *manifest = 0);
QScopedPointer<AppxEnginePrivate> d_ptr;
diff --git a/src/winrtrunner/appxengine_p.h b/src/winrtrunner/appxengine_p.h
index 4d20acf91..982c484b2 100644
--- a/src/winrtrunner/appxengine_p.h
+++ b/src/winrtrunner/appxengine_p.h
@@ -73,6 +73,7 @@ public:
QString manifest;
QString packageFullName;
QString packageFamilyName;
+ QString publisherName;
ABI::Windows::System::ProcessorArchitecture packageArchitecture;
QString executable;
qint64 pid;
diff --git a/src/winrtrunner/appxphoneengine.cpp b/src/winrtrunner/appxphoneengine.cpp
index e7cbf6709..edbb58ea5 100644
--- a/src/winrtrunner/appxphoneengine.cpp
+++ b/src/winrtrunner/appxphoneengine.cpp
@@ -258,6 +258,14 @@ AppxPhoneEngine::~AppxPhoneEngine()
QString AppxPhoneEngine::extensionSdkPath() const
{
+#if _MSC_VER >= 1900
+ const QByteArray extensionSdkDirRaw = qgetenv("ExtensionSdkDir");
+ if (extensionSdkDirRaw.isEmpty()) {
+ qCWarning(lcWinRtRunner) << "The environment variable ExtensionSdkDir is not set.";
+ return QString();
+ }
+ return QString::fromLocal8Bit(extensionSdkDirRaw);
+#else // _MSC_VER < 1900
HKEY regKey;
LONG hr = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
@@ -278,6 +286,7 @@ QString AppxPhoneEngine::extensionSdkPath() const
return QString::fromWCharArray(pathData, (pathLength - 1) / sizeof(wchar_t))
+ QLatin1String("ExtensionSDKs");
+#endif // _MSC_VER < 1900
}
bool AppxPhoneEngine::installPackage(IAppxManifestReader *reader, const QString &filePath)
@@ -384,6 +393,9 @@ bool AppxPhoneEngine::install(bool removeFirst)
if (!createPackage(packageFileName))
return false;
+ if (!sign(packageFileName))
+ return false;
+
ComPtr<IStream> manifestStream;
hr = SHCreateStreamOnFile(wchar(d->manifest), STGM_READ, &manifestStream);
RETURN_FALSE_IF_FAILED("Failed to open manifest stream");
diff --git a/src/winrtrunner/winrtrunner.pro b/src/winrtrunner/winrtrunner.pro
index c98f0df70..73ca2cdd4 100644
--- a/src/winrtrunner/winrtrunner.pro
+++ b/src/winrtrunner/winrtrunner.pro
@@ -17,4 +17,7 @@ win32-msvc2013|win32-msvc2015 {
include(../shared/corecon/corecon.pri)
}
+# Windows 10 requires signing
+*msvc2015: LIBS += -lcrypt32
+
load(qt_tool)