wintrust(2/4): Implement SPC PE image encoding
Juan Lang
juan.lang at gmail.com
Mon Aug 13 19:38:19 CDT 2007
--Juan
-------------- next part --------------
From a99c24d1f045b1f6f12d19cf29da2f43c526373f Mon Sep 17 00:00:00 2001
From: Juan Lang <juan.lang at gmail.com>
Date: Mon, 13 Aug 2007 14:35:13 -0700
Subject: [PATCH] Implement SPC PE image encoding
---
dlls/wintrust/asn.c | 230 ++++++++++++++++++++++++++++++++++++++++++++-
dlls/wintrust/tests/asn.c | 7 -
2 files changed, 227 insertions(+), 10 deletions(-)
diff --git a/dlls/wintrust/asn.c b/dlls/wintrust/asn.c
index f60fba8..02c0005 100644
--- a/dlls/wintrust/asn.c
+++ b/dlls/wintrust/asn.c
@@ -143,7 +143,8 @@ BOOL WINAPI WVTAsn1SpcLinkEncode(DWORD d
DWORD fileNameLen, fileNameLenBytes;
LPWSTR ptr;
- fileNameLen = lstrlenW(link->u.pwszFile) * sizeof(WCHAR);
+ fileNameLen = link->u.pwszFile ?
+ lstrlenW(link->u.pwszFile) * sizeof(WCHAR) : 0;
CRYPT_EncodeLen(fileNameLen, NULL, &fileNameLenBytes);
CRYPT_EncodeLen(1 + fileNameLenBytes + fileNameLen, NULL,
&lenBytes);
@@ -274,14 +275,237 @@ BOOL WINAPI WVTAsn1SpcLinkEncode(DWORD d
return ret;
}
+typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
+ BYTE *, DWORD *);
+
+struct AsnEncodeSequenceItem
+{
+ const void *pvStructInfo;
+ CryptEncodeObjectFunc encodeFunc;
+ DWORD size; /* used during encoding, not for your use */
+};
+
+static BOOL WINAPI CRYPT_AsnEncodeSequence(DWORD dwCertEncodingType,
+ struct AsnEncodeSequenceItem items[], DWORD cItem, BYTE *pbEncoded,
+ DWORD *pcbEncoded)
+{
+ BOOL ret;
+ DWORD i, dataLen = 0;
+
+ TRACE("%p, %d, %p, %d\n", items, cItem, pbEncoded, *pcbEncoded);
+ for (i = 0, ret = TRUE; ret && i < cItem; i++)
+ {
+ ret = items[i].encodeFunc(dwCertEncodingType, NULL,
+ items[i].pvStructInfo, NULL, &items[i].size);
+ /* Some functions propagate their errors through the size */
+ if (!ret)
+ *pcbEncoded = items[i].size;
+ dataLen += items[i].size;
+ }
+ if (ret)
+ {
+ DWORD lenBytes, bytesNeeded;
+
+ CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
+ bytesNeeded = 1 + lenBytes + dataLen;
+ if (!pbEncoded)
+ *pcbEncoded = bytesNeeded;
+ else if (*pcbEncoded < bytesNeeded)
+ {
+ *pcbEncoded = bytesNeeded;
+ SetLastError(ERROR_MORE_DATA);
+ ret = FALSE;
+ }
+ else
+ {
+ *pcbEncoded = bytesNeeded;
+ *pbEncoded++ = ASN_SEQUENCE;
+ CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
+ pbEncoded += lenBytes;
+ for (i = 0; ret && i < cItem; i++)
+ {
+ ret = items[i].encodeFunc(dwCertEncodingType, NULL,
+ items[i].pvStructInfo, pbEncoded, &items[i].size);
+ /* Some functions propagate their errors through the size */
+ if (!ret)
+ *pcbEncoded = items[i].size;
+ pbEncoded += items[i].size;
+ }
+ }
+ }
+ TRACE("returning %d\n", ret);
+ return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
+ DWORD *pcbEncoded)
+{
+ BOOL ret = FALSE;
+
+ __TRY
+ {
+ const CRYPT_BIT_BLOB *blob = (const CRYPT_BIT_BLOB *)pvStructInfo;
+ DWORD bytesNeeded, lenBytes, dataBytes;
+ BYTE unusedBits;
+
+ /* yep, MS allows cUnusedBits to be >= 8 */
+ if (!blob->cUnusedBits)
+ {
+ dataBytes = blob->cbData;
+ unusedBits = 0;
+ }
+ else if (blob->cbData * 8 > blob->cUnusedBits)
+ {
+ dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
+ unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
+ blob->cUnusedBits;
+ }
+ else
+ {
+ dataBytes = 0;
+ unusedBits = 0;
+ }
+ CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
+ bytesNeeded = 1 + lenBytes + dataBytes + 1;
+ if (!pbEncoded)
+ {
+ *pcbEncoded = bytesNeeded;
+ ret = TRUE;
+ }
+ else if (*pcbEncoded < bytesNeeded)
+ {
+ *pcbEncoded = bytesNeeded;
+ SetLastError(ERROR_MORE_DATA);
+ }
+ else
+ {
+ ret = TRUE;
+ *pcbEncoded = bytesNeeded;
+ *pbEncoded++ = ASN_BITSTRING;
+ CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
+ pbEncoded += lenBytes;
+ *pbEncoded++ = unusedBits;
+ if (dataBytes)
+ {
+ BYTE mask = 0xff << unusedBits;
+
+ if (dataBytes > 1)
+ {
+ memcpy(pbEncoded, blob->pbData, dataBytes - 1);
+ pbEncoded += dataBytes - 1;
+ }
+ *pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
+ }
+ }
+ }
+ __EXCEPT_PAGE_FAULT
+ {
+ SetLastError(STATUS_ACCESS_VIOLATION);
+ }
+ __ENDTRY
+ return ret;
+}
+
+struct AsnConstructedItem
+{
+ BYTE tag;
+ const void *pvStructInfo;
+ CryptEncodeObjectFunc encodeFunc;
+};
+
+static BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
+ DWORD *pcbEncoded)
+{
+ BOOL ret;
+ const struct AsnConstructedItem *item =
+ (const struct AsnConstructedItem *)pvStructInfo;
+ DWORD len;
+
+ if ((ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
+ item->pvStructInfo, NULL, &len)))
+ {
+ DWORD dataLen, bytesNeeded;
+
+ CRYPT_EncodeLen(len, NULL, &dataLen);
+ bytesNeeded = 1 + dataLen + len;
+ if (!pbEncoded)
+ *pcbEncoded = bytesNeeded;
+ else if (*pcbEncoded < bytesNeeded)
+ {
+ *pcbEncoded = bytesNeeded;
+ SetLastError(ERROR_MORE_DATA);
+ ret = FALSE;
+ }
+ else
+ {
+ *pcbEncoded = bytesNeeded;
+ *pbEncoded++ = ASN_CONTEXT | ASN_CONSTRUCTOR | item->tag;
+ CRYPT_EncodeLen(len, pbEncoded, &dataLen);
+ pbEncoded += dataLen;
+ ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
+ item->pvStructInfo, pbEncoded, &len);
+ if (!ret)
+ {
+ /* Some functions propagate their errors through the size */
+ *pcbEncoded = len;
+ }
+ }
+ }
+ else
+ {
+ /* Some functions propagate their errors through the size */
+ *pcbEncoded = len;
+ }
+ return ret;
+}
+
+
BOOL WINAPI WVTAsn1SpcPeImageDataEncode(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
DWORD *pcbEncoded)
{
- FIXME("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
+ const SPC_PE_IMAGE_DATA *imageData =
+ (const SPC_PE_IMAGE_DATA *)pvStructInfo;
+ BOOL ret = FALSE;
+
+ TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
pcbEncoded);
- return FALSE;
+
+ __TRY
+ {
+ struct AsnEncodeSequenceItem items[2] = {
+ { 0 }
+ };
+ struct AsnConstructedItem constructed = { 0, imageData->pFile,
+ WVTAsn1SpcLinkEncode };
+ DWORD cItem = 0;
+
+ if (imageData->Flags.cbData)
+ {
+ items[cItem].pvStructInfo = &imageData->Flags;
+ items[cItem].encodeFunc = CRYPT_AsnEncodeBits;
+ cItem++;
+ }
+ if (imageData->pFile)
+ {
+ items[cItem].pvStructInfo = &constructed;
+ items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
+ cItem++;
+ }
+
+ ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
+ pbEncoded, pcbEncoded);
+ }
+ __EXCEPT_PAGE_FAULT
+ {
+ SetLastError(STATUS_ACCESS_VIOLATION);
+ }
+ __ENDTRY
+ TRACE("returning %d\n", ret);
+ return ret;
}
/* Gets the number of length bytes from the given (leading) length byte */
diff --git a/dlls/wintrust/tests/asn.c b/dlls/wintrust/tests/asn.c
index b47f790..43b1cba 100644
--- a/dlls/wintrust/tests/asn.c
+++ b/dlls/wintrust/tests/asn.c
@@ -240,7 +240,6 @@ static void test_encodeSPCPEImage(void)
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT,
&imageData, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
- todo_wine
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
if (ret)
{
@@ -254,7 +253,6 @@ static void test_encodeSPCPEImage(void)
SetLastError(0xdeadbeef);
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT,
&imageData, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
- todo_wine
ok(!ret && GetLastError () == E_INVALIDARG,
"Expected E_INVALIDARG, got %08x\n", GetLastError());
/* With just unused bits field set: */
@@ -262,7 +260,6 @@ static void test_encodeSPCPEImage(void)
imageData.Flags.cUnusedBits = 1;
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT,
&imageData, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
- todo_wine
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
if (ret)
{
@@ -277,7 +274,6 @@ static void test_encodeSPCPEImage(void)
imageData.Flags.cbData = sizeof(flags);
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT,
&imageData, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
- todo_wine
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
if (ret)
{
@@ -292,7 +288,6 @@ static void test_encodeSPCPEImage(void)
imageData.pFile = &link;
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT,
&imageData, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
- todo_wine
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
if (ret)
{
@@ -306,7 +301,6 @@ static void test_encodeSPCPEImage(void)
imageData.Flags.cbData = sizeof(flags);
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT,
&imageData, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
- todo_wine
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
if (ret)
{
@@ -320,7 +314,6 @@ static void test_encodeSPCPEImage(void)
link.pwszFile = (LPWSTR)nihongoURL;
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_PE_IMAGE_DATA_STRUCT,
&imageData, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
- todo_wine
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
if (ret)
{
--
1.4.1
More information about the wine-patches
mailing list