📄 decode.c
字号:
: NULL, &items[i].size);
if (ret)
{
if (nextData && items[i].hasPointer &&
items[i].size > items[i].minSize)
{
nextData += items[i].size - items[i].minSize;
/* align nextData to DWORD boundaries */
if (items[i].size % sizeof(DWORD))
nextData += sizeof(DWORD) - items[i].size %
sizeof(DWORD);
}
/* Account for alignment padding */
if (items[i].size % sizeof(DWORD))
items[i].size += sizeof(DWORD) -
items[i].size % sizeof(DWORD);
ptr += 1 + nextItemLenBytes + nextItemLen;
}
else if (items[i].optional &&
GetLastError() == CRYPT_E_ASN1_BADTAG)
{
TRACE("skipping optional item %d\n", i);
items[i].size = items[i].minSize;
SetLastError(NOERROR);
ret = TRUE;
}
else
TRACE("item %d failed: %08x\n", i,
GetLastError());
}
else
items[i].size = items[i].minSize;
}
else if (items[i].optional)
{
TRACE("skipping optional item %d\n", i);
items[i].size = items[i].minSize;
}
else
{
TRACE("tag %02x doesn't match expected %02x\n",
ptr[0], items[i].tag);
SetLastError(CRYPT_E_ASN1_BADTAG);
ret = FALSE;
}
}
}
else if (items[i].optional)
{
TRACE("missing optional item %d, skipping\n", i);
items[i].size = items[i].minSize;
}
else
{
TRACE("not enough bytes for item %d, failing\n", i);
SetLastError(CRYPT_E_ASN1_CORRUPT);
ret = FALSE;
}
}
if (cbEncoded - (ptr - pbEncoded) != 0)
{
TRACE("%d remaining bytes, failing\n", cbEncoded -
(ptr - pbEncoded));
SetLastError(CRYPT_E_ASN1_CORRUPT);
ret = FALSE;
}
return ret;
}
/* This decodes an arbitrary sequence into a contiguous block of memory
* (basically, a struct.) Each element being decoded is described by a struct
* AsnDecodeSequenceItem, see above.
* startingPointer is an optional pointer to the first place where dynamic
* data will be stored. If you know the starting offset, you may pass it
* here. Otherwise, pass NULL, and one will be inferred from the items.
* Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
* If any undecoded data are left over, fails with CRYPT_E_ASN1_CORRUPT.
*/
static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
void *pvStructInfo, DWORD *pcbStructInfo, void *startingPointer)
{
BOOL ret;
TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
startingPointer);
if (pbEncoded[0] == ASN_SEQUENCE)
{
DWORD dataLen;
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
{
DWORD i;
ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, pbEncoded,
cbEncoded, dwFlags, NULL, NULL);
if (ret)
{
DWORD bytesNeeded = 0, structSize = 0;
for (i = 0; i < cItem; i++)
{
bytesNeeded += items[i].size;
structSize += items[i].minSize;
}
if (!pvStructInfo)
*pcbStructInfo = bytesNeeded;
else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
{
BYTE *nextData;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
pvStructInfo = *(BYTE **)pvStructInfo;
if (startingPointer)
nextData = (BYTE *)startingPointer;
else
nextData = (BYTE *)pvStructInfo + structSize;
memset(pvStructInfo, 0, structSize);
ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
pbEncoded, cbEncoded, dwFlags, pvStructInfo, nextData);
}
}
}
}
else
{
SetLastError(CRYPT_E_ASN1_BADTAG);
ret = FALSE;
}
TRACE("returning %d (%08x)\n", ret, GetLastError());
return ret;
}
/* tag:
* The expected tag of the entire encoded array (usually a variant
* of ASN_SETOF or ASN_SEQUENCEOF.)
* decodeFunc:
* used to decode each item in the array
* itemSize:
* is the minimum size of each decoded item
* hasPointer:
* indicates whether each item has a dynamic pointer
* pointerOffset:
* indicates the offset within itemSize at which the pointer exists
*/
struct AsnArrayDescriptor
{
BYTE tag;
CryptDecodeObjectExFunc decodeFunc;
DWORD itemSize;
BOOL hasPointer;
DWORD pointerOffset;
};
struct AsnArrayItemSize
{
DWORD encodedLen;
DWORD size;
};
/* Decodes an array of like types into a struct GenericArray.
* The layout and decoding of the array are described by a struct
* AsnArrayDescriptor.
*/
static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
void *startingPointer)
{
BOOL ret = TRUE;
TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
startingPointer);
if (pbEncoded[0] == arrayDesc->tag)
{
DWORD dataLen;
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
{
DWORD bytesNeeded, cItems = 0;
BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
/* There can be arbitrarily many items, but there is often only one.
*/
struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
bytesNeeded = sizeof(struct GenericArray);
if (dataLen)
{
const BYTE *ptr;
for (ptr = pbEncoded + 1 + lenBytes; ret &&
ptr - pbEncoded - 1 - lenBytes < dataLen; )
{
DWORD itemLenBytes, itemDataLen, size;
itemLenBytes = GET_LEN_BYTES(ptr[1]);
/* Each item decoded may not tolerate extraneous bytes, so
* get the length of the next element and pass it directly.
*/
ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
&itemDataLen);
if (ret)
ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
1 + itemLenBytes + itemDataLen,
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL,
&size);
if (ret)
{
DWORD nextLen;
cItems++;
if (itemSizes != &itemSize)
itemSizes = CryptMemRealloc(itemSizes,
cItems * sizeof(struct AsnArrayItemSize));
else
{
itemSizes =
CryptMemAlloc(
cItems * sizeof(struct AsnArrayItemSize));
if (itemSizes)
memcpy(itemSizes, &itemSize, sizeof(itemSize));
}
if (itemSizes)
{
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 (ret)
{
if (!pvStructInfo)
*pcbStructInfo = bytesNeeded;
else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
{
DWORD i;
BYTE *nextData;
const BYTE *ptr;
struct GenericArray *array;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
pvStructInfo = *(BYTE **)pvStructInfo;
array = (struct GenericArray *)pvStructInfo;
array->cItems = cItems;
if (startingPointer)
array->rgItems = startingPointer;
else
array->rgItems = (BYTE *)array +
sizeof(struct GenericArray);
nextData = (BYTE *)array->rgItems +
array->cItems * arrayDesc->itemSize;
for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
i < cItems && ptr - pbEncoded - 1 - lenBytes <
dataLen; i++)
{
if (arrayDesc->hasPointer)
*(BYTE **)(array->rgItems + i * arrayDesc->itemSize
+ arrayDesc->pointerOffset) = nextData;
ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
itemSizes[i].encodedLen,
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
array->rgItems + i * arrayDesc->itemSize,
&itemSizes[i].size);
if (ret)
{
DWORD nextLen;
nextData += itemSizes[i].size - arrayDesc->itemSize;
ret = CRYPT_GetLen(ptr,
cbEncoded - (ptr - pbEncoded), &nextLen);
if (ret)
ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
}
}
}
}
if (itemSizes != &itemSize)
CryptMemFree(itemSizes);
}
}
else
{
SetLastError(CRYPT_E_ASN1_BADTAG);
ret = FALSE;
}
return ret;
}
/* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
* pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
* to CRYPT_E_ASN1_CORRUPT.
* Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
* set!
*/
static BOOL WINAPI CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
BOOL ret;
DWORD dataLen;
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
{
BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
bytesNeeded += 1 + lenBytes + dataLen;
if (!pvStructInfo)
*pcbStructInfo = bytesNeeded;
else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
pvStructInfo, pcbStructInfo, bytesNeeded)))
{
CRYPT_DER_BLOB *blob;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
pvStructInfo = *(BYTE **)pvStructInfo;
blob = (CRYPT_DER_BLOB *)pvStructInfo;
blob->cbData = 1 + lenBytes + dataLen;
if (blob->cbData)
{
if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
blob->pbData = (BYTE *)pbEncoded;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -