crypt32: Separate checking the tag of encoded bits from decoding the bits.

This commit is contained in:
Juan Lang 2008-11-05 11:47:38 -08:00 committed by Alexandre Julliard
parent ed2ba3a467
commit aa1effe3b2
2 changed files with 43 additions and 43 deletions

View File

@ -96,6 +96,7 @@ static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded, static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
DWORD *pcbDecoded); DWORD *pcbDecoded);
/* Doesn't check the tag, assumes the caller does so */
static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded, static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded); DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded, static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
@ -3298,64 +3299,54 @@ static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded) DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
{ {
BOOL ret; BOOL ret;
DWORD bytesNeeded, dataLen;
BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags, TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
pvStructInfo, *pcbStructInfo, pcbDecoded); pvStructInfo, *pcbStructInfo, pcbDecoded);
if (pbEncoded[0] == ASN_BITSTRING) if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
{ {
DWORD bytesNeeded, dataLen; if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); bytesNeeded = sizeof(CRYPT_BIT_BLOB);
else
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
if (pcbDecoded)
*pcbDecoded = 1 + lenBytes + dataLen;
if (!pvStructInfo)
*pcbStructInfo = bytesNeeded;
else if (*pcbStructInfo < bytesNeeded)
{ {
*pcbStructInfo = bytesNeeded;
SetLastError(ERROR_MORE_DATA);
ret = FALSE;
}
else
{
CRYPT_BIT_BLOB *blob;
*pcbStructInfo = bytesNeeded;
blob = (CRYPT_BIT_BLOB *)pvStructInfo;
blob->cbData = dataLen - 1;
blob->cUnusedBits = *(pbEncoded + 1 + lenBytes);
if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
bytesNeeded = sizeof(CRYPT_BIT_BLOB);
else
bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
if (pcbDecoded)
*pcbDecoded = 1 + lenBytes + dataLen;
if (!pvStructInfo)
*pcbStructInfo = bytesNeeded;
else if (*pcbStructInfo < bytesNeeded)
{ {
*pcbStructInfo = bytesNeeded; blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes;
SetLastError(ERROR_MORE_DATA);
ret = FALSE;
} }
else else
{ {
CRYPT_BIT_BLOB *blob; assert(blob->pbData);
if (blob->cbData)
*pcbStructInfo = bytesNeeded;
blob = (CRYPT_BIT_BLOB *)pvStructInfo;
blob->cbData = dataLen - 1;
blob->cUnusedBits = *(pbEncoded + 1 + lenBytes);
if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
{ {
blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes; BYTE mask = 0xff << blob->cUnusedBits;
}
else
{
assert(blob->pbData);
if (blob->cbData)
{
BYTE mask = 0xff << blob->cUnusedBits;
memcpy(blob->pbData, pbEncoded + 2 + lenBytes, memcpy(blob->pbData, pbEncoded + 2 + lenBytes,
blob->cbData); blob->cbData);
blob->pbData[blob->cbData - 1] &= mask; blob->pbData[blob->cbData - 1] &= mask;
}
} }
} }
} }
} }
else
{
SetLastError(CRYPT_E_ASN1_BADTAG);
ret = FALSE;
}
TRACE("returning %d (%08x)\n", ret, GetLastError());
return ret; return ret;
} }
@ -3372,7 +3363,17 @@ static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
{ {
DWORD bytesNeeded; DWORD bytesNeeded;
if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded, if (!cbEncoded)
{
SetLastError(CRYPT_E_ASN1_CORRUPT);
ret = FALSE;
}
else if (pbEncoded[0] != ASN_BITSTRING)
{
SetLastError(CRYPT_E_ASN1_BADTAG);
ret = FALSE;
}
else if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL))) dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
{ {
if (!pvStructInfo) if (!pvStructInfo)

View File

@ -3323,7 +3323,6 @@ static void test_decodeCRLDistPoints(DWORD dwEncoding)
ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG, distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
NULL, (BYTE *)&buf, &size); NULL, (BYTE *)&buf, &size);
todo_wine
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
if (ret) if (ret)
{ {