/*
- * Copyright 2005 Juan Lang
+ * Copyright 2005-2009 Juan Lang
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
*
* This file implements ASN.1 DER decoding of a limited set of types.
* It isn't a full ASN.1 implementation. Microsoft implements BER
- * encoding of many of the basic types in msasn1.dll, but that interface is
- * undocumented, so I implement them here.
+ * encoding of many of the basic types in msasn1.dll, but that interface isn't
+ * implemented, so I implement them here.
*
* References:
* "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
*
* RFC3280, http://www.faqs.org/rfcs/rfc3280.html
*
- * MSDN, especially:
- * http://msdn.microsoft.com/library/en-us/seccrypto/security/constants_for_cryptencodeobject_and_cryptdecodeobject.asp
+ * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject"
*/
+#include "config.h"
+#include "wine/port.h"
+
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include "windef.h"
#include "winbase.h"
-#include "excpt.h"
#include "wincrypt.h"
#include "winnls.h"
-#include "winreg.h"
#include "snmp.h"
#include "wine/debug.h"
#include "wine/exception.h"
#define ASN_FLAGS_MASK 0xe0
#define ASN_TYPE_MASK 0x1f
-WINE_DEFAULT_DEBUG_CHANNEL(crypt);
-
-struct GenericArray
-{
- DWORD cItems;
- BYTE *rgItems;
-};
+WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
+WINE_DECLARE_DEBUG_CHANNEL(crypt);
typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
DWORD, DWORD, void *, DWORD *);
typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
-/* Prototypes for built-in decoders. They follow the Ex style prototypes.
- * The dwCertEncodingType and lpszStructType are ignored by the built-in
- * functions, but the parameters are retained to simplify CryptDecodeObjectEx,
- * since it must call functions in external DLLs that follow these signatures.
+/* Internal decoders don't do memory allocation or exception handling, and
+ * they report how many bytes they decoded.
*/
-static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
-static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
-/* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
- * time, doesn't do memory allocation, and doesn't do exception handling.
- * (This isn't intended to be the externally-called one.)
+typedef BOOL (*InternalDecodeFunc)(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
+
+static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded);
+static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded);
+/* Assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set ahead of time.
*/
-static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
-/* Assumes algo->Parameters.pbData is set ahead of time. Internal func. */
-static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
-/* Internal function */
-static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
+static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
+/* Assumes algo->Parameters.pbData is set ahead of time. */
+static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
+static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
/* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
-static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
-/* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
- * member has been initialized, doesn't do exception handling, and doesn't do
- * memory allocation.
- */
-static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
-static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
-static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
+static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded);
+/* Doesn't check the tag, assumes the caller does so */
+static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
+static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
/* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
* member has been initialized, doesn't do exception handling, and doesn't do
* memory allocation. Also doesn't check tag, assumes the caller has checked
* it.
*/
-static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
+static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded);
/* Like CRYPT_AsnDecodeInteger, but unsigned. */
-static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
- DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
- DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
- void *pvStructInfo, DWORD *pcbStructInfo);
-
-BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
- const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
- DWORD *pcbStructInfo)
-{
- static HCRYPTOIDFUNCSET set = NULL;
- BOOL ret = FALSE;
- CryptDecodeObjectFunc pCryptDecodeObject;
- HCRYPTOIDFUNCADDR hFunc;
-
- TRACE("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
- debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
- pvStructInfo, pcbStructInfo);
-
- if (!pvStructInfo && !pcbStructInfo)
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
-
- /* Try registered DLL first.. */
- if (!set)
- set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
- CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
- (void **)&pCryptDecodeObject, &hFunc);
- if (pCryptDecodeObject)
- {
- ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
- pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
- CryptFreeOIDFunctionAddress(hFunc, 0);
- }
- else
- {
- /* If not, use CryptDecodeObjectEx */
- ret = CryptDecodeObjectEx(dwCertEncodingType, lpszStructType, pbEncoded,
- cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo);
- }
- return ret;
-}
+static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded);
+static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded);
/* Gets the number of length bytes from the given (leading) length byte */
-#define GET_LEN_BYTES(b) ((b) <= 0x7f ? 1 : 1 + ((b) & 0x7f))
+#define GET_LEN_BYTES(b) ((b) <= 0x80 ? 1 : 1 + ((b) & 0x7f))
/* Helper function to get the encoded length of the data starting at pbEncoded,
* where pbEncoded[0] is the tag. If the data are too short to contain a
* length or if the length is too large for cbEncoded, sets an appropriate
- * error code and returns FALSE.
+ * error code and returns FALSE. If the encoded length is unknown due to
+ * indefinite length encoding, *len is set to CMSG_INDEFINITE_LENGTH.
*/
-static BOOL WINAPI CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded,
+static BOOL CRYPT_GetLengthIndefinite(const BYTE *pbEncoded, DWORD cbEncoded,
DWORD *len)
{
BOOL ret;
ret = TRUE;
}
}
+ else if (pbEncoded[1] == 0x80)
+ {
+ *len = CMSG_INDEFINITE_LENGTH;
+ ret = TRUE;
+ }
else
{
BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
return ret;
}
+/* Like CRYPT_GetLengthIndefinite, but disallows indefinite-length encoding. */
+static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
+{
+ BOOL ret;
+
+ if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, len)) &&
+ *len == CMSG_INDEFINITE_LENGTH)
+ {
+ SetLastError(CRYPT_E_ASN1_CORRUPT);
+ ret = FALSE;
+ }
+ return ret;
+}
+
/* Helper function to check *pcbStructInfo, set it to the required size, and
* optionally to allocate memory. Assumes pvStructInfo is not NULL.
* If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
SetLastError(ERROR_MORE_DATA);
ret = FALSE;
}
+ else
+ *pcbStructInfo = bytesNeeded;
+ return ret;
+}
+
+static void CRYPT_FreeSpace(PCRYPT_DECODE_PARA pDecodePara, LPVOID pv)
+{
+ if (pDecodePara && pDecodePara->pfnFree)
+ pDecodePara->pfnFree(pv);
+ else
+ LocalFree(pv);
+}
+
+/* Helper function to check *pcbStructInfo and set it to the required size.
+ * Assumes pvStructInfo is not NULL.
+ */
+static BOOL CRYPT_DecodeCheckSpace(DWORD *pcbStructInfo, DWORD bytesNeeded)
+{
+ BOOL ret;
+
+ if (*pcbStructInfo < bytesNeeded)
+ {
+ *pcbStructInfo = bytesNeeded;
+ SetLastError(ERROR_MORE_DATA);
+ ret = FALSE;
+ }
+ else
+ {
+ *pcbStructInfo = bytesNeeded;
+ ret = TRUE;
+ }
return ret;
}
* If true, and the tag doesn't match the expected tag for this item,
* or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
* filled with 0 for this member.
- * hasPointer, pointerOffset, minSize:
+ * hasPointer, pointerOffset:
* If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
- * the offset within the (outer) struct of the data pointer (or to the
+ * the offset within the struct of the data pointer (or to the
* first data pointer, if more than one exist).
* size:
* Used by CRYPT_AsnDecodeSequence, not for your use.
*/
struct AsnDecodeSequenceItem
{
- BYTE tag;
- DWORD offset;
- CryptDecodeObjectExFunc decodeFunc;
- DWORD minSize;
- BOOL optional;
- BOOL hasPointer;
- DWORD pointerOffset;
- DWORD size;
+ BYTE tag;
+ DWORD offset;
+ InternalDecodeFunc decodeFunc;
+ DWORD minSize;
+ BOOL optional;
+ BOOL hasPointer;
+ DWORD pointerOffset;
+ DWORD size;
};
-static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
- struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
- DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData)
+#define FINALMEMBERSIZE(s, member) (sizeof(s) - offsetof(s, member))
+#define MEMBERSIZE(s, member, nextmember) \
+ (offsetof(s, nextmember) - offsetof(s, member))
+
+/* Decodes the items in a sequence, where the items are described in items,
+ * the encoded data are in pbEncoded with length cbEncoded. Decodes into
+ * pvStructInfo. nextData is a pointer to the memory location at which the
+ * first decoded item with a dynamic pointer should point.
+ * Upon decoding, *cbDecoded is the total number of bytes decoded.
+ * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
+ */
+static BOOL CRYPT_AsnDecodeSequenceItems(struct AsnDecodeSequenceItem items[],
+ DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ void *pvStructInfo, BYTE *nextData, DWORD *cbDecoded)
{
BOOL ret;
- DWORD i;
- const BYTE *ptr;
+ DWORD i, decoded = 0;
+ const BYTE *ptr = pbEncoded;
+
+ TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
+ cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
- ptr = pbEncoded + 1 + GET_LEN_BYTES(pbEncoded[1]);
for (i = 0, ret = TRUE; ret && i < cItem; i++)
{
if (cbEncoded - (ptr - pbEncoded) != 0)
{
- DWORD nextItemLen;
+ DWORD itemLen;
- if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
- &nextItemLen)))
+ if ((ret = CRYPT_GetLengthIndefinite(ptr,
+ cbEncoded - (ptr - pbEncoded), &itemLen)))
{
- BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
+ BYTE itemLenBytes = GET_LEN_BYTES(ptr[1]);
if (ptr[0] == items[i].tag || !items[i].tag)
{
+ DWORD itemEncodedLen;
+
+ if (itemLen == CMSG_INDEFINITE_LENGTH)
+ itemEncodedLen = cbEncoded - (ptr - pbEncoded);
+ else
+ itemEncodedLen = 1 + itemLenBytes + itemLen;
if (nextData && pvStructInfo && items[i].hasPointer)
{
TRACE("Setting next pointer to %p\n",
}
if (items[i].decodeFunc)
{
+ DWORD itemDecoded;
+
if (pvStructInfo)
TRACE("decoding item %d\n", i);
else
TRACE("sizing item %d\n", i);
- ret = items[i].decodeFunc(dwCertEncodingType,
- NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
- dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
+ ret = items[i].decodeFunc(ptr, itemEncodedLen,
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
- : NULL, &items[i].size);
+ : NULL, &items[i].size, &itemDecoded);
if (ret)
{
+ if (items[i].size < items[i].minSize)
+ items[i].size = items[i].minSize;
+ else if (items[i].size > items[i].minSize)
+ {
+ /* Account for alignment padding */
+ items[i].size = ALIGN_DWORD_PTR(items[i].size);
+ }
+ TRACE("item %d size: %d\n", i, items[i].size);
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);
+ if (itemDecoded > itemEncodedLen)
+ {
+ WARN("decoded length %d exceeds encoded %d\n",
+ itemDecoded, itemEncodedLen);
+ SetLastError(CRYPT_E_ASN1_CORRUPT);
+ ret = FALSE;
+ }
+ else
+ {
+ ptr += itemDecoded;
+ decoded += itemDecoded;
+ TRACE("item %d: decoded %d bytes\n", i,
+ itemDecoded);
}
- /* 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("item %d failed: %08x\n", i,
GetLastError());
}
+ else if (itemLen == CMSG_INDEFINITE_LENGTH)
+ {
+ ERR("can't use indefinite length encoding without a decoder\n");
+ SetLastError(CRYPT_E_ASN1_CORRUPT);
+ ret = FALSE;
+ }
else
+ {
+ TRACE("item %d: decoded %d bytes\n", i, itemEncodedLen);
+ ptr += itemEncodedLen;
+ decoded += itemEncodedLen;
items[i].size = items[i].minSize;
+ }
}
else if (items[i].optional)
{
}
else
{
- TRACE("tag %02x doesn't match expected %02x\n",
- ptr[0], items[i].tag);
+ TRACE("item %d: tag %02x doesn't match expected %02x\n",
+ i, ptr[0], items[i].tag);
SetLastError(CRYPT_E_ASN1_BADTAG);
ret = FALSE;
}
ret = FALSE;
}
}
- if (cbEncoded - (ptr - pbEncoded) != 0)
- {
- TRACE("%d remaining bytes, failing\n", cbEncoded -
- (ptr - pbEncoded));
- SetLastError(CRYPT_E_ASN1_CORRUPT);
- ret = FALSE;
- }
+ if (cbDecoded)
+ *cbDecoded = decoded;
+ TRACE("returning %d\n", ret);
return ret;
}
* 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)
+static BOOL CRYPT_AsnDecodeSequence(struct AsnDecodeSequenceItem items[],
+ DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded, void *startingPointer)
{
BOOL ret;
cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
startingPointer);
+ if (!cbEncoded)
+ {
+ SetLastError(CRYPT_E_ASN1_EOD);
+ return FALSE;
+ }
if (pbEncoded[0] == ASN_SEQUENCE)
{
DWORD dataLen;
- if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
+ if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
{
- DWORD i;
+ DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
+ const BYTE *ptr = pbEncoded + 1 + lenBytes;
+ BOOL indefinite = FALSE;
- ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, pbEncoded,
- cbEncoded, dwFlags, NULL, NULL);
+ cbEncoded -= 1 + lenBytes;
+ if (dataLen == CMSG_INDEFINITE_LENGTH)
+ {
+ dataLen = cbEncoded;
+ indefinite = TRUE;
+ }
+ else if (cbEncoded < dataLen)
+ {
+ TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
+ cbEncoded);
+ SetLastError(CRYPT_E_ASN1_CORRUPT);
+ ret = FALSE;
+ }
+ if (ret)
+ {
+ ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
+ ptr, dataLen, dwFlags, NULL, NULL, &cbDecoded);
+ if (ret && dataLen == CMSG_INDEFINITE_LENGTH)
+ {
+ if (cbDecoded > cbEncoded - 2)
+ {
+ /* Not enough space for 0 TLV */
+ SetLastError(CRYPT_E_ASN1_CORRUPT);
+ ret = FALSE;
+ }
+ else if (*(ptr + cbDecoded) != 0 ||
+ *(ptr + cbDecoded + 1) != 0)
+ {
+ TRACE("expected 0 TLV\n");
+ SetLastError(CRYPT_E_ASN1_CORRUPT);
+ ret = FALSE;
+ }
+ else
+ cbDecoded += 2;
+ }
+ }
+ if (ret && !indefinite && cbDecoded != dataLen)
+ {
+ TRACE("expected %d decoded, got %d, failing\n", dataLen,
+ cbDecoded);
+ SetLastError(CRYPT_E_ASN1_CORRUPT);
+ ret = FALSE;
+ }
if (ret)
{
- DWORD bytesNeeded = 0, structSize = 0;
+ DWORD i, bytesNeeded = 0, structSize = 0;
for (i = 0; i < cItem; i++)
{
bytesNeeded += items[i].size;
- structSize += items[i].minSize;
+ structSize = max( structSize, items[i].offset + items[i].minSize );
}
+ if (pcbDecoded)
+ *pcbDecoded = 1 + lenBytes + cbDecoded;
if (!pvStructInfo)
*pcbStructInfo = bytesNeeded;
else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
pvStructInfo = *(BYTE **)pvStructInfo;
if (startingPointer)
- nextData = (BYTE *)startingPointer;
+ nextData = startingPointer;
else
nextData = (BYTE *)pvStructInfo + structSize;
memset(pvStructInfo, 0, structSize);
- ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
- pbEncoded, cbEncoded, dwFlags, pvStructInfo, nextData);
+ ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
+ ptr, dataLen, dwFlags, pvStructInfo, nextData,
+ &cbDecoded);
+ if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
+ CRYPT_FreeSpace(pDecodePara, pvStructInfo);
}
}
}
/* tag:
* The expected tag of the entire encoded array (usually a variant
- * of ASN_SETOF or ASN_SEQUENCEOF.)
+ * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
+ * regardless of the tag seen.
+ * countOffset:
+ * The offset within the outer structure at which the count exists.
+ * For example, a structure such as CRYPT_ATTRIBUTES has countOffset == 0,
+ * while CRYPT_ATTRIBUTE has countOffset ==
+ * offsetof(CRYPT_ATTRIBUTE, cValue).
+ * arrayOffset:
+ * The offset within the outer structure at which the array pointer exists.
+ * For example, CRYPT_ATTRIBUTES has arrayOffset ==
+ * offsetof(CRYPT_ATTRIBUTES, rgAttr).
+ * minArraySize:
+ * The minimum size of the decoded array. On WIN32, this is always 8:
+ * sizeof(DWORD) + sizeof(void *). On WIN64, it can be larger due to
+ * alignment.
* decodeFunc:
* used to decode each item in the array
* itemSize:
*/
struct AsnArrayDescriptor
{
- BYTE tag;
- CryptDecodeObjectExFunc decodeFunc;
- DWORD itemSize;
- BOOL hasPointer;
- DWORD pointerOffset;
+ BYTE tag;
+ DWORD countOffset;
+ DWORD arrayOffset;
+ DWORD minArraySize;
+ InternalDecodeFunc decodeFunc;
+ DWORD itemSize;
+ BOOL hasPointer;
+ DWORD pointerOffset;
};
struct AsnArrayItemSize
DWORD size;
};
-/* Decodes an array of like types into a struct GenericArray.
- * The layout and decoding of the array are described by a struct
+/* Decodes an array of like types into a structure 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)
+ DWORD *pcbDecoded)
{
BOOL ret = TRUE;
- TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
- cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
- startingPointer);
+ TRACE("%p, %p, %d, %p, %d\n", arrayDesc, pbEncoded,
+ cbEncoded, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
- if (pbEncoded[0] == arrayDesc->tag)
+ if (!cbEncoded)
+ {
+ SetLastError(CRYPT_E_ASN1_EOD);
+ ret = FALSE;
+ }
+ else if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
{
DWORD dataLen;
- if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
+ if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
{
- DWORD bytesNeeded, cItems = 0;
+ DWORD bytesNeeded = arrayDesc->minArraySize, cItems = 0, decoded;
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);
+ decoded = 1 + lenBytes;
if (dataLen)
{
const BYTE *ptr;
+ BOOL doneDecoding = FALSE;
- for (ptr = pbEncoded + 1 + lenBytes; ret &&
- ptr - pbEncoded - 1 - lenBytes < dataLen; )
+ for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
{
- 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)
+ if (dataLen == CMSG_INDEFINITE_LENGTH)
+ {
+ if (ptr[0] == 0)
+ {
+ doneDecoding = TRUE;
+ if (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 nextLen;
+ DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
- cItems++;
- if (itemSizes != &itemSize)
- itemSizes = CryptMemRealloc(itemSizes,
- cItems * sizeof(struct AsnArrayItemSize));
- else
+ /* Each item decoded may not tolerate extraneous bytes,
+ * so get the length of the next element if known.
+ */
+ if ((ret = CRYPT_GetLengthIndefinite(ptr,
+ cbEncoded - (ptr - pbEncoded), &itemDataLen)))
{
- itemSizes =
- CryptMemAlloc(
- cItems * sizeof(struct AsnArrayItemSize));
- if (itemSizes)
- memcpy(itemSizes, &itemSize, sizeof(itemSize));
+ if (itemDataLen == CMSG_INDEFINITE_LENGTH)
+ itemEncoded = cbEncoded - (ptr - pbEncoded);
+ else
+ itemEncoded = 1 + GET_LEN_BYTES(ptr[1]) +
+ itemDataLen;
}
- if (itemSizes)
+ if (ret)
+ ret = arrayDesc->decodeFunc(ptr, itemEncoded,
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size,
+ &itemDecoded);
+ if (ret)
{
- 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]);
+ 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)
+ {
+ decoded += itemDecoded;
+ itemSizes[cItems - 1].encodedLen = itemEncoded;
+ itemSizes[cItems - 1].size = size;
+ bytesNeeded += size;
+ ptr += itemEncoded;
+ }
+ else
+ ret = FALSE;
}
- else
- ret = FALSE;
}
}
}
if (ret)
{
+ if (pcbDecoded)
+ *pcbDecoded = decoded;
if (!pvStructInfo)
*pcbStructInfo = bytesNeeded;
- else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
- pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
+ else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
+ pvStructInfo, pcbStructInfo, bytesNeeded)))
{
- DWORD i;
+ DWORD i, *pcItems;
BYTE *nextData;
const BYTE *ptr;
- struct GenericArray *array;
+ void *rgItems;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
- pvStructInfo = *(BYTE **)pvStructInfo;
- array = (struct GenericArray *)pvStructInfo;
- array->cItems = cItems;
- if (startingPointer)
- array->rgItems = startingPointer;
+ pvStructInfo = *(void **)pvStructInfo;
+ pcItems = pvStructInfo;
+ *pcItems = cItems;
+ if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
+ {
+ rgItems = (BYTE *)pvStructInfo +
+ arrayDesc->minArraySize;
+ *(void **)((BYTE *)pcItems -
+ arrayDesc->countOffset + arrayDesc->arrayOffset) =
+ rgItems;
+ }
else
- array->rgItems = (BYTE *)array +
- sizeof(struct GenericArray);
- nextData = (BYTE *)array->rgItems +
- array->cItems * arrayDesc->itemSize;
+ rgItems = *(void **)((BYTE *)pcItems -
+ arrayDesc->countOffset + arrayDesc->arrayOffset);
+ nextData = (BYTE *)rgItems + cItems * arrayDesc->itemSize;
for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
i < cItems && ptr - pbEncoded - 1 - lenBytes <
dataLen; i++)
{
+ DWORD itemDecoded;
+
if (arrayDesc->hasPointer)
- *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
+ *(BYTE **)((BYTE *)rgItems + i * arrayDesc->itemSize
+ arrayDesc->pointerOffset) = nextData;
- ret = arrayDesc->decodeFunc(X509_ASN_ENCODING, 0, ptr,
+ ret = arrayDesc->decodeFunc(ptr,
itemSizes[i].encodedLen,
- dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
- array->rgItems + i * arrayDesc->itemSize,
- &itemSizes[i].size);
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
+ (BYTE *)rgItems + i * arrayDesc->itemSize,
+ &itemSizes[i].size, &itemDecoded);
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]);
+ ptr += itemDecoded;
}
}
}
* 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)
+static BOOL CRYPT_AsnDecodeDerBlob(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
{
BOOL ret;
DWORD 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 (pcbDecoded)
+ *pcbDecoded = 1 + lenBytes + dataLen;
if (!pvStructInfo)
*pcbStructInfo = bytesNeeded;
- else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
- pvStructInfo, pcbStructInfo, bytesNeeded)))
+ else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded)))
{
CRYPT_DER_BLOB *blob;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
pvStructInfo = *(BYTE **)pvStructInfo;
- blob = (CRYPT_DER_BLOB *)pvStructInfo;
+ blob = pvStructInfo;
blob->cbData = 1 + lenBytes + dataLen;
if (blob->cbData)
{
}
/* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
-static BOOL WINAPI CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+static BOOL CRYPT_AsnDecodeBitsSwapBytes(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
{
BOOL ret;
- TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, *pcbStructInfo);
+ TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo, pcbDecoded);
/* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
* place.
*/
- ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType, lpszStructType,
- pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
- pvStructInfo, pcbStructInfo);
+ ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
+ pcbDecoded);
if (ret && pvStructInfo)
{
- CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
+ CRYPT_BIT_BLOB *blob = pvStructInfo;
if (blob->cbData)
{
if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
- ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
- sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, pcbStructInfo, NULL);
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
+ pcbStructInfo, NULL, NULL);
}
__EXCEPT_PAGE_FAULT
{
return ret;
}
-/* Internal function */
-static BOOL WINAPI CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+static BOOL CRYPT_AsnDecodeCertVersion(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
{
BOOL ret;
DWORD dataLen;
{
BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
- ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
- pbEncoded + 1 + lenBytes, dataLen, dwFlags, pDecodePara,
- pvStructInfo, pcbStructInfo);
+ ret = CRYPT_AsnDecodeIntInternal(pbEncoded + 1 + lenBytes, dataLen,
+ dwFlags, pvStructInfo, pcbStructInfo, NULL);
+ if (pcbDecoded)
+ *pcbDecoded = 1 + lenBytes + dataLen;
}
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+static BOOL CRYPT_AsnDecodeValidity(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
{
BOOL ret;
struct AsnDecodeSequenceItem items[] = {
{ 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
- CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
+ CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
{ 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
- CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
+ CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
};
- ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
- sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, pcbStructInfo, NULL);
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
+ pcbDecoded, NULL);
return ret;
}
-/* Internal function */
-static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+static BOOL CRYPT_AsnDecodeCertExtensionsInternal(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ BOOL ret = TRUE;
+ struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
+ offsetof(CERT_INFO, cExtension), offsetof(CERT_INFO, rgExtension),
+ FINALMEMBERSIZE(CERT_INFO, cExtension),
+ CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
+ offsetof(CERT_EXTENSION, pszObjId) };
+
+ TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo, pcbDecoded);
+
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
+ return ret;
+}
+
+static BOOL CRYPT_AsnDecodeCertExtensions(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
{
BOOL ret;
DWORD dataLen;
{
BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
- ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
- X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
- pDecodePara, pvStructInfo, pcbStructInfo);
+ ret = CRYPT_AsnDecodeCertExtensionsInternal(pbEncoded + 1 + lenBytes,
+ dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
+ if (ret && pcbDecoded)
+ *pcbDecoded = 1 + lenBytes + dataLen;
}
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
+static BOOL CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
FALSE, TRUE, offsetof(CERT_INFO,
SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
- { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
+ { ASN_CONTEXT | 1, offsetof(CERT_INFO, IssuerUniqueId),
CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
- { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
+ { ASN_CONTEXT | 2, offsetof(CERT_INFO, SubjectUniqueId),
CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
{ ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
- CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
- offsetof(CERT_INFO, rgExtension), 0 },
+ CRYPT_AsnDecodeCertExtensions, FINALMEMBERSIZE(CERT_INFO, cExtension),
+ TRUE, TRUE, offsetof(CERT_INFO, rgExtension), 0 },
};
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
pDecodePara, pvStructInfo, *pcbStructInfo);
- ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
- sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, pcbStructInfo, NULL);
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
+ NULL, NULL);
+ if (ret && pvStructInfo)
+ {
+ CERT_INFO *info;
+
+ if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
+ info = *(CERT_INFO **)pvStructInfo;
+ else
+ info = pvStructInfo;
+ if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
+ !info->Subject.cbData)
+ {
+ SetLastError(CRYPT_E_ASN1_CORRUPT);
+ /* Don't need to deallocate, because it should have failed on the
+ * first pass (and no memory was allocated.)
+ */
+ ret = FALSE;
+ }
+ }
TRACE("Returning %d (%08x)\n", ret, GetLastError());
return ret;
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
- BOOL ret = TRUE;
+ BOOL ret = FALSE;
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
pDecodePara, pvStructInfo, *pcbStructInfo);
__TRY
{
- PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
DWORD size = 0;
- /* First try to decode it as a signed cert. */
- ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT,
- pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
- (BYTE *)&signedCert, &size);
- if (ret)
+ /* Unless told not to, first try to decode it as a signed cert. */
+ if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
{
- size = 0;
- ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
- X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
- signedCert->ToBeSigned.cbData, dwFlags, pDecodePara, pvStructInfo,
- pcbStructInfo);
- LocalFree(signedCert);
+ PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
+
+ ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
+ X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
+ &signedCert, &size);
+ if (ret)
+ {
+ size = 0;
+ ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
+ X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
+ signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
+ pvStructInfo, pcbStructInfo);
+ LocalFree(signedCert);
+ }
}
/* Failing that, try it as an unsigned cert */
if (!ret)
__EXCEPT_PAGE_FAULT
{
SetLastError(STATUS_ACCESS_VIOLATION);
- ret = FALSE;
}
__ENDTRY
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeCRLEntry(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+static BOOL CRYPT_AsnDecodeCRLEntryExtensions(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ BOOL ret = TRUE;
+ struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
+ offsetof(CRL_ENTRY, cExtension), offsetof(CRL_ENTRY, rgExtension),
+ FINALMEMBERSIZE(CRL_ENTRY, cExtension),
+ CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
+ offsetof(CERT_EXTENSION, pszObjId) };
+
+ TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo, pcbDecoded);
+
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
+ return ret;
+}
+
+static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
{
BOOL ret;
struct AsnDecodeSequenceItem items[] = {
{ ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
- { 0, offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime,
- sizeof(FILETIME), FALSE, FALSE, 0 },
+ { 0, offsetof(CRL_ENTRY, RevocationDate),
+ CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
{ ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
- CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
+ CRYPT_AsnDecodeCRLEntryExtensions,
+ FINALMEMBERSIZE(CRL_ENTRY, cExtension), TRUE, TRUE,
offsetof(CRL_ENTRY, rgExtension), 0 },
};
- PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
+ PCRL_ENTRY entry = pvStructInfo;
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
*pcbStructInfo);
- ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
- sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
- NULL, entry, pcbStructInfo, entry ? entry->SerialNumber.pbData : NULL);
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, pcbDecoded,
+ entry ? entry->SerialNumber.pbData : NULL);
+ if (ret && entry && !entry->SerialNumber.cbData)
+ {
+ WARN("empty CRL entry serial number\n");
+ SetLastError(CRYPT_E_ASN1_CORRUPT);
+ ret = FALSE;
+ }
return ret;
}
-/* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
- * been set prior to calling.
+/* Warning: assumes pvStructInfo points to the cCRLEntry member of a CRL_INFO
+ * whose rgCRLEntry member has been set prior to calling.
*/
-static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+static BOOL CRYPT_AsnDecodeCRLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
{
BOOL ret;
struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
+ offsetof(CRL_INFO, cCRLEntry), offsetof(CRL_INFO, rgCRLEntry),
+ MEMBERSIZE(CRL_INFO, cCRLEntry, cExtension),
CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
offsetof(CRL_ENTRY, SerialNumber.pbData) };
- struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
- TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, *pcbStructInfo);
+ TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo, pcbDecoded);
- ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, pcbStructInfo,
- entries ? entries->rgItems : NULL);
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
TRACE("Returning %d (%08x)\n", ret, GetLastError());
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
+static BOOL CRYPT_AsnDecodeCRLExtensionsInternal(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ BOOL ret = TRUE;
+ struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
+ offsetof(CRL_INFO, cExtension), offsetof(CRL_INFO, rgExtension),
+ FINALMEMBERSIZE(CRL_INFO, cExtension),
+ CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
+ offsetof(CERT_EXTENSION, pszObjId) };
+
+ TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo, pcbDecoded);
+
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
+ return ret;
+}
+
+static BOOL CRYPT_AsnDecodeCRLExtensions(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ BOOL ret;
+ DWORD dataLen;
+
+ if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
+ {
+ BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
+
+ ret = CRYPT_AsnDecodeCRLExtensionsInternal(pbEncoded + 1 + lenBytes,
+ dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
+ if (ret && pcbDecoded)
+ *pcbDecoded = 1 + lenBytes + dataLen;
+ }
+ return ret;
+}
+
+static BOOL CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
struct AsnDecodeSequenceItem items[] = {
{ ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
- CRYPT_AsnDecodeInt, sizeof(DWORD), TRUE, FALSE, 0, 0 },
+ CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
{ ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
{ 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
Issuer.pbData) },
- { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime,
+ { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
sizeof(FILETIME), FALSE, FALSE, 0 },
- { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime,
+ { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
sizeof(FILETIME), TRUE, FALSE, 0 },
{ ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
- CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
- offsetof(CRL_INFO, rgCRLEntry), 0 },
+ CRYPT_AsnDecodeCRLEntries, MEMBERSIZE(CRL_INFO, cCRLEntry, cExtension),
+ TRUE, TRUE, offsetof(CRL_INFO, rgCRLEntry), 0 },
{ ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
- CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
- offsetof(CRL_INFO, rgExtension), 0 },
+ CRYPT_AsnDecodeCRLExtensions, FINALMEMBERSIZE(CRL_INFO, cExtension),
+ TRUE, TRUE, offsetof(CRL_INFO, rgExtension), 0 },
};
BOOL ret = TRUE;
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
pDecodePara, pvStructInfo, *pcbStructInfo);
- ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
- sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, pcbStructInfo, NULL);
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
+ NULL, NULL);
TRACE("Returning %d (%08x)\n", ret, GetLastError());
return ret;
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
- BOOL ret = TRUE;
+ BOOL ret = FALSE;
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
pDecodePara, pvStructInfo, *pcbStructInfo);
__TRY
{
- PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
DWORD size = 0;
- /* First try to decode it as a signed crl. */
- ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType, X509_CERT,
- pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
- (BYTE *)&signedCrl, &size);
- if (ret)
+ /* Unless told not to, first try to decode it as a signed crl. */
+ if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
{
- size = 0;
- ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
- X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
- signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
- pvStructInfo, pcbStructInfo);
- LocalFree(signedCrl);
+ PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
+
+ ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
+ X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
+ &signedCrl, &size);
+ if (ret)
+ {
+ size = 0;
+ ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
+ X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
+ signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
+ pvStructInfo, pcbStructInfo);
+ LocalFree(signedCrl);
+ }
}
/* Failing that, try it as an unsigned crl */
if (!ret)
__EXCEPT_PAGE_FAULT
{
SetLastError(STATUS_ACCESS_VIOLATION);
- ret = FALSE;
}
__ENDTRY
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeOidInternal(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
{
BOOL ret = TRUE;
+ DWORD dataLen;
- TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, *pcbStructInfo);
+ TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo);
- if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
+ if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
{
- DWORD dataLen;
+ BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
+ DWORD bytesNeeded = sizeof(LPSTR);
- if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
+ if (dataLen)
{
- BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
- DWORD bytesNeeded = sizeof(LPSTR);
+ /* The largest possible string for the first two components
+ * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
+ */
+ char firstTwo[6];
+ const BYTE *ptr;
+
+ snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
+ pbEncoded[1 + lenBytes] / 40,
+ pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
+ * 40);
+ bytesNeeded += strlen(firstTwo) + 1;
+ for (ptr = pbEncoded + 2 + lenBytes; ret &&
+ ptr - pbEncoded - 1 - lenBytes < dataLen; )
+ {
+ /* large enough for ".4000000" */
+ char str[9];
+ int val = 0;
+ while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
+ (*ptr & 0x80))
+ {
+ val <<= 7;
+ val |= *ptr & 0x7f;
+ ptr++;
+ }
+ if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
+ (*ptr & 0x80))
+ {
+ SetLastError(CRYPT_E_ASN1_CORRUPT);
+ ret = FALSE;
+ }
+ else
+ {
+ val <<= 7;
+ val |= *ptr++;
+ snprintf(str, sizeof(str), ".%d", val);
+ bytesNeeded += strlen(str);
+ }
+ }
+ }
+ if (pcbDecoded)
+ *pcbDecoded = 1 + lenBytes + dataLen;
+ if (!pvStructInfo)
+ *pcbStructInfo = bytesNeeded;
+ else if (*pcbStructInfo < bytesNeeded)
+ {
+ *pcbStructInfo = bytesNeeded;
+ SetLastError(ERROR_MORE_DATA);
+ ret = FALSE;
+ }
+ else
+ {
if (dataLen)
{
- /* The largest possible string for the first two components
- * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
- */
- char firstTwo[6];
const BYTE *ptr;
+ LPSTR pszObjId = *(LPSTR *)pvStructInfo;
- snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
- pbEncoded[1 + lenBytes] / 40,
- pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
- * 40);
- bytesNeeded += strlen(firstTwo) + 1;
+ *pszObjId = 0;
+ sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
+ pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
+ 40) * 40);
+ pszObjId += strlen(pszObjId);
for (ptr = pbEncoded + 2 + lenBytes; ret &&
ptr - pbEncoded - 1 - lenBytes < dataLen; )
{
- /* large enough for ".4000000" */
- char str[9];
int val = 0;
while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
val |= *ptr & 0x7f;
ptr++;
}
- if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
- (*ptr & 0x80))
- {
- SetLastError(CRYPT_E_ASN1_CORRUPT);
- ret = FALSE;
- }
- else
- {
- val <<= 7;
- val |= *ptr++;
- snprintf(str, sizeof(str), ".%d", val);
- bytesNeeded += strlen(str);
- }
+ val <<= 7;
+ val |= *ptr++;
+ sprintf(pszObjId, ".%d", val);
+ pszObjId += strlen(pszObjId);
}
}
- if (!pvStructInfo)
- *pcbStructInfo = bytesNeeded;
- else if (*pcbStructInfo < bytesNeeded)
- {
- *pcbStructInfo = bytesNeeded;
- SetLastError(ERROR_MORE_DATA);
- ret = FALSE;
- }
else
- {
- if (dataLen)
- {
- const BYTE *ptr;
- LPSTR pszObjId = *(LPSTR *)pvStructInfo;
+ *(LPSTR *)pvStructInfo = NULL;
+ *pcbStructInfo = bytesNeeded;
+ }
+ }
+ return ret;
+}
- *pszObjId = 0;
- sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
- pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
- 40) * 40);
- pszObjId += strlen(pszObjId);
- for (ptr = pbEncoded + 2 + lenBytes; ret &&
- ptr - pbEncoded - 1 - lenBytes < dataLen; )
- {
- int val = 0;
+static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
+{
+ BOOL ret;
- while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
- (*ptr & 0x80))
- {
- val <<= 7;
- val |= *ptr & 0x7f;
- ptr++;
- }
- val <<= 7;
- val |= *ptr++;
- sprintf(pszObjId, ".%d", val);
- pszObjId += strlen(pszObjId);
- }
- }
- else
- *(LPSTR *)pvStructInfo = NULL;
- *pcbStructInfo = bytesNeeded;
- }
- }
+ TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo);
+
+ if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
+ ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, pcbStructInfo, pcbDecoded);
+ else
+ {
+ SetLastError(CRYPT_E_ASN1_BADTAG);
+ ret = FALSE;
}
return ret;
}
-/* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
- * ahead of time!
- */
-static BOOL WINAPI CRYPT_AsnDecodeExtension(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
{
struct AsnDecodeSequenceItem items[] = {
{ ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
- CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
+ CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
offsetof(CERT_EXTENSION, pszObjId), 0 },
{ ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
sizeof(BOOL), TRUE, FALSE, 0, 0 },
offsetof(CERT_EXTENSION, Value.pbData) },
};
BOOL ret = TRUE;
- PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
+ PCERT_EXTENSION ext = pvStructInfo;
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
*pcbStructInfo);
if (ext)
TRACE("ext->pszObjId is %p\n", ext->pszObjId);
- ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
- sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
- ext, pcbStructInfo, ext ? ext->pszObjId : NULL);
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, NULL, ext, pcbStructInfo,
+ pcbDecoded, ext ? ext->pszObjId : NULL);
if (ext)
TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
debugstr_a(ext->pszObjId));
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
-{
- BOOL ret = TRUE;
- struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
- CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
- offsetof(CERT_EXTENSION, pszObjId) };
- PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
-
- TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, *pcbStructInfo);
-
- ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, pcbStructInfo, exts ? exts->rgExtension : NULL);
- return ret;
-}
-
static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
BOOL ret = TRUE;
+ TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
+
__TRY
{
- ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
- lpszStructType, pbEncoded, cbEncoded,
- dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
- if (ret && pvStructInfo)
- {
- ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
- pcbStructInfo, *pcbStructInfo);
- if (ret)
- {
- CERT_EXTENSIONS *exts;
+ struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
+ offsetof(CERT_EXTENSIONS, cExtension),
+ offsetof(CERT_EXTENSIONS, rgExtension),
+ sizeof(CERT_EXTENSIONS),
+ CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
+ offsetof(CERT_EXTENSION, pszObjId) };
- if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
- pvStructInfo = *(BYTE **)pvStructInfo;
- exts = (CERT_EXTENSIONS *)pvStructInfo;
- exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
- sizeof(CERT_EXTENSIONS));
- ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
- lpszStructType, pbEncoded, cbEncoded,
- dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
- pcbStructInfo);
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
}
- }
- }
__EXCEPT_PAGE_FAULT
{
SetLastError(STATUS_ACCESS_VIOLATION);
* order to avoid overwriting memory. (In some cases, it may change it, if it
* doesn't copy anything to memory.) Be sure to set it correctly!
*/
-static BOOL WINAPI CRYPT_AsnDecodeNameValueInternal(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+static BOOL CRYPT_AsnDecodeNameValueInternal(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
{
BOOL ret = TRUE;
DWORD dataLen;
- CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
+ CERT_NAME_VALUE *value = pvStructInfo;
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
{
return FALSE;
}
+ if (pcbDecoded)
+ *pcbDecoded = 1 + lenBytes + dataLen;
if (!value)
*pcbStructInfo = bytesNeeded;
else if (*pcbStructInfo < bytesNeeded)
LPWSTR str = (LPWSTR)value->Value.pbData;
value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
- (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
+ (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
break;
}
__TRY
{
- ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
- lpszStructType, pbEncoded, cbEncoded,
- dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
+ ret = CRYPT_AsnDecodeNameValueInternal(pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
if (ret && pvStructInfo)
{
ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
pvStructInfo = *(BYTE **)pvStructInfo;
- value = (CERT_NAME_VALUE *)pvStructInfo;
+ value = pvStructInfo;
value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
- ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
- lpszStructType, pbEncoded, cbEncoded,
- dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
- pcbStructInfo);
+ ret = CRYPT_AsnDecodeNameValueInternal( pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
+ pcbStructInfo, NULL);
}
}
}
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValueInternal(
- DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
- DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
- void *pvStructInfo, DWORD *pcbStructInfo)
+static BOOL CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
{
BOOL ret = TRUE;
DWORD dataLen;
- CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
+ CERT_NAME_VALUE *value = pvStructInfo;
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
{
{
case ASN_NUMERICSTRING:
valueType = CERT_RDN_NUMERIC_STRING;
- bytesNeeded += dataLen * 2;
+ if (dataLen)
+ bytesNeeded += (dataLen + 1) * 2;
break;
case ASN_PRINTABLESTRING:
valueType = CERT_RDN_PRINTABLE_STRING;
- bytesNeeded += dataLen * 2;
+ if (dataLen)
+ bytesNeeded += (dataLen + 1) * 2;
break;
case ASN_IA5STRING:
valueType = CERT_RDN_IA5_STRING;
- bytesNeeded += dataLen * 2;
+ if (dataLen)
+ bytesNeeded += (dataLen + 1) * 2;
break;
case ASN_T61STRING:
valueType = CERT_RDN_T61_STRING;
- bytesNeeded += dataLen * 2;
+ if (dataLen)
+ bytesNeeded += (dataLen + 1) * 2;
break;
case ASN_VIDEOTEXSTRING:
valueType = CERT_RDN_VIDEOTEX_STRING;
- bytesNeeded += dataLen * 2;
+ if (dataLen)
+ bytesNeeded += (dataLen + 1) * 2;
break;
case ASN_GRAPHICSTRING:
valueType = CERT_RDN_GRAPHIC_STRING;
- bytesNeeded += dataLen * 2;
+ if (dataLen)
+ bytesNeeded += (dataLen + 1) * 2;
break;
case ASN_VISIBLESTRING:
valueType = CERT_RDN_VISIBLE_STRING;
- bytesNeeded += dataLen * 2;
+ if (dataLen)
+ bytesNeeded += (dataLen + 1) * 2;
break;
case ASN_GENERALSTRING:
valueType = CERT_RDN_GENERAL_STRING;
- bytesNeeded += dataLen * 2;
+ if (dataLen)
+ bytesNeeded += (dataLen + 1) * 2;
break;
case ASN_UNIVERSALSTRING:
valueType = CERT_RDN_UNIVERSAL_STRING;
- bytesNeeded += dataLen / 2;
+ if (dataLen)
+ bytesNeeded += dataLen / 2 + sizeof(WCHAR);
break;
case ASN_BMPSTRING:
valueType = CERT_RDN_BMP_STRING;
- bytesNeeded += dataLen;
+ if (dataLen)
+ bytesNeeded += dataLen + sizeof(WCHAR);
break;
case ASN_UTF8STRING:
valueType = CERT_RDN_UTF8_STRING;
- bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
- (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
+ if (dataLen)
+ bytesNeeded += (MultiByteToWideChar(CP_UTF8, 0,
+ (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) + 1) * 2;
break;
default:
SetLastError(CRYPT_E_ASN1_BADTAG);
return FALSE;
}
+ if (pcbDecoded)
+ *pcbDecoded = 1 + lenBytes + dataLen;
if (!value)
*pcbStructInfo = bytesNeeded;
else if (*pcbStructInfo < bytesNeeded)
value->Value.cbData = dataLen * 2;
for (i = 0; i < dataLen; i++)
str[i] = pbEncoded[1 + lenBytes + i];
+ str[i] = 0;
break;
case ASN_UNIVERSALSTRING:
value->Value.cbData = dataLen / 2;
for (i = 0; i < dataLen / 4; i++)
str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
| pbEncoded[1 + lenBytes + 2 * i + 3];
+ str[i] = 0;
break;
case ASN_BMPSTRING:
value->Value.cbData = dataLen;
for (i = 0; i < dataLen / 2; i++)
str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
pbEncoded[1 + lenBytes + 2 * i + 1];
+ str[i] = 0;
break;
case ASN_UTF8STRING:
value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
(LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
- str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
+ str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * sizeof(WCHAR);
+ *(WCHAR *)(value->Value.pbData + value->Value.cbData) = 0;
+ value->Value.cbData += sizeof(WCHAR);
break;
}
}
__TRY
{
- ret = CRYPT_AsnDecodeUnicodeNameValueInternal(dwCertEncodingType,
- lpszStructType, pbEncoded, cbEncoded,
- dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
+ ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
if (ret && pvStructInfo)
{
ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
pvStructInfo = *(BYTE **)pvStructInfo;
- value = (CERT_NAME_VALUE *)pvStructInfo;
+ value = pvStructInfo;
value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
- ret = CRYPT_AsnDecodeUnicodeNameValueInternal(
- dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded,
- dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
- pcbStructInfo);
+ ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded,
+ cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
+ pcbStructInfo, NULL);
}
}
}
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
{
BOOL ret;
struct AsnDecodeSequenceItem items[] = {
{ ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
- CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
+ CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
offsetof(CERT_RDN_ATTR, pszObjId), 0 },
{ 0, offsetof(CERT_RDN_ATTR, dwValueType),
CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
};
- CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
+ CERT_RDN_ATTR *attr = pvStructInfo;
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
pvStructInfo, *pcbStructInfo);
if (attr)
TRACE("attr->pszObjId is %p\n", attr->pszObjId);
- ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
- sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
- attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
+ attr ? attr->pszObjId : NULL);
if (attr)
{
TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeRdn(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
{
BOOL ret = TRUE;
struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
+ offsetof(CERT_RDN, cRDNAttr), offsetof(CERT_RDN, rgRDNAttr),
+ sizeof(CERT_RDN),
CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
offsetof(CERT_RDN_ATTR, pszObjId) };
- PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
+ NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
return ret;
}
__TRY
{
struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
+ offsetof(CERT_NAME_INFO, cRDN), offsetof(CERT_NAME_INFO, rgRDN),
+ sizeof(CERT_NAME_INFO),
CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
offsetof(CERT_RDN, rgRDNAttr) };
+ DWORD bytesNeeded;
+
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded,
+ NULL);
+ if (ret)
+ {
+ if (!pvStructInfo)
+ *pcbStructInfo = bytesNeeded;
+ else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
+ pvStructInfo, pcbStructInfo, bytesNeeded)))
+ {
+ CERT_NAME_INFO *info;
- ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, pcbStructInfo, NULL);
+ if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
+ pvStructInfo = *(BYTE **)pvStructInfo;
+ info = pvStructInfo;
+ info->rgRDN = (CERT_RDN *)((BYTE *)pvStructInfo +
+ sizeof(CERT_NAME_INFO));
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
+ &bytesNeeded, NULL);
+ }
+ }
}
__EXCEPT_PAGE_FAULT
{
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeUnicodeRdnAttr(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
{
BOOL ret;
struct AsnDecodeSequenceItem items[] = {
{ ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
- CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
+ CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
offsetof(CERT_RDN_ATTR, pszObjId), 0 },
{ 0, offsetof(CERT_RDN_ATTR, dwValueType),
CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
};
- CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
+ CERT_RDN_ATTR *attr = pvStructInfo;
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
pvStructInfo, *pcbStructInfo);
if (attr)
TRACE("attr->pszObjId is %p\n", attr->pszObjId);
- ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
- sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
- attr, pcbStructInfo, attr ? attr->pszObjId : NULL);
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
+ attr ? attr->pszObjId : NULL);
if (attr)
{
TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeUnicodeRdn(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
{
BOOL ret = TRUE;
struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
+ offsetof(CERT_RDN, cRDNAttr), offsetof(CERT_RDN, rgRDNAttr),
+ sizeof(CERT_RDN),
CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
offsetof(CERT_RDN_ATTR, pszObjId) };
- PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
+ NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
return ret;
}
__TRY
{
struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
+ offsetof(CERT_NAME_INFO, cRDN), offsetof(CERT_NAME_INFO, rgRDN),
+ sizeof(CERT_NAME_INFO),
CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
offsetof(CERT_RDN, rgRDNAttr) };
+ DWORD bytesNeeded;
+
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded,
+ NULL);
+ if (ret)
+ {
+ if (!pvStructInfo)
+ *pcbStructInfo = bytesNeeded;
+ else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
+ pvStructInfo, pcbStructInfo, bytesNeeded)))
+ {
+ CERT_NAME_INFO *info;
- ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, pcbStructInfo, NULL);
+ if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
+ pvStructInfo = *(BYTE **)pvStructInfo;
+ info = pvStructInfo;
+ info->rgRDN = (CERT_RDN *)((BYTE *)pvStructInfo +
+ sizeof(CERT_NAME_INFO));
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
+ &bytesNeeded, NULL);
+ }
+ }
}
__EXCEPT_PAGE_FAULT
{
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+static BOOL CRYPT_FindEncodedLen(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD *pcbDecoded)
{
- BOOL ret = TRUE;
- DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
+ BOOL ret = TRUE, done = FALSE;
+ DWORD indefiniteNestingLevels = 0, decoded = 0;
- TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, *pcbStructInfo);
+ TRACE("(%p, %d)\n", pbEncoded, cbEncoded);
- if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
- bytesNeeded += cbEncoded;
- if (!pvStructInfo)
- *pcbStructInfo = bytesNeeded;
- else if (*pcbStructInfo < bytesNeeded)
- {
- SetLastError(ERROR_MORE_DATA);
- *pcbStructInfo = bytesNeeded;
- ret = FALSE;
- }
- else
- {
- PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
+ do {
+ DWORD dataLen;
- *pcbStructInfo = bytesNeeded;
- blob->cbData = cbEncoded;
- if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
- blob->pbData = (LPBYTE)pbEncoded;
- else
+ if (!cbEncoded)
+ done = TRUE;
+ else if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded,
+ &dataLen)))
{
- assert(blob->pbData);
- memcpy(blob->pbData, pbEncoded, blob->cbData);
+ BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
+
+ if (dataLen == CMSG_INDEFINITE_LENGTH)
+ {
+ indefiniteNestingLevels++;
+ pbEncoded += 1 + lenBytes;
+ cbEncoded -= 1 + lenBytes;
+ decoded += 1 + lenBytes;
+ TRACE("indefiniteNestingLevels = %d\n",
+ indefiniteNestingLevels);
+ }
+ else
+ {
+ if (pbEncoded[0] == 0 && pbEncoded[1] == 0 &&
+ indefiniteNestingLevels)
+ {
+ indefiniteNestingLevels--;
+ TRACE("indefiniteNestingLevels = %d\n",
+ indefiniteNestingLevels);
+ }
+ pbEncoded += 1 + lenBytes + dataLen;
+ cbEncoded -= 1 + lenBytes + dataLen;
+ decoded += 1 + lenBytes + dataLen;
+ if (!indefiniteNestingLevels)
+ done = TRUE;
+ }
}
+ } while (ret && !done);
+ /* If we haven't found all 0 TLVs, we haven't found the end */
+ if (ret && indefiniteNestingLevels)
+ {
+ SetLastError(CRYPT_E_ASN1_EOD);
+ ret = FALSE;
}
+ if (ret)
+ *pcbDecoded = decoded;
+ TRACE("returning %d (%d)\n", ret, ret ? *pcbDecoded : 0);
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+static BOOL CRYPT_AsnDecodeCopyBytes(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
{
- CRYPT_ALGORITHM_IDENTIFIER *algo =
- (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
BOOL ret = TRUE;
- struct AsnDecodeSequenceItem items[] = {
- { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
- CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
- offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
- { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
- CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
- offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
- };
+ DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB), encodedLen = 0;
- TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, *pcbStructInfo);
+ TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo);
- ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
- sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, pcbStructInfo, algo ? algo->pszObjId : NULL);
- if (ret && pvStructInfo)
+ if ((ret = CRYPT_FindEncodedLen(pbEncoded, cbEncoded, &encodedLen)))
{
- TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
- debugstr_a(algo->pszObjId));
+ if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
+ bytesNeeded += encodedLen;
+ if (!pvStructInfo)
+ *pcbStructInfo = bytesNeeded;
+ else if (*pcbStructInfo < bytesNeeded)
+ {
+ SetLastError(ERROR_MORE_DATA);
+ *pcbStructInfo = bytesNeeded;
+ ret = FALSE;
+ }
+ else
+ {
+ PCRYPT_OBJID_BLOB blob = pvStructInfo;
+
+ *pcbStructInfo = bytesNeeded;
+ blob->cbData = encodedLen;
+ if (encodedLen)
+ {
+ if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
+ blob->pbData = (LPBYTE)pbEncoded;
+ else
+ {
+ assert(blob->pbData);
+ memcpy(blob->pbData, pbEncoded, blob->cbData);
+ }
+ }
+ else
+ blob->pbData = NULL;
+ }
+ if (pcbDecoded)
+ *pcbDecoded = encodedLen;
}
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+static BOOL CRYPT_AsnDecodeCTLUsage(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
+{
+ BOOL ret;
+ struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
+ offsetof(CTL_USAGE, cUsageIdentifier),
+ offsetof(CTL_USAGE, rgpszUsageIdentifier),
+ sizeof(CTL_USAGE),
+ CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
+
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
+ NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
+ return ret;
+}
+
+static BOOL CRYPT_AsnDecodeCTLEntryAttributes(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ struct AsnArrayDescriptor arrayDesc = { 0,
+ offsetof(CTL_ENTRY, cAttribute), offsetof(CTL_ENTRY, rgAttribute),
+ FINALMEMBERSIZE(CTL_ENTRY, cAttribute),
+ CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
+ offsetof(CRYPT_ATTRIBUTE, pszObjId) };
+ BOOL ret;
+
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
+ return ret;
+}
+
+static BOOL CRYPT_AsnDecodeCTLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
{
- BOOL ret = TRUE;
struct AsnDecodeSequenceItem items[] = {
- { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
- CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
- FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
- Algorithm.pszObjId) },
- { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
- CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
- offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
+ { ASN_OCTETSTRING, offsetof(CTL_ENTRY, SubjectIdentifier),
+ CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE,
+ offsetof(CTL_ENTRY, SubjectIdentifier.pbData), 0 },
+ { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CTL_ENTRY, cAttribute),
+ CRYPT_AsnDecodeCTLEntryAttributes,
+ FINALMEMBERSIZE(CTL_ENTRY, cAttribute), FALSE, TRUE,
+ offsetof(CTL_ENTRY, rgAttribute), 0 },
};
- PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
+ BOOL ret = TRUE;
+ CTL_ENTRY *entry = pvStructInfo;
+
+ TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
+ *pcbStructInfo);
- ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
- sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, pcbStructInfo, info ?
- info->Algorithm.Parameters.pbData : NULL);
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo,
+ pcbDecoded, entry ? entry->SubjectIdentifier.pbData : NULL);
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
+static BOOL CRYPT_AsnDecodeCTLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
+{
+ BOOL ret;
+ struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
+ offsetof(CTL_INFO, cCTLEntry), offsetof(CTL_INFO, rgCTLEntry),
+ FINALMEMBERSIZE(CTL_INFO, cExtension),
+ CRYPT_AsnDecodeCTLEntry, sizeof(CTL_ENTRY), TRUE,
+ offsetof(CTL_ENTRY, SubjectIdentifier.pbData) };
+
+ TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo, pcbDecoded);
+
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
+ return ret;
+}
+
+static BOOL CRYPT_AsnDecodeCTLExtensionsInternal(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ BOOL ret = TRUE;
+ struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
+ offsetof(CTL_INFO, cExtension), offsetof(CTL_INFO, rgExtension),
+ FINALMEMBERSIZE(CTL_INFO, cExtension),
+ CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
+ offsetof(CERT_EXTENSION, pszObjId) };
+
+ TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo, pcbDecoded);
+
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
+ return ret;
+}
+
+static BOOL CRYPT_AsnDecodeCTLExtensions(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ BOOL ret;
+ DWORD dataLen;
+
+ if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
+ {
+ BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
+
+ ret = CRYPT_AsnDecodeCTLExtensionsInternal(pbEncoded + 1 + lenBytes,
+ dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
+ if (ret && pcbDecoded)
+ *pcbDecoded = 1 + lenBytes + dataLen;
+ }
+ return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnDecodeCTL(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
- BOOL ret = TRUE;
+ BOOL ret = FALSE;
+
+ TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+ pDecodePara, pvStructInfo, *pcbStructInfo);
__TRY
{
- DWORD bytesNeeded;
-
- if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
- lpszStructType, pbEncoded, cbEncoded,
- dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
- {
- if (!pvStructInfo)
- *pcbStructInfo = bytesNeeded;
- else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
- pvStructInfo, pcbStructInfo, bytesNeeded)))
- {
- PCERT_PUBLIC_KEY_INFO info;
+ struct AsnDecodeSequenceItem items[] = {
+ { ASN_INTEGER, offsetof(CTL_INFO, dwVersion),
+ CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
+ { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectUsage),
+ CRYPT_AsnDecodeCTLUsage, sizeof(CTL_USAGE), FALSE, TRUE,
+ offsetof(CTL_INFO, SubjectUsage.rgpszUsageIdentifier), 0 },
+ { ASN_OCTETSTRING, offsetof(CTL_INFO, ListIdentifier),
+ CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), TRUE,
+ TRUE, offsetof(CTL_INFO, ListIdentifier.pbData), 0 },
+ { ASN_INTEGER, offsetof(CTL_INFO, SequenceNumber),
+ CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
+ TRUE, TRUE, offsetof(CTL_INFO, SequenceNumber.pbData), 0 },
+ { 0, offsetof(CTL_INFO, ThisUpdate),
+ CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE,
+ 0 },
+ { 0, offsetof(CTL_INFO, NextUpdate),
+ CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), TRUE, FALSE,
+ 0 },
+ { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectAlgorithm),
+ CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
+ FALSE, TRUE, offsetof(CTL_INFO, SubjectAlgorithm.pszObjId), 0 },
+ { ASN_SEQUENCEOF, offsetof(CTL_INFO, cCTLEntry),
+ CRYPT_AsnDecodeCTLEntries,
+ MEMBERSIZE(CTL_INFO, cCTLEntry, cExtension),
+ TRUE, TRUE, offsetof(CTL_INFO, rgCTLEntry), 0 },
+ { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CTL_INFO, cExtension),
+ CRYPT_AsnDecodeCTLExtensions, FINALMEMBERSIZE(CTL_INFO, cExtension),
+ TRUE, TRUE, offsetof(CTL_INFO, rgExtension), 0 },
+ };
- if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
- pvStructInfo = *(BYTE **)pvStructInfo;
- info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
- info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
- sizeof(CERT_PUBLIC_KEY_INFO);
- ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
- lpszStructType, pbEncoded, cbEncoded,
- dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
- &bytesNeeded);
- }
- }
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
+ pcbStructInfo, NULL, NULL);
}
__EXCEPT_PAGE_FAULT
{
SetLastError(STATUS_ACCESS_VIOLATION);
- ret = FALSE;
}
__ENDTRY
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+static BOOL CRYPT_AsnDecodeSMIMECapability(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
{
BOOL ret;
+ struct AsnDecodeSequenceItem items[] = {
+ { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_SMIME_CAPABILITY, pszObjId),
+ CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
+ offsetof(CRYPT_SMIME_CAPABILITY, pszObjId), 0 },
+ { 0, offsetof(CRYPT_SMIME_CAPABILITY, Parameters),
+ CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
+ offsetof(CRYPT_SMIME_CAPABILITY, Parameters.pbData), 0 },
+ };
+ PCRYPT_SMIME_CAPABILITY capability = pvStructInfo;
- if (cbEncoded < 3)
- {
- SetLastError(CRYPT_E_ASN1_CORRUPT);
- return FALSE;
- }
- if (GET_LEN_BYTES(pbEncoded[1]) > 1)
- {
- SetLastError(CRYPT_E_ASN1_CORRUPT);
- return FALSE;
- }
- if (pbEncoded[1] > 1)
- {
- SetLastError(CRYPT_E_ASN1_CORRUPT);
- return FALSE;
- }
- if (!pvStructInfo)
- {
- *pcbStructInfo = sizeof(BOOL);
- ret = TRUE;
- }
- else if (*pcbStructInfo < sizeof(BOOL))
- {
- *pcbStructInfo = sizeof(BOOL);
- SetLastError(ERROR_MORE_DATA);
- ret = FALSE;
- }
- else
- {
- *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
- ret = TRUE;
- }
- TRACE("returning %d (%08x)\n", ret, GetLastError());
+ TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo);
+
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
+ pcbDecoded, capability ? capability->pszObjId : NULL);
+ TRACE("returning %d\n", ret);
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeAltNameEntry(DWORD dwCertEncodingType,
+static BOOL WINAPI CRYPT_AsnDecodeSMIMECapabilities(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
- PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
- DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
- BOOL ret;
+ BOOL ret = FALSE;
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
pDecodePara, pvStructInfo, *pcbStructInfo);
- if (cbEncoded < 2)
- {
- SetLastError(CRYPT_E_ASN1_CORRUPT);
- return FALSE;
- }
- if ((pbEncoded[0] & ASN_FLAGS_MASK) != ASN_CONTEXT)
+ __TRY
{
- SetLastError(CRYPT_E_ASN1_BADTAG);
- return FALSE;
- }
- lenBytes = GET_LEN_BYTES(pbEncoded[1]);
- if (1 + lenBytes > cbEncoded)
+ struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
+ offsetof(CRYPT_SMIME_CAPABILITIES, cCapability),
+ offsetof(CRYPT_SMIME_CAPABILITIES, rgCapability),
+ sizeof(CRYPT_SMIME_CAPABILITIES),
+ CRYPT_AsnDecodeSMIMECapability, sizeof(CRYPT_SMIME_CAPABILITY), TRUE,
+ offsetof(CRYPT_SMIME_CAPABILITY, pszObjId) };
+
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
+ }
+ __EXCEPT_PAGE_FAULT
{
- SetLastError(CRYPT_E_ASN1_CORRUPT);
- return FALSE;
+ SetLastError(STATUS_ACCESS_VIOLATION);
}
+ __ENDTRY
+ TRACE("returning %d\n", ret);
+ return ret;
+}
+
+static BOOL CRYPT_AsnDecodeIA5String(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ BOOL ret = TRUE;
+ DWORD dataLen;
+ LPSTR *pStr = pvStructInfo;
+
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
{
- switch (pbEncoded[0] & ASN_TYPE_MASK)
+ BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
+ DWORD bytesNeeded = sizeof(LPSTR) + sizeof(char);
+
+ if (pbEncoded[0] != ASN_IA5STRING)
{
- case 1: /* rfc822Name */
- case 2: /* dNSName */
- case 6: /* uniformResourceIdentifier */
- bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
- break;
- case 7: /* iPAddress */
- bytesNeeded += dataLen;
- break;
- case 8: /* registeredID */
- /* FIXME: decode as OID */
- case 0: /* otherName */
- case 4: /* directoryName */
- FIXME("stub\n");
- SetLastError(CRYPT_E_ASN1_BADTAG);
- ret = FALSE;
- break;
- case 3: /* x400Address, unimplemented */
- case 5: /* ediPartyName, unimplemented */
- SetLastError(CRYPT_E_ASN1_BADTAG);
- ret = FALSE;
- break;
- default:
SetLastError(CRYPT_E_ASN1_CORRUPT);
ret = FALSE;
}
- if (ret)
+ else
{
- if (!entry)
+ bytesNeeded += dataLen;
+ if (pcbDecoded)
+ *pcbDecoded = 1 + lenBytes + dataLen;
+ if (!pvStructInfo)
*pcbStructInfo = bytesNeeded;
else if (*pcbStructInfo < bytesNeeded)
{
else
{
*pcbStructInfo = bytesNeeded;
- /* MS used values one greater than the asn1 ones.. sigh */
- entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
- switch (pbEncoded[0] & ASN_TYPE_MASK)
- {
- case 1: /* rfc822Name */
- case 2: /* dNSName */
- case 6: /* uniformResourceIdentifier */
+ if (dataLen)
{
- DWORD i;
+ LPSTR str = *pStr;
- for (i = 0; i < dataLen; i++)
- entry->u.pwszURL[i] =
- (WCHAR)pbEncoded[1 + lenBytes + i];
- entry->u.pwszURL[i] = 0;
- TRACE("URL is %p (%s)\n", entry->u.pwszURL,
- debugstr_w(entry->u.pwszURL));
- break;
- }
- case 7: /* iPAddress */
- /* The next data pointer is in the pwszURL spot, that is,
- * the first 4 bytes. Need to move it to the next spot.
- */
- entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
- entry->u.IPAddress.cbData = dataLen;
- memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
- dataLen);
- break;
+ assert(str);
+ memcpy(str, pbEncoded + 1 + lenBytes, dataLen);
+ str[dataLen] = 0;
}
+ else
+ *pStr = NULL;
}
}
}
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+static BOOL CRYPT_AsnDecodeNoticeNumbers(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
{
- BOOL ret = TRUE;
struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
- CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
- offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
- PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
+ offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers),
+ offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, rgNoticeNumbers),
+ FINALMEMBERSIZE(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers),
+ CRYPT_AsnDecodeIntInternal, sizeof(int), FALSE, 0 };
+ BOOL ret;
- TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, *pcbStructInfo);
+ TRACE("(%p, %d, %08x, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, pvStructInfo ? *pcbDecoded : 0);
- if (info)
- TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
- ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, pcbStructInfo, info ? info->rgAltEntry : NULL);
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
+ TRACE("returning %d\n", ret);
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+static BOOL CRYPT_AsnDecodeNoticeReference(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
{
BOOL ret;
+ struct AsnDecodeSequenceItem items[] = {
+ { ASN_IA5STRING, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
+ pszOrganization), CRYPT_AsnDecodeIA5String, sizeof(LPSTR), FALSE, TRUE,
+ offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, pszOrganization), 0 },
+ { ASN_SEQUENCEOF, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
+ cNoticeNumbers), CRYPT_AsnDecodeNoticeNumbers,
+ FINALMEMBERSIZE(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers),
+ FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
+ rgNoticeNumbers), 0 },
+ };
+ DWORD bytesNeeded;
- __TRY
+ TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
+
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, NULL, NULL, &bytesNeeded, pcbDecoded,
+ NULL);
+ if (ret)
{
- struct AsnDecodeSequenceItem items[] = {
- { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
- CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_DATA_BLOB),
- TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
- { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
- offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
- CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
- offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
- { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
- CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
- sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
- offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
- };
+ /* The caller is expecting a pointer to a
+ * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE to be decoded, whereas
+ * CRYPT_AsnDecodeSequence is decoding a
+ * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE. Increment the bytes
+ * needed, and decode again if the requisite space is available.
+ */
+ bytesNeeded += sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE);
+ if (!pvStructInfo)
+ *pcbStructInfo = bytesNeeded;
+ else if (*pcbStructInfo < bytesNeeded)
+ {
+ *pcbStructInfo = bytesNeeded;
+ SetLastError(ERROR_MORE_DATA);
+ ret = FALSE;
+ }
+ else
+ {
+ PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE noticeRef;
- ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
- sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, pcbStructInfo, NULL);
+ *pcbStructInfo = bytesNeeded;
+ /* The pointer (pvStructInfo) passed in points to the first dynamic
+ * pointer, so use it as the pointer to the
+ * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, and create the
+ * appropriate offset for the first dynamic pointer within the
+ * notice reference by pointing to the first memory location past
+ * the CERT_POLICY_QUALIFIER_NOTICE_REFERENCE.
+ */
+ noticeRef =
+ *(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE *)pvStructInfo;
+ noticeRef->pszOrganization = (LPSTR)((LPBYTE)noticeRef +
+ sizeof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE));
+ ret = CRYPT_AsnDecodeSequence(items,
+ sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
+ NULL, noticeRef, &bytesNeeded, pcbDecoded,
+ noticeRef->pszOrganization);
+ }
}
- __EXCEPT_PAGE_FAULT
+ TRACE("returning %d\n", ret);
+ return ret;
+}
+
+static BOOL CRYPT_AsnDecodeUnicodeString(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ BOOL ret = TRUE;
+ DWORD dataLen;
+
+ if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
{
- SetLastError(STATUS_ACCESS_VIOLATION);
- ret = FALSE;
+ BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
+ DWORD bytesNeeded = sizeof(LPWSTR);
+
+ switch (pbEncoded[0])
+ {
+ case ASN_NUMERICSTRING:
+ if (dataLen)
+ bytesNeeded += (dataLen + 1) * 2;
+ break;
+ case ASN_PRINTABLESTRING:
+ if (dataLen)
+ bytesNeeded += (dataLen + 1) * 2;
+ break;
+ case ASN_IA5STRING:
+ if (dataLen)
+ bytesNeeded += (dataLen + 1) * 2;
+ break;
+ case ASN_T61STRING:
+ if (dataLen)
+ bytesNeeded += (dataLen + 1) * 2;
+ break;
+ case ASN_VIDEOTEXSTRING:
+ if (dataLen)
+ bytesNeeded += (dataLen + 1) * 2;
+ break;
+ case ASN_GRAPHICSTRING:
+ if (dataLen)
+ bytesNeeded += (dataLen + 1) * 2;
+ break;
+ case ASN_VISIBLESTRING:
+ if (dataLen)
+ bytesNeeded += (dataLen + 1) * 2;
+ break;
+ case ASN_GENERALSTRING:
+ if (dataLen)
+ bytesNeeded += (dataLen + 1) * 2;
+ break;
+ case ASN_UNIVERSALSTRING:
+ if (dataLen)
+ bytesNeeded += dataLen / 2 + sizeof(WCHAR);
+ break;
+ case ASN_BMPSTRING:
+ if (dataLen)
+ bytesNeeded += dataLen + sizeof(WCHAR);
+ break;
+ case ASN_UTF8STRING:
+ if (dataLen)
+ bytesNeeded += (MultiByteToWideChar(CP_UTF8, 0,
+ (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) + 1) * 2;
+ break;
+ default:
+ SetLastError(CRYPT_E_ASN1_BADTAG);
+ return FALSE;
+ }
+
+ if (pcbDecoded)
+ *pcbDecoded = 1 + lenBytes + dataLen;
+ if (!pvStructInfo)
+ *pcbStructInfo = bytesNeeded;
+ else if (*pcbStructInfo < bytesNeeded)
+ {
+ *pcbStructInfo = bytesNeeded;
+ SetLastError(ERROR_MORE_DATA);
+ ret = FALSE;
+ }
+ else
+ {
+ LPWSTR *pStr = pvStructInfo;
+
+ *pcbStructInfo = bytesNeeded;
+ if (dataLen)
+ {
+ DWORD i;
+ LPWSTR str = *(LPWSTR *)pStr;
+
+ assert(str);
+ switch (pbEncoded[0])
+ {
+ case ASN_NUMERICSTRING:
+ case ASN_PRINTABLESTRING:
+ case ASN_IA5STRING:
+ case ASN_T61STRING:
+ case ASN_VIDEOTEXSTRING:
+ case ASN_GRAPHICSTRING:
+ case ASN_VISIBLESTRING:
+ case ASN_GENERALSTRING:
+ for (i = 0; i < dataLen; i++)
+ str[i] = pbEncoded[1 + lenBytes + i];
+ str[i] = 0;
+ break;
+ case ASN_UNIVERSALSTRING:
+ for (i = 0; i < dataLen / 4; i++)
+ str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
+ | pbEncoded[1 + lenBytes + 2 * i + 3];
+ str[i] = 0;
+ break;
+ case ASN_BMPSTRING:
+ for (i = 0; i < dataLen / 2; i++)
+ str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
+ pbEncoded[1 + lenBytes + 2 * i + 1];
+ str[i] = 0;
+ break;
+ case ASN_UTF8STRING:
+ {
+ int len = MultiByteToWideChar(CP_UTF8, 0,
+ (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
+ str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
+ str[len] = 0;
+ break;
+ }
+ }
+ }
+ else
+ *pStr = NULL;
+ }
}
- __ENDTRY
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+static BOOL CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(
+ const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
+ DWORD *pcbStructInfo, DWORD *pcbDecoded)
{
- BOOL ret = TRUE;
+ BOOL ret;
+ struct AsnDecodeSequenceItem items[] = {
+ { ASN_SEQUENCE, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE,
+ pNoticeReference), CRYPT_AsnDecodeNoticeReference,
+ sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE), TRUE, TRUE,
+ offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pNoticeReference), 0 },
+ { 0, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pszDisplayText),
+ CRYPT_AsnDecodeUnicodeString, sizeof(LPWSTR), TRUE, TRUE,
+ offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pszDisplayText), 0 },
+ };
+ PCERT_POLICY_QUALIFIER_USER_NOTICE notice = pvStructInfo;
+
+ TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo);
+
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
+ pcbDecoded, notice ? notice->pNoticeReference : NULL);
+ TRACE("returning %d\n", ret);
+ return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnDecodePolicyQualifierUserNotice(
+ DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
+ void *pvStructInfo, DWORD *pcbStructInfo)
+{
+ BOOL ret = FALSE;
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
pDecodePara, pvStructInfo, *pcbStructInfo);
__TRY
{
- struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
- CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
- offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
+ DWORD bytesNeeded;
+
+ ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(pbEncoded,
+ cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
+ NULL);
+ if (ret)
+ {
+ if (!pvStructInfo)
+ *pcbStructInfo = bytesNeeded;
+ else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
+ pvStructInfo, pcbStructInfo, bytesNeeded)))
+ {
+ PCERT_POLICY_QUALIFIER_USER_NOTICE notice;
- ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, pcbStructInfo, NULL);
+ if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
+ pvStructInfo = *(BYTE **)pvStructInfo;
+ notice = pvStructInfo;
+ notice->pNoticeReference =
+ (PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE)
+ ((BYTE *)pvStructInfo +
+ sizeof(CERT_POLICY_QUALIFIER_USER_NOTICE));
+ ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(
+ pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
+ pvStructInfo, &bytesNeeded, NULL);
+ }
+ }
}
__EXCEPT_PAGE_FAULT
{
SetLastError(STATUS_ACCESS_VIOLATION);
- ret = FALSE;
}
__ENDTRY
+ TRACE("returning %d\n", ret);
return ret;
}
-struct PATH_LEN_CONSTRAINT
+static BOOL CRYPT_AsnDecodePKCSAttributeValue(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
{
- BOOL fPathLenConstraint;
- DWORD dwPathLenConstraint;
-};
+ BOOL ret;
+ struct AsnArrayDescriptor arrayDesc = { 0,
+ offsetof(CRYPT_ATTRIBUTE, cValue), offsetof(CRYPT_ATTRIBUTE, rgValue),
+ FINALMEMBERSIZE(CRYPT_ATTRIBUTE, cValue),
+ CRYPT_AsnDecodeCopyBytes,
+ sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
-static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+ TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
+
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
+ return ret;
+}
+
+static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
{
- BOOL ret = TRUE;
+ BOOL ret;
+ struct AsnDecodeSequenceItem items[] = {
+ { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
+ CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
+ offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
+ { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
+ CRYPT_AsnDecodePKCSAttributeValue,
+ FINALMEMBERSIZE(CRYPT_ATTRIBUTE, cValue), FALSE,
+ TRUE, offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
+ };
+ PCRYPT_ATTRIBUTE attr = pvStructInfo;
TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
pvStructInfo, *pcbStructInfo);
- if (cbEncoded)
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
+ pcbDecoded, attr ? attr->pszObjId : NULL);
+ TRACE("returning %d\n", ret);
+ return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+{
+ BOOL ret = FALSE;
+
+ TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+ pDecodePara, pvStructInfo, *pcbStructInfo);
+
+ __TRY
{
- if (pbEncoded[0] == ASN_INTEGER)
- {
- DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT);
+ DWORD bytesNeeded;
+ ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
+ if (ret)
+ {
if (!pvStructInfo)
*pcbStructInfo = bytesNeeded;
- else if (*pcbStructInfo < bytesNeeded)
- {
- SetLastError(ERROR_MORE_DATA);
- *pcbStructInfo = bytesNeeded;
- ret = FALSE;
- }
- else
+ else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
+ pvStructInfo, pcbStructInfo, bytesNeeded)))
{
- struct PATH_LEN_CONSTRAINT *constraint =
- (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
- DWORD size = sizeof(constraint->dwPathLenConstraint);
+ PCRYPT_ATTRIBUTE attr;
- ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
- pbEncoded, cbEncoded, 0, NULL,
- &constraint->dwPathLenConstraint, &size);
- if (ret)
- constraint->fPathLenConstraint = TRUE;
- TRACE("got an int, dwPathLenConstraint is %d\n",
- constraint->dwPathLenConstraint);
+ if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
+ pvStructInfo = *(BYTE **)pvStructInfo;
+ attr = pvStructInfo;
+ attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
+ sizeof(CRYPT_ATTRIBUTE));
+ ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
+ NULL);
}
}
- else
- {
- SetLastError(CRYPT_E_ASN1_CORRUPT);
- ret = FALSE;
- }
}
- TRACE("returning %d (%08x)\n", ret, GetLastError());
+ __EXCEPT_PAGE_FAULT
+ {
+ SetLastError(STATUS_ACCESS_VIOLATION);
+ }
+ __ENDTRY
+ TRACE("returning %d\n", ret);
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeSubtreeConstraints(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
{
+ struct AsnArrayDescriptor arrayDesc = { 0,
+ offsetof(CRYPT_ATTRIBUTES, cAttr), offsetof(CRYPT_ATTRIBUTES, rgAttr),
+ sizeof(CRYPT_ATTRIBUTES),
+ CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
+ offsetof(CRYPT_ATTRIBUTE, pszObjId) };
BOOL ret;
- struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
- CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
- offsetof(CERT_NAME_BLOB, pbData) };
- struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
-
- TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, *pcbStructInfo);
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, pcbStructInfo,
- entries ? entries->rgItems : NULL);
- TRACE("Returning %d (%08x)\n", ret, GetLastError());
+ NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
+static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
- BOOL ret;
+ BOOL ret = FALSE;
+
+ TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+ pDecodePara, pvStructInfo, *pcbStructInfo);
__TRY
{
- struct AsnDecodeSequenceItem items[] = {
- { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
- CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
- offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
- { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
- fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
- sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
- { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
- cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
- sizeof(struct GenericArray), TRUE, TRUE,
- offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
- };
+ struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
+ offsetof(CRYPT_ATTRIBUTES, cAttr), offsetof(CRYPT_ATTRIBUTES, rgAttr),
+ sizeof(CRYPT_ATTRIBUTES),
+ CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE),
+ TRUE, offsetof(CRYPT_ATTRIBUTE, pszObjId) };
- ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
- sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, pcbStructInfo, NULL);
- }
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
+ }
__EXCEPT_PAGE_FAULT
{
SetLastError(STATUS_ACCESS_VIOLATION);
- ret = FALSE;
}
__ENDTRY
+ TRACE("returning %d\n", ret);
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
{
- BOOL ret;
-
- __TRY
- {
- struct AsnDecodeSequenceItem items[] = {
- { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
- CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
- { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
- fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
- sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
- };
+ CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
+ BOOL ret = TRUE;
+ struct AsnDecodeSequenceItem items[] = {
+ { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
+ CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
+ offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
+ { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
+ CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
+ offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
+ };
- ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
- sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, pcbStructInfo, NULL);
- }
- __EXCEPT_PAGE_FAULT
+ TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo, pcbDecoded);
+
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
+ pcbDecoded, algo ? algo->pszObjId : NULL);
+ if (ret && pvStructInfo)
{
- SetLastError(STATUS_ACCESS_VIOLATION);
- ret = FALSE;
+ TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
+ debugstr_a(algo->pszObjId));
}
- __ENDTRY
return ret;
}
-#define RSA1_MAGIC 0x31415352
-
-struct DECODED_RSA_PUB_KEY
+static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
{
- DWORD pubexp;
- CRYPT_INTEGER_BLOB modulus;
-};
+ BOOL ret = TRUE;
+ struct AsnDecodeSequenceItem items[] = {
+ { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
+ CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
+ FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
+ Algorithm.pszObjId) },
+ { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
+ CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
+ offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
+ };
+ PCERT_PUBLIC_KEY_INFO info = pvStructInfo;
-static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
+ pcbDecoded, info ? info->Algorithm.Parameters.pbData : NULL);
+ return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
- BOOL ret;
+ BOOL ret = TRUE;
__TRY
{
- struct AsnDecodeSequenceItem items[] = {
- { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
- CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
- FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
- 0 },
- { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
- CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
- };
- struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
- DWORD size = 0;
+ DWORD bytesNeeded;
- ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
- sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
- CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, &size, NULL);
- if (ret)
+ if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
{
- DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
- decodedKey->modulus.cbData;
-
if (!pvStructInfo)
- {
*pcbStructInfo = bytesNeeded;
- ret = TRUE;
- }
else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
pvStructInfo, pcbStructInfo, bytesNeeded)))
{
- BLOBHEADER *hdr;
- RSAPUBKEY *rsaPubKey;
+ PCERT_PUBLIC_KEY_INFO info;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
pvStructInfo = *(BYTE **)pvStructInfo;
- hdr = (BLOBHEADER *)pvStructInfo;
- hdr->bType = PUBLICKEYBLOB;
- hdr->bVersion = CUR_BLOB_VERSION;
- hdr->reserved = 0;
- hdr->aiKeyAlg = CALG_RSA_KEYX;
- rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
- sizeof(BLOBHEADER));
- rsaPubKey->magic = RSA1_MAGIC;
- rsaPubKey->pubexp = decodedKey->pubexp;
- rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
- memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
- sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
- decodedKey->modulus.cbData);
+ info = pvStructInfo;
+ info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
+ sizeof(CERT_PUBLIC_KEY_INFO);
+ ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
+ &bytesNeeded, NULL);
}
- LocalFree(decodedKey);
}
}
__EXCEPT_PAGE_FAULT
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
{
BOOL ret;
- DWORD bytesNeeded, dataLen;
-
- TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, *pcbStructInfo);
- if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
+ if (cbEncoded < 3)
{
- if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
- bytesNeeded = sizeof(CRYPT_DATA_BLOB);
- else
- bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
- if (!pvStructInfo)
- *pcbStructInfo = bytesNeeded;
- else if (*pcbStructInfo < bytesNeeded)
- {
- SetLastError(ERROR_MORE_DATA);
- *pcbStructInfo = bytesNeeded;
- ret = FALSE;
- }
- else
- {
- CRYPT_DATA_BLOB *blob;
- BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
-
- blob = (CRYPT_DATA_BLOB *)pvStructInfo;
- blob->cbData = dataLen;
- if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
- blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
- else
- {
- assert(blob->pbData);
- if (blob->cbData)
- memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
- blob->cbData);
- }
- }
+ SetLastError(CRYPT_E_ASN1_CORRUPT);
+ return FALSE;
}
- return ret;
-}
-
-static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
-{
- BOOL ret;
-
- TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, *pcbStructInfo);
-
- __TRY
+ if (GET_LEN_BYTES(pbEncoded[1]) > 1)
{
- DWORD bytesNeeded;
-
- if (!cbEncoded)
- {
- SetLastError(CRYPT_E_ASN1_CORRUPT);
- ret = FALSE;
- }
- else if (pbEncoded[0] != ASN_OCTETSTRING)
- {
- SetLastError(CRYPT_E_ASN1_BADTAG);
- ret = FALSE;
- }
- else if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
- lpszStructType, pbEncoded, cbEncoded,
- dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
- {
- if (!pvStructInfo)
- *pcbStructInfo = bytesNeeded;
- else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
- pvStructInfo, pcbStructInfo, bytesNeeded)))
- {
- CRYPT_DATA_BLOB *blob;
-
- if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
- pvStructInfo = *(BYTE **)pvStructInfo;
- blob = (CRYPT_DATA_BLOB *)pvStructInfo;
- blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
- ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
- lpszStructType, pbEncoded, cbEncoded,
- dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
- &bytesNeeded);
- }
- }
+ SetLastError(CRYPT_E_ASN1_CORRUPT);
+ return FALSE;
}
- __EXCEPT_PAGE_FAULT
+ if (pbEncoded[1] > 1)
{
- SetLastError(STATUS_ACCESS_VIOLATION);
+ SetLastError(CRYPT_E_ASN1_CORRUPT);
+ return FALSE;
+ }
+ if (pcbDecoded)
+ *pcbDecoded = 3;
+ if (!pvStructInfo)
+ {
+ *pcbStructInfo = sizeof(BOOL);
+ ret = TRUE;
+ }
+ else if (*pcbStructInfo < sizeof(BOOL))
+ {
+ *pcbStructInfo = sizeof(BOOL);
+ SetLastError(ERROR_MORE_DATA);
ret = FALSE;
}
- __ENDTRY
+ else
+ {
+ *pcbStructInfo = sizeof(BOOL);
+ *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
+ ret = TRUE;
+ }
+ TRACE("returning %d (%08x)\n", ret, GetLastError());
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
{
+ PCERT_ALT_NAME_ENTRY entry = pvStructInfo;
+ DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
BOOL ret;
- TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, *pcbStructInfo);
+ TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo);
- if (pbEncoded[0] == ASN_BITSTRING)
+ if (cbEncoded < 2)
{
- DWORD bytesNeeded, dataLen;
-
- if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
+ SetLastError(CRYPT_E_ASN1_CORRUPT);
+ return FALSE;
+ }
+ lenBytes = GET_LEN_BYTES(pbEncoded[1]);
+ if (1 + lenBytes > cbEncoded)
+ {
+ SetLastError(CRYPT_E_ASN1_CORRUPT);
+ return FALSE;
+ }
+ if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
+ {
+ switch (pbEncoded[0] & ASN_TYPE_MASK)
{
- if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
- bytesNeeded = sizeof(CRYPT_BIT_BLOB);
+ case 1: /* rfc822Name */
+ case 2: /* dNSName */
+ case 6: /* uniformResourceIdentifier */
+ if (memchr(pbEncoded + 1 + lenBytes, 0, dataLen))
+ {
+ SetLastError(CRYPT_E_ASN1_RULE);
+ ret = FALSE;
+ }
else
- bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
- if (!pvStructInfo)
+ bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
+ break;
+ case 4: /* directoryName */
+ case 7: /* iPAddress */
+ bytesNeeded += dataLen;
+ break;
+ case 8: /* registeredID */
+ ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
+ &dataLen, NULL);
+ if (ret)
+ {
+ /* FIXME: ugly, shouldn't need to know internals of OID decode
+ * function to use it.
+ */
+ bytesNeeded += dataLen - sizeof(LPSTR);
+ }
+ break;
+ case 0: /* otherName */
+ FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
+ SetLastError(CRYPT_E_ASN1_BADTAG);
+ ret = FALSE;
+ break;
+ case 3: /* x400Address, unimplemented */
+ case 5: /* ediPartyName, unimplemented */
+ TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
+ SetLastError(CRYPT_E_ASN1_BADTAG);
+ ret = FALSE;
+ break;
+ default:
+ TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
+ SetLastError(CRYPT_E_ASN1_CORRUPT);
+ ret = FALSE;
+ }
+ if (ret)
+ {
+ if (pcbDecoded)
+ *pcbDecoded = 1 + lenBytes + dataLen;
+ if (!entry)
*pcbStructInfo = bytesNeeded;
else if (*pcbStructInfo < bytesNeeded)
{
}
else
{
- CRYPT_BIT_BLOB *blob;
-
- blob = (CRYPT_BIT_BLOB *)pvStructInfo;
- blob->cbData = dataLen - 1;
- blob->cUnusedBits = *(pbEncoded + 1 +
- GET_LEN_BYTES(pbEncoded[1]));
- if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
+ *pcbStructInfo = bytesNeeded;
+ /* MS used values one greater than the asn1 ones.. sigh */
+ entry->dwAltNameChoice = (pbEncoded[0] & ASN_TYPE_MASK) + 1;
+ switch (pbEncoded[0] & ASN_TYPE_MASK)
{
- blob->pbData = (BYTE *)pbEncoded + 2 +
- GET_LEN_BYTES(pbEncoded[1]);
- }
- else
+ case 1: /* rfc822Name */
+ case 2: /* dNSName */
+ case 6: /* uniformResourceIdentifier */
{
- assert(blob->pbData);
- if (blob->cbData)
- {
- BYTE mask = 0xff << blob->cUnusedBits;
+ DWORD i;
- memcpy(blob->pbData, pbEncoded + 2 +
- GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
- blob->pbData[blob->cbData - 1] &= mask;
- }
- }
- }
+ for (i = 0; i < dataLen; i++)
+ entry->u.pwszURL[i] =
+ (WCHAR)pbEncoded[1 + lenBytes + i];
+ entry->u.pwszURL[i] = 0;
+ TRACE("URL is %p (%s)\n", entry->u.pwszURL,
+ debugstr_w(entry->u.pwszURL));
+ break;
+ }
+ case 4: /* directoryName */
+ /* The data are memory-equivalent with the IPAddress case,
+ * fall-through
+ */
+ case 7: /* iPAddress */
+ /* The next data pointer is in the pwszURL spot, that is,
+ * the first 4 bytes. Need to move it to the next spot.
+ */
+ entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
+ entry->u.IPAddress.cbData = dataLen;
+ memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
+ dataLen);
+ break;
+ case 8: /* registeredID */
+ ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
+ &entry->u.pszRegisteredID, &dataLen, NULL);
+ break;
+ }
+ }
}
}
- else
+ return ret;
+}
+
+static BOOL CRYPT_AsnDecodeAltNameInternal(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ BOOL ret;
+ struct AsnArrayDescriptor arrayDesc = { 0,
+ offsetof(CERT_ALT_NAME_INFO, cAltEntry),
+ offsetof(CERT_ALT_NAME_INFO, rgAltEntry),
+ sizeof(CERT_ALT_NAME_INFO),
+ CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
+ offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
+
+ TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo, pcbDecoded);
+
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
+ NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
+ return ret;
+}
+
+/* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */
+static BOOL CRYPT_AsnDecodeIntegerSwapBytes(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ BOOL ret;
+
+ TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo, pcbDecoded);
+
+ /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
+ * place.
+ */
+ ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
+ pcbDecoded);
+ if (ret && pvStructInfo)
{
- SetLastError(CRYPT_E_ASN1_BADTAG);
- ret = FALSE;
+ CRYPT_DATA_BLOB *blob = pvStructInfo;
+
+ if (blob->cbData)
+ {
+ DWORD i;
+ BYTE temp;
+
+ for (i = 0; i < blob->cbData / 2; i++)
+ {
+ temp = blob->pbData[i];
+ blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
+ blob->pbData[blob->cbData - i - 1] = temp;
+ }
+ }
}
TRACE("returning %d (%08x)\n", ret, GetLastError());
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
+static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
BOOL ret;
- TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, pcbStructInfo);
-
__TRY
{
- DWORD bytesNeeded;
-
- if ((ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
- lpszStructType, pbEncoded, cbEncoded,
- dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
- {
- if (!pvStructInfo)
- *pcbStructInfo = bytesNeeded;
- else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
- pvStructInfo, pcbStructInfo, bytesNeeded)))
- {
- CRYPT_BIT_BLOB *blob;
+ struct AsnDecodeSequenceItem items[] = {
+ { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
+ CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
+ TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
+ { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
+ offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
+ CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
+ offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
+ { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
+ CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
+ sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
+ offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
+ };
- if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
- pvStructInfo = *(BYTE **)pvStructInfo;
- blob = (CRYPT_BIT_BLOB *)pvStructInfo;
- blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
- ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
- lpszStructType, pbEncoded, cbEncoded,
- dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
- &bytesNeeded);
- }
- }
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
+ pcbStructInfo, NULL, NULL);
}
__EXCEPT_PAGE_FAULT
{
ret = FALSE;
}
__ENDTRY
- TRACE("returning %d (%08x)\n", ret, GetLastError());
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
+static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
BOOL ret;
- if (!pvStructInfo)
- {
- *pcbStructInfo = sizeof(int);
- return TRUE;
- }
__TRY
{
- BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
- CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
- DWORD size = sizeof(buf);
-
- blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
- if (pbEncoded[0] != ASN_INTEGER)
- {
- SetLastError(CRYPT_E_ASN1_BADTAG);
- ret = FALSE;
- }
- else
- ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
- X509_MULTI_BYTE_INTEGER, pbEncoded, cbEncoded, 0, NULL, &buf,
- &size);
- if (ret)
- {
- if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
- pvStructInfo, pcbStructInfo, sizeof(int))))
- {
- int val, i;
+ struct AsnDecodeSequenceItem items[] = {
+ { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
+ CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
+ TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
+ { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
+ offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
+ CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
+ TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
+ AuthorityCertIssuer.rgAltEntry), 0 },
+ { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
+ AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
+ sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
+ offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
+ AuthorityCertSerialNumber.pbData), 0 },
+ };
- if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
- pvStructInfo = *(BYTE **)pvStructInfo;
- if (blob->pbData[blob->cbData - 1] & 0x80)
- {
- /* initialize to a negative value to sign-extend */
- val = -1;
- }
- else
- val = 0;
- for (i = 0; i < blob->cbData; i++)
- {
- val <<= 8;
- val |= blob->pbData[blob->cbData - i - 1];
- }
- memcpy(pvStructInfo, &val, sizeof(int));
- }
- }
- else if (GetLastError() == ERROR_MORE_DATA)
- SetLastError(CRYPT_E_ASN1_LARGE);
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
+ pcbStructInfo, NULL, NULL);
}
__EXCEPT_PAGE_FAULT
{
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
+static BOOL CRYPT_AsnDecodeAccessDescription(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ struct AsnDecodeSequenceItem items[] = {
+ { 0, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod),
+ CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
+ offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod), 0 },
+ { 0, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation),
+ CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), FALSE,
+ TRUE, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation.u.pwszURL), 0 },
+ };
+ CERT_ACCESS_DESCRIPTION *descr = pvStructInfo;
+
+ return CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
+ pcbDecoded, descr ? descr->pszAccessMethod : NULL);
+}
+
+static BOOL WINAPI CRYPT_AsnDecodeAuthorityInfoAccess(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
BOOL ret;
- DWORD bytesNeeded, dataLen;
- if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
+ TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+ pDecodePara, pvStructInfo, *pcbStructInfo);
+
+ __TRY
{
- BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
+ struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
+ offsetof(CERT_AUTHORITY_INFO_ACCESS, cAccDescr),
+ offsetof(CERT_AUTHORITY_INFO_ACCESS, rgAccDescr),
+ sizeof(CERT_AUTHORITY_INFO_ACCESS),
+ CRYPT_AsnDecodeAccessDescription, sizeof(CERT_ACCESS_DESCRIPTION),
+ TRUE, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod) };
- bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
- if (!pvStructInfo)
- *pcbStructInfo = bytesNeeded;
- else if (*pcbStructInfo < bytesNeeded)
- {
- *pcbStructInfo = bytesNeeded;
- SetLastError(ERROR_MORE_DATA);
- ret = FALSE;
- }
- else
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
+ }
+ __EXCEPT_PAGE_FAULT
+ {
+ SetLastError(STATUS_ACCESS_VIOLATION);
+ ret = FALSE;
+ }
+ __ENDTRY
+ return ret;
+}
+
+static BOOL CRYPT_AsnDecodePKCSContent(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
+{
+ BOOL ret;
+ DWORD dataLen;
+
+ TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo, pcbDecoded);
+
+ /* The caller has already checked the tag, no need to check it again.
+ * Check the outer length is valid:
+ */
+ if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
+ {
+ BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
+ DWORD innerLen;
+
+ pbEncoded += 1 + lenBytes;
+ cbEncoded -= 1 + lenBytes;
+ if (dataLen == CMSG_INDEFINITE_LENGTH)
+ cbEncoded -= 2; /* space for 0 TLV */
+ /* Check the inner length is valid: */
+ if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &innerLen)))
{
- CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
+ DWORD decodedLen;
- blob->cbData = dataLen;
- assert(blob->pbData);
- if (blob->cbData)
+ ret = CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, pcbStructInfo, &decodedLen);
+ if (dataLen == CMSG_INDEFINITE_LENGTH)
{
- DWORD i;
-
- for (i = 0; i < blob->cbData; i++)
+ if (*(pbEncoded + decodedLen) != 0 ||
+ *(pbEncoded + decodedLen + 1) != 0)
{
- blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
- dataLen - i - 1);
+ TRACE("expected 0 TLV, got {%02x,%02x}\n",
+ *(pbEncoded + decodedLen),
+ *(pbEncoded + decodedLen + 1));
+ SetLastError(CRYPT_E_ASN1_CORRUPT);
+ ret = FALSE;
}
+ else
+ decodedLen += 2;
+ }
+ if (ret && pcbDecoded)
+ {
+ *pcbDecoded = 1 + lenBytes + decodedLen;
+ TRACE("decoded %d bytes\n", *pcbDecoded);
}
}
}
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
+static BOOL CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ CRYPT_CONTENT_INFO *info = pvStructInfo;
+ struct AsnDecodeSequenceItem items[] = {
+ { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
+ CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
+ offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
+ { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
+ offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
+ sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
+ offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
+ };
+ BOOL ret;
+
+ TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo, pcbDecoded);
+
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
+ pcbDecoded, info ? info->pszObjId : NULL);
+ return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+{
+ BOOL ret = FALSE;
+
+ TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+ pDecodePara, pvStructInfo, *pcbStructInfo);
+
+ __TRY
+ {
+ ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
+ if (ret && pvStructInfo)
+ {
+ ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
+ pcbStructInfo, *pcbStructInfo);
+ if (ret)
+ {
+ CRYPT_CONTENT_INFO *info;
+
+ if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
+ pvStructInfo = *(BYTE **)pvStructInfo;
+ info = pvStructInfo;
+ info->pszObjId = (LPSTR)((BYTE *)info +
+ sizeof(CRYPT_CONTENT_INFO));
+ ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded,
+ cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
+ pcbStructInfo, NULL);
+ }
+ }
+ }
+ __EXCEPT_PAGE_FAULT
+ {
+ SetLastError(STATUS_ACCESS_VIOLATION);
+ }
+ __ENDTRY
+ return ret;
+}
+
+BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
+ CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
{
BOOL ret;
+ struct AsnDecodeSequenceItem items[] = {
+ { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version),
+ CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
+ { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
+ CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
+ FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
+ 0 },
+ { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
+ CRYPT_AsnDecodePKCSContentInfoInternal,
+ sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
+ ContentInfo.pszObjId), 0 },
+ { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
+ CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
+ offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
+ };
+
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, pDecodePara, digestedData, pcbDigestedData,
+ NULL, NULL);
+ return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+{
+ BOOL ret = TRUE;
+
+ TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+ pDecodePara, pvStructInfo, *pcbStructInfo);
__TRY
{
DWORD bytesNeeded;
- if (pbEncoded[0] != ASN_INTEGER)
- {
- SetLastError(CRYPT_E_ASN1_BADTAG);
- ret = FALSE;
- }
- else
- ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
- lpszStructType, pbEncoded, cbEncoded,
- dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded);
- if (ret)
+ if ((ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
{
if (!pvStructInfo)
*pcbStructInfo = bytesNeeded;
else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
pvStructInfo, pcbStructInfo, bytesNeeded)))
{
- CRYPT_INTEGER_BLOB *blob;
+ CERT_ALT_NAME_INFO *name;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
pvStructInfo = *(BYTE **)pvStructInfo;
- blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
- blob->pbData = (BYTE *)pvStructInfo +
- sizeof(CRYPT_INTEGER_BLOB);
- ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
- lpszStructType, pbEncoded, cbEncoded,
- dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
- &bytesNeeded);
+ name = pvStructInfo;
+ name->rgAltEntry = (PCERT_ALT_NAME_ENTRY)
+ ((BYTE *)pvStructInfo + sizeof(CERT_ALT_NAME_INFO));
+ ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
+ &bytesNeeded, NULL);
}
}
}
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
- DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
- DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
- void *pvStructInfo, DWORD *pcbStructInfo)
+struct PATH_LEN_CONSTRAINT
{
- BOOL ret;
+ BOOL fPathLenConstraint;
+ DWORD dwPathLenConstraint;
+};
- if (pbEncoded[0] == ASN_INTEGER)
- {
- DWORD bytesNeeded, dataLen;
+static BOOL CRYPT_AsnDecodePathLenConstraint(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ BOOL ret = TRUE;
+ DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT), size;
- if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
- {
- BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
-
- bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
- if (!pvStructInfo)
- *pcbStructInfo = bytesNeeded;
- else if (*pcbStructInfo < bytesNeeded)
- {
- *pcbStructInfo = bytesNeeded;
- SetLastError(ERROR_MORE_DATA);
- ret = FALSE;
- }
- else
- {
- CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
-
- blob->cbData = dataLen;
- assert(blob->pbData);
- /* remove leading zero byte if it exists */
- if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
- {
- blob->cbData--;
- blob->pbData++;
- }
- if (blob->cbData)
- {
- DWORD i;
+ TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo, pcbDecoded);
- for (i = 0; i < blob->cbData; i++)
- {
- blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
- dataLen - i - 1);
- }
- }
- }
- }
+ if (!pvStructInfo)
+ {
+ ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, NULL,
+ &size, pcbDecoded);
+ *pcbStructInfo = bytesNeeded;
}
- else
+ else if (*pcbStructInfo < bytesNeeded)
{
- SetLastError(CRYPT_E_ASN1_BADTAG);
+ SetLastError(ERROR_MORE_DATA);
+ *pcbStructInfo = bytesNeeded;
ret = FALSE;
}
+ else
+ {
+ struct PATH_LEN_CONSTRAINT *constraint = pvStructInfo;
+
+ *pcbStructInfo = bytesNeeded;
+ size = sizeof(constraint->dwPathLenConstraint);
+ ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
+ &constraint->dwPathLenConstraint, &size, pcbDecoded);
+ if (ret)
+ constraint->fPathLenConstraint = TRUE;
+ TRACE("got an int, dwPathLenConstraint is %d\n",
+ constraint->dwPathLenConstraint);
+ }
+ TRACE("returning %d (%08x)\n", ret, GetLastError());
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
+static BOOL CRYPT_AsnDecodeSubtreeConstraints(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ BOOL ret;
+ struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
+ offsetof(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint),
+ offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint),
+ FINALMEMBERSIZE(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint),
+ CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
+ offsetof(CERT_NAME_BLOB, pbData) };
+
+ TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo, pcbDecoded);
+
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
+ TRACE("Returning %d (%08x)\n", ret, GetLastError());
+ return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
__TRY
{
- DWORD bytesNeeded;
-
- if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
- lpszStructType, pbEncoded, cbEncoded,
- dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
- {
- if (!pvStructInfo)
- *pcbStructInfo = bytesNeeded;
- else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
- pvStructInfo, pcbStructInfo, bytesNeeded)))
- {
- CRYPT_INTEGER_BLOB *blob;
+ struct AsnDecodeSequenceItem items[] = {
+ { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
+ CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
+ offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
+ { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
+ fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
+ sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
+ { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
+ cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
+ FINALMEMBERSIZE(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint),
+ TRUE, TRUE,
+ offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
+ };
- if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
- pvStructInfo = *(BYTE **)pvStructInfo;
- blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
- blob->pbData = (BYTE *)pvStructInfo +
- sizeof(CRYPT_INTEGER_BLOB);
- ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
- lpszStructType, pbEncoded, cbEncoded,
- dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
- &bytesNeeded);
- }
- }
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
+ pcbStructInfo, NULL, NULL);
}
__EXCEPT_PAGE_FAULT
{
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
+static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
BOOL ret;
- if (!pvStructInfo)
- {
- *pcbStructInfo = sizeof(int);
- return TRUE;
- }
__TRY
{
- if (pbEncoded[0] == ASN_ENUMERATED)
- {
- unsigned int val = 0, i;
+ struct AsnDecodeSequenceItem items[] = {
+ { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
+ CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
+ { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
+ fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
+ sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
+ };
- if (cbEncoded <= 1)
- {
- SetLastError(CRYPT_E_ASN1_EOD);
- ret = FALSE;
- }
- else if (pbEncoded[1] == 0)
- {
- SetLastError(CRYPT_E_ASN1_CORRUPT);
- ret = FALSE;
- }
- else
- {
- /* A little strange looking, but we have to accept a sign byte:
- * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
- * assuming a small length is okay here, it has to be in short
- * form.
- */
- if (pbEncoded[1] > sizeof(unsigned int) + 1)
- {
- SetLastError(CRYPT_E_ASN1_LARGE);
- return FALSE;
- }
- for (i = 0; i < pbEncoded[1]; i++)
- {
- val <<= 8;
- val |= pbEncoded[2 + i];
- }
- if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
- pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
- {
- if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
- pvStructInfo = *(BYTE **)pvStructInfo;
- memcpy(pvStructInfo, &val, sizeof(unsigned int));
- }
- }
- }
- else
- {
- SetLastError(CRYPT_E_ASN1_BADTAG);
- ret = FALSE;
- }
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
+ pcbStructInfo, NULL, NULL);
}
__EXCEPT_PAGE_FAULT
{
return ret;
}
-/* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
- * if it fails.
- */
-#define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
- do { \
- BYTE i; \
- \
- (word) = 0; \
- for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
- { \
- if (!isdigit(*(pbEncoded))) \
- { \
- SetLastError(CRYPT_E_ASN1_CORRUPT); \
- ret = FALSE; \
- } \
- else \
- { \
- (word) *= 10; \
- (word) += *(pbEncoded)++ - '0'; \
- } \
- } \
- } while (0)
+static BOOL CRYPT_AsnDecodePolicyQualifier(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ struct AsnDecodeSequenceItem items[] = {
+ { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_QUALIFIER_INFO,
+ pszPolicyQualifierId), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
+ FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId),
+ 0 },
+ { 0, offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier),
+ CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
+ offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier.pbData), 0 },
+ };
+ BOOL ret;
+ CERT_POLICY_QUALIFIER_INFO *qualifier = pvStructInfo;
-static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
- SYSTEMTIME *sysTime)
+ TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
+
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
+ pcbDecoded, qualifier ? qualifier->pszPolicyQualifierId : NULL);
+ return ret;
+}
+
+static BOOL CRYPT_AsnDecodePolicyQualifiers(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ BOOL ret;
+ struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
+ offsetof(CERT_POLICY_INFO, cPolicyQualifier),
+ offsetof(CERT_POLICY_INFO, rgPolicyQualifier),
+ FINALMEMBERSIZE(CERT_POLICY_INFO, cPolicyQualifier),
+ CRYPT_AsnDecodePolicyQualifier, sizeof(CERT_POLICY_QUALIFIER_INFO), TRUE,
+ offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId) };
+
+ TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
+
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
+ TRACE("Returning %d (%08x)\n", ret, GetLastError());
+ return ret;
+}
+
+static BOOL CRYPT_AsnDecodeCertPolicy(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
{
+ struct AsnDecodeSequenceItem items[] = {
+ { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_INFO, pszPolicyIdentifier),
+ CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
+ offsetof(CERT_POLICY_INFO, pszPolicyIdentifier), 0 },
+ { ASN_SEQUENCEOF, offsetof(CERT_POLICY_INFO, cPolicyQualifier),
+ CRYPT_AsnDecodePolicyQualifiers,
+ FINALMEMBERSIZE(CERT_POLICY_INFO, cPolicyQualifier), TRUE,
+ TRUE, offsetof(CERT_POLICY_INFO, rgPolicyQualifier), 0 },
+ };
+ CERT_POLICY_INFO *info = pvStructInfo;
BOOL ret;
+ TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
+
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
+ pcbDecoded, info ? info->pszPolicyIdentifier : NULL);
+ return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnDecodeCertPolicies(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+{
+ BOOL ret = FALSE;
+
+ TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+ pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
+
__TRY
{
- ret = TRUE;
- if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
- {
- WORD hours, minutes = 0;
- BYTE sign = *pbEncoded++;
+ struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
+ offsetof(CERT_POLICIES_INFO, cPolicyInfo),
+ offsetof(CERT_POLICIES_INFO, rgPolicyInfo),
+ sizeof(CERT_POLICIES_INFO),
+ CRYPT_AsnDecodeCertPolicy, sizeof(CERT_POLICY_INFO), TRUE,
+ offsetof(CERT_POLICY_INFO, pszPolicyIdentifier) };
- len--;
- CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
- if (ret && hours >= 24)
- {
- SetLastError(CRYPT_E_ASN1_CORRUPT);
- ret = FALSE;
- }
- else if (len >= 2)
- {
- CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
- if (ret && minutes >= 60)
- {
- SetLastError(CRYPT_E_ASN1_CORRUPT);
- ret = FALSE;
- }
- }
- if (ret)
- {
- if (sign == '+')
- {
- sysTime->wHour += hours;
- sysTime->wMinute += minutes;
- }
- else
- {
- if (hours > sysTime->wHour)
- {
- sysTime->wDay--;
- sysTime->wHour = 24 - (hours - sysTime->wHour);
- }
- else
- sysTime->wHour -= hours;
- if (minutes > sysTime->wMinute)
- {
- sysTime->wHour--;
- sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
- }
- else
- sysTime->wMinute -= minutes;
- }
- }
- }
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
}
__EXCEPT_PAGE_FAULT
{
SetLastError(STATUS_ACCESS_VIOLATION);
- ret = FALSE;
}
__ENDTRY
return ret;
}
-#define MIN_ENCODED_TIME_LENGTH 10
+static BOOL CRYPT_AsnDecodeCertPolicyMapping(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ struct AsnDecodeSequenceItem items[] = {
+ { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_MAPPING,
+ pszIssuerDomainPolicy), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
+ FALSE, TRUE, offsetof(CERT_POLICY_MAPPING, pszIssuerDomainPolicy), 0 },
+ { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_MAPPING,
+ pszSubjectDomainPolicy), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
+ FALSE, TRUE, offsetof(CERT_POLICY_MAPPING, pszSubjectDomainPolicy), 0 },
+ };
+ CERT_POLICY_MAPPING *mapping = pvStructInfo;
+ BOOL ret;
-static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
+ TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
+
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
+ pcbDecoded, mapping ? mapping->pszIssuerDomainPolicy : NULL);
+ return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnDecodeCertPolicyMappings(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
- BOOL ret;
+ BOOL ret = FALSE;
+
+ TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+ pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
- if (!pvStructInfo)
- {
- *pcbStructInfo = sizeof(FILETIME);
- return TRUE;
- }
__TRY
{
- ret = TRUE;
- if (pbEncoded[0] == ASN_UTCTIME)
- {
- if (cbEncoded <= 1)
+ struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
+ offsetof(CERT_POLICY_MAPPINGS_INFO, cPolicyMapping),
+ offsetof(CERT_POLICY_MAPPINGS_INFO, rgPolicyMapping),
+ sizeof(CERT_POLICY_MAPPING),
+ CRYPT_AsnDecodeCertPolicyMapping, sizeof(CERT_POLICY_MAPPING), TRUE,
+ offsetof(CERT_POLICY_MAPPING, pszIssuerDomainPolicy) };
+
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
+ }
+ __EXCEPT_PAGE_FAULT
+ {
+ SetLastError(STATUS_ACCESS_VIOLATION);
+ }
+ __ENDTRY
+ return ret;
+}
+
+static BOOL CRYPT_AsnDecodeRequireExplicit(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ BOOL ret;
+ DWORD skip, size = sizeof(skip);
+
+ if (!cbEncoded)
+ {
+ SetLastError(CRYPT_E_ASN1_EOD);
+ return FALSE;
+ }
+ if (pbEncoded[0] != (ASN_CONTEXT | 0))
+ {
+ SetLastError(CRYPT_E_ASN1_BADTAG);
+ return FALSE;
+ }
+ if ((ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
+ &skip, &size, pcbDecoded)))
+ {
+ DWORD bytesNeeded = MEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO,
+ fRequireExplicitPolicy, fInhibitPolicyMapping);
+
+ if (!pvStructInfo)
+ *pcbStructInfo = bytesNeeded;
+ else if (*pcbStructInfo < bytesNeeded)
+ {
+ *pcbStructInfo = bytesNeeded;
+ SetLastError(ERROR_MORE_DATA);
+ ret = FALSE;
+ }
+ else
+ {
+ CERT_POLICY_CONSTRAINTS_INFO *info =
+ (CERT_POLICY_CONSTRAINTS_INFO *)((BYTE *)pvStructInfo -
+ offsetof(CERT_POLICY_CONSTRAINTS_INFO, fRequireExplicitPolicy));
+
+ *pcbStructInfo = bytesNeeded;
+ /* The BOOL is implicit: if the integer is present, then it's
+ * TRUE.
+ */
+ info->fRequireExplicitPolicy = TRUE;
+ info->dwRequireExplicitPolicySkipCerts = skip;
+ }
+ }
+ return ret;
+}
+
+static BOOL CRYPT_AsnDecodeInhibitMapping(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ BOOL ret;
+ DWORD skip, size = sizeof(skip);
+
+ if (!cbEncoded)
+ {
+ SetLastError(CRYPT_E_ASN1_EOD);
+ return FALSE;
+ }
+ if (pbEncoded[0] != (ASN_CONTEXT | 1))
+ {
+ SetLastError(CRYPT_E_ASN1_BADTAG);
+ return FALSE;
+ }
+ if ((ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
+ &skip, &size, pcbDecoded)))
+ {
+ DWORD bytesNeeded = FINALMEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO,
+ fInhibitPolicyMapping);
+
+ if (!pvStructInfo)
+ *pcbStructInfo = bytesNeeded;
+ else if (*pcbStructInfo < bytesNeeded)
+ {
+ *pcbStructInfo = bytesNeeded;
+ SetLastError(ERROR_MORE_DATA);
+ ret = FALSE;
+ }
+ else
+ {
+ CERT_POLICY_CONSTRAINTS_INFO *info =
+ (CERT_POLICY_CONSTRAINTS_INFO *)((BYTE *)pvStructInfo -
+ offsetof(CERT_POLICY_CONSTRAINTS_INFO, fInhibitPolicyMapping));
+
+ *pcbStructInfo = bytesNeeded;
+ /* The BOOL is implicit: if the integer is present, then it's
+ * TRUE.
+ */
+ info->fInhibitPolicyMapping = TRUE;
+ info->dwInhibitPolicyMappingSkipCerts = skip;
+ }
+ }
+ return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnDecodeCertPolicyConstraints(
+ DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
+ void *pvStructInfo, DWORD *pcbStructInfo)
+{
+ BOOL ret = FALSE;
+
+ TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+ pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
+
+ __TRY
+ {
+ struct AsnDecodeSequenceItem items[] = {
+ { ASN_CONTEXT | 0,
+ offsetof(CERT_POLICY_CONSTRAINTS_INFO, fRequireExplicitPolicy),
+ CRYPT_AsnDecodeRequireExplicit,
+ MEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO, fRequireExplicitPolicy,
+ fInhibitPolicyMapping), TRUE, FALSE, 0, 0 },
+ { ASN_CONTEXT | 1,
+ offsetof(CERT_POLICY_CONSTRAINTS_INFO, fInhibitPolicyMapping),
+ CRYPT_AsnDecodeInhibitMapping,
+ FINALMEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO, fInhibitPolicyMapping),
+ TRUE, FALSE, 0, 0 },
+ };
+
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
+ pcbStructInfo, NULL, NULL);
+ }
+ __EXCEPT_PAGE_FAULT
+ {
+ SetLastError(STATUS_ACCESS_VIOLATION);
+ }
+ __ENDTRY
+ return ret;
+}
+
+#define RSA1_MAGIC 0x31415352
+
+struct DECODED_RSA_PUB_KEY
+{
+ DWORD pubexp;
+ CRYPT_INTEGER_BLOB modulus;
+};
+
+static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+{
+ BOOL ret;
+
+ __TRY
+ {
+ struct AsnDecodeSequenceItem items[] = {
+ { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
+ CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
+ FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
+ 0 },
+ { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
+ CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
+ };
+ struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
+ DWORD size = 0;
+
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
+ &size, NULL, NULL);
+ if (ret)
+ {
+ DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
+ decodedKey->modulus.cbData;
+
+ if (!pvStructInfo)
+ {
+ *pcbStructInfo = bytesNeeded;
+ ret = TRUE;
+ }
+ else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
+ pvStructInfo, pcbStructInfo, bytesNeeded)))
+ {
+ BLOBHEADER *hdr;
+ RSAPUBKEY *rsaPubKey;
+
+ if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
+ pvStructInfo = *(BYTE **)pvStructInfo;
+ hdr = pvStructInfo;
+ hdr->bType = PUBLICKEYBLOB;
+ hdr->bVersion = CUR_BLOB_VERSION;
+ hdr->reserved = 0;
+ hdr->aiKeyAlg = CALG_RSA_KEYX;
+ rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
+ sizeof(BLOBHEADER));
+ rsaPubKey->magic = RSA1_MAGIC;
+ rsaPubKey->pubexp = decodedKey->pubexp;
+ rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
+ memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
+ sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
+ decodedKey->modulus.cbData);
+ }
+ LocalFree(decodedKey);
+ }
+ }
+ __EXCEPT_PAGE_FAULT
+ {
+ SetLastError(STATUS_ACCESS_VIOLATION);
+ ret = FALSE;
+ }
+ __ENDTRY
+ return ret;
+}
+
+static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ BOOL ret;
+ DWORD bytesNeeded, dataLen;
+
+ TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo, pcbDecoded);
+
+ if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
+ {
+ BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
+
+ if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
+ bytesNeeded = sizeof(CRYPT_DATA_BLOB);
+ else
+ bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
+ if (pcbDecoded)
+ *pcbDecoded = 1 + lenBytes + dataLen;
+ if (!pvStructInfo)
+ *pcbStructInfo = bytesNeeded;
+ else if (*pcbStructInfo < bytesNeeded)
+ {
+ SetLastError(ERROR_MORE_DATA);
+ *pcbStructInfo = bytesNeeded;
+ ret = FALSE;
+ }
+ else
+ {
+ CRYPT_DATA_BLOB *blob;
+
+ *pcbStructInfo = bytesNeeded;
+ blob = pvStructInfo;
+ blob->cbData = dataLen;
+ if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
+ blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
+ else
+ {
+ assert(blob->pbData);
+ if (blob->cbData)
+ memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
+ blob->cbData);
+ }
+ }
+ }
+ return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+{
+ BOOL ret;
+
+ TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+ pDecodePara, pvStructInfo, *pcbStructInfo);
+
+ __TRY
+ {
+ DWORD bytesNeeded;
+
+ if (!cbEncoded)
+ {
+ SetLastError(CRYPT_E_ASN1_CORRUPT);
+ ret = FALSE;
+ }
+ else if (pbEncoded[0] != ASN_OCTETSTRING)
+ {
+ SetLastError(CRYPT_E_ASN1_BADTAG);
+ ret = FALSE;
+ }
+ else if ((ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
+ {
+ if (!pvStructInfo)
+ *pcbStructInfo = bytesNeeded;
+ else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
+ pvStructInfo, pcbStructInfo, bytesNeeded)))
+ {
+ CRYPT_DATA_BLOB *blob;
+
+ if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
+ pvStructInfo = *(BYTE **)pvStructInfo;
+ blob = pvStructInfo;
+ blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
+ ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
+ &bytesNeeded, NULL);
+ }
+ }
+ }
+ __EXCEPT_PAGE_FAULT
+ {
+ SetLastError(STATUS_ACCESS_VIOLATION);
+ ret = FALSE;
+ }
+ __ENDTRY
+ return ret;
+}
+
+static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
+{
+ BOOL ret;
+ DWORD bytesNeeded, dataLen;
+ BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
+
+ TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo, pcbDecoded);
+
+ if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
+ {
+ 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;
+ SetLastError(ERROR_MORE_DATA);
+ ret = FALSE;
+ }
+ else
+ {
+ CRYPT_BIT_BLOB *blob;
+
+ *pcbStructInfo = bytesNeeded;
+ blob = pvStructInfo;
+ blob->cbData = dataLen - 1;
+ blob->cUnusedBits = *(pbEncoded + 1 + lenBytes);
+ if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
+ {
+ blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes;
+ }
+ else
+ {
+ assert(blob->pbData);
+ if (blob->cbData)
+ {
+ BYTE mask = 0xff << blob->cUnusedBits;
+
+ memcpy(blob->pbData, pbEncoded + 2 + lenBytes,
+ blob->cbData);
+ blob->pbData[blob->cbData - 1] &= mask;
+ }
+ }
+ }
+ }
+ return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+{
+ BOOL ret;
+
+ TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
+ pDecodePara, pvStructInfo, pcbStructInfo);
+
+ __TRY
+ {
+ DWORD bytesNeeded;
+
+ 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)))
+ {
+ if (!pvStructInfo)
+ *pcbStructInfo = bytesNeeded;
+ else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
+ pvStructInfo, pcbStructInfo, bytesNeeded)))
+ {
+ CRYPT_BIT_BLOB *blob;
+
+ if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
+ pvStructInfo = *(BYTE **)pvStructInfo;
+ blob = pvStructInfo;
+ blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
+ ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
+ &bytesNeeded, NULL);
+ }
+ }
+ }
+ __EXCEPT_PAGE_FAULT
+ {
+ SetLastError(STATUS_ACCESS_VIOLATION);
+ ret = FALSE;
+ }
+ __ENDTRY
+ TRACE("returning %d (%08x)\n", ret, GetLastError());
+ return ret;
+}
+
+/* Ignores tag. Only allows integers 4 bytes or smaller in size. */
+static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
+{
+ BOOL ret;
+ DWORD dataLen;
+
+ if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
+ {
+ BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
+
+ if (pcbDecoded)
+ *pcbDecoded = 1 + lenBytes + dataLen;
+ if (dataLen > sizeof(int))
+ {
+ SetLastError(CRYPT_E_ASN1_LARGE);
+ ret = FALSE;
+ }
+ else if (!pvStructInfo)
+ *pcbStructInfo = sizeof(int);
+ else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int))))
+ {
+ int val, i;
+
+ if (dataLen && pbEncoded[1 + lenBytes] & 0x80)
+ {
+ /* initialize to a negative value to sign-extend */
+ val = -1;
+ }
+ else
+ val = 0;
+ for (i = 0; i < dataLen; i++)
+ {
+ val <<= 8;
+ val |= pbEncoded[1 + lenBytes + i];
+ }
+ memcpy(pvStructInfo, &val, sizeof(int));
+ }
+ }
+ return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+{
+ BOOL ret;
+
+ __TRY
+ {
+ DWORD bytesNeeded;
+
+ if (!cbEncoded)
+ {
+ SetLastError(CRYPT_E_ASN1_EOD);
+ ret = FALSE;
+ }
+ else if (pbEncoded[0] != ASN_INTEGER)
+ {
+ SetLastError(CRYPT_E_ASN1_BADTAG);
+ ret = FALSE;
+ }
+ else
+ ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
+ if (ret)
+ {
+ if (!pvStructInfo)
+ *pcbStructInfo = bytesNeeded;
+ else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
+ pvStructInfo, pcbStructInfo, bytesNeeded)))
+ {
+ if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
+ pvStructInfo = *(BYTE **)pvStructInfo;
+ ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
+ &bytesNeeded, NULL);
+ }
+ }
+ }
+ __EXCEPT_PAGE_FAULT
+ {
+ SetLastError(STATUS_ACCESS_VIOLATION);
+ ret = FALSE;
+ }
+ __ENDTRY
+ return ret;
+}
+
+static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ BOOL ret;
+ DWORD bytesNeeded, dataLen;
+
+ if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
+ {
+ BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
+
+ bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_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_INTEGER_BLOB *blob = pvStructInfo;
+
+ *pcbStructInfo = bytesNeeded;
+ blob->cbData = dataLen;
+ assert(blob->pbData);
+ if (blob->cbData)
+ {
+ DWORD i;
+
+ for (i = 0; i < blob->cbData; i++)
+ {
+ blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
+ dataLen - i - 1);
+ }
+ }
+ }
+ }
+ return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+{
+ BOOL ret;
+
+ __TRY
+ {
+ DWORD bytesNeeded;
+
+ if (pbEncoded[0] != ASN_INTEGER)
+ {
+ SetLastError(CRYPT_E_ASN1_BADTAG);
+ ret = FALSE;
+ }
+ else
+ ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
+ if (ret)
+ {
+ if (!pvStructInfo)
+ *pcbStructInfo = bytesNeeded;
+ else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
+ pvStructInfo, pcbStructInfo, bytesNeeded)))
+ {
+ CRYPT_INTEGER_BLOB *blob;
+
+ if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
+ pvStructInfo = *(BYTE **)pvStructInfo;
+ blob = pvStructInfo;
+ blob->pbData = (BYTE *)pvStructInfo +
+ sizeof(CRYPT_INTEGER_BLOB);
+ ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
+ &bytesNeeded, NULL);
+ }
+ }
+ }
+ __EXCEPT_PAGE_FAULT
+ {
+ SetLastError(STATUS_ACCESS_VIOLATION);
+ ret = FALSE;
+ }
+ __ENDTRY
+ return ret;
+}
+
+static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ BOOL ret;
+
+ if (pbEncoded[0] == ASN_INTEGER)
+ {
+ DWORD bytesNeeded, dataLen;
+
+ if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
+ {
+ BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
+
+ if (pcbDecoded)
+ *pcbDecoded = 1 + lenBytes + dataLen;
+ bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
+ if (!pvStructInfo)
+ *pcbStructInfo = bytesNeeded;
+ else if (*pcbStructInfo < bytesNeeded)
+ {
+ *pcbStructInfo = bytesNeeded;
+ SetLastError(ERROR_MORE_DATA);
+ ret = FALSE;
+ }
+ else
+ {
+ CRYPT_INTEGER_BLOB *blob = pvStructInfo;
+
+ *pcbStructInfo = bytesNeeded;
+ blob->cbData = dataLen;
+ assert(blob->pbData);
+ /* remove leading zero byte if it exists */
+ if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
+ {
+ blob->cbData--;
+ blob->pbData++;
+ }
+ if (blob->cbData)
+ {
+ DWORD i;
+
+ for (i = 0; i < blob->cbData; i++)
+ {
+ blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
+ dataLen - i - 1);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ SetLastError(CRYPT_E_ASN1_BADTAG);
+ ret = FALSE;
+ }
+ return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+{
+ BOOL ret;
+
+ __TRY
+ {
+ DWORD bytesNeeded;
+
+ if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
+ {
+ if (!pvStructInfo)
+ *pcbStructInfo = bytesNeeded;
+ else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
+ pvStructInfo, pcbStructInfo, bytesNeeded)))
+ {
+ CRYPT_INTEGER_BLOB *blob;
+
+ if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
+ pvStructInfo = *(BYTE **)pvStructInfo;
+ blob = pvStructInfo;
+ blob->pbData = (BYTE *)pvStructInfo +
+ sizeof(CRYPT_INTEGER_BLOB);
+ ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded,
+ cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
+ &bytesNeeded, NULL);
+ }
+ }
+ }
+ __EXCEPT_PAGE_FAULT
+ {
+ SetLastError(STATUS_ACCESS_VIOLATION);
+ ret = FALSE;
+ }
+ __ENDTRY
+ return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+{
+ BOOL ret;
+
+ if (!pvStructInfo)
+ {
+ *pcbStructInfo = sizeof(int);
+ return TRUE;
+ }
+ __TRY
+ {
+ if (pbEncoded[0] == ASN_ENUMERATED)
+ {
+ unsigned int val = 0, i;
+
+ if (cbEncoded <= 1)
+ {
+ SetLastError(CRYPT_E_ASN1_EOD);
+ ret = FALSE;
+ }
+ else if (pbEncoded[1] == 0)
+ {
+ SetLastError(CRYPT_E_ASN1_CORRUPT);
+ ret = FALSE;
+ }
+ else
+ {
+ /* A little strange looking, but we have to accept a sign byte:
+ * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
+ * assuming a small length is okay here, it has to be in short
+ * form.
+ */
+ if (pbEncoded[1] > sizeof(unsigned int) + 1)
+ {
+ SetLastError(CRYPT_E_ASN1_LARGE);
+ return FALSE;
+ }
+ for (i = 0; i < pbEncoded[1]; i++)
+ {
+ val <<= 8;
+ val |= pbEncoded[2 + i];
+ }
+ if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
+ pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
+ {
+ if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
+ pvStructInfo = *(BYTE **)pvStructInfo;
+ memcpy(pvStructInfo, &val, sizeof(unsigned int));
+ }
+ }
+ }
+ else
+ {
+ SetLastError(CRYPT_E_ASN1_BADTAG);
+ ret = FALSE;
+ }
+ }
+ __EXCEPT_PAGE_FAULT
+ {
+ SetLastError(STATUS_ACCESS_VIOLATION);
+ ret = FALSE;
+ }
+ __ENDTRY
+ return ret;
+}
+
+/* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
+ * if it fails.
+ */
+#define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
+ do { \
+ BYTE i; \
+ \
+ (word) = 0; \
+ for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
+ { \
+ if (!isdigit(*(pbEncoded))) \
+ { \
+ SetLastError(CRYPT_E_ASN1_CORRUPT); \
+ ret = FALSE; \
+ } \
+ else \
+ { \
+ (word) *= 10; \
+ (word) += *(pbEncoded)++ - '0'; \
+ } \
+ } \
+ } while (0)
+
+static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
+ SYSTEMTIME *sysTime)
+{
+ BOOL ret = TRUE;
+
+ if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
+ {
+ WORD hours, minutes = 0;
+ BYTE sign = *pbEncoded++;
+
+ len--;
+ CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
+ if (ret && hours >= 24)
+ {
+ SetLastError(CRYPT_E_ASN1_CORRUPT);
+ ret = FALSE;
+ }
+ else if (len >= 2)
+ {
+ CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
+ if (ret && minutes >= 60)
+ {
+ SetLastError(CRYPT_E_ASN1_CORRUPT);
+ ret = FALSE;
+ }
+ }
+ if (ret)
+ {
+ if (sign == '+')
+ {
+ sysTime->wHour += hours;
+ sysTime->wMinute += minutes;
+ }
+ else
+ {
+ if (hours > sysTime->wHour)
+ {
+ sysTime->wDay--;
+ sysTime->wHour = 24 - (hours - sysTime->wHour);
+ }
+ else
+ sysTime->wHour -= hours;
+ if (minutes > sysTime->wMinute)
+ {
+ sysTime->wHour--;
+ sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
+ }
+ else
+ sysTime->wMinute -= minutes;
+ }
+ }
+ }
+ return ret;
+}
+
+#define MIN_ENCODED_TIME_LENGTH 10
+
+static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ BOOL ret = FALSE;
+
+ if (pbEncoded[0] == ASN_UTCTIME)
+ {
+ if (cbEncoded <= 1)
+ SetLastError(CRYPT_E_ASN1_EOD);
+ else if (pbEncoded[1] > 0x7f)
+ {
+ /* long-form date strings really can't be valid */
+ SetLastError(CRYPT_E_ASN1_CORRUPT);
+ }
+ else
+ {
+ SYSTEMTIME sysTime = { 0 };
+ BYTE len = pbEncoded[1];
+
+ if (len < MIN_ENCODED_TIME_LENGTH)
+ SetLastError(CRYPT_E_ASN1_CORRUPT);
+ else
+ {
+ ret = TRUE;
+ if (pcbDecoded)
+ *pcbDecoded = 2 + len;
+ pbEncoded += 2;
+ CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
+ if (sysTime.wYear >= 50)
+ sysTime.wYear += 1900;
+ else
+ sysTime.wYear += 2000;
+ CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
+ CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
+ CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
+ CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
+ if (ret && len > 0)
+ {
+ if (len >= 2 && isdigit(*pbEncoded) &&
+ isdigit(*(pbEncoded + 1)))
+ CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
+ sysTime.wSecond);
+ else if (isdigit(*pbEncoded))
+ CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
+ sysTime.wSecond);
+ if (ret)
+ ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
+ &sysTime);
+ }
+ if (ret)
+ {
+ if (!pvStructInfo)
+ *pcbStructInfo = sizeof(FILETIME);
+ else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
+ sizeof(FILETIME))))
+ ret = SystemTimeToFileTime(&sysTime, pvStructInfo);
+ }
+ }
+ }
+ }
+ else
+ SetLastError(CRYPT_E_ASN1_BADTAG);
+ return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+{
+ BOOL ret = FALSE;
+
+ __TRY
+ {
+ DWORD bytesNeeded;
+
+ ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
+ if (ret)
+ {
+ if (!pvStructInfo)
+ *pcbStructInfo = bytesNeeded;
+ else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
+ pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
+ {
+ if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
+ pvStructInfo = *(BYTE **)pvStructInfo;
+ ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
+ &bytesNeeded, NULL);
+ }
+ }
+ }
+ __EXCEPT_PAGE_FAULT
+ {
+ SetLastError(STATUS_ACCESS_VIOLATION);
+ }
+ __ENDTRY
+ return ret;
+}
+
+static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ BOOL ret = FALSE;
+
+ if (pbEncoded[0] == ASN_GENERALTIME)
+ {
+ if (cbEncoded <= 1)
+ SetLastError(CRYPT_E_ASN1_EOD);
+ else if (pbEncoded[1] > 0x7f)
+ {
+ /* long-form date strings really can't be valid */
+ SetLastError(CRYPT_E_ASN1_CORRUPT);
+ }
+ else
+ {
+ BYTE len = pbEncoded[1];
+
+ if (len < MIN_ENCODED_TIME_LENGTH)
+ SetLastError(CRYPT_E_ASN1_CORRUPT);
+ else
+ {
+ SYSTEMTIME sysTime = { 0 };
+
+ ret = TRUE;
+ if (pcbDecoded)
+ *pcbDecoded = 2 + len;
+ pbEncoded += 2;
+ CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
+ CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
+ CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
+ CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
+ if (ret && len > 0)
+ {
+ CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
+ sysTime.wMinute);
+ if (ret && len > 0)
+ CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
+ sysTime.wSecond);
+ if (ret && len > 0 && (*pbEncoded == '.' ||
+ *pbEncoded == ','))
+ {
+ BYTE digits;
+
+ pbEncoded++;
+ len--;
+ /* workaround macro weirdness */
+ digits = min(len, 3);
+ CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
+ sysTime.wMilliseconds);
+ }
+ if (ret)
+ ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
+ &sysTime);
+ }
+ if (ret)
+ {
+ if (!pvStructInfo)
+ *pcbStructInfo = sizeof(FILETIME);
+ else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
+ sizeof(FILETIME))))
+ ret = SystemTimeToFileTime(&sysTime, pvStructInfo);
+ }
+ }
+ }
+ }
+ else
+ SetLastError(CRYPT_E_ASN1_BADTAG);
+ return ret;
+}
+
+static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ BOOL ret;
+ InternalDecodeFunc decode = NULL;
+
+ if (pbEncoded[0] == ASN_UTCTIME)
+ decode = CRYPT_AsnDecodeUtcTimeInternal;
+ else if (pbEncoded[0] == ASN_GENERALTIME)
+ decode = CRYPT_AsnDecodeGeneralizedTime;
+ if (decode)
+ ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
+ pcbStructInfo, pcbDecoded);
+ else
+ {
+ SetLastError(CRYPT_E_ASN1_BADTAG);
+ ret = FALSE;
+ }
+ return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+{
+ BOOL ret;
+
+ __TRY
+ {
+ DWORD bytesNeeded;
+
+ ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
+ if (ret)
+ {
+ if (!pvStructInfo)
+ *pcbStructInfo = bytesNeeded;
+ else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
+ pvStructInfo, pcbStructInfo, bytesNeeded)))
+ {
+ if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
+ pvStructInfo = *(BYTE **)pvStructInfo;
+ ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
+ &bytesNeeded, NULL);
+ }
+ }
+ }
+ __EXCEPT_PAGE_FAULT
+ {
+ SetLastError(STATUS_ACCESS_VIOLATION);
+ ret = FALSE;
+ }
+ __ENDTRY
+ return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+{
+ BOOL ret = TRUE;
+
+ __TRY
+ {
+ if (pbEncoded[0] == ASN_SEQUENCEOF)
+ {
+ DWORD bytesNeeded, dataLen, remainingLen, cValue;
+
+ if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
+ {
+ BYTE lenBytes;
+ const BYTE *ptr;
+
+ lenBytes = GET_LEN_BYTES(pbEncoded[1]);
+ bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
+ cValue = 0;
+ ptr = pbEncoded + 1 + lenBytes;
+ remainingLen = dataLen;
+ while (ret && remainingLen)
+ {
+ DWORD nextLen;
+
+ ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
+ if (ret)
+ {
+ DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
+
+ remainingLen -= 1 + nextLenBytes + nextLen;
+ ptr += 1 + nextLenBytes + nextLen;
+ bytesNeeded += sizeof(CRYPT_DER_BLOB);
+ if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
+ bytesNeeded += 1 + nextLenBytes + nextLen;
+ cValue++;
+ }
+ }
+ if (ret)
+ {
+ CRYPT_SEQUENCE_OF_ANY *seq;
+ BYTE *nextPtr;
+ DWORD i;
+
+ if (!pvStructInfo)
+ *pcbStructInfo = bytesNeeded;
+ else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
+ pvStructInfo, pcbStructInfo, bytesNeeded)))
+ {
+ if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
+ pvStructInfo = *(BYTE **)pvStructInfo;
+ seq = pvStructInfo;
+ seq->cValue = cValue;
+ seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
+ sizeof(*seq));
+ nextPtr = (BYTE *)seq->rgValue +
+ cValue * sizeof(CRYPT_DER_BLOB);
+ ptr = pbEncoded + 1 + lenBytes;
+ remainingLen = dataLen;
+ i = 0;
+ while (ret && remainingLen)
+ {
+ DWORD nextLen;
+
+ ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
+ if (ret)
+ {
+ DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
+
+ seq->rgValue[i].cbData = 1 + nextLenBytes +
+ nextLen;
+ if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
+ seq->rgValue[i].pbData = (BYTE *)ptr;
+ else
+ {
+ seq->rgValue[i].pbData = nextPtr;
+ memcpy(nextPtr, ptr, 1 + nextLenBytes +
+ nextLen);
+ nextPtr += 1 + nextLenBytes + nextLen;
+ }
+ remainingLen -= 1 + nextLenBytes + nextLen;
+ ptr += 1 + nextLenBytes + nextLen;
+ i++;
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ SetLastError(CRYPT_E_ASN1_BADTAG);
+ ret = FALSE;
+ }
+ }
+ __EXCEPT_PAGE_FAULT
+ {
+ SetLastError(STATUS_ACCESS_VIOLATION);
+ ret = FALSE;
+ }
+ __ENDTRY
+ return ret;
+}
+
+static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ BOOL ret;
+
+ if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
+ {
+ DWORD bytesNeeded, dataLen;
+
+ if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
+ {
+ struct AsnArrayDescriptor arrayDesc = {
+ ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
+ offsetof(CRL_DIST_POINT_NAME, u.FullName.cAltEntry),
+ offsetof(CRL_DIST_POINT_NAME, u.FullName.rgAltEntry),
+ FINALMEMBERSIZE(CRL_DIST_POINT_NAME, u),
+ CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
+ offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
+ BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
+ DWORD nameLen;
+
+ if (dataLen)
{
- SetLastError(CRYPT_E_ASN1_EOD);
- ret = FALSE;
+ ret = CRYPT_AsnDecodeArray(&arrayDesc,
+ pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
+ dwFlags, NULL, NULL, &nameLen, NULL);
+ bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen -
+ FINALMEMBERSIZE(CRL_DIST_POINT_NAME, u);
}
- else if (pbEncoded[1] > 0x7f)
+ else
+ bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
+ if (pcbDecoded)
+ *pcbDecoded = 1 + lenBytes + dataLen;
+ if (!pvStructInfo)
+ *pcbStructInfo = bytesNeeded;
+ else if (*pcbStructInfo < bytesNeeded)
{
- /* long-form date strings really can't be valid */
- SetLastError(CRYPT_E_ASN1_CORRUPT);
+ *pcbStructInfo = bytesNeeded;
+ SetLastError(ERROR_MORE_DATA);
ret = FALSE;
}
else
{
- SYSTEMTIME sysTime = { 0 };
- BYTE len = pbEncoded[1];
+ CRL_DIST_POINT_NAME *name = pvStructInfo;
- if (len < MIN_ENCODED_TIME_LENGTH)
+ *pcbStructInfo = bytesNeeded;
+ if (dataLen)
{
- SetLastError(CRYPT_E_ASN1_CORRUPT);
- ret = FALSE;
+ name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
+ ret = CRYPT_AsnDecodeArray(&arrayDesc,
+ pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
+ dwFlags, NULL, &name->u.FullName.cAltEntry, &nameLen,
+ NULL);
}
else
- {
- pbEncoded += 2;
- CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
- if (sysTime.wYear >= 50)
- sysTime.wYear += 1900;
- else
- sysTime.wYear += 2000;
- CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
- CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
- CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
- CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
- if (ret && len > 0)
- {
- if (len >= 2 && isdigit(*pbEncoded) &&
- isdigit(*(pbEncoded + 1)))
- CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
- sysTime.wSecond);
- else if (isdigit(*pbEncoded))
- CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
- sysTime.wSecond);
- if (ret)
- ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
- &sysTime);
- }
- if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
- pDecodePara, pvStructInfo, pcbStructInfo,
- sizeof(FILETIME))))
- {
- if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
- pvStructInfo = *(BYTE **)pvStructInfo;
- ret = SystemTimeToFileTime(&sysTime,
- (FILETIME *)pvStructInfo);
- }
- }
+ name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
}
}
+ }
+ else
+ {
+ SetLastError(CRYPT_E_ASN1_BADTAG);
+ ret = FALSE;
+ }
+ return ret;
+}
+
+static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
+{
+ struct AsnDecodeSequenceItem items[] = {
+ { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
+ DistPointName), CRYPT_AsnDecodeDistPointName,
+ sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
+ DistPointName.u.FullName.rgAltEntry), 0 },
+ { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
+ CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
+ offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
+ { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
+ CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
+ offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
+ };
+ CRL_DIST_POINT *point = pvStructInfo;
+ BOOL ret;
+
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
+ pcbDecoded, point ? point->DistPointName.u.FullName.rgAltEntry : NULL);
+ return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+{
+ BOOL ret;
+
+ TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+ pDecodePara, pvStructInfo, *pcbStructInfo);
+
+ __TRY
+ {
+ struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
+ offsetof(CRL_DIST_POINTS_INFO, cDistPoint),
+ offsetof(CRL_DIST_POINTS_INFO, rgDistPoint),
+ sizeof(CRL_DIST_POINTS_INFO),
+ CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
+ offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
+
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
+ }
+ __EXCEPT_PAGE_FAULT
+ {
+ SetLastError(STATUS_ACCESS_VIOLATION);
+ ret = FALSE;
+ }
+ __ENDTRY
+ return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+{
+ BOOL ret;
+
+ TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+ pDecodePara, pvStructInfo, *pcbStructInfo);
+
+ __TRY
+ {
+ struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
+ offsetof(CERT_ENHKEY_USAGE, cUsageIdentifier),
+ offsetof(CERT_ENHKEY_USAGE, rgpszUsageIdentifier),
+ sizeof(CERT_ENHKEY_USAGE),
+ CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
+
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
+ }
+ __EXCEPT_PAGE_FAULT
+ {
+ SetLastError(STATUS_ACCESS_VIOLATION);
+ ret = FALSE;
+ }
+ __ENDTRY
+ return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+{
+ BOOL ret;
+
+ TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+ pDecodePara, pvStructInfo, *pcbStructInfo);
+
+ __TRY
+ {
+ struct AsnDecodeSequenceItem items[] = {
+ { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
+ DistPointName), CRYPT_AsnDecodeDistPointName,
+ sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
+ offsetof(CRL_ISSUING_DIST_POINT,
+ DistPointName.u.FullName.rgAltEntry), 0 },
+ { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
+ fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
+ FALSE, 0 },
+ { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
+ fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
+ FALSE, 0 },
+ { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
+ OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
+ sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
+ OnlySomeReasonFlags.pbData), 0 },
+ { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
+ fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
+ };
+
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
+ pcbStructInfo, NULL, NULL);
+ }
+ __EXCEPT_PAGE_FAULT
+ {
+ SetLastError(STATUS_ACCESS_VIOLATION);
+ ret = FALSE;
+ }
+ __ENDTRY
+ return ret;
+}
+
+static BOOL CRYPT_AsnDecodeMaximum(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ BOOL ret;
+ DWORD max, size = sizeof(max);
+
+ TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo, pcbDecoded);
+
+ if (!cbEncoded)
+ {
+ SetLastError(CRYPT_E_ASN1_EOD);
+ return FALSE;
+ }
+ if (pbEncoded[0] != (ASN_CONTEXT | 1))
+ {
+ SetLastError(CRYPT_E_ASN1_BADTAG);
+ return FALSE;
+ }
+ if ((ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
+ &max, &size, pcbDecoded)))
+ {
+ DWORD bytesNeeded = FINALMEMBERSIZE(CERT_GENERAL_SUBTREE, fMaximum);
+
+ if (!pvStructInfo)
+ *pcbStructInfo = bytesNeeded;
+ else if (*pcbStructInfo < bytesNeeded)
+ {
+ *pcbStructInfo = bytesNeeded;
+ SetLastError(ERROR_MORE_DATA);
+ ret = FALSE;
+ }
else
{
- SetLastError(CRYPT_E_ASN1_BADTAG);
- ret = FALSE;
+ CERT_GENERAL_SUBTREE *subtree = (CERT_GENERAL_SUBTREE *)
+ ((BYTE *)pvStructInfo - offsetof(CERT_GENERAL_SUBTREE, fMaximum));
+
+ *pcbStructInfo = bytesNeeded;
+ /* The BOOL is implicit: if the integer is present, then it's
+ * TRUE.
+ */
+ subtree->fMaximum = TRUE;
+ subtree->dwMaximum = max;
}
}
- __EXCEPT_PAGE_FAULT
+ TRACE("returning %d\n", ret);
+ return ret;
+}
+
+static BOOL CRYPT_AsnDecodeSubtree(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ BOOL ret;
+ struct AsnDecodeSequenceItem items[] = {
+ { 0, offsetof(CERT_GENERAL_SUBTREE, Base),
+ CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE, TRUE,
+ offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL), 0 },
+ { ASN_CONTEXT | 0, offsetof(CERT_GENERAL_SUBTREE, dwMinimum),
+ CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
+ { ASN_CONTEXT | 1, offsetof(CERT_GENERAL_SUBTREE, fMaximum),
+ CRYPT_AsnDecodeMaximum, FINALMEMBERSIZE(CERT_GENERAL_SUBTREE, fMaximum),
+ TRUE, FALSE, 0, 0 },
+ };
+ CERT_GENERAL_SUBTREE *subtree = pvStructInfo;
+
+ TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo, pcbDecoded);
+
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
+ pcbDecoded, subtree ? subtree->Base.u.pwszURL : NULL);
+ if (pcbDecoded)
{
- SetLastError(STATUS_ACCESS_VIOLATION);
- ret = FALSE;
+ TRACE("%d\n", *pcbDecoded);
+ if (*pcbDecoded < cbEncoded)
+ TRACE("%02x %02x\n", *(pbEncoded + *pcbDecoded),
+ *(pbEncoded + *pcbDecoded + 1));
}
- __ENDTRY
+ TRACE("returning %d\n", ret);
+ return ret;
+}
+
+static BOOL CRYPT_AsnDecodePermittedSubtree(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ BOOL ret = TRUE;
+ struct AsnArrayDescriptor arrayDesc = { 0,
+ offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
+ offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree),
+ MEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree,
+ cExcludedSubtree),
+ CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
+ offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
+
+ TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo, pcbDecoded);
+
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
+ return ret;
+}
+
+static BOOL CRYPT_AsnDecodeExcludedSubtree(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ BOOL ret = TRUE;
+ struct AsnArrayDescriptor arrayDesc = { 0,
+ offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
+ offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree),
+ FINALMEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
+ CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
+ offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
+
+ TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo, pcbDecoded);
+
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType,
+static BOOL WINAPI CRYPT_AsnDecodeNameConstraints(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
- BOOL ret;
+ BOOL ret = FALSE;
+
+ TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+ pDecodePara, pvStructInfo, *pcbStructInfo);
- if (!pvStructInfo)
- {
- *pcbStructInfo = sizeof(FILETIME);
- return TRUE;
- }
__TRY
{
- ret = TRUE;
- if (pbEncoded[0] == ASN_GENERALTIME)
- {
- if (cbEncoded <= 1)
- {
- SetLastError(CRYPT_E_ASN1_EOD);
- ret = FALSE;
- }
- else if (pbEncoded[1] > 0x7f)
- {
- /* long-form date strings really can't be valid */
- SetLastError(CRYPT_E_ASN1_CORRUPT);
- ret = FALSE;
- }
- else
- {
- BYTE len = pbEncoded[1];
-
- if (len < MIN_ENCODED_TIME_LENGTH)
- {
- SetLastError(CRYPT_E_ASN1_CORRUPT);
- ret = FALSE;
- }
- else
- {
- SYSTEMTIME sysTime = { 0 };
+ struct AsnDecodeSequenceItem items[] = {
+ { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
+ offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
+ CRYPT_AsnDecodePermittedSubtree,
+ MEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree,
+ cExcludedSubtree), TRUE, TRUE,
+ offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree), 0 },
+ { ASN_CONTEXT | ASN_CONSTRUCTOR | 1,
+ offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
+ CRYPT_AsnDecodeExcludedSubtree,
+ FINALMEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
+ TRUE, TRUE,
+ offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree), 0 },
+ };
- pbEncoded += 2;
- CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
- CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
- CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
- CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
- if (ret && len > 0)
- {
- CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
- sysTime.wMinute);
- if (ret && len > 0)
- CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
- sysTime.wSecond);
- if (ret && len > 0 && (*pbEncoded == '.' ||
- *pbEncoded == ','))
- {
- BYTE digits;
-
- pbEncoded++;
- len--;
- /* workaround macro weirdness */
- digits = min(len, 3);
- CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
- sysTime.wMilliseconds);
- }
- if (ret)
- ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
- &sysTime);
- }
- if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
- pDecodePara, pvStructInfo, pcbStructInfo,
- sizeof(FILETIME))))
- {
- if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
- pvStructInfo = *(BYTE **)pvStructInfo;
- ret = SystemTimeToFileTime(&sysTime,
- (FILETIME *)pvStructInfo);
- }
- }
- }
- }
- else
- {
- SetLastError(CRYPT_E_ASN1_BADTAG);
- ret = FALSE;
- }
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
+ pcbStructInfo, NULL, NULL);
}
__EXCEPT_PAGE_FAULT
{
SetLastError(STATUS_ACCESS_VIOLATION);
- ret = FALSE;
}
__ENDTRY
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
{
BOOL ret;
+ struct AsnDecodeSequenceItem items[] = {
+ { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
+ sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
+ Issuer.pbData) },
+ { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
+ CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
+ TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
+ };
+ CERT_ISSUER_SERIAL_NUMBER *issuerSerial = pvStructInfo;
- __TRY
- {
- if (pbEncoded[0] == ASN_UTCTIME)
- ret = CRYPT_AsnDecodeUtcTime(dwCertEncodingType, lpszStructType,
- pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
- pcbStructInfo);
- else if (pbEncoded[0] == ASN_GENERALTIME)
- ret = CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType,
- lpszStructType, pbEncoded, cbEncoded, dwFlags, pDecodePara,
- pvStructInfo, pcbStructInfo);
- else
- {
- SetLastError(CRYPT_E_ASN1_BADTAG);
- ret = FALSE;
- }
- }
- __EXCEPT_PAGE_FAULT
+ TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo, pcbDecoded);
+
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
+ pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL);
+ if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
{
- SetLastError(STATUS_ACCESS_VIOLATION);
+ SetLastError(CRYPT_E_ASN1_CORRUPT);
ret = FALSE;
}
- __ENDTRY
+ TRACE("returning %d\n", ret);
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
+static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ CMSG_SIGNER_INFO *info = pvStructInfo;
+ struct AsnDecodeSequenceItem items[] = {
+ { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
+ CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
+ { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
+ CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
+ FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
+ { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
+ CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
+ FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
+ { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
+ offsetof(CMSG_SIGNER_INFO, AuthAttrs),
+ CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
+ TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
+ { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
+ CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
+ FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
+ HashEncryptionAlgorithm.pszObjId), 0 },
+ { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
+ CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
+ FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
+ { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
+ offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
+ CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
+ TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
+ };
+ BOOL ret;
+
+ TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo);
+
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
+ pcbDecoded, info ? info->Issuer.pbData : NULL);
+ return ret;
+}
+
+static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
- BOOL ret = TRUE;
+ BOOL ret = FALSE;
+
+ TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+ pDecodePara, pvStructInfo, *pcbStructInfo);
__TRY
{
- if (pbEncoded[0] == ASN_SEQUENCEOF)
+ ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
+ if (ret && pvStructInfo)
{
- DWORD bytesNeeded, dataLen, remainingLen, cValue;
-
- if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
+ ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
+ pcbStructInfo, *pcbStructInfo);
+ if (ret)
{
- BYTE lenBytes;
- const BYTE *ptr;
-
- lenBytes = GET_LEN_BYTES(pbEncoded[1]);
- bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
- cValue = 0;
- ptr = pbEncoded + 1 + lenBytes;
- remainingLen = dataLen;
- while (ret && remainingLen)
- {
- DWORD nextLen;
-
- ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
- if (ret)
- {
- DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
-
- remainingLen -= 1 + nextLenBytes + nextLen;
- ptr += 1 + nextLenBytes + nextLen;
- bytesNeeded += sizeof(CRYPT_DER_BLOB);
- if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
- bytesNeeded += 1 + nextLenBytes + nextLen;
- cValue++;
- }
- }
- if (ret)
- {
- CRYPT_SEQUENCE_OF_ANY *seq;
- BYTE *nextPtr;
- DWORD i;
-
- if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
- pvStructInfo, pcbStructInfo, bytesNeeded)))
- {
- if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
- pvStructInfo = *(BYTE **)pvStructInfo;
- seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
- seq->cValue = cValue;
- seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
- sizeof(*seq));
- nextPtr = (BYTE *)seq->rgValue +
- cValue * sizeof(CRYPT_DER_BLOB);
- ptr = pbEncoded + 1 + lenBytes;
- remainingLen = dataLen;
- i = 0;
- while (ret && remainingLen)
- {
- DWORD nextLen;
-
- ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
- if (ret)
- {
- DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
+ CMSG_SIGNER_INFO *info;
- seq->rgValue[i].cbData = 1 + nextLenBytes +
- nextLen;
- if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
- seq->rgValue[i].pbData = (BYTE *)ptr;
- else
- {
- seq->rgValue[i].pbData = nextPtr;
- memcpy(nextPtr, ptr, 1 + nextLenBytes +
- nextLen);
- nextPtr += 1 + nextLenBytes + nextLen;
- }
- remainingLen -= 1 + nextLenBytes + nextLen;
- ptr += 1 + nextLenBytes + nextLen;
- i++;
- }
- }
- }
- }
+ if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
+ pvStructInfo = *(BYTE **)pvStructInfo;
+ info = pvStructInfo;
+ info->Issuer.pbData = ((BYTE *)info +
+ sizeof(CMSG_SIGNER_INFO));
+ ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
+ cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
+ pcbStructInfo, NULL);
}
}
- else
- {
- SetLastError(CRYPT_E_ASN1_BADTAG);
- ret = FALSE;
- }
}
__EXCEPT_PAGE_FAULT
{
SetLastError(STATUS_ACCESS_VIOLATION);
- ret = FALSE;
}
__ENDTRY
+ TRACE("returning %d\n", ret);
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeDistPointName(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+static BOOL CRYPT_AsnDecodeCMSCertEncoded(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
{
BOOL ret;
+ struct AsnArrayDescriptor arrayDesc = { 0,
+ offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
+ offsetof(CRYPT_SIGNED_INFO, rgCertEncoded),
+ MEMBERSIZE(CRYPT_SIGNED_INFO, cCertEncoded, cCrlEncoded),
+ CRYPT_AsnDecodeCopyBytes,
+ sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
+
+ TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
+
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
+ return ret;
+}
- if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
- {
- DWORD bytesNeeded, dataLen;
-
- if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
- {
- struct AsnArrayDescriptor arrayDesc = {
- ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
- sizeof(CERT_ALT_NAME_ENTRY), TRUE,
- offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
- BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
-
- if (dataLen)
- {
- DWORD nameLen;
+static BOOL CRYPT_AsnDecodeCMSCrlEncoded(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ BOOL ret;
+ struct AsnArrayDescriptor arrayDesc = { 0,
+ offsetof(CRYPT_SIGNED_INFO, cCrlEncoded),
+ offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded),
+ MEMBERSIZE(CRYPT_SIGNED_INFO, cCrlEncoded, content),
+ CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_DER_BLOB),
+ TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
+
+ TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
+
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
+ return ret;
+}
- ret = CRYPT_AsnDecodeArray(&arrayDesc,
- pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
- 0, NULL, NULL, &nameLen, NULL);
- bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen;
- }
- else
- bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
- if (!pvStructInfo)
- *pcbStructInfo = bytesNeeded;
- else if (*pcbStructInfo < bytesNeeded)
- {
- *pcbStructInfo = bytesNeeded;
- SetLastError(ERROR_MORE_DATA);
- ret = FALSE;
- }
- else
- {
- CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
+static BOOL CRYPT_AsnDecodeCMSSignerId(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
+{
+ CERT_ID *id = pvStructInfo;
+ BOOL ret = FALSE;
- if (dataLen)
- {
- name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
- ret = CRYPT_AsnDecodeArray(&arrayDesc,
- pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
- 0, NULL, &name->u.FullName, pcbStructInfo,
- name->u.FullName.rgAltEntry);
- }
- else
- name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
- }
+ if (*pbEncoded == ASN_SEQUENCEOF)
+ {
+ ret = CRYPT_AsnDecodeIssuerSerialNumber(pbEncoded, cbEncoded, dwFlags,
+ id ? &id->u.IssuerSerialNumber : NULL, pcbStructInfo, pcbDecoded);
+ if (ret)
+ {
+ if (id)
+ id->dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
+ if (*pcbStructInfo > sizeof(CERT_ISSUER_SERIAL_NUMBER))
+ *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
+ sizeof(CERT_ISSUER_SERIAL_NUMBER);
+ else
+ *pcbStructInfo = sizeof(CERT_ID);
}
}
- else
+ else if (*pbEncoded == (ASN_CONTEXT | 0))
{
- SetLastError(CRYPT_E_ASN1_BADTAG);
- ret = FALSE;
+ ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded, dwFlags,
+ id ? &id->u.KeyId : NULL, pcbStructInfo, pcbDecoded);
+ if (ret)
+ {
+ if (id)
+ id->dwIdChoice = CERT_ID_KEY_IDENTIFIER;
+ if (*pcbStructInfo > sizeof(CRYPT_DATA_BLOB))
+ *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
+ sizeof(CRYPT_DATA_BLOB);
+ else
+ *pcbStructInfo = sizeof(CERT_ID);
+ }
}
+ else
+ SetLastError(CRYPT_E_ASN1_BADTAG);
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeDistPoint(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+static BOOL CRYPT_AsnDecodeCMSSignerInfoInternal(const BYTE *pbEncoded,
+ DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
+ DWORD *pcbDecoded)
{
+ CMSG_CMS_SIGNER_INFO *info = pvStructInfo;
struct AsnDecodeSequenceItem items[] = {
- { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
- DistPointName), CRYPT_AsnDecodeDistPointName,
- sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
- DistPointName.u.FullName.rgAltEntry), 0 },
- { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
- CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
- offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
- { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
- CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
- offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
+ { ASN_INTEGER, offsetof(CMSG_CMS_SIGNER_INFO, dwVersion),
+ CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
+ { 0, offsetof(CMSG_CMS_SIGNER_INFO, SignerId),
+ CRYPT_AsnDecodeCMSSignerId, sizeof(CERT_ID), FALSE, TRUE,
+ offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData), 0 },
+ { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm),
+ CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
+ FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
+ { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
+ offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs),
+ CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
+ TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
+ { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashEncryptionAlgorithm),
+ CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
+ FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO,
+ HashEncryptionAlgorithm.pszObjId), 0 },
+ { ASN_OCTETSTRING, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash),
+ CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
+ FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash.pbData), 0 },
+ { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
+ offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs),
+ CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
+ TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
};
BOOL ret;
- ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
- sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
- dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
+ TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo);
+
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
+ pcbDecoded, info ? info->SignerId.u.KeyId.pbData : NULL);
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
+static BOOL WINAPI CRYPT_AsnDecodeCMSSignerInfo(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
- BOOL ret;
+ BOOL ret = FALSE;
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
pDecodePara, pvStructInfo, *pcbStructInfo);
__TRY
{
- struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
- CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
- offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
+ ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded, cbEncoded,
+ dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
+ if (ret && pvStructInfo)
+ {
+ ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
+ pcbStructInfo, *pcbStructInfo);
+ if (ret)
+ {
+ CMSG_CMS_SIGNER_INFO *info;
- ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, pcbStructInfo, NULL);
+ if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
+ pvStructInfo = *(BYTE **)pvStructInfo;
+ info = pvStructInfo;
+ info->SignerId.u.KeyId.pbData = ((BYTE *)info +
+ sizeof(CMSG_CMS_SIGNER_INFO));
+ ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded,
+ cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
+ pcbStructInfo, NULL);
+ }
+ }
}
__EXCEPT_PAGE_FAULT
{
SetLastError(STATUS_ACCESS_VIOLATION);
- ret = FALSE;
}
__ENDTRY
+ TRACE("returning %d\n", ret);
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+static BOOL CRYPT_DecodeSignerArray(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
{
BOOL ret;
+ struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
+ offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
+ offsetof(CRYPT_SIGNED_INFO, rgSignerInfo),
+ FINALMEMBERSIZE(CRYPT_SIGNED_INFO, cSignerInfo),
+ CRYPT_AsnDecodeCMSSignerInfoInternal, sizeof(CMSG_CMS_SIGNER_INFO), TRUE,
+ offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData) };
- TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, *pcbStructInfo);
-
- __TRY
- {
- struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
- CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
+ TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, *pcbStructInfo, pcbDecoded);
- ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, pcbStructInfo, NULL);
- }
- __EXCEPT_PAGE_FAULT
- {
- SetLastError(STATUS_ACCESS_VIOLATION);
- ret = FALSE;
- }
- __ENDTRY
+ ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+ dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
return ret;
}
-static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
- LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+BOOL CRYPT_AsnDecodeCMSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
+ DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
+ CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
{
- BOOL ret;
+ BOOL ret = FALSE;
+ struct AsnDecodeSequenceItem items[] = {
+ { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version),
+ CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
+ /* Placeholder for the hash algorithms - redundant with those in the
+ * signers, so just ignore them.
+ */
+ { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
+ { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
+ CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
+ FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
+ { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
+ offsetof(CRYPT_SIGNED_INFO, cCertEncoded), CRYPT_AsnDecodeCMSCertEncoded,
+ MEMBERSIZE(CRYPT_SIGNED_INFO, cCertEncoded, cCrlEncoded), TRUE, TRUE,
+ offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
+ { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
+ offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_AsnDecodeCMSCrlEncoded,
+ MEMBERSIZE(CRYPT_SIGNED_INFO, cCrlEncoded, content), TRUE, TRUE,
+ offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
+ { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
+ CRYPT_DecodeSignerArray,
+ FINALMEMBERSIZE(CRYPT_SIGNED_INFO, cSignerInfo), TRUE, TRUE,
+ offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
+ };
TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
- pDecodePara, pvStructInfo, *pcbStructInfo);
-
- __TRY
- {
- struct AsnDecodeSequenceItem items[] = {
- { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
- DistPointName), CRYPT_AsnDecodeDistPointName,
- sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
- offsetof(CRL_ISSUING_DIST_POINT,
- DistPointName.u.FullName.rgAltEntry), 0 },
- { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
- fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
- FALSE, 0 },
- { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
- fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
- FALSE, 0 },
- { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
- OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
- sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
- OnlySomeReasonFlags.pbData), 0 },
- { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
- fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
- };
+ pDecodePara, signedInfo, *pcbSignedInfo);
- ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
- sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
- dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
- }
- __EXCEPT_PAGE_FAULT
- {
- SetLastError(STATUS_ACCESS_VIOLATION);
- ret = FALSE;
- }
- __ENDTRY
+ ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
+ pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo,
+ NULL, NULL);
+ TRACE("returning %d\n", ret);
return ret;
}
-BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
- const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
- PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType)
{
- static HCRYPTOIDFUNCSET set = NULL;
- BOOL ret = FALSE;
CryptDecodeObjectExFunc decodeFunc = NULL;
- HCRYPTOIDFUNCADDR hFunc = NULL;
-
- TRACE("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
- dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
- cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
- if (!pvStructInfo && !pcbStructInfo)
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
&& (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
{
SetLastError(ERROR_FILE_NOT_FOUND);
- return FALSE;
- }
- if (!cbEncoded)
- {
- SetLastError(CRYPT_E_ASN1_EOD);
- return FALSE;
- }
- if (cbEncoded > MAX_ENCODED_LEN)
- {
- SetLastError(CRYPT_E_ASN1_LARGE);
- return FALSE;
+ return NULL;
}
-
- SetLastError(NOERROR);
- if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
- *(BYTE **)pvStructInfo = NULL;
if (!HIWORD(lpszStructType))
{
switch (LOWORD(lpszStructType))
{
- case (WORD)X509_CERT:
+ case LOWORD(X509_CERT):
decodeFunc = CRYPT_AsnDecodeCertSignedContent;
break;
- case (WORD)X509_CERT_TO_BE_SIGNED:
+ case LOWORD(X509_CERT_TO_BE_SIGNED):
decodeFunc = CRYPT_AsnDecodeCert;
break;
- case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
+ case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
decodeFunc = CRYPT_AsnDecodeCRL;
break;
- case (WORD)X509_EXTENSIONS:
+ case LOWORD(X509_EXTENSIONS):
decodeFunc = CRYPT_AsnDecodeExtensions;
break;
- case (WORD)X509_NAME_VALUE:
+ case LOWORD(X509_NAME_VALUE):
decodeFunc = CRYPT_AsnDecodeNameValue;
break;
- case (WORD)X509_NAME:
+ case LOWORD(X509_NAME):
decodeFunc = CRYPT_AsnDecodeName;
break;
- case (WORD)X509_PUBLIC_KEY_INFO:
+ case LOWORD(X509_PUBLIC_KEY_INFO):
decodeFunc = CRYPT_AsnDecodePubKeyInfo;
break;
- case (WORD)X509_AUTHORITY_KEY_ID:
+ case LOWORD(X509_AUTHORITY_KEY_ID):
decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
break;
- case (WORD)X509_ALTERNATE_NAME:
+ case LOWORD(X509_ALTERNATE_NAME):
decodeFunc = CRYPT_AsnDecodeAltName;
break;
- case (WORD)X509_BASIC_CONSTRAINTS:
+ case LOWORD(X509_BASIC_CONSTRAINTS):
decodeFunc = CRYPT_AsnDecodeBasicConstraints;
break;
- case (WORD)X509_BASIC_CONSTRAINTS2:
+ case LOWORD(X509_BASIC_CONSTRAINTS2):
decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
break;
- case (WORD)RSA_CSP_PUBLICKEYBLOB:
+ case LOWORD(X509_CERT_POLICIES):
+ decodeFunc = CRYPT_AsnDecodeCertPolicies;
+ break;
+ case LOWORD(RSA_CSP_PUBLICKEYBLOB):
decodeFunc = CRYPT_AsnDecodeRsaPubKey;
break;
- case (WORD)X509_UNICODE_NAME:
+ case LOWORD(X509_UNICODE_NAME):
decodeFunc = CRYPT_AsnDecodeUnicodeName;
break;
- case (WORD)X509_UNICODE_NAME_VALUE:
+ case LOWORD(PKCS_ATTRIBUTE):
+ decodeFunc = CRYPT_AsnDecodePKCSAttribute;
+ break;
+ case LOWORD(X509_UNICODE_NAME_VALUE):
decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
break;
- case (WORD)X509_OCTET_STRING:
+ case LOWORD(X509_OCTET_STRING):
decodeFunc = CRYPT_AsnDecodeOctets;
break;
- case (WORD)X509_BITS:
- case (WORD)X509_KEY_USAGE:
+ case LOWORD(X509_BITS):
+ case LOWORD(X509_KEY_USAGE):
decodeFunc = CRYPT_AsnDecodeBits;
break;
- case (WORD)X509_INTEGER:
+ case LOWORD(X509_INTEGER):
decodeFunc = CRYPT_AsnDecodeInt;
break;
- case (WORD)X509_MULTI_BYTE_INTEGER:
+ case LOWORD(X509_MULTI_BYTE_INTEGER):
decodeFunc = CRYPT_AsnDecodeInteger;
break;
- case (WORD)X509_MULTI_BYTE_UINT:
+ case LOWORD(X509_MULTI_BYTE_UINT):
decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
break;
- case (WORD)X509_ENUMERATED:
+ case LOWORD(X509_ENUMERATED):
decodeFunc = CRYPT_AsnDecodeEnumerated;
break;
- case (WORD)X509_CHOICE_OF_TIME:
+ case LOWORD(X509_CHOICE_OF_TIME):
decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
break;
- case (WORD)X509_SEQUENCE_OF_ANY:
+ case LOWORD(X509_AUTHORITY_KEY_ID2):
+ decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
+ break;
+ case LOWORD(X509_AUTHORITY_INFO_ACCESS):
+ decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
+ break;
+ case LOWORD(PKCS_CONTENT_INFO):
+ decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
+ break;
+ case LOWORD(X509_SEQUENCE_OF_ANY):
decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
break;
- case (WORD)PKCS_UTC_TIME:
+ case LOWORD(PKCS_UTC_TIME):
decodeFunc = CRYPT_AsnDecodeUtcTime;
break;
- case (WORD)X509_CRL_DIST_POINTS:
+ case LOWORD(X509_CRL_DIST_POINTS):
decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
break;
- case (WORD)X509_ENHANCED_KEY_USAGE:
+ case LOWORD(X509_ENHANCED_KEY_USAGE):
decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
break;
- case (WORD)X509_ISSUING_DIST_POINT:
+ case LOWORD(PKCS_CTL):
+ decodeFunc = CRYPT_AsnDecodeCTL;
+ break;
+ case LOWORD(PKCS_SMIME_CAPABILITIES):
+ decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
+ break;
+ case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE):
+ decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
+ break;
+ case LOWORD(PKCS_ATTRIBUTES):
+ decodeFunc = CRYPT_AsnDecodePKCSAttributes;
+ break;
+ case LOWORD(X509_ISSUING_DIST_POINT):
decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
break;
- default:
- FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
+ case LOWORD(X509_NAME_CONSTRAINTS):
+ decodeFunc = CRYPT_AsnDecodeNameConstraints;
+ break;
+ case LOWORD(X509_POLICY_MAPPINGS):
+ decodeFunc = CRYPT_AsnDecodeCertPolicyMappings;
+ break;
+ case LOWORD(X509_POLICY_CONSTRAINTS):
+ decodeFunc = CRYPT_AsnDecodeCertPolicyConstraints;
+ break;
+ case LOWORD(PKCS7_SIGNER_INFO):
+ decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
+ break;
+ case LOWORD(CMS_SIGNER_INFO):
+ decodeFunc = CRYPT_AsnDecodeCMSSignerInfo;
+ break;
}
}
else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
decodeFunc = CRYPT_AsnDecodeExtensions;
else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
decodeFunc = CRYPT_AsnDecodeUtcTime;
+ else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
+ decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
+ else if (!strcmp(lpszStructType, szOID_LEGACY_POLICY_MAPPINGS))
+ decodeFunc = CRYPT_AsnDecodeCertPolicyMappings;
+ else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
+ decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
decodeFunc = CRYPT_AsnDecodeEnumerated;
else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
decodeFunc = CRYPT_AsnDecodeAltName;
else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
+ else if (!strcmp(lpszStructType, szOID_CERT_POLICIES))
+ decodeFunc = CRYPT_AsnDecodeCertPolicies;
+ else if (!strcmp(lpszStructType, szOID_POLICY_MAPPINGS))
+ decodeFunc = CRYPT_AsnDecodeCertPolicyMappings;
+ else if (!strcmp(lpszStructType, szOID_POLICY_CONSTRAINTS))
+ decodeFunc = CRYPT_AsnDecodeCertPolicyConstraints;
else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
- else
- TRACE("OID %s not found or unimplemented, looking for DLL\n",
+ else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
+ decodeFunc = CRYPT_AsnDecodeNameConstraints;
+ else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
+ decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
+ else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
+ decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
+ else if (!strcmp(lpszStructType, szOID_CTL))
+ decodeFunc = CRYPT_AsnDecodeCTL;
+ return decodeFunc;
+}
+
+static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
+{
+ static HCRYPTOIDFUNCSET set = NULL;
+ CryptDecodeObjectFunc decodeFunc = NULL;
+
+ if (!set)
+ set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
+ CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
+ (void **)&decodeFunc, hFunc);
+ return decodeFunc;
+}
+
+static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
+ LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
+{
+ static HCRYPTOIDFUNCSET set = NULL;
+ CryptDecodeObjectExFunc decodeFunc = NULL;
+
+ if (!set)
+ set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
+ CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
+ (void **)&decodeFunc, hFunc);
+ return decodeFunc;
+}
+
+BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
+ const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
+ DWORD *pcbStructInfo)
+{
+ BOOL ret = FALSE;
+ CryptDecodeObjectFunc pCryptDecodeObject = NULL;
+ CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
+ HCRYPTOIDFUNCADDR hFunc = NULL;
+
+ TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
+ debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
+ pvStructInfo, pcbStructInfo);
+
+ if (!pvStructInfo && !pcbStructInfo)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ if (cbEncoded > MAX_ENCODED_LEN)
+ {
+ SetLastError(CRYPT_E_ASN1_LARGE);
+ return FALSE;
+ }
+
+ if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
+ lpszStructType)))
+ {
+ TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
debugstr_a(lpszStructType));
+ pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
+ lpszStructType, &hFunc);
+ if (!pCryptDecodeObject)
+ pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
+ lpszStructType, &hFunc);
+ }
+ if (pCryptDecodeObject)
+ ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
+ pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
+ else if (pCryptDecodeObjectEx)
+ ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
+ pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
+ pvStructInfo, pcbStructInfo);
+ if (hFunc)
+ CryptFreeOIDFunctionAddress(hFunc, 0);
+ TRACE_(crypt)("returning %d\n", ret);
+ return ret;
+}
+
+BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
+ const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
+ PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
+{
+ BOOL ret = FALSE;
+ CryptDecodeObjectExFunc decodeFunc;
+ HCRYPTOIDFUNCADDR hFunc = NULL;
+
+ TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
+ dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
+ cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
+
+ if (!pvStructInfo && !pcbStructInfo)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ if (cbEncoded > MAX_ENCODED_LEN)
+ {
+ SetLastError(CRYPT_E_ASN1_LARGE);
+ return FALSE;
+ }
+
+ SetLastError(NOERROR);
+ if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
+ *(BYTE **)pvStructInfo = NULL;
+ decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
if (!decodeFunc)
{
- if (!set)
- set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
- CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
- (void **)&decodeFunc, &hFunc);
+ TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
+ debugstr_a(lpszStructType));
+ decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
+ &hFunc);
}
if (decodeFunc)
ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
else
- SetLastError(ERROR_FILE_NOT_FOUND);
+ {
+ CryptDecodeObjectFunc pCryptDecodeObject =
+ CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
+
+ /* Try CryptDecodeObject function. Don't call CryptDecodeObject
+ * directly, as that could cause an infinite loop.
+ */
+ if (pCryptDecodeObject)
+ {
+ if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
+ {
+ ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
+ pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
+ if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
+ pvStructInfo, pcbStructInfo, *pcbStructInfo)))
+ ret = pCryptDecodeObject(dwCertEncodingType,
+ lpszStructType, pbEncoded, cbEncoded, dwFlags,
+ *(BYTE **)pvStructInfo, pcbStructInfo);
+ }
+ else
+ ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
+ pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
+ }
+ }
if (hFunc)
CryptFreeOIDFunctionAddress(hFunc, 0);
+ TRACE_(crypt)("returning %d\n", ret);
+ return ret;
+}
+
+BOOL WINAPI PFXIsPFXBlob(CRYPT_DATA_BLOB *pPFX)
+{
+ BOOL ret;
+
+ TRACE_(crypt)("(%p)\n", pPFX);
+
+ /* A PFX blob is an asn.1-encoded sequence, consisting of at least a
+ * version integer of length 1 (3 encoded byes) and at least one other
+ * datum (two encoded bytes), plus at least two bytes for the outer
+ * sequence. Thus, even an empty PFX blob is at least 7 bytes in length.
+ */
+ if (pPFX->cbData < 7)
+ ret = FALSE;
+ else if (pPFX->pbData[0] == ASN_SEQUENCE)
+ {
+ DWORD len;
+
+ if ((ret = CRYPT_GetLengthIndefinite(pPFX->pbData, pPFX->cbData, &len)))
+ {
+ BYTE lenLen = GET_LEN_BYTES(pPFX->pbData[1]);
+
+ /* Need at least three bytes for the integer version */
+ if (pPFX->cbData < 1 + lenLen + 3)
+ ret = FALSE;
+ else if (pPFX->pbData[1 + lenLen] != ASN_INTEGER || /* Tag */
+ pPFX->pbData[1 + lenLen + 1] != 1 || /* Definite length */
+ pPFX->pbData[1 + lenLen + 2] != 3) /* PFX version */
+ ret = FALSE;
+ }
+ }
+ else
+ ret = FALSE;
return ret;
}
+
+HCERTSTORE WINAPI PFXImportCertStore(CRYPT_DATA_BLOB *pPFX, LPCWSTR szPassword,
+ DWORD dwFlags)
+{
+ FIXME_(crypt)("(%p, %p, %08x): stub\n", pPFX, szPassword, dwFlags);
+ return NULL;
+}