Click here to Skip to main content
15,867,453 members
Please Sign up or sign in to vote.
4.80/5 (4 votes)
I came across the need to use SignerSignEx2() during to the process of submitting Kernel drivers for Microsoft’s approval.

SignerSignEx2()[^] is used to programmatically sign these drivers. Microsoft requires the use of an EV (Extended Validation) Code Signing Certificate[^] for Kernel Drivers targeted to Windows 10, and that requires a hardware token (Safenet eToekn[^], in most cases).
We access our token from a tool we developed, which makes it easy, otherwise you need to key in the token’s password each time, which is the case had we used SignTool.exe[^].

However, in order to cross sign, there is no much documentation as for how to use SignerSignEx2() (or the more recent SignerSignEx2() for that matter) to combine the EV certificate we bought, with the CA root certificate along with Microsoft’s root certificate.

See also this page about the need to cross sign.[^]

What I have tried:

Basically, following the instructions in this article[^] and in Microsoft Docs documentation. The article guides throughout the process of using SignerSignEx2().[^]
SignerSignEx2Function SignerSignEx2 = reinterpret_cast<SignerSignEx2Function>(
    GetProcAddress(msSignModule, "SignerSignEx2"));
if (SignerSignEx2)
{
    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);

There is explanation about time stamping but nothing about cross signing. Several attempts we have made caused the Root Certificate to replace our own certificate instead of being added to it in a chain.
My function assumes the EV Certificate has already been read to memory (that allows me to either read it from a .pfx file or from the eToken as PCCERT_CONTEXT ). As you can see, I tried reading the Cross Certificate (CROSSCERTPATH) and somehow combining it and that part doesn't work. I am also predefining SIGNER_TIMESTAMP_AUTHENTICODE which is the time stamping URL, and that parts does work.


HRESULT SignAppxPackage(
	_In_ PCCERT_CONTEXT signingCertContext,
	_In_ LPCWSTR packageFilePath)
{

	// First read the root certificate
	PCCERT_CONTEXT Root = OpenCert(CROSSCERTPATH);

	HRESULT hr = S_OK;

	// Initialize the parameters for SignerSignEx2
	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_STORE;
	certStoreInfo.pSigningCert = Root;		// ??? not sure
//	certStoreInfo.hCertStore = Root;


	SIGNER_CERT cert = {};
	cert.cbSize = sizeof(SIGNER_CERT);
	cert.dwCertChoice = SIGNER_CERT_POLICY_CHAIN;
	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_256;
	signatureInfo.dwAttrChoice = SIGNER_NO_ATTR;

	SIGNER_SIGN_EX2_PARAMS signerParams = {};
	signerParams.pSubjectInfo = &subjectInfo;
	signerParams.pSigningCert = &cert;
	signerParams.pSignatureInfo = &signatureInfo;
	signerParams.dwTimestampFlags = SIGNER_TIMESTAMP_AUTHENTICODE;
	signerParams.pszAlgorithmOid = NULL;
	signerParams.pwszTimestampURL = TIMESTAMPURL;
	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)
	{
		SignerSignEx2Function SignerSignEx2 = reinterpret_cast<SignerSignEx2Function>(
			GetProcAddress(msSignModule, "SignerSignEx2"));
		if (SignerSignEx2)
		{
			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);
		}
		else
		{
			DWORD lastError = GetLastError();
			hr = HRESULT_FROM_WIN32(lastError);
		}

		FreeLibrary(msSignModule);
	}
	else
	{
		DWORD lastError = GetLastError();
		hr = HRESULT_FROM_WIN32(lastError);
	}

	// Free any state used during app package signing
	if (sipClientData.pAppxSipState)
	{
		sipClientData.pAppxSipState->Release();
	}

	return hr;
}
Posted
Updated 6-Sep-18 4:48am
v3
Comments
Nelek 26-Aug-18 3:38am    
Then use the tools you have available and report it as "not being a question". And downvote it to compensate the unfair upvote.
Complaining about things but doing nothing against it, adds few to the values you are defending
Nelek 26-Aug-18 3:44am    
And just in case... I said "kind of generic and a bit wide to answer", that's why I went for incomplete. I think it could have more information to clarify the situation in order to deliver a "quick" answer
Michael Haephrati 26-Aug-18 5:14am    
Thanks for your kind comments, guys. Sure I will elaborate. It's 5:00 AM now! Later on will do.
Patrice T 26-Aug-18 8:34am    
you should ask MS.
Michael Haephrati 26-Aug-18 10:09am    
Your comment is good for almost any question about a Microsoft product, so what's your point? if I find the answer I will post it here.

1 solution

It is not clear where you stuck, but I found some good looking example code for SignerSignEx which also demonstrates the workflow. Maybe you should start with that code, for proofing your data.

PS: We are using some command line tool for signing.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900