From 4b8845ae12f944980971440f3f48d1a4701a64e4 Mon Sep 17 00:00:00 2001 From: Juan Lang Date: Mon, 10 Jul 2006 09:10:36 -0700 Subject: [PATCH] crypt32: Implement key context property, with tests. --- dlls/crypt32/cert.c | 109 +++++++++++++++++++++++++++++++++++++++++----- dlls/crypt32/tests/cert.c | 73 ++++++++++++++++++++++++++++--- 2 files changed, 163 insertions(+), 19 deletions(-) diff --git a/dlls/crypt32/cert.c b/dlls/crypt32/cert.c index eabea824a4b..3af7fa1128f 100644 --- a/dlls/crypt32/cert.c +++ b/dlls/crypt32/cert.c @@ -307,6 +307,40 @@ BOOL WINAPI CertGetCertificateContextProperty(PCCERT_CONTEXT pCertContext, ret = TRUE; } break; + case CERT_KEY_IDENTIFIER_PROP_ID: + ret = CertContext_GetProperty((void *)pCertContext, dwPropId, + pvData, pcbData); + if (!ret) + SetLastError(ERROR_INVALID_DATA); + break; + case CERT_KEY_PROV_HANDLE_PROP_ID: + { + CERT_KEY_CONTEXT keyContext; + DWORD size = sizeof(keyContext); + + ret = CertContext_GetProperty((void *)pCertContext, + CERT_KEY_CONTEXT_PROP_ID, &keyContext, &size); + if (ret) + { + if (!pvData) + { + *pcbData = sizeof(HCRYPTPROV); + ret = TRUE; + } + else if (*pcbData < sizeof(HCRYPTPROV)) + { + SetLastError(ERROR_MORE_DATA); + *pcbData = sizeof(HCRYPTPROV); + ret = FALSE; + } + else + { + *(HCRYPTPROV *)pvData = keyContext.hCryptProv; + ret = TRUE; + } + } + break; + } case CERT_KEY_PROV_INFO_PROP_ID: ret = CertContext_GetProperty((void *)pCertContext, dwPropId, pvData, pcbData); @@ -397,11 +431,6 @@ static BOOL WINAPI CertContext_SetProperty(void *context, DWORD dwPropId, if (!properties) ret = FALSE; - else if (!pvData) - { - ContextPropertyList_RemoveProperty(properties, dwPropId); - ret = TRUE; - } else { switch (dwPropId) @@ -424,20 +453,76 @@ static BOOL WINAPI CertContext_SetProperty(void *context, DWORD dwPropId, case CERT_CROSS_CERT_DIST_POINTS_PROP_ID: case CERT_RENEWAL_PROP_ID: { - PCRYPT_DATA_BLOB blob = (PCRYPT_DATA_BLOB)pvData; + if (pvData) + { + PCRYPT_DATA_BLOB blob = (PCRYPT_DATA_BLOB)pvData; - ret = ContextPropertyList_SetProperty(properties, dwPropId, - blob->pbData, blob->cbData); + ret = ContextPropertyList_SetProperty(properties, dwPropId, + blob->pbData, blob->cbData); + } + else + { + ContextPropertyList_RemoveProperty(properties, dwPropId); + ret = TRUE; + } break; } case CERT_DATE_STAMP_PROP_ID: - ret = ContextPropertyList_SetProperty(properties, dwPropId, - (LPBYTE)pvData, sizeof(FILETIME)); + if (pvData) + ret = ContextPropertyList_SetProperty(properties, dwPropId, + (LPBYTE)pvData, sizeof(FILETIME)); + else + { + ContextPropertyList_RemoveProperty(properties, dwPropId); + ret = TRUE; + } + break; + case CERT_KEY_CONTEXT_PROP_ID: + { + if (pvData) + { + PCERT_KEY_CONTEXT keyContext = (PCERT_KEY_CONTEXT)pvData; + + ret = ContextPropertyList_SetProperty(properties, dwPropId, + (const BYTE *)keyContext, keyContext->cbSize); + } + else + { + ContextPropertyList_RemoveProperty(properties, dwPropId); + ret = TRUE; + } break; + } case CERT_KEY_PROV_INFO_PROP_ID: - ret = CertContext_SetKeyProvInfoProperty(properties, - (PCRYPT_KEY_PROV_INFO)pvData); + if (pvData) + ret = CertContext_SetKeyProvInfoProperty(properties, + (PCRYPT_KEY_PROV_INFO)pvData); + else + { + ContextPropertyList_RemoveProperty(properties, dwPropId); + ret = TRUE; + } + break; + case CERT_KEY_PROV_HANDLE_PROP_ID: + { + CERT_KEY_CONTEXT keyContext; + DWORD size = sizeof(keyContext); + + ret = CertContext_GetProperty(context, CERT_KEY_CONTEXT_PROP_ID, + &keyContext, &size); + if (ret) + { + if (!(dwFlags & CERT_STORE_NO_CRYPT_RELEASE_FLAG)) + CryptReleaseContext(keyContext.hCryptProv, 0); + if (pvData) + keyContext.hCryptProv = *(HCRYPTPROV *)pvData; + else + keyContext.hCryptProv = 0; + ret = CertContext_SetProperty(context, CERT_KEY_CONTEXT_PROP_ID, + 0, &keyContext); + } break; + } default: FIXME("%ld: stub\n", dwPropId); ret = FALSE; diff --git a/dlls/crypt32/tests/cert.c b/dlls/crypt32/tests/cert.c index 917236d1c25..b03d61e1cae 100644 --- a/dlls/crypt32/tests/cert.c +++ b/dlls/crypt32/tests/cert.c @@ -310,6 +310,9 @@ static void checkHash(const BYTE *data, DWORD dataLen, ALG_ID algID, propID); } +static const WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e', + 'm','p',0 }; + static void testCertProperties(void) { PCCERT_CONTEXT context = CertCreateCertificateContext(X509_ASN_ENCODING, @@ -323,6 +326,8 @@ static void testCertProperties(void) BOOL ret; BYTE hash[20] = { 0 }, hashProperty[20]; CRYPT_DATA_BLOB blob; + CERT_KEY_CONTEXT keyContext; + HCRYPTPROV csp; /* This crashes propID = CertEnumCertificateContextProperties(NULL, 0); @@ -425,14 +430,71 @@ static void testCertProperties(void) context->pCertInfo->SubjectPublicKeyInfo.PublicKey.cbData, CALG_MD5, context, CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID); - /* Odd: this doesn't fail on other certificates, so there must be - * something weird about this cert that causes it to fail. - */ + /* Test key identifiers and handles and such */ size = 0; ret = CertGetCertificateContextProperty(context, CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size); - todo_wine ok(!ret && GetLastError() == ERROR_INVALID_DATA, + ok(!ret && GetLastError() == ERROR_INVALID_DATA, + "Expected ERROR_INVALID_DATA, got %08lx\n", GetLastError()); + size = sizeof(CERT_KEY_CONTEXT); + ret = CertGetCertificateContextProperty(context, + CERT_KEY_IDENTIFIER_PROP_ID, NULL, &size); + ok(!ret && GetLastError() == ERROR_INVALID_DATA, + "Expected ERROR_INVALID_DATA, got %08lx\n", GetLastError()); + ret = CertGetCertificateContextProperty(context, + CERT_KEY_IDENTIFIER_PROP_ID, &keyContext, &size); + ok(!ret && GetLastError() == ERROR_INVALID_DATA, "Expected ERROR_INVALID_DATA, got %08lx\n", GetLastError()); + /* Key context with an invalid size */ + keyContext.cbSize = 0; + ret = CertSetCertificateContextProperty(context, + CERT_KEY_IDENTIFIER_PROP_ID, 0, &keyContext); + ok(ret, "CertSetCertificateContextProperty failed: %08lx\n", + GetLastError()); + size = sizeof(keyContext); + ret = CertGetCertificateContextProperty(context, + CERT_KEY_IDENTIFIER_PROP_ID, &keyContext, &size); + ok(ret, "CertGetCertificateContextProperty failed: %08lx\n", + GetLastError()); + keyContext.cbSize = sizeof(keyContext); + keyContext.hCryptProv = 0; + keyContext.dwKeySpec = AT_SIGNATURE; + /* Crash + ret = CertSetCertificateContextProperty(context, + CERT_KEY_IDENTIFIER_PROP_ID, 0, &keyContext); + ret = CertSetCertificateContextProperty(context, + CERT_KEY_IDENTIFIER_PROP_ID, CERT_STORE_NO_CRYPT_RELEASE_FLAG, + &keyContext); + */ + ret = CryptAcquireContextW(&csp, cspNameW, + MS_DEF_PROV_W, PROV_RSA_FULL, CRYPT_NEWKEYSET); + ok(ret, "CryptAcquireContextW failed: %08lx\n", GetLastError()); + keyContext.hCryptProv = csp; + ret = CertSetCertificateContextProperty(context, + CERT_KEY_CONTEXT_PROP_ID, 0, &keyContext); + ok(ret, "CertSetCertificateContextProperty failed: %08lx\n", + GetLastError()); + /* Now that that's set, the key prov handle property is also gettable. + */ + size = sizeof(DWORD); + ret = CertGetCertificateContextProperty(context, + CERT_KEY_PROV_HANDLE_PROP_ID, &keyContext.hCryptProv, &size); + ok(ret, "Expected to get the CERT_KEY_PROV_HANDLE_PROP_ID, got %08lx\n", + GetLastError()); + /* Remove the key prov handle property.. */ + ret = CertSetCertificateContextProperty(context, + CERT_KEY_PROV_HANDLE_PROP_ID, 0, NULL); + ok(ret, "CertSetCertificateContextProperty failed: %08lx\n", + GetLastError()); + /* and the key context's CSP is set to NULL. */ + size = sizeof(keyContext); + ret = CertGetCertificateContextProperty(context, + CERT_KEY_CONTEXT_PROP_ID, &keyContext, &size); + ok(ret, "CertGetCertificateContextProperty failed: %08lx\n", + GetLastError()); + ok(keyContext.hCryptProv == 0, "Expected no hCryptProv\n"); + + CryptReleaseContext(csp, 0); CertFreeCertificateContext(context); } @@ -799,9 +861,6 @@ static void testCryptHashCert(void) ok(!memcmp(hash, knownHash, sizeof(knownHash)), "Unexpected hash\n"); } -static const WCHAR cspNameW[] = { 'W','i','n','e','C','r','y','p','t','T','e', - 'm','p',0 }; - static void verifySig(HCRYPTPROV csp, const BYTE *toSign, size_t toSignLen, const BYTE *sig, unsigned int sigLen) { -- 2.11.4.GIT