wintrust(4/4): Implement SPC indirect data decoding

Juan Lang juan.lang at gmail.com
Mon Aug 13 19:38:56 CDT 2007


--Juan
-------------- next part --------------
From 136def66324acf2bfb06a6dfa9134a991a4667f8 Mon Sep 17 00:00:00 2001
From: Juan Lang <juan.lang at gmail.com>
Date: Mon, 13 Aug 2007 14:36:08 -0700
Subject: [PATCH] Implement SPC indirect data decoding
---
 dlls/wintrust/asn.c         |  274 +++++++++++++++++++++++++++++++++++++++++++
 dlls/wintrust/wintrust.spec |    2 
 2 files changed, 275 insertions(+), 1 deletions(-)

diff --git a/dlls/wintrust/asn.c b/dlls/wintrust/asn.c
index 36bff15..4a95b73 100644
--- a/dlls/wintrust/asn.c
+++ b/dlls/wintrust/asn.c
@@ -1447,3 +1447,277 @@ BOOL WINAPI WVTAsn1SpcPeImageDataDecode(
     TRACE("returning %d\n", ret);
     return ret;
 }
+
+static BOOL WINAPI CRYPT_AsnDecodeOidIgnoreTag(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ void *pvStructInfo, DWORD *pcbStructInfo)
+{
+    BOOL ret = TRUE;
+    DWORD dataLen;
+
+    TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+     pvStructInfo, *pcbStructInfo);
+
+    if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
+    {
+        BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
+        DWORD bytesNeeded = sizeof(LPSTR);
+
+        if (dataLen)
+        {
+            /* The largest possible string for the first two components
+             * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
+             */
+            char firstTwo[6];
+            const BYTE *ptr;
+
+            snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
+             pbEncoded[1 + lenBytes] / 40,
+             pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
+             * 40);
+            bytesNeeded += strlen(firstTwo) + 1;
+            for (ptr = pbEncoded + 2 + lenBytes; ret &&
+             ptr - pbEncoded - 1 - lenBytes < dataLen; )
+            {
+                /* large enough for ".4000000" */
+                char str[9];
+                int val = 0;
+
+                while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
+                 (*ptr & 0x80))
+                {
+                    val <<= 7;
+                    val |= *ptr & 0x7f;
+                    ptr++;
+                }
+                if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
+                 (*ptr & 0x80))
+                {
+                    SetLastError(CRYPT_E_ASN1_CORRUPT);
+                    ret = FALSE;
+                }
+                else
+                {
+                    val <<= 7;
+                    val |= *ptr++;
+                    snprintf(str, sizeof(str), ".%d", val);
+                    bytesNeeded += strlen(str);
+                }
+            }
+        }
+        if (!pvStructInfo)
+            *pcbStructInfo = bytesNeeded;
+        else if (*pcbStructInfo < bytesNeeded)
+        {
+            *pcbStructInfo = bytesNeeded;
+            SetLastError(ERROR_MORE_DATA);
+            ret = FALSE;
+        }
+        else
+        {
+            if (dataLen)
+            {
+                const BYTE *ptr;
+                LPSTR pszObjId = *(LPSTR *)pvStructInfo;
+
+                *pszObjId = 0;
+                sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
+                 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
+                 40) * 40);
+                pszObjId += strlen(pszObjId);
+                for (ptr = pbEncoded + 2 + lenBytes; ret &&
+                 ptr - pbEncoded - 1 - lenBytes < dataLen; )
+                {
+                    int val = 0;
+
+                    while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
+                     (*ptr & 0x80))
+                    {
+                        val <<= 7;
+                        val |= *ptr & 0x7f;
+                        ptr++;
+                    }
+                    val <<= 7;
+                    val |= *ptr++;
+                    sprintf(pszObjId, ".%d", val);
+                    pszObjId += strlen(pszObjId);
+                }
+            }
+            else
+                *(LPSTR *)pvStructInfo = NULL;
+            *pcbStructInfo = bytesNeeded;
+        }
+    }
+    return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnDecodeOid(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ void *pvStructInfo, DWORD *pcbStructInfo)
+{
+    BOOL ret = FALSE;
+
+    TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+     pvStructInfo, *pcbStructInfo);
+
+    if (!cbEncoded)
+        SetLastError(CRYPT_E_ASN1_CORRUPT);
+    else if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
+        ret = CRYPT_AsnDecodeOidIgnoreTag(dwCertEncodingType, lpszStructType,
+         pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
+    else
+        SetLastError(CRYPT_E_ASN1_BADTAG);
+    return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ void *pvStructInfo, DWORD *pcbStructInfo)
+{
+    BOOL ret = TRUE;
+    DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
+
+    TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+     pvStructInfo, *pcbStructInfo);
+
+    if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
+        bytesNeeded += cbEncoded;
+    if (!pvStructInfo)
+        *pcbStructInfo = bytesNeeded;
+    else if (*pcbStructInfo < bytesNeeded)
+    {
+        SetLastError(ERROR_MORE_DATA);
+        *pcbStructInfo = bytesNeeded;
+        ret = FALSE;
+    }
+    else
+    {
+        PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
+
+        *pcbStructInfo = bytesNeeded;
+        blob->cbData = cbEncoded;
+        if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
+            blob->pbData = (LPBYTE)pbEncoded;
+        else
+        {
+            assert(blob->pbData);
+            memcpy(blob->pbData, pbEncoded, blob->cbData);
+        }
+    }
+    return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnDecodeAttributeTypeValue(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ void *pvStructInfo, DWORD *pcbStructInfo)
+{
+    CRYPT_ATTRIBUTE_TYPE_VALUE *typeValue =
+     (CRYPT_ATTRIBUTE_TYPE_VALUE *)pvStructInfo;
+    struct AsnDecodeSequenceItem items[] = {
+     { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, pszObjId),
+       CRYPT_AsnDecodeOid, sizeof(LPSTR), FALSE, TRUE,
+       offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, pszObjId), 0 },
+     { 0, offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, Value),
+       CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_DATA_BLOB), TRUE, TRUE,
+       offsetof(CRYPT_ATTRIBUTE_TYPE_VALUE, Value.pbData), 0 },
+    };
+
+    TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+     pvStructInfo, *pcbStructInfo);
+
+    return CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
+     sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
+     pvStructInfo, pcbStructInfo,
+     typeValue ? typeValue->pszObjId : NULL);
+}
+
+static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ void *pvStructInfo, DWORD *pcbStructInfo)
+{
+    CRYPT_ALGORITHM_IDENTIFIER *algo =
+     (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
+    BOOL ret = TRUE;
+    struct AsnDecodeSequenceItem items[] = {
+     { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
+       CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE, 
+       offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
+     { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
+       CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE, 
+       offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
+    };
+
+    TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+     pvStructInfo, *pcbStructInfo);
+
+    ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
+     sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
+     pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
+    if (ret && pvStructInfo)
+    {
+        TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
+         debugstr_a(algo->pszObjId));
+    }
+    return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnDecodeSPCDigest(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ void *pvStructInfo, DWORD *pcbStructInfo)
+{
+    struct SPCDigest *digest =
+     (struct SPCDigest *)pvStructInfo;
+    struct AsnDecodeSequenceItem items[] = {
+     { ASN_SEQUENCEOF, offsetof(struct SPCDigest, DigestAlgorithm),
+       CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
+       FALSE, TRUE,
+       offsetof(struct SPCDigest, DigestAlgorithm.pszObjId), 0 },
+     { ASN_OCTETSTRING, offsetof(struct SPCDigest, Digest),
+       CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB),
+       FALSE, TRUE, offsetof(struct SPCDigest, Digest.pbData), 0 },
+    };
+
+    TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+     pvStructInfo, *pcbStructInfo);
+
+    return CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
+     sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
+     pvStructInfo, pcbStructInfo,
+     digest ? digest->DigestAlgorithm.pszObjId : NULL);
+}
+
+BOOL WINAPI WVTAsn1SpcIndirectDataContentDecode(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ void *pvStructInfo, DWORD *pcbStructInfo)
+{
+    BOOL ret = FALSE;
+
+    TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+     pvStructInfo, *pcbStructInfo);
+
+    __TRY
+    {
+        struct AsnDecodeSequenceItem items[] = {
+         { ASN_SEQUENCEOF, offsetof(SPC_INDIRECT_DATA_CONTENT, Data),
+           CRYPT_AsnDecodeAttributeTypeValue,
+           sizeof(CRYPT_ATTRIBUTE_TYPE_VALUE), FALSE, TRUE,
+           offsetof(SPC_INDIRECT_DATA_CONTENT, Data.pszObjId), 0 },
+         { ASN_SEQUENCEOF, offsetof(SPC_INDIRECT_DATA_CONTENT, DigestAlgorithm),
+           CRYPT_AsnDecodeSPCDigest, sizeof(struct SPCDigest),
+           FALSE, TRUE,
+           offsetof(SPC_INDIRECT_DATA_CONTENT, DigestAlgorithm.pszObjId), 0 },
+        };
+
+        ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
+         sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
+         pvStructInfo, pcbStructInfo, NULL);
+    }
+    __EXCEPT_PAGE_FAULT
+    {
+        SetLastError(STATUS_ACCESS_VIOLATION);
+    }
+    __ENDTRY
+    TRACE("returning %d\n", ret);
+    return ret;
+}
+
diff --git a/dlls/wintrust/wintrust.spec b/dlls/wintrust/wintrust.spec
index d7df156..9242120 100644
--- a/dlls/wintrust/wintrust.spec
+++ b/dlls/wintrust/wintrust.spec
@@ -92,7 +92,7 @@
 @ stub WVTAsn1CatNameValueEncode
 @ stub WVTAsn1SpcFinancialCriteriaInfoDecode
 @ stub WVTAsn1SpcFinancialCriteriaInfoEncode
-@ stub WVTAsn1SpcIndirectDataContentDecode
+@ stdcall WVTAsn1SpcIndirectDataContentDecode(long str ptr long long ptr ptr)
 @ stdcall WVTAsn1SpcIndirectDataContentEncode(long str ptr ptr ptr)
 @ stdcall WVTAsn1SpcLinkDecode(long str ptr long long ptr ptr)
 @ stdcall WVTAsn1SpcLinkEncode(long str ptr ptr ptr)
-- 
1.4.1


More information about the wine-patches mailing list