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