crypt32: Support indefinite-length encoded arrays.

This commit is contained in:
Juan Lang 2007-09-17 16:58:25 -07:00 committed by Alexandre Julliard
parent 159a369318
commit 5d168bd4c0
2 changed files with 62 additions and 40 deletions

View File

@ -536,7 +536,7 @@ static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
{ {
DWORD dataLen; DWORD dataLen;
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
{ {
DWORD bytesNeeded, cItems = 0, decoded; DWORD bytesNeeded, cItems = 0, decoded;
BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
@ -549,53 +549,76 @@ static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
if (dataLen) if (dataLen)
{ {
const BYTE *ptr; const BYTE *ptr;
BOOL doneDecoding = FALSE;
for (ptr = pbEncoded + 1 + lenBytes; ret && for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
ptr - pbEncoded - 1 - lenBytes < dataLen; )
{ {
DWORD itemLenBytes, itemDataLen, itemDecoded, size = 0; DWORD itemLenBytes;
itemLenBytes = GET_LEN_BYTES(ptr[1]); itemLenBytes = GET_LEN_BYTES(ptr[1]);
/* Each item decoded may not tolerate extraneous bytes, so if (dataLen == CMSG_INDEFINITE_LENGTH)
* get the length of the next element and pass it directly.
*/
ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
&itemDataLen);
if (ret)
ret = arrayDesc->decodeFunc(ptr,
1 + itemLenBytes + itemDataLen,
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size,
&itemDecoded);
if (ret)
{ {
DWORD nextLen; if (ptr[0] == 0)
{
doneDecoding = TRUE;
if (itemLenBytes != 1 || ptr[1] != 0)
{
SetLastError(CRYPT_E_ASN1_CORRUPT);
ret = FALSE;
}
else
decoded += 2;
}
}
else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
doneDecoding = TRUE;
if (!doneDecoding)
{
DWORD itemDataLen, itemDecoded, size = 0;
cItems++; /* Each item decoded may not tolerate extraneous bytes,
if (itemSizes != &itemSize) * so get the length of the next element and pass it
itemSizes = CryptMemRealloc(itemSizes, * directly.
cItems * sizeof(struct AsnArrayItemSize)); */
else if (cItems > 1) ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
&itemDataLen);
if (ret)
ret = arrayDesc->decodeFunc(ptr,
1 + itemLenBytes + itemDataLen,
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size,
&itemDecoded);
if (ret)
{ {
itemSizes = DWORD nextLen;
CryptMemAlloc(
cItems * sizeof(struct AsnArrayItemSize)); cItems++;
if (itemSizes != &itemSize)
itemSizes = CryptMemRealloc(itemSizes,
cItems * sizeof(struct AsnArrayItemSize));
else if (cItems > 1)
{
itemSizes =
CryptMemAlloc(
cItems * sizeof(struct AsnArrayItemSize));
if (itemSizes)
memcpy(itemSizes, &itemSize,
sizeof(itemSize));
}
if (itemSizes) if (itemSizes)
memcpy(itemSizes, &itemSize, sizeof(itemSize)); {
decoded += itemDecoded;
itemSizes[cItems - 1].encodedLen =
1 + itemLenBytes + itemDataLen;
itemSizes[cItems - 1].size = size;
bytesNeeded += size;
ret = CRYPT_GetLen(ptr,
cbEncoded - (ptr - pbEncoded), &nextLen);
if (ret)
ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
}
else
ret = FALSE;
} }
if (itemSizes)
{
decoded += itemDecoded;
itemSizes[cItems - 1].encodedLen = 1 + itemLenBytes
+ itemDataLen;
itemSizes[cItems - 1].size = size;
bytesNeeded += size;
ret = CRYPT_GetLen(ptr,
cbEncoded - (ptr - pbEncoded), &nextLen);
if (ret)
ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
}
else
ret = FALSE;
} }
} }
} }

View File

@ -1015,7 +1015,6 @@ static void test_decodeName(DWORD dwEncoding)
ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptyIndefiniteSequence, ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptyIndefiniteSequence,
sizeof(emptyIndefiniteSequence), CRYPT_DECODE_ALLOC_FLAG, NULL, sizeof(emptyIndefiniteSequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
(BYTE *)&buf, &bufSize); (BYTE *)&buf, &bufSize);
todo_wine
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
if (ret) if (ret)
{ {