Commit 6389dbc9 authored by Juan Lang's avatar Juan Lang Committed by Alexandre Julliard

Implement CertAddSerializedElementToStore.

parent 54e9e874
......@@ -34,6 +34,8 @@
#include "wincrypt.h"
#include "wine/debug.h"
#include "wine/list.h"
#include "excpt.h"
#include "wine/exception.h"
#include "crypt32_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(crypt);
......@@ -44,6 +46,77 @@ WINE_DEFAULT_DEBUG_CHANNEL(crypt);
#define CERT_CRL_PROP_ID 33
#define CERT_CTL_PROP_ID 34
/* Some typedefs that make it easier to abstract which type of context we're
* working with.
*/
typedef const void *(WINAPI *CreateContextFunc)(DWORD dwCertEncodingType,
const BYTE *pbCertEncoded, DWORD cbCertEncoded);
typedef BOOL (WINAPI *AddContextToStoreFunc)(HCERTSTORE hCertStore,
const void *context, DWORD dwAddDisposition, const void **ppStoreContext);
typedef BOOL (WINAPI *AddEncodedContextToStoreFunc)(HCERTSTORE hCertStore,
DWORD dwCertEncodingType, const BYTE *pbEncoded, DWORD cbEncoded,
DWORD dwAddDisposition, const void **ppContext);
typedef const void *(WINAPI *EnumContextsInStoreFunc)(HCERTSTORE hCertStore,
const void *pPrevContext);
typedef BOOL (WINAPI *GetContextPropertyFunc)(const void *context,
DWORD dwPropID, void *pvData, DWORD *pcbData);
typedef BOOL (WINAPI *SetContextPropertyFunc)(const void *context,
DWORD dwPropID, DWORD dwFlags, const void *pvData);
typedef BOOL (WINAPI *SerializeElementFunc)(const void *context, DWORD dwFlags,
BYTE *pbElement, DWORD *pcbElement);
typedef BOOL (WINAPI *FreeContextFunc)(const void *context);
typedef BOOL (WINAPI *DeleteContextFunc)(const void *context);
/* An abstract context (certificate, CRL, or CTL) interface */
typedef struct _WINE_CONTEXT_INTERFACE
{
CreateContextFunc create;
AddContextToStoreFunc addContextToStore;
AddEncodedContextToStoreFunc addEncodedToStore;
EnumContextsInStoreFunc enumContextsInStore;
GetContextPropertyFunc getProp;
SetContextPropertyFunc setProp;
SerializeElementFunc serialize;
FreeContextFunc free;
DeleteContextFunc deleteFromStore;
} WINE_CONTEXT_INTERFACE, *PWINE_CONTEXT_INTERFACE;
static const WINE_CONTEXT_INTERFACE gCertInterface = {
(CreateContextFunc)CertCreateCertificateContext,
(AddContextToStoreFunc)CertAddCertificateContextToStore,
(AddEncodedContextToStoreFunc)CertAddEncodedCertificateToStore,
(EnumContextsInStoreFunc)CertEnumCertificatesInStore,
(GetContextPropertyFunc)CertGetCertificateContextProperty,
(SetContextPropertyFunc)CertSetCertificateContextProperty,
(SerializeElementFunc)CertSerializeCertificateStoreElement,
(FreeContextFunc)CertFreeCertificateContext,
(DeleteContextFunc)CertDeleteCertificateFromStore,
};
static const WINE_CONTEXT_INTERFACE gCRLInterface = {
(CreateContextFunc)CertCreateCRLContext,
(AddContextToStoreFunc)CertAddCRLContextToStore,
(AddEncodedContextToStoreFunc)CertAddEncodedCRLToStore,
(EnumContextsInStoreFunc)CertEnumCRLsInStore,
(GetContextPropertyFunc)CertGetCRLContextProperty,
(SetContextPropertyFunc)CertSetCRLContextProperty,
(SerializeElementFunc)CertSerializeCRLStoreElement,
(FreeContextFunc)CertFreeCRLContext,
(DeleteContextFunc)CertDeleteCRLFromStore,
};
static const WINE_CONTEXT_INTERFACE gCTLInterface = {
(CreateContextFunc)CertCreateCTLContext,
(AddContextToStoreFunc)CertAddCTLContextToStore,
(AddEncodedContextToStoreFunc)CertAddEncodedCTLToStore,
(EnumContextsInStoreFunc)CertEnumCTLsInStore,
(GetContextPropertyFunc)CertGetCTLContextProperty,
(SetContextPropertyFunc)CertSetCTLContextProperty,
(SerializeElementFunc)CertSerializeCTLStoreElement,
(FreeContextFunc)CertFreeCTLContext,
(DeleteContextFunc)CertDeleteCTLFromStore,
};
struct WINE_CRYPTCERTSTORE;
typedef struct WINE_CRYPTCERTSTORE * (*StoreOpenFunc)(HCRYPTPROV hCryptProv,
......@@ -205,6 +278,23 @@ static BOOL WINAPI CRYPT_GetCertificateContextProperty(
static BOOL WINAPI CRYPT_SetCertificateContextProperty(
PWINE_CERT_CONTEXT context, DWORD dwPropId, DWORD dwFlags, const void *pvData);
/* Helper function for store reading functions and
* CertAddSerializedElementToStore. Returns a context of the appropriate type
* if it can, or NULL otherwise. Doesn't validate any of the properties in
* the serialized context (for example, bad hashes are retained.)
* *pdwContentType is set to the type of the returned context.
*/
static const void * WINAPI CRYPT_ReadSerializedElement(const BYTE *pbElement,
DWORD cbElement, DWORD dwContextTypeFlags, DWORD *pdwContentType);
/* filter for page-fault exceptions */
static WINE_EXCEPTION_FILTER(page_fault)
{
if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
return EXCEPTION_EXECUTE_HANDLER;
return EXCEPTION_CONTINUE_SEARCH;
}
static void CRYPT_InitStore(WINECRYPT_CERTSTORE *store, HCRYPTPROV hCryptProv,
DWORD dwFlags, CertStoreType type)
{
......@@ -1655,14 +1745,292 @@ BOOL WINAPI CertSerializeCertificateStoreElement(PCCERT_CONTEXT pCertContext,
return ret;
}
/* Looks for the property with ID propID in the buffer buf. Returns a pointer
* to its header if a valid header is found, NULL if not. Valid means the
* length of thte property won't overrun buf, and the unknown field is 1.
*/
static const WINE_CERT_PROP_HEADER *CRYPT_findPropID(const BYTE *buf,
DWORD size, DWORD propID)
{
const WINE_CERT_PROP_HEADER *ret = NULL;
BOOL done = FALSE;
while (size && !ret && !done)
{
if (size < sizeof(WINE_CERT_PROP_HEADER))
{
SetLastError(CRYPT_E_FILE_ERROR);
done = TRUE;
}
else
{
const WINE_CERT_PROP_HEADER *hdr =
(const WINE_CERT_PROP_HEADER *)buf;
size -= sizeof(WINE_CERT_PROP_HEADER);
buf += sizeof(WINE_CERT_PROP_HEADER);
if (size < hdr->cb)
{
SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
done = TRUE;
}
else if (!hdr->propID)
{
/* assume a zero prop ID means the data are uninitialized, so
* stop looking.
*/
done = TRUE;
}
else if (hdr->unknown != 1)
{
SetLastError(ERROR_FILE_NOT_FOUND);
done = TRUE;
}
else if (hdr->propID == propID)
ret = hdr;
else
{
buf += hdr->cb;
size -= hdr->cb;
}
}
}
return ret;
}
static const void * WINAPI CRYPT_ReadSerializedElement(const BYTE *pbElement,
DWORD cbElement, DWORD dwContextTypeFlags, DWORD *pdwContentType)
{
const void *context = NULL;
TRACE("(%p, %ld, %08lx, %p)\n", pbElement, cbElement, dwContextTypeFlags,
pdwContentType);
if (!cbElement)
{
SetLastError(ERROR_END_OF_MEDIA);
return NULL;
}
__TRY
{
const WINE_CONTEXT_INTERFACE *contextInterface = NULL;
const WINE_CERT_PROP_HEADER *hdr = NULL;
DWORD type = 0;
BOOL ret;
ret = TRUE;
if (dwContextTypeFlags == CERT_STORE_ALL_CONTEXT_FLAG)
{
hdr = CRYPT_findPropID(pbElement, cbElement, CERT_CERT_PROP_ID);
if (hdr)
type = CERT_STORE_CERTIFICATE_CONTEXT;
else
{
hdr = CRYPT_findPropID(pbElement, cbElement, CERT_CRL_PROP_ID);
if (hdr)
type = CERT_STORE_CRL_CONTEXT;
else
{
hdr = CRYPT_findPropID(pbElement, cbElement,
CERT_CTL_PROP_ID);
if (hdr)
type = CERT_STORE_CTL_CONTEXT;
}
}
}
else if (dwContextTypeFlags & CERT_STORE_CERTIFICATE_CONTEXT_FLAG)
{
hdr = CRYPT_findPropID(pbElement, cbElement, CERT_CERT_PROP_ID);
type = CERT_STORE_CERTIFICATE_CONTEXT;
}
else if (dwContextTypeFlags & CERT_STORE_CRL_CONTEXT_FLAG)
{
hdr = CRYPT_findPropID(pbElement, cbElement, CERT_CRL_PROP_ID);
type = CERT_STORE_CRL_CONTEXT;
}
else if (dwContextTypeFlags & CERT_STORE_CTL_CONTEXT_FLAG)
{
hdr = CRYPT_findPropID(pbElement, cbElement, CERT_CTL_PROP_ID);
type = CERT_STORE_CTL_CONTEXT;
}
switch (type)
{
case CERT_STORE_CERTIFICATE_CONTEXT:
contextInterface = &gCertInterface;
break;
case CERT_STORE_CRL_CONTEXT:
contextInterface = &gCRLInterface;
break;
case CERT_STORE_CTL_CONTEXT:
contextInterface = &gCTLInterface;
break;
default:
SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
ret = FALSE;
}
if (!hdr)
ret = FALSE;
if (ret)
context = contextInterface->create(X509_ASN_ENCODING,
(BYTE *)hdr + sizeof(WINE_CERT_PROP_HEADER), hdr->cb);
if (ret && context)
{
BOOL noMoreProps = FALSE;
while (!noMoreProps && ret)
{
if (cbElement < sizeof(WINE_CERT_PROP_HEADER))
ret = FALSE;
else
{
const WINE_CERT_PROP_HEADER *hdr =
(const WINE_CERT_PROP_HEADER *)pbElement;
TRACE("prop is %ld\n", hdr->propID);
cbElement -= sizeof(WINE_CERT_PROP_HEADER);
pbElement += sizeof(WINE_CERT_PROP_HEADER);
if (cbElement < hdr->cb)
{
SetLastError(HRESULT_FROM_WIN32(
ERROR_INVALID_PARAMETER));
ret = FALSE;
}
else if (!hdr->propID)
{
/* Like in CRYPT_findPropID, stop if the propID is zero
*/
noMoreProps = TRUE;
}
else if (hdr->unknown != 1)
{
SetLastError(ERROR_FILE_NOT_FOUND);
ret = FALSE;
}
else if (hdr->propID != CERT_CERT_PROP_ID &&
hdr->propID != CERT_CRL_PROP_ID && hdr->propID !=
CERT_CTL_PROP_ID)
{
/* Have to create a blob for most types, but not
* for all.. arghh.
*/
switch (hdr->propID)
{
case CERT_AUTO_ENROLL_PROP_ID:
case CERT_CTL_USAGE_PROP_ID:
case CERT_DESCRIPTION_PROP_ID:
case CERT_FRIENDLY_NAME_PROP_ID:
case CERT_HASH_PROP_ID:
case CERT_KEY_IDENTIFIER_PROP_ID:
case CERT_MD5_HASH_PROP_ID:
case CERT_NEXT_UPDATE_LOCATION_PROP_ID:
case CERT_PUBKEY_ALG_PARA_PROP_ID:
case CERT_PVK_FILE_PROP_ID:
case CERT_SIGNATURE_HASH_PROP_ID:
case CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID:
case CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID:
case CERT_ENROLLMENT_PROP_ID:
case CERT_CROSS_CERT_DIST_POINTS_PROP_ID:
case CERT_RENEWAL_PROP_ID:
{
CRYPT_DATA_BLOB blob = { hdr->cb,
(LPBYTE)pbElement };
ret = contextInterface->setProp(context,
hdr->propID, 0, &blob);
break;
}
case CERT_DATE_STAMP_PROP_ID:
ret = contextInterface->setProp(context,
hdr->propID, 0, pbElement);
break;
default:
FIXME("prop ID %ld: stub\n", hdr->propID);
}
}
pbElement += hdr->cb;
cbElement -= hdr->cb;
if (!cbElement)
noMoreProps = TRUE;
}
}
if (ret)
{
if (pdwContentType)
*pdwContentType = type;
}
else
{
contextInterface->free(context);
context = NULL;
}
}
}
__EXCEPT(page_fault)
{
SetLastError(STATUS_ACCESS_VIOLATION);
context = NULL;
}
__ENDTRY
return context;
}
BOOL WINAPI CertAddSerializedElementToStore(HCERTSTORE hCertStore,
const BYTE *pbElement, DWORD cbElement, DWORD dwAddDisposition, DWORD dwFlags,
DWORD dwContextTypeFlags, DWORD *pdwContentType, const void **ppvContext)
{
FIXME("(%p, %p, %ld, %08lx, %08lx, %08lx, %p, %p): stub\n", hCertStore,
const void *context;
DWORD type;
BOOL ret;
TRACE("(%p, %p, %ld, %08lx, %08lx, %08lx, %p, %p)\n", hCertStore,
pbElement, cbElement, dwAddDisposition, dwFlags, dwContextTypeFlags,
pdwContentType, ppvContext);
return FALSE;
/* Call the internal function, then delete the hashes. Tests show this
* function uses real hash values, not whatever's stored in the hash
* property.
*/
context = CRYPT_ReadSerializedElement(pbElement, cbElement,
dwContextTypeFlags, &type);
if (context)
{
const WINE_CONTEXT_INTERFACE *contextInterface = NULL;
switch (type)
{
case CERT_STORE_CERTIFICATE_CONTEXT:
contextInterface = &gCertInterface;
break;
case CERT_STORE_CRL_CONTEXT:
contextInterface = &gCRLInterface;
break;
case CERT_STORE_CTL_CONTEXT:
contextInterface = &gCTLInterface;
break;
default:
SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
}
if (contextInterface)
{
contextInterface->setProp(context, CERT_HASH_PROP_ID, 0, NULL);
contextInterface->setProp(context, CERT_MD5_HASH_PROP_ID, 0, NULL);
contextInterface->setProp(context, CERT_SIGNATURE_HASH_PROP_ID, 0,
NULL);
if (pdwContentType)
*pdwContentType = type;
ret = contextInterface->addContextToStore(hCertStore, context,
dwAddDisposition, ppvContext);
contextInterface->free(context);
}
else
ret = FALSE;
}
else
ret = FALSE;
return ret;
}
BOOL WINAPI CertFreeCertificateContext(PCCERT_CONTEXT pCertContext)
......
......@@ -28,6 +28,18 @@
#include "wine/test.h"
/* The following aren't defined in wincrypt.h, as they're "reserved" */
#define CERT_CERT_PROP_ID 32
#define CERT_CRL_PROP_ID 33
#define CERT_CTL_PROP_ID 34
struct CertPropIDHeader
{
DWORD propID;
DWORD unknown1;
DWORD cb;
};
static void testCryptHashCert(void)
{
static const BYTE emptyHash[] = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b,
......@@ -667,6 +679,169 @@ static void testCertProperties(void)
}
}
static void testAddSerialized(void)
{
BOOL ret;
HCERTSTORE store;
BYTE buf[sizeof(struct CertPropIDHeader) * 2 + 20 + sizeof(bigCert) - 1] =
{ 0 };
BYTE hash[20];
struct CertPropIDHeader *hdr;
PCCERT_CONTEXT context;
ret = CertAddSerializedElementToStore(0, NULL, 0, 0, 0, 0, NULL, NULL);
ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
"Expected ERROR_END_OF_MEDIA, got %08lx\n", GetLastError());
store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
CERT_STORE_CREATE_NEW_FLAG, NULL);
ok(store != 0, "CertOpenStore failed: %08lx\n", GetLastError());
ret = CertAddSerializedElementToStore(store, NULL, 0, 0, 0, 0, NULL, NULL);
ok(!ret && GetLastError() == ERROR_END_OF_MEDIA,
"Expected ERROR_END_OF_MEDIA, got %08lx\n", GetLastError());
/* Test with an empty property */
hdr = (struct CertPropIDHeader *)buf;
hdr->propID = CERT_CERT_PROP_ID;
hdr->unknown1 = 1;
hdr->cb = 0;
ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
NULL, NULL);
ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
"Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
GetLastError());
/* Test with a bad size in property header */
hdr->cb = sizeof(bigCert) - 2;
memcpy(buf + sizeof(struct CertPropIDHeader), bigCert, sizeof(bigCert) - 1);
ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
NULL, NULL);
ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
"Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
GetLastError());
ret = CertAddSerializedElementToStore(store, buf,
sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0, 0, NULL,
NULL);
ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
"Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
GetLastError());
ret = CertAddSerializedElementToStore(store, buf,
sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
0, 0, NULL, NULL);
ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
"Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
GetLastError());
/* Kosher size in property header, but no context type */
hdr->cb = sizeof(bigCert) - 1;
ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0, 0,
NULL, NULL);
ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
"Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
GetLastError());
ret = CertAddSerializedElementToStore(store, buf,
sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0, 0, NULL,
NULL);
ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
"Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
GetLastError());
ret = CertAddSerializedElementToStore(store, buf,
sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
0, 0, NULL, NULL);
ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
"Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
GetLastError());
/* With a bad context type */
ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
"Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
GetLastError());
ret = CertAddSerializedElementToStore(store, buf,
sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0,
CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
"Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
GetLastError());
ret = CertAddSerializedElementToStore(store, buf,
sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
0, CERT_STORE_CRL_CONTEXT_FLAG, NULL, NULL);
ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
"Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
GetLastError());
/* Bad unknown field, good type */
hdr->unknown1 = 2;
ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
"Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
ret = CertAddSerializedElementToStore(store, buf,
sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0,
CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
"Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
ret = CertAddSerializedElementToStore(store, buf,
sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
"Expected ERROR_FILE_NOT_FOUND got %08lx\n", GetLastError());
/* Most everything okay, but bad add disposition */
hdr->unknown1 = 1;
/* This crashes
ret = CertAddSerializedElementToStore(store, buf, sizeof(buf), 0, 0,
CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
* as does this
ret = CertAddSerializedElementToStore(store, buf,
sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, 0, 0,
CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
*/
/* Everything okay, but buffer's too big */
ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
ok(ret, "CertAddSerializedElementToStore failed: %08lx\n", GetLastError());
/* Everything okay, check it's not re-added */
ret = CertAddSerializedElementToStore(store, buf,
sizeof(struct CertPropIDHeader) + sizeof(bigCert) - 1, CERT_STORE_ADD_NEW,
0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL, NULL);
ok(!ret && GetLastError() == CRYPT_E_EXISTS,
"Expected CRYPT_E_EXISTS, got %08lx\n", GetLastError());
context = CertEnumCertificatesInStore(store, NULL);
ok(context != NULL, "Expected a cert\n");
if (context)
CertDeleteCertificateFromStore(context);
/* Try adding with a bogus hash. Oddly enough, it succeeds, and the hash,
* when queried, is the real hash rather than the bogus hash.
*/
hdr = (struct CertPropIDHeader *)(buf + sizeof(struct CertPropIDHeader) +
sizeof(bigCert) - 1);
hdr->propID = CERT_HASH_PROP_ID;
hdr->unknown1 = 1;
hdr->cb = sizeof(hash);
memset(hash, 0xc, sizeof(hash));
memcpy((LPBYTE)hdr + sizeof(struct CertPropIDHeader), hash, sizeof(hash));
ret = CertAddSerializedElementToStore(store, buf, sizeof(buf),
CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, NULL,
(const void **)&context);
ok(ret, "CertAddSerializedElementToStore failed: %08lx\n", GetLastError());
if (context)
{
BYTE hashVal[20], realHash[20];
DWORD size = sizeof(hashVal);
ret = CryptHashCertificate(0, 0, 0, bigCert, sizeof(bigCert) - 1,
realHash, &size);
ok(ret, "CryptHashCertificate failed: %08lx\n", GetLastError());
ret = CertGetCertificateContextProperty(context, CERT_HASH_PROP_ID,
hashVal, &size);
ok(ret, "CertGetCertificateContextProperty failed: %08lx\n",
GetLastError());
ok(!memcmp(hashVal, realHash, size), "Unexpected hash\n");
}
CertCloseStore(store, 0);
}
START_TEST(cert)
{
testCryptHashCert();
......@@ -676,4 +851,5 @@ START_TEST(cert)
testCollectionStore();
testCertProperties();
testAddSerialized();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment