Michael Haephrati Ответов: 1

Как программно подписать код файла, когда требуется перекрестная подпись


Я столкнулся с необходимостью использовать SignerSignEx2() во время процесса отправки драйверов ядра на утверждение Microsoft.

SignerSignEx2()[^] используется для программной подписи этих драйверов. Корпорация Майкрософт требует использования Сертификат подписи кода EV (Extended Validation) [^] для драйверов ядра, ориентированных на Windows 10, и для этого требуется аппаратный маркер (Компания SafeNet eToekn[^], в большинстве случаев).
Мы получаем доступ к нашему токену с помощью разработанного нами инструмента, что делает его легким, в противном случае вам нужно каждый раз вводить пароль токена, который мы использовали SignTool.exe[^].

Однако для перекрестной подписи не существует большой документации о том, как использовать SignerSignEx2() (или более поздний SignerSignEx2 (), если уж на то пошло), чтобы объединить сертификат EV, который мы купили, с корневым сертификатом CA вместе с корневым сертификатом Microsoft.

Смотреть также эта страница о необходимости перекрестного знака.[^]

Что я уже пробовал:

В основном, следуя инструкциям в эта статья[^] и в Microsoft Docs документация. Эта статья руководит всем процессом использования 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);

Есть объяснение о штамповке времени, но ничего о перекрестной подписи. Несколько попыток, которые мы предприняли, привели к тому, что корневой сертификат заменил наш собственный сертификат вместо того, чтобы быть добавленным к нему в цепочке.
Моя функция предполагает, что сертификат EV уже считан в память (что позволяет мне либо прочитать его из файла .pfx, либо из eToken как PCCERT_CONTEXT ). Как вы можете видеть, я попытался прочитать перекрестный сертификат (CROSSCERTPATH) и каким-то образом совмещение его и этой части не работает. Я тоже предопределения SIGNER_TIMESTAMP_AUTHENTICODE это URL-адрес с отметкой времени, и эта часть действительно работает.


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;
}

Nelek

Затем используйте инструменты, которые у вас есть, и сообщите об этом как о "не являющемся вопросом". И понизьте его, чтобы компенсировать несправедливое повышение.
Жалуясь на вещи, но ничего не делая против этого, вы мало что добавляете к ценностям, которые защищаете

Nelek

И на всякий случай... Я сказал "вроде бы общий и немного широкий ответ", вот почему я пошел на неполный. Я думаю, что он мог бы иметь больше информации, чтобы прояснить ситуацию, чтобы дать "быстрый" ответ

Michael Haephrati

Спасибо за ваши добрые комментарии, ребята. Конечно, я уточню. Сейчас 5:00 утра! Позже будет сделано.

Patrice T

вы должны спросить Мисс

Michael Haephrati

Ваш комментарий хорош практически для любого вопроса о продукте Microsoft, так что же вы хотите сказать? если я найду ответ, то выложу его здесь.

1 Ответов

Рейтинг:
1

KarstenK

Пока не ясно, где вы застряли, но я нашел несколько хорошо выглядящих примеров кода для SignerSignEx что также демонстрирует рабочий процесс. Может быть, вам стоит начать с этого кода для проверки ваших данных.

PS: мы используем какой-то инструмент командной строки для подписи.