Juan Lang : crypt32: Implement verifying a decoded signed message' s signature.

Alexandre Julliard julliard at wine.codeweavers.com
Tue Aug 21 15:22:27 CDT 2007


Module: wine
Branch: master
Commit: b7e420429db8e3a2eab503f49ce0b04a4ac7f551
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=b7e420429db8e3a2eab503f49ce0b04a4ac7f551

Author: Juan Lang <juan.lang at gmail.com>
Date:   Tue Aug 21 07:34:47 2007 -0700

crypt32: Implement verifying a decoded signed message's signature.

---

 dlls/crypt32/msg.c       |   43 ++++++++++++++++++++++++++++++++++++++++++-
 dlls/crypt32/tests/msg.c |    9 ++++-----
 2 files changed, 46 insertions(+), 6 deletions(-)

diff --git a/dlls/crypt32/msg.c b/dlls/crypt32/msg.c
index ace5e51..c9226ad 100644
--- a/dlls/crypt32/msg.c
+++ b/dlls/crypt32/msg.c
@@ -2084,6 +2084,47 @@ static BOOL CDecodeHashMsg_VerifyHash(CDecodeMsg *msg)
     return ret;
 }
 
+static BOOL CDecodeSignedMsg_VerifySignature(CDecodeMsg *msg, PCERT_INFO info)
+{
+    BOOL ret = FALSE;
+    DWORD i;
+
+    for (i = 0; !ret && i < msg->u.signed_data.info->cSignerInfo; i++)
+    {
+        ret = CertCompareCertificateName(X509_ASN_ENCODING,
+         &msg->u.signed_data.info->rgSignerInfo[i].Issuer, &info->Issuer);
+        if (ret)
+            ret = CertCompareIntegerBlob(
+             &msg->u.signed_data.info->rgSignerInfo[i].SerialNumber,
+             &info->SerialNumber);
+    }
+    if (ret)
+    {
+        HCRYPTKEY key;
+
+        ret = CryptImportPublicKeyInfo(msg->crypt_prov, X509_ASN_ENCODING,
+         &info->SubjectPublicKeyInfo, &key);
+        if (ret)
+        {
+            HCRYPTHASH hash;
+
+            if (msg->u.signed_data.info->rgSignerInfo[i].AuthAttrs.cAttr)
+                hash = msg->u.signed_data.signerHandles[i].authAttrHash;
+            else
+                hash = msg->u.signed_data.signerHandles[i].contentHash;
+            ret = CryptVerifySignatureW(hash,
+             msg->u.signed_data.info->rgSignerInfo[i].EncryptedHash.pbData,
+             msg->u.signed_data.info->rgSignerInfo[i].EncryptedHash.cbData,
+             key, NULL, 0);
+            CryptDestroyKey(key);
+        }
+    }
+    else
+        SetLastError(CRYPT_E_SIGNER_NOT_FOUND);
+
+    return ret;
+}
+
 static BOOL CDecodeMsg_Control(HCRYPTMSG hCryptMsg, DWORD dwFlags,
  DWORD dwCtrlType, const void *pvCtrlPara)
 {
@@ -2096,7 +2137,7 @@ static BOOL CDecodeMsg_Control(HCRYPTMSG hCryptMsg, DWORD dwFlags,
         switch (msg->type)
         {
         case CMSG_SIGNED:
-            FIXME("CMSG_CTRL_VERIFY_SIGNATURE: stub\n");
+            ret = CDecodeSignedMsg_VerifySignature(msg, (PCERT_INFO)pvCtrlPara);
             break;
         default:
             SetLastError(CRYPT_E_INVALID_MSG_TYPE);
diff --git a/dlls/crypt32/tests/msg.c b/dlls/crypt32/tests/msg.c
index f079916..b1e6c94 100644
--- a/dlls/crypt32/tests/msg.c
+++ b/dlls/crypt32/tests/msg.c
@@ -2291,7 +2291,6 @@ static void test_msg_control(void)
      */
     SetLastError(0xdeadbeef);
     ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo);
-    todo_wine
     ok(!ret && GetLastError() == CRYPT_E_SIGNER_NOT_FOUND,
      "Expected CRYPT_E_SIGNER_NOT_FOUND, got %08x\n", GetLastError());
     /* The cert info is expected to have an issuer, serial number, and public
@@ -2303,7 +2302,6 @@ static void test_msg_control(void)
     certInfo.Issuer.pbData = encodedCommonName;
     SetLastError(0xdeadbeef);
     ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo);
-    todo_wine
     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
      "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
     CryptMsgClose(msg);
@@ -2315,7 +2313,6 @@ static void test_msg_control(void)
     /* Again, cert info needs to have a public key set */
     SetLastError(0xdeadbeef);
     ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo);
-    todo_wine
     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
      "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
     /* The public key is supposed to be in encoded form.. */
@@ -2324,7 +2321,6 @@ static void test_msg_control(void)
     certInfo.SubjectPublicKeyInfo.PublicKey.pbData = aKey;
     SetLastError(0xdeadbeef);
     ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo);
-    todo_wine
     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
      "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
     /* but not as a X509_PUBLIC_KEY_INFO.. */
@@ -2333,7 +2329,6 @@ static void test_msg_control(void)
     certInfo.SubjectPublicKeyInfo.PublicKey.pbData = encodedPubKey;
     SetLastError(0xdeadbeef);
     ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo);
-    todo_wine
     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
      "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
     /* This decodes successfully, but it doesn't match any key in the message */
@@ -2341,6 +2336,10 @@ static void test_msg_control(void)
     certInfo.SubjectPublicKeyInfo.PublicKey.pbData = mod_encoded;
     SetLastError(0xdeadbeef);
     ret = CryptMsgControl(msg, 0, CMSG_CTRL_VERIFY_SIGNATURE, &certInfo);
+    /* In Wine's rsaenh, this fails to decode because the key length is too
+     * small.  Not sure if that's a bug in rsaenh, so leaving todo_wine for
+     * now.
+     */
     todo_wine
     ok(!ret && GetLastError() == NTE_BAD_SIGNATURE,
      "Expected NTE_BAD_SIGNATURE, got %08x\n", GetLastError());




More information about the wine-cvs mailing list