diff --git a/dlls/wintrust/register.c b/dlls/wintrust/register.c index 0a02ed209da..9b97d9cc511 100644 --- a/dlls/wintrust/register.c +++ b/dlls/wintrust/register.c @@ -837,7 +837,7 @@ BOOL WINAPI WintrustLoadFunctionPointers( GUID* pgActionID, pPfns->pfnAlloc = WINTRUST_Alloc; pPfns->pfnFree = WINTRUST_Free; pPfns->pfnAddStore2Chain = WINTRUST_AddStore; - pPfns->pfnAddSgnr2Chain = NULL; + pPfns->pfnAddSgnr2Chain = WINTRUST_AddSgnr; pPfns->pfnAddCert2Chain = NULL; pPfns->pfnAddPrivData2Chain = NULL; pPfns->psUIpfns = NULL; diff --git a/dlls/wintrust/tests/softpub.c b/dlls/wintrust/tests/softpub.c index 1eb967a72e4..b1ca23a9a84 100644 --- a/dlls/wintrust/tests/softpub.c +++ b/dlls/wintrust/tests/softpub.c @@ -91,6 +91,7 @@ static void test_utils(SAFE_PROVIDER_FUNCTIONS *funcs) { CRYPT_PROVIDER_DATA data = { 0 }; HCERTSTORE store; + CRYPT_PROVIDER_SGNR sgnr = { 0 }; BOOL ret; /* Crash @@ -118,6 +119,44 @@ static void test_utils(SAFE_PROVIDER_FUNCTIONS *funcs) } else skip("CertOpenStore failed: %08x\n", GetLastError()); + + /* Crash + ret = funcs->pfnAddSgnr2Chain(NULL, FALSE, 0, NULL); + ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, NULL); + */ + ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, &sgnr); + ok(ret, "pfnAddSgnr2Chain failed: %08x\n", GetLastError()); + ok(data.csSigners == 1, "Expected 1 signer, got %d\n", data.csSigners); + ok(data.pasSigners != NULL, "Expected pasSigners to be allocated\n"); + if (data.pasSigners) + { + ok(!memcmp(&data.pasSigners[0], &sgnr, sizeof(sgnr)), + "Unexpected data in signer\n"); + /* Adds into the location specified by the index */ + sgnr.cbStruct = sizeof(CRYPT_PROVIDER_SGNR); + sgnr.sftVerifyAsOf.dwLowDateTime = 0xdeadbeef; + ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 1, &sgnr); + ok(ret, "pfnAddSgnr2Chain failed: %08x\n", GetLastError()); + ok(data.csSigners == 2, "Expected 2 signers, got %d\n", data.csSigners); + ok(!memcmp(&data.pasSigners[1], &sgnr, sizeof(sgnr)), + "Unexpected data in signer\n"); + /* This also adds, but the data aren't copied */ + sgnr.cbStruct = sizeof(DWORD); + ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, &sgnr); + ok(ret, "pfnAddSgnr2Chain failed: %08x\n", GetLastError()); + ok(data.csSigners == 3, "Expected 3 signers, got %d\n", data.csSigners); + ok(data.pasSigners[0].cbStruct == 0, "Unexpected data size %d\n", + data.pasSigners[0].cbStruct); + ok(data.pasSigners[0].sftVerifyAsOf.dwLowDateTime == 0, + "Unexpected verify time %d\n", + data.pasSigners[0].sftVerifyAsOf.dwLowDateTime); + /* But too large a thing isn't added */ + sgnr.cbStruct = sizeof(sgnr) + sizeof(DWORD); + SetLastError(0xdeadbeef); + ret = funcs->pfnAddSgnr2Chain(&data, FALSE, 0, &sgnr); + ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, + "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + } } static void testInitialize(SAFE_PROVIDER_FUNCTIONS *funcs, GUID *actionID) diff --git a/dlls/wintrust/wintrust_main.c b/dlls/wintrust/wintrust_main.c index 6ecfb1daa2d..0f6dcd609de 100644 --- a/dlls/wintrust/wintrust_main.c +++ b/dlls/wintrust/wintrust_main.c @@ -252,3 +252,54 @@ BOOL WINAPI WINTRUST_AddStore(CRYPT_PROVIDER_DATA *data, HCERTSTORE store) SetLastError(ERROR_OUTOFMEMORY); return ret; } + +BOOL WINAPI WINTRUST_AddSgnr(CRYPT_PROVIDER_DATA *data, + BOOL fCounterSigner, DWORD idxSigner, CRYPT_PROVIDER_SGNR *sgnr) +{ + BOOL ret = FALSE; + + if (sgnr->cbStruct > sizeof(CRYPT_PROVIDER_SGNR)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + if (fCounterSigner) + { + FIXME("unimplemented for counter signers\n"); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + if (data->csSigners) + data->pasSigners = WINTRUST_ReAlloc(data->pasSigners, + (data->csSigners + 1) * sizeof(CRYPT_PROVIDER_SGNR)); + else + { + data->pasSigners = WINTRUST_Alloc(sizeof(CRYPT_PROVIDER_SGNR)); + data->csSigners = 0; + } + if (data->pasSigners) + { + if (idxSigner < data->csSigners) + memmove(&data->pasSigners[idxSigner], + &data->pasSigners[idxSigner + 1], + (data->csSigners - idxSigner) * sizeof(CRYPT_PROVIDER_SGNR)); + ret = TRUE; + if (sgnr->cbStruct == sizeof(CRYPT_PROVIDER_SGNR)) + { + /* The PSDK says psSigner should be allocated using pfnAlloc, but + * it doesn't say anything about ownership. Since callers are + * internal, assume ownership is passed, and just store the + * pointer. + */ + memcpy(&data->pasSigners[idxSigner], sgnr, + sizeof(CRYPT_PROVIDER_SGNR)); + } + else + memset(&data->pasSigners[idxSigner], 0, + sizeof(CRYPT_PROVIDER_SGNR)); + data->csSigners++; + } + else + SetLastError(ERROR_OUTOFMEMORY); + return ret; +} diff --git a/dlls/wintrust/wintrust_priv.h b/dlls/wintrust/wintrust_priv.h index 40f2e5d9d1a..75b043845df 100644 --- a/dlls/wintrust/wintrust_priv.h +++ b/dlls/wintrust/wintrust_priv.h @@ -22,5 +22,7 @@ void * WINAPI WINTRUST_Alloc(DWORD cb); void * WINAPI WINTRUST_ReAlloc(void *ptr, DWORD cb); void WINAPI WINTRUST_Free(void *p); BOOL WINAPI WINTRUST_AddStore(CRYPT_PROVIDER_DATA *data, HCERTSTORE store); +BOOL WINAPI WINTRUST_AddSgnr(CRYPT_PROVIDER_DATA *data, + BOOL fCounterSigner, DWORD idxSigner, CRYPT_PROVIDER_SGNR *sgnr); #endif /* ndef __WINTRUST_PRIV_H__ */