⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 decode.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
                         : 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 + -