Juan Lang : crypt32: Implement CryptMsgGetAndVerifySigner.
Alexandre Julliard
julliard at winehq.org
Mon Aug 18 10:46:37 CDT 2008
Module: wine
Branch: master
Commit: fc8545b43a2929a9bc337a2f3acca2cc7441354c
URL: http://source.winehq.org/git/wine.git/?a=commit;h=fc8545b43a2929a9bc337a2f3acca2cc7441354c
Author: Juan Lang <juan.lang at gmail.com>
Date: Tue Aug 5 11:06:17 2008 -0700
crypt32: Implement CryptMsgGetAndVerifySigner.
---
dlls/crypt32/msg.c | 112 ++++++++++++++++++++++++++++++++++++++++++++-
dlls/crypt32/tests/msg.c | 16 -------
2 files changed, 109 insertions(+), 19 deletions(-)
diff --git a/dlls/crypt32/msg.c b/dlls/crypt32/msg.c
index 1ad6a96..ff4e0f4 100644
--- a/dlls/crypt32/msg.c
+++ b/dlls/crypt32/msg.c
@@ -2446,12 +2446,118 @@ BOOL WINAPI CryptMsgControl(HCRYPTMSG hCryptMsg, DWORD dwFlags,
return msg->control(hCryptMsg, dwFlags, dwCtrlType, pvCtrlPara);
}
+static CERT_INFO *CRYPT_GetSignerCertInfoFromMsg(HCRYPTMSG msg,
+ DWORD dwSignerIndex)
+{
+ CERT_INFO *certInfo = NULL;
+ DWORD size;
+
+ if (CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM, dwSignerIndex, NULL,
+ &size))
+ {
+ certInfo = CryptMemAlloc(size);
+ if (certInfo)
+ {
+ if (!CryptMsgGetParam(msg, CMSG_SIGNER_CERT_INFO_PARAM,
+ dwSignerIndex, certInfo, &size))
+ {
+ CryptMemFree(certInfo);
+ certInfo = NULL;
+ }
+ }
+ }
+ return certInfo;
+}
+
BOOL WINAPI CryptMsgGetAndVerifySigner(HCRYPTMSG hCryptMsg, DWORD cSignerStore,
HCERTSTORE *rghSignerStore, DWORD dwFlags, PCCERT_CONTEXT *ppSigner,
DWORD *pdwSignerIndex)
{
- FIXME("(%p, %d, %p, %08x, %p, %p): stub\n", hCryptMsg, cSignerStore,
+ HCERTSTORE store;
+ DWORD i, signerIndex;
+ PCCERT_CONTEXT signerCert = NULL;
+ BOOL ret = FALSE;
+
+ TRACE("(%p, %d, %p, %08x, %p, %p)\n", hCryptMsg, cSignerStore,
rghSignerStore, dwFlags, ppSigner, pdwSignerIndex);
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
- return FALSE;
+
+ /* Clear output parameters */
+ if (ppSigner)
+ *ppSigner = NULL;
+ if (pdwSignerIndex && !(dwFlags & CMSG_USE_SIGNER_INDEX_FLAG))
+ *pdwSignerIndex = 0;
+
+ /* Create store to search for signer certificates */
+ store = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
+ CERT_STORE_CREATE_NEW_FLAG, NULL);
+ if (!(dwFlags & CMSG_TRUSTED_SIGNER_FLAG))
+ {
+ HCERTSTORE msgStore = CertOpenStore(CERT_STORE_PROV_MSG, 0, 0, 0,
+ hCryptMsg);
+
+ CertAddStoreToCollection(store, msgStore, 0, 0);
+ CertCloseStore(msgStore, 0);
+ }
+ for (i = 0; i < cSignerStore; i++)
+ CertAddStoreToCollection(store, rghSignerStore[i], 0, 0);
+
+ /* Find signer cert */
+ if (dwFlags & CMSG_USE_SIGNER_INDEX_FLAG)
+ {
+ CERT_INFO *signer = CRYPT_GetSignerCertInfoFromMsg(hCryptMsg,
+ *pdwSignerIndex);
+
+ if (signer)
+ {
+ signerIndex = *pdwSignerIndex;
+ signerCert = CertFindCertificateInStore(store, X509_ASN_ENCODING,
+ 0, CERT_FIND_SUBJECT_CERT, signer, NULL);
+ CryptMemFree(signer);
+ }
+ }
+ else
+ {
+ DWORD count, size = sizeof(count);
+
+ if (CryptMsgGetParam(hCryptMsg, CMSG_SIGNER_COUNT_PARAM, 0, &count,
+ &size))
+ {
+ for (i = 0; !signerCert && i < count; i++)
+ {
+ CERT_INFO *signer = CRYPT_GetSignerCertInfoFromMsg(hCryptMsg,
+ i);
+
+ if (signer)
+ {
+ signerCert = CertFindCertificateInStore(store,
+ X509_ASN_ENCODING, 0, CERT_FIND_SUBJECT_CERT, signer,
+ NULL);
+ if (signerCert)
+ signerIndex = i;
+ CryptMemFree(signer);
+ }
+ }
+ }
+ if (!signerCert)
+ SetLastError(CRYPT_E_NO_TRUSTED_SIGNER);
+ }
+ if (signerCert)
+ {
+ if (!(dwFlags & CMSG_SIGNER_ONLY_FLAG))
+ ret = CryptMsgControl(hCryptMsg, 0, CMSG_CTRL_VERIFY_SIGNATURE,
+ signerCert->pCertInfo);
+ else
+ ret = TRUE;
+ if (ret)
+ {
+ if (ppSigner)
+ *ppSigner = CertDuplicateCertificateContext(signerCert);
+ if (pdwSignerIndex)
+ *pdwSignerIndex = signerIndex;
+ }
+ CertFreeCertificateContext(signerCert);
+ }
+
+ CertCloseStore(store, 0);
+ return ret;
}
diff --git a/dlls/crypt32/tests/msg.c b/dlls/crypt32/tests/msg.c
index 53652c6..0f7dcb6 100644
--- a/dlls/crypt32/tests/msg.c
+++ b/dlls/crypt32/tests/msg.c
@@ -2580,26 +2580,21 @@ static void test_msg_get_and_verify_signer(void)
/* An empty message has no signer */
SetLastError(0xdeadbeef);
ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, NULL, NULL);
- todo_wine
ok(!ret && GetLastError() == CRYPT_E_NO_TRUSTED_SIGNER,
"expected CRYPT_E_NO_TRUSTED_SIGNER, got 0x%08x\n", GetLastError());
/* The signer is cleared on error */
signer = (PCCERT_CONTEXT)0xdeadbeef;
SetLastError(0xdeadbeef);
ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, &signer, NULL);
- todo_wine
ok(!ret && GetLastError() == CRYPT_E_NO_TRUSTED_SIGNER,
"expected CRYPT_E_NO_TRUSTED_SIGNER, got 0x%08x\n", GetLastError());
- todo_wine
ok(!signer, "expected signer to be NULL\n");
/* The signer index is also cleared on error */
signerIndex = 0xdeadbeef;
SetLastError(0xdeadbeef);
ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, NULL, &signerIndex);
- todo_wine
ok(!ret && GetLastError() == CRYPT_E_NO_TRUSTED_SIGNER,
"expected CRYPT_E_NO_TRUSTED_SIGNER, got 0x%08x\n", GetLastError());
- todo_wine
ok(!signerIndex, "expected 0, got %d\n", signerIndex);
/* An unsigned message (msgData isn't a signed message at all)
* likewise has no signer.
@@ -2607,7 +2602,6 @@ static void test_msg_get_and_verify_signer(void)
CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
SetLastError(0xdeadbeef);
ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, NULL, NULL);
- todo_wine
ok(!ret && GetLastError() == CRYPT_E_NO_TRUSTED_SIGNER,
"expected CRYPT_E_NO_TRUSTED_SIGNER, got 0x%08x\n", GetLastError());
CryptMsgClose(msg);
@@ -2617,7 +2611,6 @@ static void test_msg_get_and_verify_signer(void)
CryptMsgUpdate(msg, signedEmptyContent, sizeof(signedEmptyContent), TRUE);
SetLastError(0xdeadbeef);
ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, NULL, NULL);
- todo_wine
ok(!ret && GetLastError() == CRYPT_E_NO_TRUSTED_SIGNER,
"expected CRYPT_E_NO_TRUSTED_SIGNER, got 0x%08x\n", GetLastError());
CryptMsgClose(msg);
@@ -2627,21 +2620,16 @@ static void test_msg_get_and_verify_signer(void)
CryptMsgUpdate(msg, signedWithCertWithValidPubKeyContent,
sizeof(signedWithCertWithValidPubKeyContent), TRUE);
ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, NULL, NULL);
- todo_wine
ok(ret, "CryptMsgGetAndVerifySigner failed: 0x%08x\n", GetLastError());
/* the signer index can be retrieved, .. */
signerIndex = 0xdeadbeef;
ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, NULL, &signerIndex);
- todo_wine
ok(ret, "CryptMsgGetAndVerifySigner failed: 0x%08x\n", GetLastError());
- todo_wine
ok(signerIndex == 0, "expected 0, got %d\n", signerIndex);
/* as can the signer cert. */
signer = (PCCERT_CONTEXT)0xdeadbeef;
ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, 0, &signer, NULL);
- todo_wine
ok(ret, "CryptMsgGetAndVerifySigner failed: 0x%08x\n", GetLastError());
- todo_wine
ok(signer != NULL && signer != (PCCERT_CONTEXT)0xdeadbeef,
"expected a valid signer\n");
if (signer && signer != (PCCERT_CONTEXT)0xdeadbeef)
@@ -2652,7 +2640,6 @@ static void test_msg_get_and_verify_signer(void)
SetLastError(0xdeadbeef);
ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, CMSG_USE_SIGNER_INDEX_FLAG,
NULL, &signerIndex);
- todo_wine
ok(!ret && GetLastError() == CRYPT_E_INVALID_INDEX,
"expected CRYPT_E_INVALID_INDEX, got 0x%08x\n", GetLastError());
/* Specifying CMSG_TRUSTED_SIGNER_FLAG and no cert stores causes the
@@ -2661,7 +2648,6 @@ static void test_msg_get_and_verify_signer(void)
SetLastError(0xdeadbeef);
ret = CryptMsgGetAndVerifySigner(msg, 0, NULL, CMSG_TRUSTED_SIGNER_FLAG,
NULL, NULL);
- todo_wine
ok(!ret && GetLastError() == CRYPT_E_NO_TRUSTED_SIGNER,
"expected CRYPT_E_NO_TRUSTED_SIGNER, got 0x%08x\n", GetLastError());
/* Specifying CMSG_TRUSTED_SIGNER_FLAG and an empty cert store also causes
@@ -2672,7 +2658,6 @@ static void test_msg_get_and_verify_signer(void)
SetLastError(0xdeadbeef);
ret = CryptMsgGetAndVerifySigner(msg, 1, &store, CMSG_TRUSTED_SIGNER_FLAG,
NULL, NULL);
- todo_wine
ok(!ret && GetLastError() == CRYPT_E_NO_TRUSTED_SIGNER,
"expected CRYPT_E_NO_TRUSTED_SIGNER, got 0x%08x\n", GetLastError());
ret = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
@@ -2686,7 +2671,6 @@ static void test_msg_get_and_verify_signer(void)
SetLastError(0xdeadbeef);
ret = CryptMsgGetAndVerifySigner(msg, 1, &store, CMSG_TRUSTED_SIGNER_FLAG,
NULL, NULL);
- todo_wine
ok(ret, "CryptMsgGetAndVerifySigner failed: 0x%08x\n", GetLastError());
CertCloseStore(store, 0);
CryptMsgClose(msg);
More information about the wine-cvs
mailing list