Commit 06b51457 authored by Juan Lang's avatar Juan Lang Committed by Alexandre Julliard

wintrust: Implement encoding SPC links.

parent 29cae46f
......@@ -44,14 +44,232 @@ WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
#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,
......
......@@ -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)
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment