From b29c2335b8370786647913e4fc5eac052c2b282c Mon Sep 17 00:00:00 2001 From: Juan Lang Date: Fri, 26 May 2006 09:48:13 -0700 Subject: [PATCH] crypt32: Implement CertVerifyCRLTimeValidity and partially implement CertVerifySubjectCertificateContext. --- dlls/crypt32/cert.c | 66 +++++++++++++++++++++++++------------ dlls/crypt32/crl.c | 23 +++++++++++++ dlls/crypt32/crypt32.spec | 4 +-- dlls/crypt32/tests/cert.c | 68 +++++++++++++++++++++++++++++++++++++++ include/wincrypt.h | 5 +++ 5 files changed, 143 insertions(+), 23 deletions(-) diff --git a/dlls/crypt32/cert.c b/dlls/crypt32/cert.c index f529668f28f..f4c7a42710a 100644 --- a/dlls/crypt32/cert.c +++ b/dlls/crypt32/cert.c @@ -195,8 +195,7 @@ static BOOL WINAPI CertContext_GetProperty(void *context, DWORD dwPropId, TRACE("(%p, %ld, %p, %p)\n", context, dwPropId, pvData, pcbData); if (properties) - ret = ContextPropertyList_FindProperty(properties, dwPropId, - &blob); + ret = ContextPropertyList_FindProperty(properties, dwPropId, &blob); else ret = FALSE; if (ret) @@ -737,44 +736,69 @@ PCCERT_CONTEXT WINAPI CertGetSubjectCertificateFromStore(HCERTSTORE hCertStore, CERT_FIND_SUBJECT_CERT, pCertId, NULL); } +BOOL WINAPI CertVerifySubjectCertificateContext(PCCERT_CONTEXT pSubject, + PCCERT_CONTEXT pIssuer, DWORD *pdwFlags) +{ + static const DWORD supportedFlags = CERT_STORE_REVOCATION_FLAG | + CERT_STORE_SIGNATURE_FLAG | CERT_STORE_TIME_VALIDITY_FLAG; + + if (*pdwFlags & ~supportedFlags) + { + SetLastError(E_INVALIDARG); + return FALSE; + } + if (*pdwFlags & CERT_STORE_REVOCATION_FLAG) + { + PCCRL_CONTEXT crl = CertFindCRLInStore(pSubject->hCertStore, + pSubject->dwCertEncodingType, 0, CRL_FIND_ISSUED_BY, pSubject, NULL); + + if (crl) + { + FIXME("check CRL for subject\n"); + } + else + *pdwFlags |= CERT_STORE_NO_CRL_FLAG; + } + if (*pdwFlags & CERT_STORE_TIME_VALIDITY_FLAG) + { + if (0 == CertVerifyTimeValidity(NULL, pSubject->pCertInfo)) + *pdwFlags &= ~CERT_STORE_TIME_VALIDITY_FLAG; + } + if (*pdwFlags & CERT_STORE_SIGNATURE_FLAG) + { + if (CryptVerifyCertificateSignatureEx(0, pSubject->dwCertEncodingType, + CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT, (void *)pSubject, + CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT, (void *)pIssuer, 0, NULL)) + *pdwFlags &= ~CERT_STORE_SIGNATURE_FLAG; + } + return TRUE; +} + PCCERT_CONTEXT WINAPI CertGetIssuerCertificateFromStore(HCERTSTORE hCertStore, PCCERT_CONTEXT pSubjectContext, PCCERT_CONTEXT pPrevIssuerContext, DWORD *pdwFlags) { - static const DWORD supportedFlags = CERT_STORE_REVOCATION_FLAG | - CERT_STORE_SIGNATURE_FLAG | CERT_STORE_TIME_VALIDITY_FLAG; PCCERT_CONTEXT ret; TRACE("(%p, %p, %p, %08lx)\n", hCertStore, pSubjectContext, pPrevIssuerContext, *pdwFlags); - if (*pdwFlags & ~supportedFlags) + if (!pSubjectContext) { SetLastError(E_INVALIDARG); return NULL; } + ret = CertFindCertificateInStore(hCertStore, pSubjectContext->dwCertEncodingType, 0, CERT_FIND_ISSUER_OF, pSubjectContext, pPrevIssuerContext); if (ret) { - if (*pdwFlags & CERT_STORE_REVOCATION_FLAG) + if (!CertVerifySubjectCertificateContext(pSubjectContext, ret, + pdwFlags)) { - FIXME("revocation check requires CRL support\n"); - *pdwFlags |= CERT_STORE_NO_CRL_FLAG; - } - if (*pdwFlags & CERT_STORE_TIME_VALIDITY_FLAG) - { - if (0 == CertVerifyTimeValidity(NULL, pSubjectContext->pCertInfo)) - *pdwFlags &= ~CERT_STORE_TIME_VALIDITY_FLAG; - } - if (*pdwFlags & CERT_STORE_SIGNATURE_FLAG) - { - if (CryptVerifyCertificateSignatureEx(0, - pSubjectContext->dwCertEncodingType, - CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT, (void *)pSubjectContext, - CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT, (void *)ret, 0, NULL)) - *pdwFlags &= ~CERT_STORE_SIGNATURE_FLAG; + CertFreeCertificateContext(ret); + ret = NULL; } } diff --git a/dlls/crypt32/crl.c b/dlls/crypt32/crl.c index 3c60578ad7a..dd2918ceb80 100644 --- a/dlls/crypt32/crl.c +++ b/dlls/crypt32/crl.c @@ -443,3 +443,26 @@ BOOL WINAPI CertSetCRLContextProperty(PCCRL_CONTEXT pCRLContext, TRACE("returning %d\n", ret); return ret; } + +LONG WINAPI CertVerifyCRLTimeValidity(LPFILETIME pTimeToVerify, + PCRL_INFO pCrlInfo) +{ + FILETIME fileTime; + LONG ret; + + if (!pTimeToVerify) + { + SYSTEMTIME sysTime; + + GetSystemTime(&sysTime); + SystemTimeToFileTime(&sysTime, &fileTime); + pTimeToVerify = &fileTime; + } + if ((ret = CompareFileTime(pTimeToVerify, &pCrlInfo->ThisUpdate)) >= 0) + { + ret = CompareFileTime(pTimeToVerify, &pCrlInfo->NextUpdate); + if (ret < 0) + ret = 0; + } + return ret; +} diff --git a/dlls/crypt32/crypt32.spec b/dlls/crypt32/crypt32.spec index 8900bec0978..a525c65eeac 100644 --- a/dlls/crypt32/crypt32.spec +++ b/dlls/crypt32/crypt32.spec @@ -81,10 +81,10 @@ @ stub CertStrToNameA @ stub CertStrToNameW @ stub CertVerifyCRLRevocation -@ stub CertVerifyCRLTimeValidity +@ stdcall CertVerifyCRLTimeValidity(ptr ptr) @ stub CertVerifyCTLUsage @ stub CertVerifyRevocation -@ stub CertVerifySubjectCertificateContext +@ stdcall CertVerifySubjectCertificateContext(ptr ptr ptr) @ stdcall CertVerifyTimeValidity(ptr ptr) @ stub CertVerifyValidityNesting @ stub CreateFileU diff --git a/dlls/crypt32/tests/cert.c b/dlls/crypt32/tests/cert.c index 656fb942032..776d1178b3d 100644 --- a/dlls/crypt32/tests/cert.c +++ b/dlls/crypt32/tests/cert.c @@ -836,6 +836,73 @@ void testCompareCert(void) ok(!ret, "Expected certs not to be equal\n"); } +static const BYTE bigCertWithDifferentSubject[] = { 0x30, 0x7a, 0x02, 0x01, 0x02, + 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, + 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, + 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, + 0x65, 0x78, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, + 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, + 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, + 0x01, 0x01 }; + +static void testVerifySubjectCert(void) +{ + BOOL ret; + DWORD flags; + PCCERT_CONTEXT context1, context2; + + /* Crashes + ret = CertVerifySubjectCertificateContext(NULL, NULL, NULL); + */ + flags = 0; + ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags); + ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n", + GetLastError()); + flags = CERT_STORE_NO_CRL_FLAG; + ret = CertVerifySubjectCertificateContext(NULL, NULL, &flags); + ok(!ret && GetLastError() == E_INVALIDARG, + "Expected E_INVALIDARG, got %08lx\n", GetLastError()); + + flags = 0; + context1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert, + sizeof(bigCert)); + ret = CertVerifySubjectCertificateContext(NULL, context1, &flags); + ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n", + GetLastError()); + ret = CertVerifySubjectCertificateContext(context1, NULL, &flags); + ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n", + GetLastError()); + ret = CertVerifySubjectCertificateContext(context1, context1, &flags); + ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n", + GetLastError()); + + context2 = CertCreateCertificateContext(X509_ASN_ENCODING, + bigCertWithDifferentSubject, sizeof(bigCertWithDifferentSubject)); + SetLastError(0xdeadbeef); + ret = CertVerifySubjectCertificateContext(context1, context2, &flags); + ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n", + GetLastError()); + flags = CERT_STORE_REVOCATION_FLAG; + ret = CertVerifySubjectCertificateContext(context1, context2, &flags); + ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n", + GetLastError()); + ok(flags == (CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG), + "Expected CERT_STORE_REVOCATION_FLAG | CERT_STORE_NO_CRL_FLAG, got %08lx\n", + flags); + flags = CERT_STORE_SIGNATURE_FLAG; + ret = CertVerifySubjectCertificateContext(context1, context2, &flags); + ok(ret, "CertVerifySubjectCertificateContext failed; %08lx\n", + GetLastError()); + ok(flags == CERT_STORE_SIGNATURE_FLAG, + "Expected CERT_STORE_SIGNATURE_FLAG, got %08lx\n", flags); + CertFreeCertificateContext(context2); + + CertFreeCertificateContext(context1); +} + START_TEST(cert) { init_function_pointers(); @@ -847,4 +914,5 @@ START_TEST(cert) testCompareIntegerBlob(); testComparePublicKeyInfo(); testCompareCert(); + testVerifySubjectCert(); } diff --git a/include/wincrypt.h b/include/wincrypt.h index a5f426924da..771ec9914eb 100644 --- a/include/wincrypt.h +++ b/include/wincrypt.h @@ -2840,6 +2840,11 @@ PCERT_EXTENSION WINAPI CertFindExtension(LPCSTR pszObjId, DWORD cExtensions, CERT_EXTENSION rgExtensions[]); PCERT_RDN_ATTR WINAPI CertFindRDNAttr(LPCSTR pszObjId, PCERT_NAME_INFO pName); +BOOL WINAPI CertVerifySubjectCertificateContext(PCCERT_CONTEXT pSubject, + PCCERT_CONTEXT pIssuer, DWORD *pdwFlags); + +LONG WINAPI CertVerifyCRLTimeValidity(LPFILETIME pTimeToVerify, + PCRL_INFO pCrlInfo); LONG WINAPI CertVerifyTimeValidity(LPFILETIME pTimeToVerify, PCERT_INFO pCertInfo);