Juan Lang : wintrust: Implement SPC indirect data encoding.

Alexandre Julliard julliard at wine.codeweavers.com
Tue Aug 14 07:13:13 CDT 2007


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

Author: Juan Lang <juan.lang at gmail.com>
Date:   Mon Aug 13 14:35:39 2007 -0700

wintrust: Implement SPC indirect data encoding.

---

 dlls/wintrust/asn.c         |  226 +++++++++++++++++++++++++++++++++++++++++++
 dlls/wintrust/wintrust.spec |    2 +-
 2 files changed, 227 insertions(+), 1 deletions(-)

diff --git a/dlls/wintrust/asn.c b/dlls/wintrust/asn.c
index 02c0005..36bff15 100644
--- a/dlls/wintrust/asn.c
+++ b/dlls/wintrust/asn.c
@@ -18,6 +18,7 @@
  *
  */
 #include <stdarg.h>
+#include <stdio.h>
 #include <assert.h>
 #define NONAMELESSUNION
 #include "windef.h"
@@ -508,6 +509,231 @@ BOOL WINAPI WVTAsn1SpcPeImageDataEncode(DWORD dwCertEncodingType,
     return ret;
 }
 
+static BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
+ DWORD *pcbEncoded)
+{
+    LPCSTR pszObjId = (LPCSTR)pvStructInfo;
+    DWORD bytesNeeded = 0, lenBytes;
+    BOOL ret = TRUE;
+    int firstPos = 0;
+    BYTE firstByte = 0;
+
+    TRACE("%s\n", debugstr_a(pszObjId));
+
+    if (pszObjId)
+    {
+        const char *ptr;
+        int val1, val2;
+
+        if (sscanf(pszObjId, "%d.%d.%n", &val1, &val2, &firstPos) != 2)
+        {
+            SetLastError(CRYPT_E_ASN1_ERROR);
+            return FALSE;
+        }
+        bytesNeeded++;
+        firstByte = val1 * 40 + val2;
+        ptr = pszObjId + firstPos;
+        while (ret && *ptr)
+        {
+            int pos;
+
+            /* note I assume each component is at most 32-bits long in base 2 */
+            if (sscanf(ptr, "%d%n", &val1, &pos) == 1)
+            {
+                if (val1 >= 0x10000000)
+                    bytesNeeded += 5;
+                else if (val1 >= 0x200000)
+                    bytesNeeded += 4;
+                else if (val1 >= 0x4000)
+                    bytesNeeded += 3;
+                else if (val1 >= 0x80)
+                    bytesNeeded += 2;
+                else
+                    bytesNeeded += 1;
+                ptr += pos;
+                if (*ptr == '.')
+                    ptr++;
+            }
+            else
+            {
+                SetLastError(CRYPT_E_ASN1_ERROR);
+                return FALSE;
+            }
+        }
+        CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
+    }
+    else
+        lenBytes = 1;
+    bytesNeeded += 1 + lenBytes;
+    if (pbEncoded)
+    {
+        if (*pcbEncoded < bytesNeeded)
+        {
+            SetLastError(ERROR_MORE_DATA);
+            ret = FALSE;
+        }
+        else
+        {
+            *pbEncoded++ = ASN_OBJECTIDENTIFIER;
+            CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes);
+            pbEncoded += lenBytes;
+            if (pszObjId)
+            {
+                const char *ptr;
+                int val, pos;
+
+                *pbEncoded++ = firstByte;
+                ptr = pszObjId + firstPos;
+                while (ret && *ptr)
+                {
+                    sscanf(ptr, "%d%n", &val, &pos);
+                    {
+                        unsigned char outBytes[5];
+                        int numBytes, i;
+
+                        if (val >= 0x10000000)
+                            numBytes = 5;
+                        else if (val >= 0x200000)
+                            numBytes = 4;
+                        else if (val >= 0x4000)
+                            numBytes = 3;
+                        else if (val >= 0x80)
+                            numBytes = 2;
+                        else
+                            numBytes = 1;
+                        for (i = numBytes; i > 0; i--)
+                        {
+                            outBytes[i - 1] = val & 0x7f;
+                            val >>= 7;
+                        }
+                        for (i = 0; i < numBytes - 1; i++)
+                            *pbEncoded++ = outBytes[i] | 0x80;
+                        *pbEncoded++ = outBytes[i];
+                        ptr += pos;
+                        if (*ptr == '.')
+                            ptr++;
+                    }
+                }
+            }
+        }
+    }
+    *pcbEncoded = bytesNeeded;
+    return ret;
+}
+
+static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
+ DWORD *pcbEncoded)
+{
+    const CRYPT_DER_BLOB *blob = (const CRYPT_DER_BLOB *)pvStructInfo;
+    BOOL ret = TRUE;
+
+    if (!pbEncoded)
+        *pcbEncoded = blob->cbData;
+    else if (*pcbEncoded < blob->cbData)
+    {
+        *pcbEncoded = blob->cbData;
+        SetLastError(ERROR_MORE_DATA);
+        ret = FALSE;
+    }
+    else
+    {
+        if (blob->cbData)
+            memcpy(pbEncoded, blob->pbData, blob->cbData);
+        *pcbEncoded = blob->cbData;
+    }
+    return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnEncodeAlgorithmIdWithNullParams(
+ DWORD dwCertEncodingType, LPCSTR lpszStructType, const void *pvStructInfo,
+ BYTE *pbEncoded, DWORD *pcbEncoded)
+{
+    const CRYPT_ALGORITHM_IDENTIFIER *algo =
+     (const CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
+    static const BYTE asn1Null[] = { ASN_NULL, 0 };
+    static const CRYPT_DATA_BLOB nullBlob = { sizeof(asn1Null),
+     (LPBYTE)asn1Null };
+    BOOL ret;
+    struct AsnEncodeSequenceItem items[2] = {
+     { algo->pszObjId, CRYPT_AsnEncodeOid, 0 },
+     { NULL,           CRYPT_CopyEncodedBlob, 0 },
+    };
+
+    if (algo->Parameters.cbData)
+        items[1].pvStructInfo = &algo->Parameters;
+    else
+        items[1].pvStructInfo = &nullBlob;
+    ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items,
+     sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
+    return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnEncodeAttributeTypeValue(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
+ DWORD *pcbEncoded)
+{
+    const CRYPT_ATTRIBUTE_TYPE_VALUE *typeValue =
+     (const CRYPT_ATTRIBUTE_TYPE_VALUE *)pvStructInfo;
+    struct AsnEncodeSequenceItem items[] = {
+     { &typeValue->pszObjId, CRYPT_AsnEncodeOid, 0 },
+     { &typeValue->Value,    CRYPT_CopyEncodedBlob, 0 },
+    };
+
+    return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
+     items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
+}
+
+struct SPCDigest
+{
+    CRYPT_ALGORITHM_IDENTIFIER DigestAlgorithm;
+    CRYPT_HASH_BLOB            Digest;
+};
+
+static BOOL WINAPI CRYPT_AsnEncodeSPCDigest(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
+ DWORD *pcbEncoded)
+{
+    const struct SPCDigest *digest = (const struct SPCDigest *)pvStructInfo;
+    struct AsnEncodeSequenceItem items[] = {
+     { &digest->DigestAlgorithm, CRYPT_AsnEncodeAlgorithmIdWithNullParams, 0 },
+     { &digest->Digest,          CRYPT_CopyEncodedBlob, 0 },
+    };
+
+    return CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
+     items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
+}
+
+BOOL WINAPI WVTAsn1SpcIndirectDataContentEncode(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
+ DWORD *pcbEncoded)
+{
+    BOOL ret = FALSE;
+
+    TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
+     debugstr_a(lpszStructType), pvStructInfo, pbEncoded, pcbEncoded);
+
+    __TRY
+    {
+        const SPC_INDIRECT_DATA_CONTENT *data =
+         (const SPC_INDIRECT_DATA_CONTENT *)pvStructInfo;
+        struct AsnEncodeSequenceItem items[] = {
+         { &data->Data,            CRYPT_AsnEncodeAttributeTypeValue, 0 },
+         { &data->DigestAlgorithm, CRYPT_AsnEncodeSPCDigest, 0 },
+        };
+
+        ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING,
+         items, sizeof(items) / sizeof(items[0]), pbEncoded, pcbEncoded);
+    }
+    __EXCEPT_PAGE_FAULT
+    {
+        SetLastError(STATUS_ACCESS_VIOLATION);
+    }
+    __ENDTRY
+    return ret;
+}
+
 /* Gets the number of length bytes from the given (leading) length byte */
 #define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
 
diff --git a/dlls/wintrust/wintrust.spec b/dlls/wintrust/wintrust.spec
index 7e31548..d7df156 100644
--- a/dlls/wintrust/wintrust.spec
+++ b/dlls/wintrust/wintrust.spec
@@ -93,7 +93,7 @@
 @ stub WVTAsn1SpcFinancialCriteriaInfoDecode
 @ stub WVTAsn1SpcFinancialCriteriaInfoEncode
 @ stub WVTAsn1SpcIndirectDataContentDecode
-@ stub WVTAsn1SpcIndirectDataContentEncode
+@ stdcall WVTAsn1SpcIndirectDataContentEncode(long str ptr ptr ptr)
 @ stdcall WVTAsn1SpcLinkDecode(long str ptr long long ptr ptr)
 @ stdcall WVTAsn1SpcLinkEncode(long str ptr ptr ptr)
 @ stub WVTAsn1SpcMinimalCriteriaInfoDecode




More information about the wine-cvs mailing list