wintrust(6/7): Implement encoding SPC links
Juan Lang
juan.lang at gmail.com
Fri Aug 10 16:41:49 CDT 2007
--Juan
-------------- next part --------------
From 8ac410ff3f4b23d6521c482c4f9084bd4448008b Mon Sep 17 00:00:00 2001
From: Juan Lang <juan.lang at gmail.com>
Date: Fri, 10 Aug 2007 14:06:39 -0700
Subject: [PATCH] Implement encoding SPC links
---
dlls/wintrust/asn.c | 222 +++++++++++++++++++++++++++++++++++++++++++++
dlls/wintrust/tests/asn.c | 8 --
2 files changed, 220 insertions(+), 10 deletions(-)
diff --git a/dlls/wintrust/asn.c b/dlls/wintrust/asn.c
index 77c42d1..7ae2544 100644
--- a/dlls/wintrust/asn.c
+++ b/dlls/wintrust/asn.c
@@ -44,14 +44,232 @@ #define n16toh(x) RtlUshortByteSwap(x)
#endif
+static BOOL CRYPT_EncodeLen(DWORD len, BYTE *pbEncoded, DWORD *pcbEncoded)
+{
+ DWORD bytesNeeded, significantBytes = 0;
+
+ if (len <= 0x7f)
+ bytesNeeded = 1;
+ else
+ {
+ DWORD temp;
+
+ for (temp = len, significantBytes = sizeof(temp); !(temp & 0xff000000);
+ temp <<= 8, significantBytes--)
+ ;
+ bytesNeeded = significantBytes + 1;
+ }
+ if (!pbEncoded)
+ {
+ *pcbEncoded = bytesNeeded;
+ return TRUE;
+ }
+ if (*pcbEncoded < bytesNeeded)
+ {
+ SetLastError(ERROR_MORE_DATA);
+ return FALSE;
+ }
+ if (len <= 0x7f)
+ *pbEncoded = (BYTE)len;
+ else
+ {
+ DWORD i;
+
+ *pbEncoded++ = significantBytes | 0x80;
+ for (i = 0; i < significantBytes; i++)
+ {
+ *(pbEncoded + significantBytes - i - 1) = (BYTE)(len & 0xff);
+ len >>= 8;
+ }
+ }
+ *pcbEncoded = bytesNeeded;
+ return TRUE;
+}
+
+static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
+ DWORD *pcbEncoded)
+{
+ BOOL ret = TRUE;
+ const CRYPT_DATA_BLOB *blob = (const CRYPT_DATA_BLOB *)pvStructInfo;
+ DWORD bytesNeeded, lenBytes;
+
+ TRACE("(%d, %p), %p, %d\n", blob->cbData, blob->pbData, pbEncoded,
+ *pcbEncoded);
+
+ CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
+ bytesNeeded = 1 + lenBytes + blob->cbData;
+ if (!pbEncoded)
+ *pcbEncoded = bytesNeeded;
+ else if (*pcbEncoded < bytesNeeded)
+ {
+ *pcbEncoded = bytesNeeded;
+ SetLastError(ERROR_MORE_DATA);
+ ret = FALSE;
+ }
+ else
+ {
+ *pbEncoded++ = ASN_OCTETSTRING;
+ CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
+ pbEncoded += lenBytes;
+ if (blob->cbData)
+ memcpy(pbEncoded, blob->pbData, blob->cbData);
+ }
+ TRACE("returning %d\n", ret);
+ return ret;
+}
+
BOOL WINAPI WVTAsn1SpcLinkEncode(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
DWORD *pcbEncoded)
{
- FIXME("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
+ BOOL ret = FALSE;
+
+ TRACE("(0x%08x, %s, %p, %p, %p)\n", dwCertEncodingType,
debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
pcbEncoded);
- return FALSE;
+
+ __TRY
+ {
+ const SPC_LINK *link = (const SPC_LINK *)pvStructInfo;
+ DWORD bytesNeeded, lenBytes;
+
+ switch (link->dwLinkChoice)
+ {
+ case SPC_FILE_LINK_CHOICE:
+ {
+ DWORD fileNameLen, fileNameLenBytes;
+ LPWSTR ptr;
+
+ fileNameLen = lstrlenW(link->u.pwszFile) * sizeof(WCHAR);
+ CRYPT_EncodeLen(fileNameLen, NULL, &fileNameLenBytes);
+ CRYPT_EncodeLen(1 + fileNameLenBytes + fileNameLen, NULL,
+ &lenBytes);
+ bytesNeeded = 2 + lenBytes + fileNameLenBytes + fileNameLen;
+ if (!pbEncoded)
+ {
+ *pcbEncoded = bytesNeeded;
+ ret = TRUE;
+ }
+ else if (*pcbEncoded < bytesNeeded)
+ {
+ SetLastError(ERROR_MORE_DATA);
+ *pcbEncoded = bytesNeeded;
+ }
+ else
+ {
+ *pcbEncoded = bytesNeeded;
+ *pbEncoded++ = ASN_CONSTRUCTOR | ASN_CONTEXT | 2;
+ CRYPT_EncodeLen(1 + fileNameLenBytes + fileNameLen, pbEncoded,
+ &lenBytes);
+ pbEncoded += lenBytes;
+ *pbEncoded++ = ASN_CONTEXT;
+ CRYPT_EncodeLen(fileNameLen, pbEncoded, &fileNameLenBytes);
+ pbEncoded += fileNameLenBytes;
+ for (ptr = link->u.pwszFile; ptr && *ptr; ptr++)
+ {
+ *(WCHAR *)pbEncoded = hton16(*ptr);
+ pbEncoded += sizeof(WCHAR);
+ }
+ ret = TRUE;
+ }
+ break;
+ }
+ case SPC_MONIKER_LINK_CHOICE:
+ {
+ DWORD classIdLenBytes, dataLenBytes, dataLen;
+ CRYPT_DATA_BLOB classId = { sizeof(link->u.Moniker.ClassId),
+ (BYTE *)&link->u.Moniker.ClassId };
+
+ CRYPT_EncodeLen(classId.cbData, NULL, &classIdLenBytes);
+ CRYPT_EncodeLen(link->u.Moniker.SerializedData.cbData, NULL,
+ &dataLenBytes);
+ dataLen = 2 + classIdLenBytes + classId.cbData +
+ dataLenBytes + link->u.Moniker.SerializedData.cbData;
+ CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
+ bytesNeeded = 1 + dataLen + lenBytes;
+ if (!pbEncoded)
+ {
+ *pcbEncoded = bytesNeeded;
+ ret = TRUE;
+ }
+ else if (*pcbEncoded < bytesNeeded)
+ {
+ SetLastError(ERROR_MORE_DATA);
+ *pcbEncoded = bytesNeeded;
+ }
+ else
+ {
+ DWORD size;
+
+ *pcbEncoded = bytesNeeded;
+ *pbEncoded++ = ASN_CONSTRUCTOR | ASN_CONTEXT | 1;
+ CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
+ pbEncoded += lenBytes;
+ size = 1 + classIdLenBytes + classId.cbData;
+ CRYPT_AsnEncodeOctets(X509_ASN_ENCODING, NULL, &classId,
+ pbEncoded, &size);
+ pbEncoded += size;
+ size = 1 + dataLenBytes + link->u.Moniker.SerializedData.cbData;
+ CRYPT_AsnEncodeOctets(X509_ASN_ENCODING, NULL,
+ &link->u.Moniker.SerializedData, pbEncoded, &size);
+ pbEncoded += size;
+ ret = TRUE;
+ }
+ break;
+ }
+ case SPC_URL_LINK_CHOICE:
+ {
+ LPWSTR ptr;
+ DWORD urlLen;
+
+ /* Check for invalid characters in URL */
+ ret = TRUE;
+ urlLen = 0;
+ for (ptr = link->u.pwszUrl; ptr && *ptr && ret; ptr++)
+ if (*ptr > 0x7f)
+ {
+ *pcbEncoded = 0;
+ SetLastError(CRYPT_E_INVALID_IA5_STRING);
+ ret = FALSE;
+ }
+ else
+ urlLen++;
+ if (ret)
+ {
+ CRYPT_EncodeLen(urlLen, NULL, &lenBytes);
+ bytesNeeded = 1 + lenBytes + urlLen;
+ if (!pbEncoded)
+ *pcbEncoded = bytesNeeded;
+ else if (*pcbEncoded < bytesNeeded)
+ {
+ SetLastError(ERROR_MORE_DATA);
+ *pcbEncoded = bytesNeeded;
+ ret = FALSE;
+ }
+ else
+ {
+ *pcbEncoded = bytesNeeded;
+ *pbEncoded++ = ASN_CONTEXT;
+ CRYPT_EncodeLen(urlLen, pbEncoded, &lenBytes);
+ pbEncoded += lenBytes;
+ for (ptr = link->u.pwszUrl; ptr && *ptr; ptr++)
+ *pbEncoded++ = (BYTE)*ptr;
+ }
+ }
+ break;
+ }
+ default:
+ SetLastError(E_INVALIDARG);
+ }
+ }
+ __EXCEPT_PAGE_FAULT
+ {
+ SetLastError(STATUS_ACCESS_VIOLATION);
+ }
+ __ENDTRY
+ TRACE("returning %d\n", ret);
+ return ret;
}
BOOL WINAPI WVTAsn1SpcPeImageDataEncode(DWORD dwCertEncodingType,
diff --git a/dlls/wintrust/tests/asn.c b/dlls/wintrust/tests/asn.c
index 01e6bd0..e5e7f6e 100644
--- a/dlls/wintrust/tests/asn.c
+++ b/dlls/wintrust/tests/asn.c
@@ -55,13 +55,11 @@ static void test_encodeSPCLink(void)
SetLastError(0xdeadbeef);
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
- todo_wine
ok(!ret && GetLastError() == E_INVALIDARG,
"Expected E_INVALIDARG, got %08x\n", GetLastError());
link.dwLinkChoice = SPC_URL_LINK_CHOICE;
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
- todo_wine
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
if (ret)
{
@@ -75,18 +73,15 @@ static void test_encodeSPCLink(void)
SetLastError(0xdeadbeef);
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
- todo_wine
ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
"Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
/* Unlike the crypt32 string encoding routines, size is not set to the
* index of the first invalid character.
*/
- todo_wine
ok(size == 0, "Expected size 0, got %d\n", size);
link.pwszUrl = url;
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
- todo_wine
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
if (ret)
{
@@ -98,7 +93,6 @@ static void test_encodeSPCLink(void)
link.pwszFile = (LPWSTR)nihongoURL;
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
- todo_wine
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
if (ret)
{
@@ -110,7 +104,6 @@ static void test_encodeSPCLink(void)
memset(&link.Moniker, 0, sizeof(link.Moniker));
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
- todo_wine
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
if (ret)
{
@@ -123,7 +116,6 @@ static void test_encodeSPCLink(void)
link.Moniker.SerializedData.cbData = sizeof(data);
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
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