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