wintrust: Implement encoding SPC links.
This commit is contained in:
parent
29cae46fce
commit
06b51457e1
|
@ -44,14 +44,232 @@ WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
|
||||||
|
|
||||||
#endif
|
#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,
|
BOOL WINAPI WVTAsn1SpcLinkEncode(DWORD dwCertEncodingType,
|
||||||
LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
|
LPCSTR lpszStructType, const void *pvStructInfo, BYTE *pbEncoded,
|
||||||
DWORD *pcbEncoded)
|
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,
|
debugstr_a(lpszStructType), pvStructInfo, pbEncoded,
|
||||||
pcbEncoded);
|
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,
|
BOOL WINAPI WVTAsn1SpcPeImageDataEncode(DWORD dwCertEncodingType,
|
||||||
|
|
|
@ -55,13 +55,11 @@ static void test_encodeSPCLink(void)
|
||||||
SetLastError(0xdeadbeef);
|
SetLastError(0xdeadbeef);
|
||||||
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
|
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
|
||||||
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
||||||
todo_wine
|
|
||||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||||
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||||
link.dwLinkChoice = SPC_URL_LINK_CHOICE;
|
link.dwLinkChoice = SPC_URL_LINK_CHOICE;
|
||||||
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
|
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
|
||||||
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
||||||
todo_wine
|
|
||||||
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
|
@ -75,18 +73,15 @@ static void test_encodeSPCLink(void)
|
||||||
SetLastError(0xdeadbeef);
|
SetLastError(0xdeadbeef);
|
||||||
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
|
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
|
||||||
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
||||||
todo_wine
|
|
||||||
ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
|
ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
|
||||||
"Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
|
"Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
|
||||||
/* Unlike the crypt32 string encoding routines, size is not set to the
|
/* Unlike the crypt32 string encoding routines, size is not set to the
|
||||||
* index of the first invalid character.
|
* index of the first invalid character.
|
||||||
*/
|
*/
|
||||||
todo_wine
|
|
||||||
ok(size == 0, "Expected size 0, got %d\n", size);
|
ok(size == 0, "Expected size 0, got %d\n", size);
|
||||||
link.pwszUrl = url;
|
link.pwszUrl = url;
|
||||||
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
|
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
|
||||||
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
||||||
todo_wine
|
|
||||||
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
|
@ -98,7 +93,6 @@ static void test_encodeSPCLink(void)
|
||||||
link.pwszFile = (LPWSTR)nihongoURL;
|
link.pwszFile = (LPWSTR)nihongoURL;
|
||||||
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
|
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
|
||||||
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
||||||
todo_wine
|
|
||||||
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
|
@ -110,7 +104,6 @@ static void test_encodeSPCLink(void)
|
||||||
memset(&link.Moniker, 0, sizeof(link.Moniker));
|
memset(&link.Moniker, 0, sizeof(link.Moniker));
|
||||||
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
|
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
|
||||||
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
||||||
todo_wine
|
|
||||||
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
|
@ -123,7 +116,6 @@ static void test_encodeSPCLink(void)
|
||||||
link.Moniker.SerializedData.cbData = sizeof(data);
|
link.Moniker.SerializedData.cbData = sizeof(data);
|
||||||
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
|
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, SPC_LINK_STRUCT, &link,
|
||||||
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
||||||
todo_wine
|
|
||||||
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue