diff --git a/patches/crypt32-CRYPT_KEY_PROV_INFO/0001-crypt32-Fix-reading-and-writing-CRYPT_KEY_PROV_INFO-.patch b/patches/crypt32-CRYPT_KEY_PROV_INFO/0001-crypt32-Fix-reading-and-writing-CRYPT_KEY_PROV_INFO-.patch new file mode 100644 index 00000000..2d566aca --- /dev/null +++ b/patches/crypt32-CRYPT_KEY_PROV_INFO/0001-crypt32-Fix-reading-and-writing-CRYPT_KEY_PROV_INFO-.patch @@ -0,0 +1,677 @@ +From bfa13a38c04bf3ef50cca78d0b9bf0e849fb9cc8 Mon Sep 17 00:00:00 2001 +From: Dmitry Timoshkov +Date: Tue, 10 Nov 2020 10:22:19 +0300 +Subject: [PATCH] crypt32: Fix reading and writing CRYPT_KEY_PROV_INFO + certificate property. + +v2: Updated for current git. + +Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50024 +Signed-off-by: Dmitry Timoshkov +--- + dlls/crypt32/cert.c | 251 +++++++++++++-------------------- + dlls/crypt32/crypt32_private.h | 8 -- + dlls/crypt32/serialize.c | 187 +++++++++++++++++++++++- + dlls/crypt32/tests/cert.c | 96 +++++++++++++ + 4 files changed, 375 insertions(+), 167 deletions(-) + +diff --git a/dlls/crypt32/cert.c b/dlls/crypt32/cert.c +index c0bec721fd1..aad8fa047b7 100644 +--- a/dlls/crypt32/cert.c ++++ b/dlls/crypt32/cert.c +@@ -434,6 +434,84 @@ void CRYPT_ConvertKeyContext(const struct store_CERT_KEY_CONTEXT *src, CERT_KEY_ + dst->dwKeySpec = src->dwKeySpec; + } + ++/* ++ * Fix offsets in a continuous block of memory of CRYPT_KEY_PROV_INFO with ++ * its associated data. ++ */ ++static void fix_KeyProvInfoProperty(CRYPT_KEY_PROV_INFO *info) ++{ ++ BYTE *data; ++ DWORD i; ++ ++ data = (BYTE *)(info + 1) + sizeof(CRYPT_KEY_PROV_PARAM) * info->cProvParam; ++ ++ if (info->pwszContainerName) ++ { ++ info->pwszContainerName = (LPWSTR)data; ++ data += (lstrlenW(info->pwszContainerName) + 1) * sizeof(WCHAR); ++ } ++ ++ if (info->pwszProvName) ++ { ++ info->pwszProvName = (LPWSTR)data; ++ data += (lstrlenW(info->pwszProvName) + 1) * sizeof(WCHAR); ++ } ++ ++ info->rgProvParam = info->cProvParam ? (CRYPT_KEY_PROV_PARAM *)(info + 1) : NULL; ++ ++ for (i = 0; i < info->cProvParam; i++) ++ { ++ info->rgProvParam[i].pbData = info->rgProvParam[i].cbData ? data : NULL; ++ data += info->rgProvParam[i].cbData; ++ } ++} ++ ++/* ++ * Copy to a continuous block of memory of CRYPT_KEY_PROV_INFO with ++ * its associated data. ++ */ ++static void copy_KeyProvInfoProperty(const CRYPT_KEY_PROV_INFO *from, CRYPT_KEY_PROV_INFO *to) ++{ ++ BYTE *data; ++ DWORD i; ++ ++ data = (BYTE *)(to + 1) + sizeof(CRYPT_KEY_PROV_PARAM) * from->cProvParam; ++ ++ if (from->pwszContainerName) ++ { ++ to->pwszContainerName = (LPWSTR)data; ++ lstrcpyW((LPWSTR)data, from->pwszContainerName); ++ data += (lstrlenW(from->pwszContainerName) + 1) * sizeof(WCHAR); ++ } ++ else ++ to->pwszContainerName = NULL; ++ ++ if (from->pwszProvName) ++ { ++ to->pwszProvName = (LPWSTR)data; ++ lstrcpyW((LPWSTR)data, from->pwszProvName); ++ data += (lstrlenW(from->pwszProvName) + 1) * sizeof(WCHAR); ++ } ++ else ++ to->pwszProvName = NULL; ++ ++ to->dwProvType = from->dwProvType; ++ to->dwFlags = from->dwFlags; ++ to->cProvParam = from->cProvParam; ++ to->rgProvParam = from->cProvParam ? (CRYPT_KEY_PROV_PARAM *)(to + 1) : NULL; ++ to->dwKeySpec = from->dwKeySpec; ++ ++ for (i = 0; i < from->cProvParam; i++) ++ { ++ to->rgProvParam[i].dwParam = from->rgProvParam[i].dwParam; ++ to->rgProvParam[i].dwFlags = from->rgProvParam[i].dwFlags; ++ to->rgProvParam[i].cbData = from->rgProvParam[i].cbData; ++ to->rgProvParam[i].pbData = from->rgProvParam[i].cbData ? data : NULL; ++ memcpy(data, from->rgProvParam[i].pbData, from->rgProvParam[i].cbData); ++ data += from->rgProvParam[i].cbData; ++ } ++} ++ + static BOOL CertContext_GetProperty(cert_t *cert, DWORD dwPropId, + void *pvData, DWORD *pcbData) + { +@@ -535,87 +613,6 @@ static BOOL CertContext_GetProperty(cert_t *cert, DWORD dwPropId, + return ret; + } + +-/* 64-bit compatible layout, so that 64-bit crypt32 is able to read +- * the structure saved by 32-bit crypt32. +- */ +-typedef struct +-{ +- ULONG64 pwszContainerName; +- ULONG64 pwszProvName; +- DWORD dwProvType; +- DWORD dwFlags; +- DWORD cProvParam; +- ULONG64 rgProvParam; +- DWORD dwKeySpec; +-} store_CRYPT_KEY_PROV_INFO; +- +-typedef struct +-{ +- DWORD dwParam; +- ULONG64 pbData; +- DWORD cbData; +- DWORD dwFlags; +-} store_CRYPT_KEY_PROV_PARAM; +- +-void CRYPT_FixKeyProvInfoPointers(PCRYPT_KEY_PROV_INFO buf) +-{ +- CRYPT_KEY_PROV_INFO info; +- store_CRYPT_KEY_PROV_INFO *store = (store_CRYPT_KEY_PROV_INFO *)buf; +- BYTE *p = (BYTE *)(store + 1); +- +- if (store->pwszContainerName) +- { +- info.pwszContainerName = (LPWSTR)((BYTE *)store + store->pwszContainerName); +- p += (lstrlenW(info.pwszContainerName) + 1) * sizeof(WCHAR); +- } +- else +- info.pwszContainerName = NULL; +- +- if (store->pwszProvName) +- { +- info.pwszProvName = (LPWSTR)((BYTE *)store + store->pwszProvName); +- p += (lstrlenW(info.pwszProvName) + 1) * sizeof(WCHAR); +- } +- else +- info.pwszProvName = NULL; +- +- info.dwProvType = store->dwProvType; +- info.dwFlags = store->dwFlags; +- info.dwKeySpec = store->dwKeySpec; +- info.cProvParam = store->cProvParam; +- +- if (info.cProvParam) +- { +- DWORD i; +- +- info.rgProvParam = (CRYPT_KEY_PROV_PARAM *)p; +- +- for (i = 0; i < store->cProvParam; i++) +- { +- CRYPT_KEY_PROV_PARAM param; +- store_CRYPT_KEY_PROV_PARAM *store_param; +- +- store_param = (store_CRYPT_KEY_PROV_PARAM *)p; +- p += sizeof(*store_param); +- +- param.dwParam = store_param[i].dwParam; +- param.dwFlags = store_param[i].dwFlags; +- param.cbData = store_param[i].cbData; +- param.pbData = param.cbData ? p : NULL; +- p += store_param[i].cbData; +- +- memcpy(&info.rgProvParam[i], ¶m, sizeof(param)); +- } +- } +- else +- info.rgProvParam = NULL; +- +- TRACE("%s,%s,%u,%08x,%u,%p,%u\n", debugstr_w(info.pwszContainerName), debugstr_w(info.pwszProvName), +- info.dwProvType, info.dwFlags, info.cProvParam, info.rgProvParam, info.dwKeySpec); +- +- *buf = info; +-} +- + BOOL WINAPI CertGetCertificateContextProperty(PCCERT_CONTEXT pCertContext, + DWORD dwPropId, void *pvData, DWORD *pcbData) + { +@@ -649,10 +646,9 @@ BOOL WINAPI CertGetCertificateContextProperty(PCCERT_CONTEXT pCertContext, + break; + } + case CERT_KEY_PROV_INFO_PROP_ID: +- ret = CertContext_GetProperty(cert, dwPropId, pvData, +- pcbData); ++ ret = CertContext_GetProperty(cert, dwPropId, pvData, pcbData); + if (ret && pvData) +- CRYPT_FixKeyProvInfoPointers(pvData); ++ fix_KeyProvInfoProperty(pvData); + break; + default: + ret = CertContext_GetProperty(cert, dwPropId, pvData, +@@ -663,69 +659,14 @@ BOOL WINAPI CertGetCertificateContextProperty(PCCERT_CONTEXT pCertContext, + return ret; + } + +-/* Copies key provider info from from into to, where to is assumed to be a +- * contiguous buffer of memory large enough for from and all its associated +- * data, but whose pointers are uninitialized. +- * Upon return, to contains a contiguous copy of from, packed in the following +- * order: +- * - store_CRYPT_KEY_PROV_INFO +- * - pwszContainerName +- * - pwszProvName +- * - store_CRYPT_KEY_PROV_PARAM[0] +- * - store_CRYPT_KEY_PROV_PARAM[0].data +- * - ... ++/* ++ * Create a continuous block of memory for CRYPT_KEY_PROV_INFO with ++ * its associated data, and add it to the certificate properties. + */ +-static void CRYPT_CopyKeyProvInfo(store_CRYPT_KEY_PROV_INFO *to, const CRYPT_KEY_PROV_INFO *from) ++static BOOL CertContext_SetKeyProvInfoProperty(CONTEXT_PROPERTY_LIST *properties, const CRYPT_KEY_PROV_INFO *info) + { +- DWORD i; +- BYTE *p; +- store_CRYPT_KEY_PROV_PARAM *param; +- +- p = (BYTE *)(to + 1); +- +- if (from->pwszContainerName) +- { +- to->pwszContainerName = p - (BYTE *)to; +- lstrcpyW((LPWSTR)p, from->pwszContainerName); +- p += (lstrlenW(from->pwszContainerName) + 1) * sizeof(WCHAR); +- } +- else +- to->pwszContainerName = 0; +- +- if (from->pwszProvName) +- { +- to->pwszProvName = p - (BYTE *)to; +- lstrcpyW((LPWSTR)p, from->pwszProvName); +- p += (lstrlenW(from->pwszProvName) + 1) * sizeof(WCHAR); +- } +- else +- to->pwszProvName = 0; +- +- to->dwProvType = from->dwProvType; +- to->dwFlags = from->dwFlags; +- to->cProvParam = from->cProvParam; +- to->rgProvParam = 0; +- to->dwKeySpec = from->dwKeySpec; +- +- for (i = 0; i < to->cProvParam; i++) +- { +- param = (store_CRYPT_KEY_PROV_PARAM *)p; +- p += sizeof(*param); +- +- param->dwParam = from->rgProvParam[i].dwParam; +- param->pbData = 0; +- param->cbData = from->rgProvParam[i].cbData; +- param->dwFlags = from->rgProvParam[i].dwFlags; +- memcpy(p, from->rgProvParam[i].pbData, from->rgProvParam[i].cbData); +- p += from->rgProvParam[i].cbData; +- } +-} +- +-static BOOL CertContext_SetKeyProvInfoProperty(CONTEXT_PROPERTY_LIST *properties, +- const CRYPT_KEY_PROV_INFO *info) +-{ +- BYTE *buf; +- DWORD size = sizeof(store_CRYPT_KEY_PROV_INFO), i; ++ CRYPT_KEY_PROV_INFO *prop; ++ DWORD size = sizeof(CRYPT_KEY_PROV_INFO), i; + BOOL ret; + + if (info->pwszContainerName) +@@ -734,18 +675,20 @@ static BOOL CertContext_SetKeyProvInfoProperty(CONTEXT_PROPERTY_LIST *properties + size += (lstrlenW(info->pwszProvName) + 1) * sizeof(WCHAR); + + for (i = 0; i < info->cProvParam; i++) +- size += sizeof(store_CRYPT_KEY_PROV_PARAM) + info->rgProvParam[i].cbData; ++ size += sizeof(CRYPT_KEY_PROV_PARAM) + info->rgProvParam[i].cbData; + +- buf = CryptMemAlloc(size); +- if (buf) ++ prop = HeapAlloc(GetProcessHeap(), 0, size); ++ if (!prop) + { +- CRYPT_CopyKeyProvInfo((store_CRYPT_KEY_PROV_INFO *)buf, info); +- ret = ContextPropertyList_SetProperty(properties, +- CERT_KEY_PROV_INFO_PROP_ID, buf, size); +- CryptMemFree(buf); ++ SetLastError(ERROR_OUTOFMEMORY); ++ return FALSE; + } +- else +- ret = FALSE; ++ ++ copy_KeyProvInfoProperty(info, prop); ++ ++ ret = ContextPropertyList_SetProperty(properties, CERT_KEY_PROV_INFO_PROP_ID, (const BYTE *)prop, size); ++ HeapFree(GetProcessHeap(), 0, prop); ++ + return ret; + } + +diff --git a/dlls/crypt32/crypt32_private.h b/dlls/crypt32/crypt32_private.h +index a4664ed85a9..30cf4334de4 100644 +--- a/dlls/crypt32/crypt32_private.h ++++ b/dlls/crypt32/crypt32_private.h +@@ -370,14 +370,6 @@ BOOL CRYPT_ReadSerializedStoreFromFile(HANDLE file, HCERTSTORE store) DECLSPEC_H + BOOL CRYPT_ReadSerializedStoreFromBlob(const CRYPT_DATA_BLOB *blob, + HCERTSTORE store) DECLSPEC_HIDDEN; + +-/* Fixes up the pointers in info, where info is assumed to be a +- * CRYPT_KEY_PROV_INFO, followed by its container name, provider name, and any +- * provider parameters, in a contiguous buffer, but where info's pointers are +- * assumed to be invalid. Upon return, info's pointers point to the +- * appropriate memory locations. +- */ +-void CRYPT_FixKeyProvInfoPointers(PCRYPT_KEY_PROV_INFO info) DECLSPEC_HIDDEN; +- + struct store_CERT_KEY_CONTEXT + { + DWORD cbSize; +diff --git a/dlls/crypt32/serialize.c b/dlls/crypt32/serialize.c +index d5153deb106..8fa24370b65 100644 +--- a/dlls/crypt32/serialize.c ++++ b/dlls/crypt32/serialize.c +@@ -36,6 +36,86 @@ typedef struct _WINE_CERT_PROP_HEADER + DWORD cb; + } WINE_CERT_PROP_HEADER; + ++struct store_CRYPT_KEY_PROV_INFO ++{ ++ DWORD pwszContainerName; ++ DWORD pwszProvName; ++ DWORD dwProvType; ++ DWORD dwFlags; ++ DWORD cProvParam; ++ DWORD rgProvParam; ++ DWORD dwKeySpec; ++}; ++ ++struct store_CRYPT_KEY_PROV_PARAM ++{ ++ DWORD dwParam; ++ DWORD pbData; ++ DWORD cbData; ++ DWORD dwFlags; ++}; ++ ++static DWORD serialize_KeyProvInfoProperty(const CRYPT_KEY_PROV_INFO *info, struct store_CRYPT_KEY_PROV_INFO **ret) ++{ ++ struct store_CRYPT_KEY_PROV_INFO *store; ++ struct store_CRYPT_KEY_PROV_PARAM *param; ++ DWORD size = sizeof(struct store_CRYPT_KEY_PROV_INFO), i; ++ BYTE *data; ++ ++ if (info->pwszContainerName) ++ size += (lstrlenW(info->pwszContainerName) + 1) * sizeof(WCHAR); ++ if (info->pwszProvName) ++ size += (lstrlenW(info->pwszProvName) + 1) * sizeof(WCHAR); ++ ++ for (i = 0; i < info->cProvParam; i++) ++ size += sizeof(struct store_CRYPT_KEY_PROV_PARAM) + info->rgProvParam[i].cbData; ++ ++ if (!ret) return size; ++ ++ store = HeapAlloc(GetProcessHeap(), 0, size); ++ if (!store) return 0; ++ ++ param = (struct store_CRYPT_KEY_PROV_PARAM *)(store + 1); ++ data = (BYTE *)param + sizeof(struct store_CRYPT_KEY_PROV_PARAM) * info->cProvParam; ++ ++ if (info->pwszContainerName) ++ { ++ store->pwszContainerName = data - (BYTE *)store; ++ lstrcpyW((LPWSTR)data, info->pwszContainerName); ++ data += (lstrlenW(info->pwszContainerName) + 1) * sizeof(WCHAR); ++ } ++ else ++ store->pwszContainerName = 0; ++ ++ if (info->pwszProvName) ++ { ++ store->pwszProvName = data - (BYTE *)store; ++ lstrcpyW((LPWSTR)data, info->pwszProvName); ++ data += (lstrlenW(info->pwszProvName) + 1) * sizeof(WCHAR); ++ } ++ else ++ store->pwszProvName = 0; ++ ++ store->dwProvType = info->dwProvType; ++ store->dwFlags = info->dwFlags; ++ store->cProvParam = info->cProvParam; ++ store->rgProvParam = info->cProvParam ? (BYTE *)param - (BYTE *)store : 0; ++ store->dwKeySpec = info->dwKeySpec; ++ ++ for (i = 0; i < info->cProvParam; i++) ++ { ++ param[i].dwParam = info->rgProvParam[i].dwParam; ++ param[i].dwFlags = info->rgProvParam[i].dwFlags; ++ param[i].cbData = info->rgProvParam[i].cbData; ++ param[i].pbData = param[i].cbData ? data - (BYTE *)store : 0; ++ memcpy(data, info->rgProvParam[i].pbData, info->rgProvParam[i].cbData); ++ data += info->rgProvParam[i].cbData; ++ } ++ ++ *ret = store; ++ return size; ++} ++ + static BOOL CRYPT_SerializeStoreElement(const void *context, + const BYTE *encodedContext, DWORD cbEncodedContext, DWORD contextPropID, + const WINE_CONTEXT_INTERFACE *contextInterface, DWORD dwFlags, BOOL omitHashes, +@@ -60,7 +140,16 @@ static BOOL CRYPT_SerializeStoreElement(const void *context, + + ret = contextInterface->getProp(context, prop, NULL, &propSize); + if (ret) ++ { ++ if (prop == CERT_KEY_PROV_INFO_PROP_ID) ++ { ++ BYTE *info = CryptMemAlloc(propSize); ++ contextInterface->getProp(context, prop, info, &propSize); ++ propSize = serialize_KeyProvInfoProperty((const CRYPT_KEY_PROV_INFO *)info, NULL); ++ CryptMemFree(info); ++ } + bytesNeeded += sizeof(WINE_CERT_PROP_HEADER) + propSize; ++ } + } + } while (ret && prop != 0); + +@@ -106,6 +195,14 @@ static BOOL CRYPT_SerializeStoreElement(const void *context, + &propSize); + if (ret) + { ++ if (prop == CERT_KEY_PROV_INFO_PROP_ID) ++ { ++ struct store_CRYPT_KEY_PROV_INFO *store; ++ propSize = serialize_KeyProvInfoProperty((const CRYPT_KEY_PROV_INFO *)buf, &store); ++ CryptMemFree(buf); ++ buf = (BYTE *)store; ++ } ++ + hdr = (WINE_CERT_PROP_HEADER*)pbElement; + hdr->propID = prop; + hdr->unknown = 1; +@@ -215,6 +312,83 @@ static const WINE_CERT_PROP_HEADER *CRYPT_findPropID(const BYTE *buf, + return ret; + } + ++static DWORD read_serialized_KeyProvInfoProperty(const struct store_CRYPT_KEY_PROV_INFO *store, CRYPT_KEY_PROV_INFO **ret) ++{ ++ const struct store_CRYPT_KEY_PROV_PARAM *param; ++ CRYPT_KEY_PROV_INFO *info; ++ DWORD size = sizeof(CRYPT_KEY_PROV_INFO), i; ++ const BYTE *base; ++ BYTE *data; ++ ++ base = (const BYTE *)store; ++ param = (const struct store_CRYPT_KEY_PROV_PARAM *)(base + store->rgProvParam); ++ ++ if (store->pwszContainerName) ++ size += (lstrlenW((LPCWSTR)(base + store->pwszContainerName)) + 1) * sizeof(WCHAR); ++ if (store->pwszProvName) ++ size += (lstrlenW((LPCWSTR)(base + store->pwszProvName)) + 1) * sizeof(WCHAR); ++ ++ for (i = 0; i < store->cProvParam; i++) ++ size += sizeof(CRYPT_KEY_PROV_PARAM) + param[i].cbData; ++ ++ info = HeapAlloc(GetProcessHeap(), 0, size); ++ if (!info) ++ { ++ SetLastError(ERROR_OUTOFMEMORY); ++ return 0; ++ } ++ ++ data = (BYTE *)(info + 1) + sizeof(CRYPT_KEY_PROV_PARAM) * store->cProvParam; ++ ++ if (store->pwszContainerName) ++ { ++ info->pwszContainerName = (LPWSTR)data; ++ lstrcpyW(info->pwszContainerName, (LPCWSTR)((const BYTE *)store + store->pwszContainerName)); ++ data += (lstrlenW(info->pwszContainerName) + 1) * sizeof(WCHAR); ++ } ++ else ++ info->pwszContainerName = NULL; ++ ++ if (store->pwszProvName) ++ { ++ info->pwszProvName = (LPWSTR)data; ++ lstrcpyW(info->pwszProvName, (LPCWSTR)((const BYTE *)store + store->pwszProvName)); ++ data += (lstrlenW(info->pwszProvName) + 1) * sizeof(WCHAR); ++ } ++ else ++ info->pwszProvName = NULL; ++ ++ info->dwProvType = store->dwProvType; ++ info->dwFlags = store->dwFlags; ++ info->dwKeySpec = store->dwKeySpec; ++ info->cProvParam = store->cProvParam; ++ ++ if (info->cProvParam) ++ { ++ DWORD i; ++ ++ info->rgProvParam = (CRYPT_KEY_PROV_PARAM *)(info + 1); ++ ++ for (i = 0; i < info->cProvParam; i++) ++ { ++ info->rgProvParam[i].dwParam = param[i].dwParam; ++ info->rgProvParam[i].dwFlags = param[i].dwFlags; ++ info->rgProvParam[i].cbData = param[i].cbData; ++ info->rgProvParam[i].pbData = param[i].cbData ? data : NULL; ++ memcpy(info->rgProvParam[i].pbData, base + param[i].pbData, param[i].cbData); ++ data += param[i].cbData; ++ } ++ } ++ else ++ info->rgProvParam = NULL; ++ ++ TRACE("%s,%s,%u,%08x,%u,%p,%u\n", debugstr_w(info->pwszContainerName), debugstr_w(info->pwszProvName), ++ info->dwProvType, info->dwFlags, info->cProvParam, info->rgProvParam, info->dwKeySpec); ++ ++ *ret = info; ++ return size; ++} ++ + static BOOL CRYPT_ReadContextProp( + const WINE_CONTEXT_INTERFACE *contextInterface, const void *context, + const WINE_CERT_PROP_HEADER *hdr, const BYTE *pbElement, DWORD cbElement) +@@ -269,12 +443,15 @@ static BOOL CRYPT_ReadContextProp( + break; + case CERT_KEY_PROV_INFO_PROP_ID: + { +- PCRYPT_KEY_PROV_INFO info = +- (PCRYPT_KEY_PROV_INFO)pbElement; ++ CRYPT_KEY_PROV_INFO *info; + +- CRYPT_FixKeyProvInfoPointers(info); +- ret = contextInterface->setProp(context, +- hdr->propID, 0, pbElement); ++ if (read_serialized_KeyProvInfoProperty((const struct store_CRYPT_KEY_PROV_INFO *)pbElement, &info)) ++ { ++ ret = contextInterface->setProp(context, hdr->propID, 0, info); ++ CryptMemFree(info); ++ } ++ else ++ ret = FALSE; + break; + } + case CERT_KEY_CONTEXT_PROP_ID: +diff --git a/dlls/crypt32/tests/cert.c b/dlls/crypt32/tests/cert.c +index d9f839c72d2..745770f0095 100644 +--- a/dlls/crypt32/tests/cert.c ++++ b/dlls/crypt32/tests/cert.c +@@ -4142,6 +4142,101 @@ static void testGetPublicKeyLength(void) + "Expected length 56, got %d\n", ret); + } + ++static void testKeyProvInfo(void) ++{ ++ static WCHAR containerW[] = L"Wine Test Container"; ++ static WCHAR providerW[] = L"Hello World CSP"; ++ static CRYPT_KEY_PROV_PARAM param[2] = { { 0x4444, (BYTE *)"param", 6, 0x5555 }, { 0x7777, (BYTE *)"param2", 7, 0x8888 } }; ++ HCERTSTORE store; ++ const CERT_CONTEXT *cert; ++ CERT_NAME_BLOB name; ++ CRYPT_KEY_PROV_INFO *info, info2; ++ BOOL ret; ++ DWORD size; ++ ++ store = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0, ++ CERT_SYSTEM_STORE_CURRENT_USER, "My"); ++ ok(store != NULL, "CertOpenStore error %u\n", GetLastError()); ++ ++ cert = CertCreateCertificateContext(X509_ASN_ENCODING, selfSignedCert, sizeof(selfSignedCert)); ++ ok(cert != NULL, "CertCreateCertificateContext error %#x\n", GetLastError()); ++ ++ info2.pwszContainerName = containerW; ++ info2.pwszProvName = providerW; ++ info2.dwProvType = 0x12345678; ++ info2.dwFlags = 0x87654321; ++ info2.cProvParam = ARRAY_SIZE(param); ++ info2.rgProvParam = param; ++ info2.dwKeySpec = 0x11223344; ++ ret = CertSetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, 0, &info2); ++ ok(ret, "CertSetCertificateContextProperty error %#x\n", GetLastError()); ++ ++ ret = CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, NULL, &size); ++ ok(ret, "CertGetCertificateContextProperty error %#x\n", GetLastError()); ++ info = HeapAlloc(GetProcessHeap(), 0, size); ++ ret = CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, info, &size); ++ ok(ret, "CertGetCertificateContextProperty error %#x\n", GetLastError()); ++ ok(!lstrcmpW(info->pwszContainerName, containerW), "got %s\n", wine_dbgstr_w(info->pwszContainerName)); ++ ok(!lstrcmpW(info->pwszProvName, providerW), "got %s\n", wine_dbgstr_w(info->pwszProvName)); ++ ok(info->dwProvType == 0x12345678, "got %#x\n", info->dwProvType); ++ ok(info->dwFlags == 0x87654321, "got %#x\n", info->dwFlags); ++ ok(info->dwKeySpec == 0x11223344, "got %#x\n", info->dwKeySpec); ++ ok(info->cProvParam == 2, "got %#x\n", info->cProvParam); ++ ok(info->rgProvParam != NULL, "got %p\n", info->rgProvParam); ++ ok(info->rgProvParam[0].dwParam == param[0].dwParam, "got %#x\n", info->rgProvParam[0].dwParam); ++ ok(info->rgProvParam[0].cbData == param[0].cbData, "got %#x\n", info->rgProvParam[0].cbData); ++ ok(!memcmp(info->rgProvParam[0].pbData, param[0].pbData, param[0].cbData), "param1 mismatch\n"); ++ ok(info->rgProvParam[0].dwFlags == param[0].dwFlags, "got %#x\n", info->rgProvParam[1].dwFlags); ++ ok(info->rgProvParam[1].dwParam == param[1].dwParam, "got %#x\n", info->rgProvParam[1].dwParam); ++ ok(info->rgProvParam[1].cbData == param[1].cbData, "got %#x\n", info->rgProvParam[1].cbData); ++ ok(!memcmp(info->rgProvParam[1].pbData, param[1].pbData, param[1].cbData), "param2 mismatch\n"); ++ ok(info->rgProvParam[1].dwFlags == param[1].dwFlags, "got %#x\n", info->rgProvParam[1].dwFlags); ++ HeapFree(GetProcessHeap(), 0, info); ++ ++ ret = CertAddCertificateContextToStore(store, cert, CERT_STORE_ADD_NEW, NULL); ++ ok(ret, "CertAddCertificateContextToStore error %#x\n", GetLastError()); ++ ++ CertFreeCertificateContext(cert); ++ CertCloseStore(store, 0); ++ ++ store = CertOpenStore(CERT_STORE_PROV_SYSTEM_A, 0, 0, ++ CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG, "My"); ++ ok(store != NULL, "CertOpenStore error %u\n", GetLastError()); ++ ++ name.pbData = subjectName; ++ name.cbData = sizeof(subjectName); ++ cert = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_NAME, &name, NULL); ++ ok(cert != NULL, "certificate should exist in My store\n"); ++ ++ ret = CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, NULL, &size); ++ ok(ret, "CertGetCertificateContextProperty error %#x\n", GetLastError()); ++ info = HeapAlloc(GetProcessHeap(), 0, size); ++ ret = CertGetCertificateContextProperty(cert, CERT_KEY_PROV_INFO_PROP_ID, info, &size); ++ ok(ret, "CertGetCertificateContextProperty error %#x\n", GetLastError()); ++ ok(!lstrcmpW(info->pwszContainerName, containerW), "got %s\n", wine_dbgstr_w(info->pwszContainerName)); ++ ok(!lstrcmpW(info->pwszProvName, providerW), "got %s\n", wine_dbgstr_w(info->pwszProvName)); ++ ok(info->dwProvType == 0x12345678, "got %#x\n", info->dwProvType); ++ ok(info->dwFlags == 0x87654321, "got %#x\n", info->dwFlags); ++ ok(info->dwKeySpec == 0x11223344, "got %#x\n", info->dwKeySpec); ++ ok(info->cProvParam == 2, "got %#x\n", info->cProvParam); ++ ok(info->rgProvParam != NULL, "got %p\n", info->rgProvParam); ++ ok(info->rgProvParam[0].dwParam == param[0].dwParam, "got %#x\n", info->rgProvParam[0].dwParam); ++ ok(info->rgProvParam[0].cbData == param[0].cbData, "got %#x\n", info->rgProvParam[0].cbData); ++ ok(!memcmp(info->rgProvParam[0].pbData, param[0].pbData, param[0].cbData), "param1 mismatch\n"); ++ ok(info->rgProvParam[0].dwFlags == param[0].dwFlags, "got %#x\n", info->rgProvParam[1].dwFlags); ++ ok(info->rgProvParam[1].dwParam == param[1].dwParam, "got %#x\n", info->rgProvParam[1].dwParam); ++ ok(info->rgProvParam[1].cbData == param[1].cbData, "got %#x\n", info->rgProvParam[1].cbData); ++ ok(!memcmp(info->rgProvParam[1].pbData, param[1].pbData, param[1].cbData), "param2 mismatch\n"); ++ ok(info->rgProvParam[1].dwFlags == param[1].dwFlags, "got %#x\n", info->rgProvParam[1].dwFlags); ++ HeapFree(GetProcessHeap(), 0, info); ++ ++ ret = CertDeleteCertificateFromStore(cert); ++ ok(ret, "CertDeleteCertificateFromStore error %#x\n", GetLastError()); ++ ++ CertFreeCertificateContext(cert); ++ CertCloseStore(store, 0); ++} ++ + START_TEST(cert) + { + init_function_pointers(); +@@ -4154,6 +4249,7 @@ START_TEST(cert) + testGetSubjectCert(); + testGetIssuerCert(); + testLinkCert(); ++ testKeyProvInfo(); + + testCryptHashCert(); + testCryptHashCert2(); +-- +2.29.2 + diff --git a/patches/crypt32-CRYPT_KEY_PROV_INFO/definition b/patches/crypt32-CRYPT_KEY_PROV_INFO/definition new file mode 100644 index 00000000..8a386d2f --- /dev/null +++ b/patches/crypt32-CRYPT_KEY_PROV_INFO/definition @@ -0,0 +1 @@ +Fixes: [50024] signtool.exe from Windows 7 SDK fails to find certificates diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index 04d7f052..66ded6ad 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -95,6 +95,7 @@ patch_enable_all () enable_comctl32_version_6="$1" enable_comdlg32_lpstrFileTitle="$1" enable_crypt32_CMS_Certificates="$1" + enable_crypt32_CRYPT_KEY_PROV_INFO="$1" enable_cryptext_CryptExtOpenCER="$1" enable_d3d11_Deferred_Context="$1" enable_d3dx9_32bpp_Alpha_Channel="$1" @@ -361,6 +362,9 @@ patch_enable () crypt32-CMS_Certificates) enable_crypt32_CMS_Certificates="$2" ;; + crypt32-CRYPT_KEY_PROV_INFO) + enable_crypt32_CRYPT_KEY_PROV_INFO="$2" + ;; cryptext-CryptExtOpenCER) enable_cryptext_CryptExtOpenCER="$2" ;; @@ -1791,6 +1795,18 @@ if test "$enable_crypt32_CMS_Certificates" -eq 1; then patch_apply crypt32-CMS_Certificates/0001-crypt32-Skip-unknown-item-when-decoding-a-CMS-certif.patch fi +# Patchset crypt32-CRYPT_KEY_PROV_INFO +# | +# | This patchset fixes the following Wine bugs: +# | * [#50024] signtool.exe from Windows 7 SDK fails to find certificates +# | +# | Modified files: +# | * dlls/crypt32/cert.c, dlls/crypt32/crypt32_private.h, dlls/crypt32/serialize.c, dlls/crypt32/tests/cert.c +# | +if test "$enable_crypt32_CRYPT_KEY_PROV_INFO" -eq 1; then + patch_apply crypt32-CRYPT_KEY_PROV_INFO/0001-crypt32-Fix-reading-and-writing-CRYPT_KEY_PROV_INFO-.patch +fi + # Patchset cryptext-CryptExtOpenCER # | # | Modified files: