crypt32(1/2): Partially implement updating decode messages

Juan Lang juan.lang at gmail.com
Fri Jul 13 13:51:39 CDT 2007


Not to be confused with the other 2-patch series I sent earlier having
to do with decoding :/
--Juan
-------------- next part --------------
From c533a0f5cd25d7a0435a707d513009e695d287cd Mon Sep 17 00:00:00 2001
From: Juan Lang <juanlang at juan.corp.google.com>
Date: Fri, 13 Jul 2007 11:45:03 -0700
Subject: [PATCH] Partially implement updating decode messages
---
 dlls/crypt32/msg.c       |  111 ++++++++++++++++++++++++++++++++++++++++++++--
 dlls/crypt32/tests/msg.c |   11 -----
 2 files changed, 106 insertions(+), 16 deletions(-)

diff --git a/dlls/crypt32/msg.c b/dlls/crypt32/msg.c
index 78130d2..470bf58 100644
--- a/dlls/crypt32/msg.c
+++ b/dlls/crypt32/msg.c
@@ -607,9 +607,10 @@ HCRYPTMSG WINAPI CryptMsgOpenToEncode(DW
 
 typedef struct _CDecodeMsg
 {
-    CryptMsgBase base;
-    DWORD        type;
-    HCRYPTPROV   crypt_prov;
+    CryptMsgBase    base;
+    DWORD           type;
+    HCRYPTPROV      crypt_prov;
+    CRYPT_DATA_BLOB msg_data;
 } CDecodeMsg;
 
 static void CDecodeMsg_Close(HCRYPTMSG hCryptMsg)
@@ -618,13 +619,111 @@ static void CDecodeMsg_Close(HCRYPTMSG h
 
     if (msg->base.open_flags & CMSG_CRYPT_RELEASE_CONTEXT_FLAG)
         CryptReleaseContext(msg->crypt_prov, 0);
+    CryptMemFree(msg->msg_data.pbData);
+}
+
+static BOOL CDecodeMsg_CopyData(CDecodeMsg *msg, const BYTE *pbData,
+ DWORD cbData)
+{
+    BOOL ret = TRUE;
+
+    if (cbData)
+    {
+        if (msg->msg_data.cbData)
+            msg->msg_data.pbData = CryptMemRealloc(msg->msg_data.pbData,
+             msg->msg_data.cbData + cbData);
+        else
+            msg->msg_data.pbData = CryptMemAlloc(cbData);
+        if (msg->msg_data.pbData)
+        {
+            memcpy(msg->msg_data.pbData + msg->msg_data.cbData, pbData, cbData);
+            msg->msg_data.cbData += cbData;
+        }
+        else
+            ret = FALSE;
+    }
+    return ret;
+}
+
+/* Decodes the content in blob as the type given, and updates the value
+ * (type, parameters, etc.) of msg based on what blob contains.
+ * It doesn't just use msg's type, to allow a recursive call from an implicitly
+ * typed message once the outer content info has been decoded.
+ */
+static BOOL CDecodeMsg_DecodeContent(CDecodeMsg *msg, CRYPT_DER_BLOB *blob,
+ DWORD type)
+{
+    BOOL ret;
+
+    switch (type)
+    {
+    case CMSG_DATA:
+    case CMSG_HASHED:
+    case CMSG_ENVELOPED:
+    case CMSG_SIGNED:
+        FIXME("unimplemented for type %s\n", MSG_TYPE_STR(type));
+        ret = TRUE;
+        break;
+    default:
+    {
+        CRYPT_CONTENT_INFO *info;
+        DWORD size;
+
+        ret = CryptDecodeObjectEx(X509_ASN_ENCODING, PKCS_CONTENT_INFO,
+         msg->msg_data.pbData, msg->msg_data.cbData, CRYPT_DECODE_ALLOC_FLAG,
+         NULL, (LPBYTE)&info, &size);
+        if (ret)
+        {
+            if (!strcmp(info->pszObjId, szOID_RSA_data))
+                ret = CDecodeMsg_DecodeContent(msg, &info->Content, CMSG_DATA);
+            else if (!strcmp(info->pszObjId, szOID_RSA_digestedData))
+                ret = CDecodeMsg_DecodeContent(msg, &info->Content,
+                 CMSG_HASHED);
+            else if (!strcmp(info->pszObjId, szOID_RSA_envelopedData))
+                ret = CDecodeMsg_DecodeContent(msg, &info->Content,
+                 CMSG_ENVELOPED);
+            else if (!strcmp(info->pszObjId, szOID_RSA_signedData))
+                ret = CDecodeMsg_DecodeContent(msg, &info->Content,
+                 CMSG_SIGNED);
+            else
+            {
+                SetLastError(CRYPT_E_INVALID_MSG_TYPE);
+                ret = FALSE;
+            }
+            LocalFree(info);
+        }
+    }
+    }
+    return ret;
 }
 
 static BOOL CDecodeMsg_Update(HCRYPTMSG hCryptMsg, const BYTE *pbData,
  DWORD cbData, BOOL fFinal)
 {
-    FIXME("(%p, %p, %d, %d): stub\n", hCryptMsg, pbData, cbData, fFinal);
-    return FALSE;
+    CDecodeMsg *msg = (CDecodeMsg *)hCryptMsg;
+    BOOL ret = FALSE;
+
+    TRACE("(%p, %p, %d, %d)\n", hCryptMsg, pbData, cbData, fFinal);
+
+    if (msg->base.streamed)
+    {
+        ret = CDecodeMsg_CopyData(msg, pbData, cbData);
+        FIXME("(%p, %p, %d, %d): streamed update stub\n", hCryptMsg, pbData,
+         cbData, fFinal);
+    }
+    else
+    {
+        if (!fFinal)
+            SetLastError(CRYPT_E_MSG_ERROR);
+        else
+        {
+            ret = CDecodeMsg_CopyData(msg, pbData, cbData);
+            if (ret)
+                ret = CDecodeMsg_DecodeContent(msg, &msg->msg_data, msg->type);
+
+        }
+    }
+    return ret;
 }
 
 static BOOL CDecodeMsg_GetParam(HCRYPTMSG hCryptMsg, DWORD dwParamType,
@@ -673,6 +772,8 @@ HCRYPTMSG WINAPI CryptMsgOpenToDecode(DW
             msg->crypt_prov = CRYPT_GetDefaultProvider();
             msg->base.open_flags &= ~CMSG_CRYPT_RELEASE_CONTEXT_FLAG;
         }
+        msg->msg_data.cbData = 0;
+        msg->msg_data.pbData = NULL;
     }
     return msg;
 }
diff --git a/dlls/crypt32/tests/msg.c b/dlls/crypt32/tests/msg.c
index a41a310..17beca1 100644
--- a/dlls/crypt32/tests/msg.c
+++ b/dlls/crypt32/tests/msg.c
@@ -989,7 +989,6 @@ static void test_decode_msg_update(void)
     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
     /* Update with a full message in a final update */
     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
-    todo_wine
     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
     /* Can't update after a final update */
     SetLastError(0xdeadbeef);
@@ -1003,12 +1002,10 @@ static void test_decode_msg_update(void)
     SetLastError(0xdeadbeef);
     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
      FALSE);
-    todo_wine
     ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
      "Expected CRYPT_E_MSG_ERROR, got %x\n", GetLastError());
     /* A subsequent final update succeeds */
     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent), TRUE);
-    todo_wine
     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
     CryptMsgClose(msg);
 
@@ -1035,7 +1032,6 @@ static void test_decode_msg_update(void)
     /* Empty non-final updates are allowed when streaming.. */
     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
     ret = CryptMsgUpdate(msg, NULL, 0, FALSE);
-    todo_wine
     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
     /* but final updates aren't when not enough data has been received. */
     SetLastError(0xdeadbeef);
@@ -1051,11 +1047,9 @@ static void test_decode_msg_update(void)
     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, &streamInfo);
     for (i = 0, ret = TRUE; ret && i < sizeof(dataEmptyContent); i++)
         ret = CryptMsgUpdate(msg, &dataEmptyContent[i], 1, FALSE);
-    todo_wine {
     ok(ret, "CryptMsgUpdate failed on byte %d: %x\n", i, GetLastError());
     ret = CryptMsgUpdate(msg, NULL, 0, TRUE);
     ok(ret, "CryptMsgUpdate failed on byte %d: %x\n", i, GetLastError());
-    }
     CryptMsgClose(msg);
     todo_wine
     check_updates("byte-by-byte empty content", &a4, &accum);
@@ -1065,7 +1059,6 @@ static void test_decode_msg_update(void)
     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
     SetLastError(0xdeadbeef);
     ret = CryptMsgUpdate(msg, msgData, sizeof(msgData), TRUE);
-    todo_wine
     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
      "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
     CryptMsgClose(msg);
@@ -1092,7 +1085,6 @@ static void test_decode_msg_update(void)
     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
     ret = CryptMsgUpdate(msg, dataEmptyContent, sizeof(dataEmptyContent),
      TRUE);
-    todo_wine
     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
     /* but decoding it as an explicitly typed message fails. */
     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, CMSG_DATA, 0, NULL,
@@ -1111,7 +1103,6 @@ static void test_decode_msg_update(void)
     SetLastError(0xdeadbeef);
     ret = CryptMsgUpdate(msg, dataEmptyBareContent,
      sizeof(dataEmptyBareContent), TRUE);
-    todo_wine
     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
      "Expected CRYPT_E_ASN1_BADTAG, got %x\n", GetLastError());
     CryptMsgClose(msg);
@@ -1120,7 +1111,6 @@ static void test_decode_msg_update(void)
      NULL);
     ret = CryptMsgUpdate(msg, dataEmptyBareContent,
      sizeof(dataEmptyBareContent), TRUE);
-    todo_wine
     ok(ret, "CryptMsgUpdate failed: %x\n", GetLastError());
     CryptMsgClose(msg);
 
@@ -1128,7 +1118,6 @@ static void test_decode_msg_update(void)
     msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING, 0, 0, 0, NULL, NULL);
     SetLastError(0xdeadbeef);
     ret = CryptMsgUpdate(msg, bogusOIDContent, sizeof(bogusOIDContent), TRUE);
-    todo_wine
     ok(!ret && GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
      "Expected CRYPT_E_INVALID_MSG_TYPE, got %x\n", GetLastError());
     CryptMsgClose(msg);
-- 
1.4.1


More information about the wine-patches mailing list