2 * Copyright 2005-2007 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 * This file implements ASN.1 DER decoding of a limited set of types.
19 * It isn't a full ASN.1 implementation. Microsoft implements BER
20 * encoding of many of the basic types in msasn1.dll, but that interface isn't
21 * implemented, so I implement them here.
24 * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
25 * (available online, look for a PDF copy as the HTML versions tend to have
26 * translation errors.)
28 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
30 * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject"
38 #define NONAMELESSUNION
45 #include "wine/debug.h"
46 #include "wine/exception.h"
47 #include "crypt32_private.h"
49 /* This is a bit arbitrary, but to set some limit: */
50 #define MAX_ENCODED_LEN 0x02000000
52 #define ASN_FLAGS_MASK 0xe0
53 #define ASN_TYPE_MASK 0x1f
55 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
56 WINE_DECLARE_DEBUG_CHANNEL(crypt);
64 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
65 DWORD, DWORD, void *, DWORD *);
66 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
67 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
69 /* Internal decoders don't do memory allocation or exception handling, and
70 * they report how many bytes they decoded.
72 typedef BOOL (*InternalDecodeFunc)(const BYTE *pbEncoded, DWORD cbEncoded,
73 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
75 /* Prototypes for built-in decoders. They follow the Ex style prototypes.
76 * The dwCertEncodingType and lpszStructType are ignored by the built-in
77 * functions, but the parameters are retained to simplify CryptDecodeObjectEx,
78 * since it must call functions in external DLLs that follow these signatures.
80 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
81 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
82 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
83 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
84 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
85 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
86 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
87 * time, doesn't do memory allocation, and doesn't do exception handling.
88 * (This isn't intended to be the externally-called one.)
90 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
91 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
92 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
93 /* Assumes algo->Parameters.pbData is set ahead of time. Internal func. */
94 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
95 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
96 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
97 /* Internal function */
98 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
99 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
100 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
101 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
102 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
103 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
104 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
105 /* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
106 * member has been initialized, doesn't do exception handling, and doesn't do
109 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
110 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
111 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
112 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
113 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
114 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
115 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
116 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
117 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
118 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
119 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
120 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
121 * member has been initialized, doesn't do exception handling, and doesn't do
122 * memory allocation. Also doesn't check tag, assumes the caller has checked
125 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
126 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
127 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
128 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
129 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
130 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
131 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
132 void *pvStructInfo, DWORD *pcbStructInfo);
134 /* Gets the number of length bytes from the given (leading) length byte */
135 #define GET_LEN_BYTES(b) ((b) <= 0x80 ? 1 : 1 + ((b) & 0x7f))
137 /* Helper function to get the encoded length of the data starting at pbEncoded,
138 * where pbEncoded[0] is the tag. If the data are too short to contain a
139 * length or if the length is too large for cbEncoded, sets an appropriate
140 * error code and returns FALSE. If the encoded length is unknown due to
141 * indefinite length encoding, *len is set to CMSG_INDEFINITE_LENGTH.
143 static BOOL CRYPT_GetLengthIndefinite(const BYTE *pbEncoded, DWORD cbEncoded,
150 SetLastError(CRYPT_E_ASN1_CORRUPT);
153 else if (pbEncoded[1] <= 0x7f)
155 if (pbEncoded[1] + 1 > cbEncoded)
157 SetLastError(CRYPT_E_ASN1_EOD);
166 else if (pbEncoded[1] == 0x80)
168 *len = CMSG_INDEFINITE_LENGTH;
173 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
175 if (lenLen > sizeof(DWORD) + 1)
177 SetLastError(CRYPT_E_ASN1_LARGE);
180 else if (lenLen + 2 > cbEncoded)
182 SetLastError(CRYPT_E_ASN1_CORRUPT);
195 if (out + lenLen + 1 > cbEncoded)
197 SetLastError(CRYPT_E_ASN1_EOD);
210 /* Like CRYPT_GetLengthIndefinite, but disallows indefinite-length encoding. */
211 static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
215 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, len)) &&
216 *len == CMSG_INDEFINITE_LENGTH)
218 SetLastError(CRYPT_E_ASN1_CORRUPT);
224 /* Helper function to check *pcbStructInfo, set it to the required size, and
225 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
226 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
227 * pointer to the newly allocated memory.
229 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
230 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
235 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
237 if (pDecodePara && pDecodePara->pfnAlloc)
238 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
240 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
241 if (!*(BYTE **)pvStructInfo)
244 *pcbStructInfo = bytesNeeded;
246 else if (*pcbStructInfo < bytesNeeded)
248 *pcbStructInfo = bytesNeeded;
249 SetLastError(ERROR_MORE_DATA);
255 /* Helper function to check *pcbStructInfo and set it to the required size.
256 * Assumes pvStructInfo is not NULL.
258 static BOOL CRYPT_DecodeCheckSpace(DWORD *pcbStructInfo, DWORD bytesNeeded)
262 if (*pcbStructInfo < bytesNeeded)
264 *pcbStructInfo = bytesNeeded;
265 SetLastError(ERROR_MORE_DATA);
270 *pcbStructInfo = bytesNeeded;
277 * The expected tag of the item. If tag is 0, decodeFunc is called
278 * regardless of the tag value seen.
280 * A sequence is decoded into a struct. The offset member is the
281 * offset of this item within that struct.
283 * The decoder function to use. If this is NULL, then the member isn't
284 * decoded, but minSize space is reserved for it.
286 * The minimum amount of space occupied after decoding. You must set this.
288 * If true, and the tag doesn't match the expected tag for this item,
289 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
290 * filled with 0 for this member.
291 * hasPointer, pointerOffset:
292 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
293 * the offset within the struct of the data pointer (or to the
294 * first data pointer, if more than one exist).
296 * Used by CRYPT_AsnDecodeSequence, not for your use.
298 struct AsnDecodeSequenceItem
302 CryptDecodeObjectExFunc decodeFunc;
310 /* Decodes the items in a sequence, where the items are described in items,
311 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
312 * pvStructInfo. nextData is a pointer to the memory location at which the
313 * first decoded item with a dynamic pointer should point.
314 * Upon decoding, *cbDecoded is the total number of bytes decoded.
315 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
317 static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
318 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
319 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData,
323 DWORD i, decoded = 0;
324 const BYTE *ptr = pbEncoded;
326 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
327 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
329 for (i = 0, ret = TRUE; ret && i < cItem; i++)
331 if (cbEncoded - (ptr - pbEncoded) != 0)
335 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
338 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
340 if (ptr[0] == items[i].tag || !items[i].tag)
342 if (nextData && pvStructInfo && items[i].hasPointer)
344 TRACE("Setting next pointer to %p\n",
346 *(BYTE **)((BYTE *)pvStructInfo +
347 items[i].pointerOffset) = nextData;
349 if (items[i].decodeFunc)
352 TRACE("decoding item %d\n", i);
354 TRACE("sizing item %d\n", i);
355 ret = items[i].decodeFunc(dwCertEncodingType,
356 NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
357 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
358 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
359 : NULL, &items[i].size);
362 /* Account for alignment padding */
363 if (items[i].size % sizeof(DWORD_PTR))
364 items[i].size += sizeof(DWORD_PTR) -
365 items[i].size % sizeof(DWORD_PTR);
366 TRACE("item %d size: %d\n", i, items[i].size);
367 if (nextData && items[i].hasPointer &&
368 items[i].size > items[i].minSize)
369 nextData += items[i].size - items[i].minSize;
370 ptr += 1 + nextItemLenBytes + nextItemLen;
371 decoded += 1 + nextItemLenBytes + nextItemLen;
372 TRACE("item %d: decoded %d bytes\n", i,
373 1 + nextItemLenBytes + nextItemLen);
375 else if (items[i].optional &&
376 GetLastError() == CRYPT_E_ASN1_BADTAG)
378 TRACE("skipping optional item %d\n", i);
379 items[i].size = items[i].minSize;
380 SetLastError(NOERROR);
384 TRACE("item %d failed: %08x\n", i,
389 TRACE("item %d: decoded %d bytes\n", i,
390 1 + nextItemLenBytes + nextItemLen);
391 ptr += 1 + nextItemLenBytes + nextItemLen;
392 decoded += 1 + nextItemLenBytes + nextItemLen;
393 items[i].size = items[i].minSize;
396 else if (items[i].optional)
398 TRACE("skipping optional item %d\n", i);
399 items[i].size = items[i].minSize;
403 TRACE("item %d: tag %02x doesn't match expected %02x\n",
404 i, ptr[0], items[i].tag);
405 SetLastError(CRYPT_E_ASN1_BADTAG);
410 else if (items[i].optional)
412 TRACE("missing optional item %d, skipping\n", i);
413 items[i].size = items[i].minSize;
417 TRACE("not enough bytes for item %d, failing\n", i);
418 SetLastError(CRYPT_E_ASN1_CORRUPT);
423 *cbDecoded = decoded;
424 TRACE("returning %d\n", ret);
428 /* This decodes an arbitrary sequence into a contiguous block of memory
429 * (basically, a struct.) Each element being decoded is described by a struct
430 * AsnDecodeSequenceItem, see above.
431 * startingPointer is an optional pointer to the first place where dynamic
432 * data will be stored. If you know the starting offset, you may pass it
433 * here. Otherwise, pass NULL, and one will be inferred from the items.
435 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
436 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
437 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
438 void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded,
439 void *startingPointer)
443 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
444 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
447 if (pbEncoded[0] == ASN_SEQUENCE)
451 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
453 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
454 const BYTE *ptr = pbEncoded + 1 + lenBytes;
456 cbEncoded -= 1 + lenBytes;
457 if (cbEncoded < dataLen)
459 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
461 SetLastError(CRYPT_E_ASN1_CORRUPT);
465 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, ptr,
466 cbEncoded, dwFlags, NULL, NULL, &cbDecoded);
467 if (ret && cbDecoded != dataLen)
469 TRACE("expected %d decoded, got %d, failing\n", dataLen,
471 SetLastError(CRYPT_E_ASN1_CORRUPT);
476 DWORD i, bytesNeeded = 0, structSize = 0;
478 for (i = 0; i < cItem; i++)
480 bytesNeeded += items[i].size;
481 structSize += items[i].minSize;
483 if (ret && pcbDecoded)
484 *pcbDecoded = 1 + lenBytes + cbDecoded;
486 *pcbStructInfo = bytesNeeded;
487 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
488 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
492 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
493 pvStructInfo = *(BYTE **)pvStructInfo;
495 nextData = (BYTE *)startingPointer;
497 nextData = (BYTE *)pvStructInfo + structSize;
498 memset(pvStructInfo, 0, structSize);
499 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
500 ptr, cbEncoded, dwFlags, pvStructInfo, nextData,
508 SetLastError(CRYPT_E_ASN1_BADTAG);
511 TRACE("returning %d (%08x)\n", ret, GetLastError());
516 * The expected tag of the entire encoded array (usually a variant
517 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
518 * regardless of the tag seen.
520 * used to decode each item in the array
522 * is the minimum size of each decoded item
524 * indicates whether each item has a dynamic pointer
526 * indicates the offset within itemSize at which the pointer exists
528 struct AsnArrayDescriptor
531 InternalDecodeFunc decodeFunc;
537 struct AsnArrayItemSize
543 /* Decodes an array of like types into a struct GenericArray.
544 * The layout and decoding of the array are described by a struct
545 * AsnArrayDescriptor.
547 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
548 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
549 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
550 DWORD *pcbDecoded, void *startingPointer)
554 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
555 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
558 if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
562 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
564 DWORD bytesNeeded, cItems = 0, decoded;
565 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
566 /* There can be arbitrarily many items, but there is often only one.
568 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
570 decoded = 1 + lenBytes;
571 bytesNeeded = sizeof(struct GenericArray);
575 BOOL doneDecoding = FALSE;
577 for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
581 itemLenBytes = GET_LEN_BYTES(ptr[1]);
582 if (dataLen == CMSG_INDEFINITE_LENGTH)
587 if (itemLenBytes != 1 || ptr[1] != 0)
589 SetLastError(CRYPT_E_ASN1_CORRUPT);
596 else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
600 DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
602 /* Each item decoded may not tolerate extraneous bytes,
603 * so get the length of the next element if known.
605 if ((ret = CRYPT_GetLengthIndefinite(ptr,
606 cbEncoded - (ptr - pbEncoded), &itemDataLen)))
608 if (itemDataLen == CMSG_INDEFINITE_LENGTH)
609 itemEncoded = cbEncoded - (ptr - pbEncoded);
611 itemEncoded = 1 + itemLenBytes + itemDataLen;
614 ret = arrayDesc->decodeFunc(ptr, itemEncoded,
615 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size,
620 if (itemSizes != &itemSize)
621 itemSizes = CryptMemRealloc(itemSizes,
622 cItems * sizeof(struct AsnArrayItemSize));
627 cItems * sizeof(struct AsnArrayItemSize));
629 memcpy(itemSizes, &itemSize,
634 decoded += itemDecoded;
635 itemSizes[cItems - 1].encodedLen = itemEncoded;
636 itemSizes[cItems - 1].size = size;
649 *pcbDecoded = decoded;
651 *pcbStructInfo = bytesNeeded;
652 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
653 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
658 struct GenericArray *array;
660 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
661 pvStructInfo = *(BYTE **)pvStructInfo;
662 array = (struct GenericArray *)pvStructInfo;
663 array->cItems = cItems;
665 array->rgItems = startingPointer;
667 array->rgItems = (BYTE *)array +
668 sizeof(struct GenericArray);
669 nextData = (BYTE *)array->rgItems +
670 array->cItems * arrayDesc->itemSize;
671 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
672 i < cItems && ptr - pbEncoded - 1 - lenBytes <
675 if (arrayDesc->hasPointer)
676 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
677 + arrayDesc->pointerOffset) = nextData;
678 ret = arrayDesc->decodeFunc(ptr,
679 itemSizes[i].encodedLen,
680 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
681 array->rgItems + i * arrayDesc->itemSize,
682 &itemSizes[i].size, NULL);
687 nextData += itemSizes[i].size - arrayDesc->itemSize;
688 ret = CRYPT_GetLen(ptr,
689 cbEncoded - (ptr - pbEncoded), &nextLen);
691 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
696 if (itemSizes != &itemSize)
697 CryptMemFree(itemSizes);
702 SetLastError(CRYPT_E_ASN1_BADTAG);
708 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
709 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
710 * to CRYPT_E_ASN1_CORRUPT.
711 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
714 static BOOL WINAPI CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType,
715 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
716 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
721 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
723 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
724 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
726 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
727 bytesNeeded += 1 + lenBytes + dataLen;
730 *pcbStructInfo = bytesNeeded;
731 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded)))
733 CRYPT_DER_BLOB *blob;
735 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
736 pvStructInfo = *(BYTE **)pvStructInfo;
737 blob = (CRYPT_DER_BLOB *)pvStructInfo;
738 blob->cbData = 1 + lenBytes + dataLen;
741 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
742 blob->pbData = (BYTE *)pbEncoded;
745 assert(blob->pbData);
746 memcpy(blob->pbData, pbEncoded, blob->cbData);
751 SetLastError(CRYPT_E_ASN1_CORRUPT);
759 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
760 static BOOL WINAPI CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType,
761 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
762 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
766 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
767 pDecodePara, pvStructInfo, *pcbStructInfo);
769 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
772 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType, lpszStructType,
773 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
774 pvStructInfo, pcbStructInfo);
775 if (ret && pvStructInfo)
777 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
784 for (i = 0; i < blob->cbData / 2; i++)
786 temp = blob->pbData[i];
787 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
788 blob->pbData[blob->cbData - i - 1] = temp;
792 TRACE("returning %d (%08x)\n", ret, GetLastError());
796 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
797 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
798 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
802 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
803 pDecodePara, pvStructInfo, *pcbStructInfo);
807 struct AsnDecodeSequenceItem items[] = {
808 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
809 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
810 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
811 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
812 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
813 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
814 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
815 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
816 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
817 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
820 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
821 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
822 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
823 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
824 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
828 SetLastError(STATUS_ACCESS_VIOLATION);
833 TRACE("Returning %d (%08x)\n", ret, GetLastError());
837 /* Internal function */
838 static BOOL WINAPI CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType,
839 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
840 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
845 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
847 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
849 ret = CRYPT_AsnDecodeIntInternal(pbEncoded + 1 + lenBytes, dataLen,
850 dwFlags, pvStructInfo, pcbStructInfo, NULL);
855 static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
856 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
857 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
861 struct AsnDecodeSequenceItem items[] = {
862 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
863 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
864 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
865 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
868 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
869 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
870 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
874 /* Internal function */
875 static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType,
876 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
877 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
882 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
884 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
886 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
887 X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
888 pDecodePara, pvStructInfo, pcbStructInfo);
893 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
894 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
895 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
898 struct AsnDecodeSequenceItem items[] = {
899 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
900 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
901 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
902 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
903 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
904 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
905 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
906 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
907 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
908 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
910 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
911 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
913 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
914 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
916 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
917 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
918 FALSE, TRUE, offsetof(CERT_INFO,
919 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
920 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
921 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
922 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
923 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
924 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
925 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
926 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
927 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
928 offsetof(CERT_INFO, rgExtension), 0 },
931 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
932 pDecodePara, pvStructInfo, *pcbStructInfo);
934 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
935 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
936 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
937 if (ret && pvStructInfo)
941 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
942 info = *(CERT_INFO **)pvStructInfo;
944 info = (CERT_INFO *)pvStructInfo;
945 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
946 !info->Subject.cbData)
948 SetLastError(CRYPT_E_ASN1_CORRUPT);
949 /* Don't need to deallocate, because it should have failed on the
950 * first pass (and no memory was allocated.)
956 TRACE("Returning %d (%08x)\n", ret, GetLastError());
960 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
961 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
962 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
966 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
967 pDecodePara, pvStructInfo, *pcbStructInfo);
973 /* Unless told not to, first try to decode it as a signed cert. */
974 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
976 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
978 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
979 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
980 (BYTE *)&signedCert, &size);
984 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
985 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
986 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
987 pvStructInfo, pcbStructInfo);
988 LocalFree(signedCert);
991 /* Failing that, try it as an unsigned cert */
995 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
996 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
997 pDecodePara, pvStructInfo, pcbStructInfo);
1002 SetLastError(STATUS_ACCESS_VIOLATION);
1006 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1010 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
1011 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1014 struct AsnDecodeSequenceItem items[] = {
1015 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
1016 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
1017 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
1018 { 0, offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime,
1019 sizeof(FILETIME), FALSE, FALSE, 0 },
1020 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
1021 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1022 offsetof(CRL_ENTRY, rgExtension), 0 },
1024 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
1026 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
1029 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1030 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1031 NULL, entry, pcbStructInfo, pcbDecoded,
1032 entry ? entry->SerialNumber.pbData : NULL);
1036 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
1037 * been set prior to calling.
1039 static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType,
1040 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1041 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1044 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1045 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
1046 offsetof(CRL_ENTRY, SerialNumber.pbData) };
1047 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
1049 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1050 pDecodePara, pvStructInfo, *pcbStructInfo);
1052 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1053 pDecodePara, pvStructInfo, pcbStructInfo, NULL,
1054 entries ? entries->rgItems : NULL);
1055 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1059 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1060 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1061 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1063 struct AsnDecodeSequenceItem items[] = {
1064 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1065 CRYPT_AsnDecodeInt, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1066 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1067 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1068 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1069 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1070 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1072 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime,
1073 sizeof(FILETIME), FALSE, FALSE, 0 },
1074 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime,
1075 sizeof(FILETIME), TRUE, FALSE, 0 },
1076 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1077 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
1078 offsetof(CRL_INFO, rgCRLEntry), 0 },
1079 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1080 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1081 offsetof(CRL_INFO, rgExtension), 0 },
1085 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1086 pDecodePara, pvStructInfo, *pcbStructInfo);
1088 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1089 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1090 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1092 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1096 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1097 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1098 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1102 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1103 pDecodePara, pvStructInfo, *pcbStructInfo);
1109 /* Unless told not to, first try to decode it as a signed crl. */
1110 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1112 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1114 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1115 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1116 (BYTE *)&signedCrl, &size);
1120 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1121 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1122 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1123 pvStructInfo, pcbStructInfo);
1124 LocalFree(signedCrl);
1127 /* Failing that, try it as an unsigned crl */
1131 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1132 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1133 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1138 SetLastError(STATUS_ACCESS_VIOLATION);
1142 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1146 static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded,
1147 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1152 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1153 pvStructInfo, *pcbStructInfo);
1155 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1157 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1158 DWORD bytesNeeded = sizeof(LPSTR);
1162 /* The largest possible string for the first two components
1163 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1168 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1169 pbEncoded[1 + lenBytes] / 40,
1170 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1172 bytesNeeded += strlen(firstTwo) + 1;
1173 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1174 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1176 /* large enough for ".4000000" */
1180 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1187 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1190 SetLastError(CRYPT_E_ASN1_CORRUPT);
1197 snprintf(str, sizeof(str), ".%d", val);
1198 bytesNeeded += strlen(str);
1203 *pcbDecoded = 1 + lenBytes + dataLen;
1205 *pcbStructInfo = bytesNeeded;
1206 else if (*pcbStructInfo < bytesNeeded)
1208 *pcbStructInfo = bytesNeeded;
1209 SetLastError(ERROR_MORE_DATA);
1217 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1220 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1221 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1223 pszObjId += strlen(pszObjId);
1224 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1225 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1229 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1238 sprintf(pszObjId, ".%d", val);
1239 pszObjId += strlen(pszObjId);
1243 *(LPSTR *)pvStructInfo = NULL;
1244 *pcbStructInfo = bytesNeeded;
1250 static BOOL WINAPI CRYPT_AsnDecodeOidIgnoreTagWrap(DWORD dwCertEncodingType,
1251 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1252 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1254 return CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1255 pvStructInfo, pcbStructInfo, NULL);
1258 static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded,
1259 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1263 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1264 pvStructInfo, *pcbStructInfo);
1266 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1267 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1268 pvStructInfo, pcbStructInfo, pcbDecoded);
1271 SetLastError(CRYPT_E_ASN1_BADTAG);
1277 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1280 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
1281 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1283 struct AsnDecodeSequenceItem items[] = {
1284 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1285 CRYPT_AsnDecodeOidIgnoreTagWrap, sizeof(LPSTR), FALSE, TRUE,
1286 offsetof(CERT_EXTENSION, pszObjId), 0 },
1287 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1288 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1289 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1290 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1291 offsetof(CERT_EXTENSION, Value.pbData) },
1294 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1296 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1300 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1301 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1302 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1303 ext, pcbStructInfo, pcbDecoded, ext ? ext->pszObjId : NULL);
1305 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1306 debugstr_a(ext->pszObjId));
1307 TRACE("returning %d (%08x)\n", ret, GetLastError());
1311 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
1312 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1313 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1316 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1317 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1318 offsetof(CERT_EXTENSION, pszObjId) };
1319 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1321 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1322 pDecodePara, pvStructInfo, *pcbStructInfo);
1324 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1325 pDecodePara, pvStructInfo, pcbStructInfo, NULL,
1326 exts ? exts->rgExtension : NULL);
1330 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1331 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1332 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1338 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1339 lpszStructType, pbEncoded, cbEncoded,
1340 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1341 if (ret && pvStructInfo)
1343 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1344 pcbStructInfo, *pcbStructInfo);
1347 CERT_EXTENSIONS *exts;
1349 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1350 pvStructInfo = *(BYTE **)pvStructInfo;
1351 exts = (CERT_EXTENSIONS *)pvStructInfo;
1352 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1353 sizeof(CERT_EXTENSIONS));
1354 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1355 lpszStructType, pbEncoded, cbEncoded,
1356 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1363 SetLastError(STATUS_ACCESS_VIOLATION);
1370 /* Warning: this assumes the address of value->Value.pbData is already set, in
1371 * order to avoid overwriting memory. (In some cases, it may change it, if it
1372 * doesn't copy anything to memory.) Be sure to set it correctly!
1374 static BOOL WINAPI CRYPT_AsnDecodeNameValueInternal(DWORD dwCertEncodingType,
1375 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1376 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1380 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1382 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1384 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1385 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1387 switch (pbEncoded[0])
1389 case ASN_OCTETSTRING:
1390 valueType = CERT_RDN_OCTET_STRING;
1391 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1392 bytesNeeded += dataLen;
1394 case ASN_NUMERICSTRING:
1395 valueType = CERT_RDN_NUMERIC_STRING;
1396 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1397 bytesNeeded += dataLen;
1399 case ASN_PRINTABLESTRING:
1400 valueType = CERT_RDN_PRINTABLE_STRING;
1401 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1402 bytesNeeded += dataLen;
1405 valueType = CERT_RDN_IA5_STRING;
1406 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1407 bytesNeeded += dataLen;
1410 valueType = CERT_RDN_T61_STRING;
1411 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1412 bytesNeeded += dataLen;
1414 case ASN_VIDEOTEXSTRING:
1415 valueType = CERT_RDN_VIDEOTEX_STRING;
1416 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1417 bytesNeeded += dataLen;
1419 case ASN_GRAPHICSTRING:
1420 valueType = CERT_RDN_GRAPHIC_STRING;
1421 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1422 bytesNeeded += dataLen;
1424 case ASN_VISIBLESTRING:
1425 valueType = CERT_RDN_VISIBLE_STRING;
1426 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1427 bytesNeeded += dataLen;
1429 case ASN_GENERALSTRING:
1430 valueType = CERT_RDN_GENERAL_STRING;
1431 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1432 bytesNeeded += dataLen;
1434 case ASN_UNIVERSALSTRING:
1435 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1436 SetLastError(CRYPT_E_ASN1_BADTAG);
1439 valueType = CERT_RDN_BMP_STRING;
1440 bytesNeeded += dataLen;
1442 case ASN_UTF8STRING:
1443 valueType = CERT_RDN_UTF8_STRING;
1444 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1445 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1448 SetLastError(CRYPT_E_ASN1_BADTAG);
1453 *pcbStructInfo = bytesNeeded;
1454 else if (*pcbStructInfo < bytesNeeded)
1456 *pcbStructInfo = bytesNeeded;
1457 SetLastError(ERROR_MORE_DATA);
1462 *pcbStructInfo = bytesNeeded;
1463 value->dwValueType = valueType;
1468 assert(value->Value.pbData);
1469 switch (pbEncoded[0])
1471 case ASN_OCTETSTRING:
1472 case ASN_NUMERICSTRING:
1473 case ASN_PRINTABLESTRING:
1476 case ASN_VIDEOTEXSTRING:
1477 case ASN_GRAPHICSTRING:
1478 case ASN_VISIBLESTRING:
1479 case ASN_GENERALSTRING:
1480 value->Value.cbData = dataLen;
1483 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1484 memcpy(value->Value.pbData,
1485 pbEncoded + 1 + lenBytes, dataLen);
1487 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1493 LPWSTR str = (LPWSTR)value->Value.pbData;
1495 value->Value.cbData = dataLen;
1496 for (i = 0; i < dataLen / 2; i++)
1497 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1498 pbEncoded[1 + lenBytes + 2 * i + 1];
1501 case ASN_UTF8STRING:
1503 LPWSTR str = (LPWSTR)value->Value.pbData;
1505 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1506 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1507 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1514 value->Value.cbData = 0;
1515 value->Value.pbData = NULL;
1522 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1523 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1524 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1530 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1531 lpszStructType, pbEncoded, cbEncoded,
1532 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1533 if (ret && pvStructInfo)
1535 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1536 pcbStructInfo, *pcbStructInfo);
1539 CERT_NAME_VALUE *value;
1541 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1542 pvStructInfo = *(BYTE **)pvStructInfo;
1543 value = (CERT_NAME_VALUE *)pvStructInfo;
1544 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1545 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1546 lpszStructType, pbEncoded, cbEncoded,
1547 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1554 SetLastError(STATUS_ACCESS_VIOLATION);
1561 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValueInternal(
1562 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
1563 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
1564 void *pvStructInfo, DWORD *pcbStructInfo)
1568 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1570 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1572 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1573 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1575 switch (pbEncoded[0])
1577 case ASN_NUMERICSTRING:
1578 valueType = CERT_RDN_NUMERIC_STRING;
1579 bytesNeeded += dataLen * 2;
1581 case ASN_PRINTABLESTRING:
1582 valueType = CERT_RDN_PRINTABLE_STRING;
1583 bytesNeeded += dataLen * 2;
1586 valueType = CERT_RDN_IA5_STRING;
1587 bytesNeeded += dataLen * 2;
1590 valueType = CERT_RDN_T61_STRING;
1591 bytesNeeded += dataLen * 2;
1593 case ASN_VIDEOTEXSTRING:
1594 valueType = CERT_RDN_VIDEOTEX_STRING;
1595 bytesNeeded += dataLen * 2;
1597 case ASN_GRAPHICSTRING:
1598 valueType = CERT_RDN_GRAPHIC_STRING;
1599 bytesNeeded += dataLen * 2;
1601 case ASN_VISIBLESTRING:
1602 valueType = CERT_RDN_VISIBLE_STRING;
1603 bytesNeeded += dataLen * 2;
1605 case ASN_GENERALSTRING:
1606 valueType = CERT_RDN_GENERAL_STRING;
1607 bytesNeeded += dataLen * 2;
1609 case ASN_UNIVERSALSTRING:
1610 valueType = CERT_RDN_UNIVERSAL_STRING;
1611 bytesNeeded += dataLen / 2;
1614 valueType = CERT_RDN_BMP_STRING;
1615 bytesNeeded += dataLen;
1617 case ASN_UTF8STRING:
1618 valueType = CERT_RDN_UTF8_STRING;
1619 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1620 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1623 SetLastError(CRYPT_E_ASN1_BADTAG);
1628 *pcbStructInfo = bytesNeeded;
1629 else if (*pcbStructInfo < bytesNeeded)
1631 *pcbStructInfo = bytesNeeded;
1632 SetLastError(ERROR_MORE_DATA);
1637 *pcbStructInfo = bytesNeeded;
1638 value->dwValueType = valueType;
1642 LPWSTR str = (LPWSTR)value->Value.pbData;
1644 assert(value->Value.pbData);
1645 switch (pbEncoded[0])
1647 case ASN_NUMERICSTRING:
1648 case ASN_PRINTABLESTRING:
1651 case ASN_VIDEOTEXSTRING:
1652 case ASN_GRAPHICSTRING:
1653 case ASN_VISIBLESTRING:
1654 case ASN_GENERALSTRING:
1655 value->Value.cbData = dataLen * 2;
1656 for (i = 0; i < dataLen; i++)
1657 str[i] = pbEncoded[1 + lenBytes + i];
1659 case ASN_UNIVERSALSTRING:
1660 value->Value.cbData = dataLen / 2;
1661 for (i = 0; i < dataLen / 4; i++)
1662 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1663 | pbEncoded[1 + lenBytes + 2 * i + 3];
1666 value->Value.cbData = dataLen;
1667 for (i = 0; i < dataLen / 2; i++)
1668 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1669 pbEncoded[1 + lenBytes + 2 * i + 1];
1671 case ASN_UTF8STRING:
1672 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1673 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1674 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1680 value->Value.cbData = 0;
1681 value->Value.pbData = NULL;
1688 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1689 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1690 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1696 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(dwCertEncodingType,
1697 lpszStructType, pbEncoded, cbEncoded,
1698 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1699 if (ret && pvStructInfo)
1701 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1702 pcbStructInfo, *pcbStructInfo);
1705 CERT_NAME_VALUE *value;
1707 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1708 pvStructInfo = *(BYTE **)pvStructInfo;
1709 value = (CERT_NAME_VALUE *)pvStructInfo;
1710 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1711 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(
1712 dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded,
1713 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1720 SetLastError(STATUS_ACCESS_VIOLATION);
1727 static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
1728 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1731 struct AsnDecodeSequenceItem items[] = {
1732 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1733 CRYPT_AsnDecodeOidIgnoreTagWrap, sizeof(LPSTR), FALSE, TRUE,
1734 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1735 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1736 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1737 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1739 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1741 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1742 pvStructInfo, *pcbStructInfo);
1745 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1746 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1747 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1748 attr, pcbStructInfo, pcbDecoded, attr ? attr->pszObjId : NULL);
1751 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1752 debugstr_a(attr->pszObjId));
1753 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1755 TRACE("returning %d (%08x)\n", ret, GetLastError());
1759 static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1760 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1763 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1764 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1765 offsetof(CERT_RDN_ATTR, pszObjId) };
1766 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1768 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1769 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1770 rdn ? rdn->rgRDNAttr : NULL);
1774 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1775 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1776 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1782 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1783 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1784 offsetof(CERT_RDN, rgRDNAttr) };
1786 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1787 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1791 SetLastError(STATUS_ACCESS_VIOLATION);
1798 static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
1799 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1803 struct AsnDecodeSequenceItem items[] = {
1804 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1805 CRYPT_AsnDecodeOidIgnoreTagWrap, sizeof(LPSTR), FALSE, TRUE,
1806 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1807 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1808 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1809 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1811 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1813 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1814 pvStructInfo, *pcbStructInfo);
1817 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1818 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1819 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1820 attr, pcbStructInfo, pcbDecoded, attr ? attr->pszObjId : NULL);
1823 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1824 debugstr_a(attr->pszObjId));
1825 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1827 TRACE("returning %d (%08x)\n", ret, GetLastError());
1831 static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1832 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1835 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1836 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1837 offsetof(CERT_RDN_ATTR, pszObjId) };
1838 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1840 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1841 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1842 rdn ? rdn->rgRDNAttr : NULL);
1846 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1847 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1848 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1854 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1855 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1856 offsetof(CERT_RDN, rgRDNAttr) };
1858 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1859 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1863 SetLastError(STATUS_ACCESS_VIOLATION);
1870 static BOOL CRYPT_AsnDecodeCopyBytesInternal(const BYTE *pbEncoded,
1871 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1875 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1877 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1878 pvStructInfo, *pcbStructInfo);
1880 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1881 bytesNeeded += cbEncoded;
1883 *pcbDecoded = cbEncoded;
1885 *pcbStructInfo = bytesNeeded;
1886 else if (*pcbStructInfo < bytesNeeded)
1888 SetLastError(ERROR_MORE_DATA);
1889 *pcbStructInfo = bytesNeeded;
1894 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1896 *pcbStructInfo = bytesNeeded;
1897 blob->cbData = cbEncoded;
1898 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1899 blob->pbData = (LPBYTE)pbEncoded;
1902 assert(blob->pbData);
1903 memcpy(blob->pbData, pbEncoded, blob->cbData);
1909 static BOOL WINAPI CRYPT_DecodeDERArray(DWORD dwCertEncodingType,
1910 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1911 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1914 struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytesInternal,
1915 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
1916 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
1918 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1919 pDecodePara, pvStructInfo, *pcbStructInfo);
1921 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1922 pDecodePara, pvStructInfo, pcbStructInfo, NULL,
1923 array ? array->rgItems : NULL);
1927 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
1928 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1932 struct AsnDecodeSequenceItem items[] = {
1933 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
1934 CRYPT_AsnDecodeOidIgnoreTagWrap, sizeof(LPSTR), FALSE, TRUE,
1935 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
1936 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
1937 CRYPT_DecodeDERArray, sizeof(struct GenericArray), FALSE, TRUE,
1938 offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
1940 PCRYPT_ATTRIBUTE attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
1942 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1943 pvStructInfo, *pcbStructInfo);
1945 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1946 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1947 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1948 attr ? attr->pszObjId : NULL);
1949 TRACE("returning %d\n", ret);
1953 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
1954 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1955 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1959 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1960 pDecodePara, pvStructInfo, *pcbStructInfo);
1966 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
1967 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
1971 *pcbStructInfo = bytesNeeded;
1972 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1973 pvStructInfo, pcbStructInfo, bytesNeeded)))
1975 PCRYPT_ATTRIBUTE attr;
1977 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1978 pvStructInfo = *(BYTE **)pvStructInfo;
1979 attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
1980 attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
1981 sizeof(CRYPT_ATTRIBUTE));
1982 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
1983 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
1990 SetLastError(STATUS_ACCESS_VIOLATION);
1993 TRACE("returning %d\n", ret);
1997 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributesInternal(
1998 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
1999 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2000 void *pvStructInfo, DWORD *pcbStructInfo)
2002 struct AsnArrayDescriptor arrayDesc = { 0,
2003 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2004 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2005 PCRYPT_ATTRIBUTES attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
2008 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2009 pDecodePara, pvStructInfo, pcbStructInfo, NULL, attrs ? attrs->rgAttr :
2014 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
2015 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2016 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2020 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2021 pDecodePara, pvStructInfo, *pcbStructInfo);
2028 SetLastError(CRYPT_E_ASN1_EOD);
2029 else if (pbEncoded[0] != (ASN_CONSTRUCTOR | ASN_SETOF))
2030 SetLastError(CRYPT_E_ASN1_CORRUPT);
2031 else if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(
2032 dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded,
2033 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2036 *pcbStructInfo = bytesNeeded;
2037 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2038 pvStructInfo, pcbStructInfo, bytesNeeded)))
2040 PCRYPT_ATTRIBUTES attrs;
2042 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2043 pvStructInfo = *(BYTE **)pvStructInfo;
2044 attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
2045 attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
2046 sizeof(CRYPT_ATTRIBUTES));
2047 ret = CRYPT_AsnDecodePKCSAttributesInternal(dwCertEncodingType,
2048 lpszStructType, pbEncoded, cbEncoded,
2049 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2056 SetLastError(STATUS_ACCESS_VIOLATION);
2059 TRACE("returning %d\n", ret);
2063 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
2064 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2065 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2068 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
2070 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2071 pDecodePara, pvStructInfo, *pcbStructInfo);
2073 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
2074 bytesNeeded += cbEncoded;
2076 *pcbStructInfo = bytesNeeded;
2077 else if (*pcbStructInfo < bytesNeeded)
2079 SetLastError(ERROR_MORE_DATA);
2080 *pcbStructInfo = bytesNeeded;
2085 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
2087 *pcbStructInfo = bytesNeeded;
2088 blob->cbData = cbEncoded;
2089 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2090 blob->pbData = (LPBYTE)pbEncoded;
2093 assert(blob->pbData);
2094 memcpy(blob->pbData, pbEncoded, blob->cbData);
2100 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
2101 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2102 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2104 CRYPT_ALGORITHM_IDENTIFIER *algo =
2105 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
2107 struct AsnDecodeSequenceItem items[] = {
2108 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
2109 CRYPT_AsnDecodeOidIgnoreTagWrap, sizeof(LPSTR), FALSE, TRUE,
2110 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
2111 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
2112 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2113 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
2116 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2117 pDecodePara, pvStructInfo, *pcbStructInfo);
2119 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2120 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2121 pDecodePara, pvStructInfo, pcbStructInfo, NULL,
2122 algo ? algo->pszObjId : NULL);
2123 if (ret && pvStructInfo)
2125 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
2126 debugstr_a(algo->pszObjId));
2131 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
2132 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2133 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2136 struct AsnDecodeSequenceItem items[] = {
2137 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
2138 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2139 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
2140 Algorithm.pszObjId) },
2141 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
2142 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2143 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
2145 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2147 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2148 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2149 pDecodePara, pvStructInfo, pcbStructInfo, NULL, info ?
2150 info->Algorithm.Parameters.pbData : NULL);
2154 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2155 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2156 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2164 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
2165 lpszStructType, pbEncoded, cbEncoded,
2166 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2169 *pcbStructInfo = bytesNeeded;
2170 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2171 pvStructInfo, pcbStructInfo, bytesNeeded)))
2173 PCERT_PUBLIC_KEY_INFO info;
2175 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2176 pvStructInfo = *(BYTE **)pvStructInfo;
2177 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2178 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2179 sizeof(CERT_PUBLIC_KEY_INFO);
2180 ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
2181 lpszStructType, pbEncoded, cbEncoded,
2182 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2189 SetLastError(STATUS_ACCESS_VIOLATION);
2196 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
2197 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2198 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2204 SetLastError(CRYPT_E_ASN1_CORRUPT);
2207 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2209 SetLastError(CRYPT_E_ASN1_CORRUPT);
2212 if (pbEncoded[1] > 1)
2214 SetLastError(CRYPT_E_ASN1_CORRUPT);
2219 *pcbStructInfo = sizeof(BOOL);
2222 else if (*pcbStructInfo < sizeof(BOOL))
2224 *pcbStructInfo = sizeof(BOOL);
2225 SetLastError(ERROR_MORE_DATA);
2230 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2233 TRACE("returning %d (%08x)\n", ret, GetLastError());
2237 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2238 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2240 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
2241 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2244 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2245 pvStructInfo, *pcbStructInfo);
2249 SetLastError(CRYPT_E_ASN1_CORRUPT);
2252 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2253 if (1 + lenBytes > cbEncoded)
2255 SetLastError(CRYPT_E_ASN1_CORRUPT);
2258 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2260 switch (pbEncoded[0] & ASN_TYPE_MASK)
2262 case 1: /* rfc822Name */
2263 case 2: /* dNSName */
2264 case 6: /* uniformResourceIdentifier */
2265 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
2267 case 4: /* directoryName */
2268 case 7: /* iPAddress */
2269 bytesNeeded += dataLen;
2271 case 8: /* registeredID */
2272 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
2276 /* FIXME: ugly, shouldn't need to know internals of OID decode
2277 * function to use it.
2279 bytesNeeded += dataLen - sizeof(LPSTR);
2282 case 0: /* otherName */
2283 FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
2284 SetLastError(CRYPT_E_ASN1_BADTAG);
2287 case 3: /* x400Address, unimplemented */
2288 case 5: /* ediPartyName, unimplemented */
2289 TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
2290 SetLastError(CRYPT_E_ASN1_BADTAG);
2294 TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
2295 SetLastError(CRYPT_E_ASN1_CORRUPT);
2301 *pcbDecoded = 1 + lenBytes + dataLen;
2303 *pcbStructInfo = bytesNeeded;
2304 else if (*pcbStructInfo < bytesNeeded)
2306 *pcbStructInfo = bytesNeeded;
2307 SetLastError(ERROR_MORE_DATA);
2312 *pcbStructInfo = bytesNeeded;
2313 /* MS used values one greater than the asn1 ones.. sigh */
2314 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
2315 switch (pbEncoded[0] & ASN_TYPE_MASK)
2317 case 1: /* rfc822Name */
2318 case 2: /* dNSName */
2319 case 6: /* uniformResourceIdentifier */
2323 for (i = 0; i < dataLen; i++)
2324 entry->u.pwszURL[i] =
2325 (WCHAR)pbEncoded[1 + lenBytes + i];
2326 entry->u.pwszURL[i] = 0;
2327 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2328 debugstr_w(entry->u.pwszURL));
2331 case 4: /* directoryName */
2332 entry->dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
2333 /* The data are memory-equivalent with the IPAddress case,
2336 case 7: /* iPAddress */
2337 /* The next data pointer is in the pwszURL spot, that is,
2338 * the first 4 bytes. Need to move it to the next spot.
2340 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2341 entry->u.IPAddress.cbData = dataLen;
2342 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2345 case 8: /* registeredID */
2346 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
2347 &entry->u.pszRegisteredID, &dataLen, NULL);
2356 static BOOL WINAPI CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType,
2357 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2358 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2361 struct AsnArrayDescriptor arrayDesc = { 0,
2362 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2363 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2364 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
2366 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2367 pDecodePara, pvStructInfo, *pcbStructInfo);
2370 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2371 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2372 pDecodePara, pvStructInfo, pcbStructInfo, NULL,
2373 info ? info->rgAltEntry : NULL);
2377 /* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */
2378 static BOOL WINAPI CRYPT_AsnDecodeIntegerSwapBytes(DWORD dwCertEncodingType,
2379 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2380 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2384 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2385 pDecodePara, pvStructInfo, *pcbStructInfo);
2387 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2390 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType, lpszStructType,
2391 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
2392 pvStructInfo, pcbStructInfo);
2393 if (ret && pvStructInfo)
2395 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2402 for (i = 0; i < blob->cbData / 2; i++)
2404 temp = blob->pbData[i];
2405 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
2406 blob->pbData[blob->cbData - i - 1] = temp;
2410 TRACE("returning %d (%08x)\n", ret, GetLastError());
2414 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
2415 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2416 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2422 struct AsnDecodeSequenceItem items[] = {
2423 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
2424 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2425 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
2426 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2427 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
2428 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
2429 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
2430 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
2431 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2432 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2433 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
2436 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2437 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2438 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
2442 SetLastError(STATUS_ACCESS_VIOLATION);
2449 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
2450 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2451 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2457 struct AsnDecodeSequenceItem items[] = {
2458 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
2459 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2460 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
2461 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2462 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
2463 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
2464 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2465 AuthorityCertIssuer.rgAltEntry), 0 },
2466 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2467 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2468 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2469 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2470 AuthorityCertSerialNumber.pbData), 0 },
2473 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2474 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2475 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
2479 SetLastError(STATUS_ACCESS_VIOLATION);
2486 static BOOL WINAPI CRYPT_AsnDecodePKCSContent(DWORD dwCertEncodingType,
2487 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2488 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2493 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2494 pDecodePara, pvStructInfo, *pcbStructInfo);
2496 /* The caller has already checked the tag, no need to check it again.
2497 * Check the outer length is valid by calling CRYPT_GetLen:
2499 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2501 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2504 pbEncoded += 1 + lenBytes;
2505 /* Check the inner length is valid by calling CRYPT_GetLen again: */
2506 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &innerLen)))
2508 ret = CRYPT_AsnDecodeCopyBytes(dwCertEncodingType, NULL,
2509 pbEncoded, dataLen, dwFlags, pDecodePara, pvStructInfo,
2516 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfoInternal(
2517 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2518 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2519 void *pvStructInfo, DWORD *pcbStructInfo)
2521 CRYPT_CONTENT_INFO *info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2522 struct AsnDecodeSequenceItem items[] = {
2523 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
2524 CRYPT_AsnDecodeOidIgnoreTagWrap, sizeof(LPSTR), FALSE, TRUE,
2525 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
2526 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
2527 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
2528 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
2529 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
2533 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2534 pDecodePara, pvStructInfo, *pcbStructInfo);
2536 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2537 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2538 pDecodePara, pvStructInfo, pcbStructInfo, NULL,
2539 info ? info->pszObjId : NULL);
2543 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
2544 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2545 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2549 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2550 pDecodePara, pvStructInfo, *pcbStructInfo);
2554 ret = CRYPT_AsnDecodePKCSContentInfoInternal(dwCertEncodingType,
2555 lpszStructType, pbEncoded, cbEncoded,
2556 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
2557 if (ret && pvStructInfo)
2559 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
2560 pcbStructInfo, *pcbStructInfo);
2563 CRYPT_CONTENT_INFO *info;
2565 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2566 pvStructInfo = *(BYTE **)pvStructInfo;
2567 info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2568 info->pszObjId = (LPSTR)((BYTE *)info +
2569 sizeof(CRYPT_CONTENT_INFO));
2570 ret = CRYPT_AsnDecodePKCSContentInfoInternal(dwCertEncodingType,
2571 lpszStructType, pbEncoded, cbEncoded,
2572 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2579 SetLastError(STATUS_ACCESS_VIOLATION);
2585 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
2586 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2587 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
2590 struct AsnDecodeSequenceItem items[] = {
2591 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version), CRYPT_AsnDecodeInt,
2592 sizeof(DWORD), FALSE, FALSE, 0, 0 },
2593 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
2594 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2595 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
2597 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
2598 CRYPT_AsnDecodePKCSContentInfoInternal,
2599 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
2600 ContentInfo.pszObjId), 0 },
2601 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
2602 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
2603 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
2606 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
2607 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2608 pDecodePara, digestedData, pcbDigestedData, NULL, NULL);
2612 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
2613 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2614 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2618 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2619 pDecodePara, pvStructInfo, *pcbStructInfo);
2623 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2624 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2625 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2627 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2628 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
2632 SetLastError(STATUS_ACCESS_VIOLATION);
2639 struct PATH_LEN_CONSTRAINT
2641 BOOL fPathLenConstraint;
2642 DWORD dwPathLenConstraint;
2645 static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
2646 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2647 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2651 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2652 pvStructInfo, *pcbStructInfo);
2656 if (pbEncoded[0] == ASN_INTEGER)
2658 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT);
2661 *pcbStructInfo = bytesNeeded;
2662 else if (*pcbStructInfo < bytesNeeded)
2664 SetLastError(ERROR_MORE_DATA);
2665 *pcbStructInfo = bytesNeeded;
2670 struct PATH_LEN_CONSTRAINT *constraint =
2671 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
2672 DWORD size = sizeof(constraint->dwPathLenConstraint);
2674 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, 0,
2675 &constraint->dwPathLenConstraint, &size, NULL);
2677 constraint->fPathLenConstraint = TRUE;
2678 TRACE("got an int, dwPathLenConstraint is %d\n",
2679 constraint->dwPathLenConstraint);
2684 SetLastError(CRYPT_E_ASN1_CORRUPT);
2688 TRACE("returning %d (%08x)\n", ret, GetLastError());
2692 static BOOL WINAPI CRYPT_AsnDecodeSubtreeConstraints(DWORD dwCertEncodingType,
2693 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2694 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2697 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2698 CRYPT_AsnDecodeCopyBytesInternal, sizeof(CERT_NAME_BLOB), TRUE,
2699 offsetof(CERT_NAME_BLOB, pbData) };
2700 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2702 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2703 pDecodePara, pvStructInfo, *pcbStructInfo);
2705 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2706 pDecodePara, pvStructInfo, pcbStructInfo, NULL,
2707 entries ? entries->rgItems : NULL);
2708 TRACE("Returning %d (%08x)\n", ret, GetLastError());
2712 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
2713 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2714 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2720 struct AsnDecodeSequenceItem items[] = {
2721 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
2722 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2723 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
2724 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2725 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2726 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2727 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2728 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
2729 sizeof(struct GenericArray), TRUE, TRUE,
2730 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
2733 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2734 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2735 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
2739 SetLastError(STATUS_ACCESS_VIOLATION);
2746 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
2747 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2748 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2754 struct AsnDecodeSequenceItem items[] = {
2755 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
2756 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
2757 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
2758 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2759 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2762 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2763 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2764 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
2768 SetLastError(STATUS_ACCESS_VIOLATION);
2775 #define RSA1_MAGIC 0x31415352
2777 struct DECODED_RSA_PUB_KEY
2780 CRYPT_INTEGER_BLOB modulus;
2783 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
2784 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2785 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2791 struct AsnDecodeSequenceItem items[] = {
2792 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
2793 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2794 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
2796 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
2797 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2799 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
2802 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2803 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
2804 CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, &size, NULL, NULL);
2807 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2808 decodedKey->modulus.cbData;
2812 *pcbStructInfo = bytesNeeded;
2815 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2816 pvStructInfo, pcbStructInfo, bytesNeeded)))
2819 RSAPUBKEY *rsaPubKey;
2821 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2822 pvStructInfo = *(BYTE **)pvStructInfo;
2823 hdr = (BLOBHEADER *)pvStructInfo;
2824 hdr->bType = PUBLICKEYBLOB;
2825 hdr->bVersion = CUR_BLOB_VERSION;
2827 hdr->aiKeyAlg = CALG_RSA_KEYX;
2828 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
2829 sizeof(BLOBHEADER));
2830 rsaPubKey->magic = RSA1_MAGIC;
2831 rsaPubKey->pubexp = decodedKey->pubexp;
2832 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
2833 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
2834 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
2835 decodedKey->modulus.cbData);
2837 LocalFree(decodedKey);
2842 SetLastError(STATUS_ACCESS_VIOLATION);
2849 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
2850 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2851 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2854 DWORD bytesNeeded, dataLen;
2856 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2857 pDecodePara, pvStructInfo, *pcbStructInfo);
2859 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2861 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2862 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
2864 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
2866 *pcbStructInfo = bytesNeeded;
2867 else if (*pcbStructInfo < bytesNeeded)
2869 SetLastError(ERROR_MORE_DATA);
2870 *pcbStructInfo = bytesNeeded;
2875 CRYPT_DATA_BLOB *blob;
2876 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2878 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2879 blob->cbData = dataLen;
2880 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2881 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
2884 assert(blob->pbData);
2886 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
2894 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
2895 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2896 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2900 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2901 pDecodePara, pvStructInfo, *pcbStructInfo);
2909 SetLastError(CRYPT_E_ASN1_CORRUPT);
2912 else if (pbEncoded[0] != ASN_OCTETSTRING)
2914 SetLastError(CRYPT_E_ASN1_BADTAG);
2917 else if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2918 lpszStructType, pbEncoded, cbEncoded,
2919 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2922 *pcbStructInfo = bytesNeeded;
2923 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2924 pvStructInfo, pcbStructInfo, bytesNeeded)))
2926 CRYPT_DATA_BLOB *blob;
2928 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2929 pvStructInfo = *(BYTE **)pvStructInfo;
2930 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2931 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
2932 ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2933 lpszStructType, pbEncoded, cbEncoded,
2934 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2941 SetLastError(STATUS_ACCESS_VIOLATION);
2948 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
2949 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2950 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2954 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2955 pDecodePara, pvStructInfo, *pcbStructInfo);
2957 if (pbEncoded[0] == ASN_BITSTRING)
2959 DWORD bytesNeeded, dataLen;
2961 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2963 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2964 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
2966 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
2968 *pcbStructInfo = bytesNeeded;
2969 else if (*pcbStructInfo < bytesNeeded)
2971 *pcbStructInfo = bytesNeeded;
2972 SetLastError(ERROR_MORE_DATA);
2977 CRYPT_BIT_BLOB *blob;
2979 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2980 blob->cbData = dataLen - 1;
2981 blob->cUnusedBits = *(pbEncoded + 1 +
2982 GET_LEN_BYTES(pbEncoded[1]));
2983 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2985 blob->pbData = (BYTE *)pbEncoded + 2 +
2986 GET_LEN_BYTES(pbEncoded[1]);
2990 assert(blob->pbData);
2993 BYTE mask = 0xff << blob->cUnusedBits;
2995 memcpy(blob->pbData, pbEncoded + 2 +
2996 GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
2997 blob->pbData[blob->cbData - 1] &= mask;
3005 SetLastError(CRYPT_E_ASN1_BADTAG);
3008 TRACE("returning %d (%08x)\n", ret, GetLastError());
3012 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
3013 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3014 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3018 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
3019 pDecodePara, pvStructInfo, pcbStructInfo);
3025 if ((ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
3026 lpszStructType, pbEncoded, cbEncoded,
3027 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
3030 *pcbStructInfo = bytesNeeded;
3031 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3032 pvStructInfo, pcbStructInfo, bytesNeeded)))
3034 CRYPT_BIT_BLOB *blob;
3036 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3037 pvStructInfo = *(BYTE **)pvStructInfo;
3038 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
3039 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
3040 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
3041 lpszStructType, pbEncoded, cbEncoded,
3042 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
3049 SetLastError(STATUS_ACCESS_VIOLATION);
3053 TRACE("returning %d (%08x)\n", ret, GetLastError());
3057 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3058 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3061 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
3062 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
3063 DWORD size = sizeof(buf);
3065 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
3066 if (pbEncoded[0] != ASN_INTEGER)
3068 SetLastError(CRYPT_E_ASN1_BADTAG);
3072 ret = CRYPT_AsnDecodeIntegerInternal(X509_ASN_ENCODING, NULL,
3073 pbEncoded, cbEncoded, 0, NULL, &buf, &size);
3077 *pcbStructInfo = sizeof(int);
3078 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int))))
3082 if (blob->pbData[blob->cbData - 1] & 0x80)
3084 /* initialize to a negative value to sign-extend */
3089 for (i = 0; i < blob->cbData; i++)
3092 val |= blob->pbData[blob->cbData - i - 1];
3094 memcpy(pvStructInfo, &val, sizeof(int));
3097 else if (GetLastError() == ERROR_MORE_DATA)
3098 SetLastError(CRYPT_E_ASN1_LARGE);
3102 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
3103 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3104 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3112 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3113 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3117 *pcbStructInfo = bytesNeeded;
3118 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3119 pvStructInfo, pcbStructInfo, bytesNeeded)))
3121 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3122 pvStructInfo = *(BYTE **)pvStructInfo;
3123 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3124 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3125 &bytesNeeded, NULL);
3131 SetLastError(STATUS_ACCESS_VIOLATION);
3138 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
3139 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3140 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3143 DWORD bytesNeeded, dataLen;
3145 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3147 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3149 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3151 *pcbStructInfo = bytesNeeded;
3152 else if (*pcbStructInfo < bytesNeeded)
3154 *pcbStructInfo = bytesNeeded;
3155 SetLastError(ERROR_MORE_DATA);
3160 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3162 blob->cbData = dataLen;
3163 assert(blob->pbData);
3168 for (i = 0; i < blob->cbData; i++)
3170 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3179 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
3180 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3181 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3189 if (pbEncoded[0] != ASN_INTEGER)
3191 SetLastError(CRYPT_E_ASN1_BADTAG);
3195 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
3196 lpszStructType, pbEncoded, cbEncoded,
3197 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded);
3201 *pcbStructInfo = bytesNeeded;
3202 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3203 pvStructInfo, pcbStructInfo, bytesNeeded)))
3205 CRYPT_INTEGER_BLOB *blob;
3207 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3208 pvStructInfo = *(BYTE **)pvStructInfo;
3209 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3210 blob->pbData = (BYTE *)pvStructInfo +
3211 sizeof(CRYPT_INTEGER_BLOB);
3212 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
3213 lpszStructType, pbEncoded, cbEncoded,
3214 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
3221 SetLastError(STATUS_ACCESS_VIOLATION);
3228 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
3229 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
3230 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3231 void *pvStructInfo, DWORD *pcbStructInfo)
3235 if (pbEncoded[0] == ASN_INTEGER)
3237 DWORD bytesNeeded, dataLen;
3239 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3241 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3243 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3245 *pcbStructInfo = bytesNeeded;
3246 else if (*pcbStructInfo < bytesNeeded)
3248 *pcbStructInfo = bytesNeeded;
3249 SetLastError(ERROR_MORE_DATA);
3254 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3256 blob->cbData = dataLen;
3257 assert(blob->pbData);
3258 /* remove leading zero byte if it exists */
3259 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
3268 for (i = 0; i < blob->cbData; i++)
3270 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3279 SetLastError(CRYPT_E_ASN1_BADTAG);
3285 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
3286 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3287 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3295 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
3296 lpszStructType, pbEncoded, cbEncoded,
3297 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
3300 *pcbStructInfo = bytesNeeded;
3301 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3302 pvStructInfo, pcbStructInfo, bytesNeeded)))
3304 CRYPT_INTEGER_BLOB *blob;
3306 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3307 pvStructInfo = *(BYTE **)pvStructInfo;
3308 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3309 blob->pbData = (BYTE *)pvStructInfo +
3310 sizeof(CRYPT_INTEGER_BLOB);
3311 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
3312 lpszStructType, pbEncoded, cbEncoded,
3313 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
3320 SetLastError(STATUS_ACCESS_VIOLATION);
3327 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
3328 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3329 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3335 *pcbStructInfo = sizeof(int);
3340 if (pbEncoded[0] == ASN_ENUMERATED)
3342 unsigned int val = 0, i;
3346 SetLastError(CRYPT_E_ASN1_EOD);
3349 else if (pbEncoded[1] == 0)
3351 SetLastError(CRYPT_E_ASN1_CORRUPT);
3356 /* A little strange looking, but we have to accept a sign byte:
3357 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
3358 * assuming a small length is okay here, it has to be in short
3361 if (pbEncoded[1] > sizeof(unsigned int) + 1)
3363 SetLastError(CRYPT_E_ASN1_LARGE);
3366 for (i = 0; i < pbEncoded[1]; i++)
3369 val |= pbEncoded[2 + i];
3371 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3372 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
3374 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3375 pvStructInfo = *(BYTE **)pvStructInfo;
3376 memcpy(pvStructInfo, &val, sizeof(unsigned int));
3382 SetLastError(CRYPT_E_ASN1_BADTAG);
3388 SetLastError(STATUS_ACCESS_VIOLATION);
3395 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
3398 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
3403 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
3405 if (!isdigit(*(pbEncoded))) \
3407 SetLastError(CRYPT_E_ASN1_CORRUPT); \
3413 (word) += *(pbEncoded)++ - '0'; \
3418 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
3419 SYSTEMTIME *sysTime)
3426 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
3428 WORD hours, minutes = 0;
3429 BYTE sign = *pbEncoded++;
3432 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
3433 if (ret && hours >= 24)
3435 SetLastError(CRYPT_E_ASN1_CORRUPT);
3440 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
3441 if (ret && minutes >= 60)
3443 SetLastError(CRYPT_E_ASN1_CORRUPT);
3451 sysTime->wHour += hours;
3452 sysTime->wMinute += minutes;
3456 if (hours > sysTime->wHour)
3459 sysTime->wHour = 24 - (hours - sysTime->wHour);
3462 sysTime->wHour -= hours;
3463 if (minutes > sysTime->wMinute)
3466 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
3469 sysTime->wMinute -= minutes;
3476 SetLastError(STATUS_ACCESS_VIOLATION);
3483 #define MIN_ENCODED_TIME_LENGTH 10
3485 static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
3486 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3491 if (pbEncoded[0] == ASN_UTCTIME)
3494 SetLastError(CRYPT_E_ASN1_EOD);
3495 else if (pbEncoded[1] > 0x7f)
3497 /* long-form date strings really can't be valid */
3498 SetLastError(CRYPT_E_ASN1_CORRUPT);
3502 SYSTEMTIME sysTime = { 0 };
3503 BYTE len = pbEncoded[1];
3505 if (len < MIN_ENCODED_TIME_LENGTH)
3506 SetLastError(CRYPT_E_ASN1_CORRUPT);
3511 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
3512 if (sysTime.wYear >= 50)
3513 sysTime.wYear += 1900;
3515 sysTime.wYear += 2000;
3516 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3517 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3518 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3519 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
3522 if (len >= 2 && isdigit(*pbEncoded) &&
3523 isdigit(*(pbEncoded + 1)))
3524 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3526 else if (isdigit(*pbEncoded))
3527 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
3530 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3536 *pcbStructInfo = sizeof(FILETIME);
3537 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
3539 ret = SystemTimeToFileTime(&sysTime,
3540 (FILETIME *)pvStructInfo);
3546 SetLastError(CRYPT_E_ASN1_BADTAG);
3550 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
3551 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3552 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3560 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
3561 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3565 *pcbStructInfo = bytesNeeded;
3566 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
3567 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
3569 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3570 pvStructInfo = *(BYTE **)pvStructInfo;
3571 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
3572 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3573 &bytesNeeded, NULL);
3579 SetLastError(STATUS_ACCESS_VIOLATION);
3585 static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
3586 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3591 if (pbEncoded[0] == ASN_GENERALTIME)
3594 SetLastError(CRYPT_E_ASN1_EOD);
3595 else if (pbEncoded[1] > 0x7f)
3597 /* long-form date strings really can't be valid */
3598 SetLastError(CRYPT_E_ASN1_CORRUPT);
3602 BYTE len = pbEncoded[1];
3604 if (len < MIN_ENCODED_TIME_LENGTH)
3605 SetLastError(CRYPT_E_ASN1_CORRUPT);
3608 SYSTEMTIME sysTime = { 0 };
3612 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
3613 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3614 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3615 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3618 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3621 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3623 if (ret && len > 0 && (*pbEncoded == '.' ||
3630 /* workaround macro weirdness */
3631 digits = min(len, 3);
3632 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
3633 sysTime.wMilliseconds);
3636 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3642 *pcbStructInfo = sizeof(FILETIME);
3643 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
3645 ret = SystemTimeToFileTime(&sysTime,
3646 (FILETIME *)pvStructInfo);
3652 SetLastError(CRYPT_E_ASN1_BADTAG);
3656 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
3657 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3661 InternalDecodeFunc decode = NULL;
3663 if (pbEncoded[0] == ASN_UTCTIME)
3664 decode = CRYPT_AsnDecodeUtcTimeInternal;
3665 else if (pbEncoded[0] == ASN_GENERALTIME)
3666 decode = CRYPT_AsnDecodeGeneralizedTime;
3668 ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
3669 pcbStructInfo, pcbDecoded);
3672 SetLastError(CRYPT_E_ASN1_BADTAG);
3678 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
3679 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3680 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3688 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
3689 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3693 *pcbStructInfo = bytesNeeded;
3694 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3695 pvStructInfo, pcbStructInfo, bytesNeeded)))
3697 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3698 pvStructInfo = *(BYTE **)pvStructInfo;
3699 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
3700 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3701 &bytesNeeded, NULL);
3707 SetLastError(STATUS_ACCESS_VIOLATION);
3714 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
3715 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3716 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3722 if (pbEncoded[0] == ASN_SEQUENCEOF)
3724 DWORD bytesNeeded, dataLen, remainingLen, cValue;
3726 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3731 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3732 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
3734 ptr = pbEncoded + 1 + lenBytes;
3735 remainingLen = dataLen;
3736 while (ret && remainingLen)
3740 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3743 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3745 remainingLen -= 1 + nextLenBytes + nextLen;
3746 ptr += 1 + nextLenBytes + nextLen;
3747 bytesNeeded += sizeof(CRYPT_DER_BLOB);
3748 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3749 bytesNeeded += 1 + nextLenBytes + nextLen;
3755 CRYPT_SEQUENCE_OF_ANY *seq;
3759 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3760 pvStructInfo, pcbStructInfo, bytesNeeded)))
3762 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3763 pvStructInfo = *(BYTE **)pvStructInfo;
3764 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
3765 seq->cValue = cValue;
3766 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
3768 nextPtr = (BYTE *)seq->rgValue +
3769 cValue * sizeof(CRYPT_DER_BLOB);
3770 ptr = pbEncoded + 1 + lenBytes;
3771 remainingLen = dataLen;
3773 while (ret && remainingLen)
3777 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3780 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3782 seq->rgValue[i].cbData = 1 + nextLenBytes +
3784 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3785 seq->rgValue[i].pbData = (BYTE *)ptr;
3788 seq->rgValue[i].pbData = nextPtr;
3789 memcpy(nextPtr, ptr, 1 + nextLenBytes +
3791 nextPtr += 1 + nextLenBytes + nextLen;
3793 remainingLen -= 1 + nextLenBytes + nextLen;
3794 ptr += 1 + nextLenBytes + nextLen;
3804 SetLastError(CRYPT_E_ASN1_BADTAG);
3810 SetLastError(STATUS_ACCESS_VIOLATION);
3817 static BOOL WINAPI CRYPT_AsnDecodeDistPointName(DWORD dwCertEncodingType,
3818 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3819 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3823 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
3825 DWORD bytesNeeded, dataLen;
3827 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3829 struct AsnArrayDescriptor arrayDesc = {
3830 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
3831 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3832 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3833 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3839 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3840 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3841 0, NULL, NULL, &nameLen, NULL, NULL);
3842 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen;
3845 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
3847 *pcbStructInfo = bytesNeeded;
3848 else if (*pcbStructInfo < bytesNeeded)
3850 *pcbStructInfo = bytesNeeded;
3851 SetLastError(ERROR_MORE_DATA);
3856 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
3860 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3861 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3862 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3863 0, NULL, &name->u.FullName, pcbStructInfo, NULL,
3864 name->u.FullName.rgAltEntry);
3867 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3873 SetLastError(CRYPT_E_ASN1_BADTAG);
3879 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
3880 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3882 struct AsnDecodeSequenceItem items[] = {
3883 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
3884 DistPointName), CRYPT_AsnDecodeDistPointName,
3885 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
3886 DistPointName.u.FullName.rgAltEntry), 0 },
3887 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
3888 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
3889 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
3890 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
3891 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
3892 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
3896 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
3897 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3898 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded, NULL);
3902 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
3903 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3904 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3908 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3909 pDecodePara, pvStructInfo, *pcbStructInfo);
3913 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3914 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
3915 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
3917 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3918 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
3922 SetLastError(STATUS_ACCESS_VIOLATION);
3929 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3930 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3931 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3935 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3936 pDecodePara, pvStructInfo, *pcbStructInfo);
3940 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3941 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
3943 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3944 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
3948 SetLastError(STATUS_ACCESS_VIOLATION);
3955 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
3956 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3957 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3961 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3962 pDecodePara, pvStructInfo, *pcbStructInfo);
3966 struct AsnDecodeSequenceItem items[] = {
3967 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
3968 DistPointName), CRYPT_AsnDecodeDistPointName,
3969 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
3970 offsetof(CRL_ISSUING_DIST_POINT,
3971 DistPointName.u.FullName.rgAltEntry), 0 },
3972 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
3973 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3975 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
3976 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3978 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
3979 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
3980 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
3981 OnlySomeReasonFlags.pbData), 0 },
3982 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
3983 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
3986 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3987 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3988 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
3992 SetLastError(STATUS_ACCESS_VIOLATION);
3999 static BOOL WINAPI CRYPT_AsnDecodeIssuerSerialNumber(DWORD dwCertEncodingType,
4000 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4001 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4004 struct AsnDecodeSequenceItem items[] = {
4005 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
4006 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
4008 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
4009 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
4010 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
4012 CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
4013 (CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
4015 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4016 pDecodePara, pvStructInfo, *pcbStructInfo);
4018 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
4019 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
4020 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL,
4021 issuerSerial ? issuerSerial->Issuer.pbData : NULL);
4022 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
4024 SetLastError(CRYPT_E_ASN1_CORRUPT);
4027 TRACE("returning %d\n", ret);
4031 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
4032 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4035 CMSG_SIGNER_INFO *info = (CMSG_SIGNER_INFO *)pvStructInfo;
4036 struct AsnDecodeSequenceItem items[] = {
4037 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
4038 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4039 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
4040 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
4041 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
4042 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
4043 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4044 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
4045 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4046 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
4047 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4048 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
4049 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
4050 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4051 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
4052 HashEncryptionAlgorithm.pszObjId), 0 },
4053 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
4054 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
4055 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
4056 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4057 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
4058 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4059 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
4063 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4064 pvStructInfo, *pcbStructInfo);
4066 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
4067 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
4068 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
4069 info ? info->Issuer.pbData : NULL);
4073 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
4074 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4075 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4079 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4080 pDecodePara, pvStructInfo, *pcbStructInfo);
4084 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
4085 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
4086 if (ret && pvStructInfo)
4088 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
4089 pcbStructInfo, *pcbStructInfo);
4092 CMSG_SIGNER_INFO *info;
4094 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4095 pvStructInfo = *(BYTE **)pvStructInfo;
4096 info = (CMSG_SIGNER_INFO *)pvStructInfo;
4097 info->Issuer.pbData = ((BYTE *)info +
4098 sizeof(CMSG_SIGNER_INFO));
4099 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
4100 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4101 pcbStructInfo, NULL);
4107 SetLastError(STATUS_ACCESS_VIOLATION);
4110 TRACE("returning %d\n", ret);
4114 static BOOL WINAPI CRYPT_DecodeSignerArray(DWORD dwCertEncodingType,
4115 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4116 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4119 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
4120 CRYPT_AsnDecodePKCSSignerInfoInternal, sizeof(CMSG_SIGNER_INFO), TRUE,
4121 offsetof(CMSG_SIGNER_INFO, Issuer.pbData) };
4122 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
4124 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4125 pDecodePara, pvStructInfo, *pcbStructInfo);
4127 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4128 pDecodePara, pvStructInfo, pcbStructInfo, NULL,
4129 array ? array->rgItems : NULL);
4133 BOOL CRYPT_AsnDecodePKCSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
4134 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
4135 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
4138 struct AsnDecodeSequenceItem items[] = {
4139 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version), CRYPT_AsnDecodeInt,
4140 sizeof(DWORD), FALSE, FALSE, 0, 0 },
4141 /* Placeholder for the hash algorithms - redundant with those in the
4142 * signers, so just ignore them.
4144 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
4145 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
4146 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
4147 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
4148 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4149 offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
4150 CRYPT_DecodeDERArray, sizeof(struct GenericArray), TRUE, TRUE,
4151 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
4152 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4153 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_DecodeDERArray,
4154 sizeof(struct GenericArray), TRUE, TRUE,
4155 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
4156 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
4157 CRYPT_DecodeSignerArray, sizeof(struct GenericArray), TRUE, TRUE,
4158 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
4161 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4162 pDecodePara, signedInfo, *pcbSignedInfo);
4164 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
4165 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
4166 pDecodePara, signedInfo, pcbSignedInfo, NULL, NULL);
4167 TRACE("returning %d\n", ret);
4171 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
4172 LPCSTR lpszStructType)
4174 CryptDecodeObjectExFunc decodeFunc = NULL;
4176 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
4177 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
4179 SetLastError(ERROR_FILE_NOT_FOUND);
4182 if (!HIWORD(lpszStructType))
4184 switch (LOWORD(lpszStructType))
4186 case (WORD)X509_CERT:
4187 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
4189 case (WORD)X509_CERT_TO_BE_SIGNED:
4190 decodeFunc = CRYPT_AsnDecodeCert;
4192 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
4193 decodeFunc = CRYPT_AsnDecodeCRL;
4195 case (WORD)X509_EXTENSIONS:
4196 decodeFunc = CRYPT_AsnDecodeExtensions;
4198 case (WORD)X509_NAME_VALUE:
4199 decodeFunc = CRYPT_AsnDecodeNameValue;
4201 case (WORD)X509_NAME:
4202 decodeFunc = CRYPT_AsnDecodeName;
4204 case (WORD)X509_PUBLIC_KEY_INFO:
4205 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
4207 case (WORD)X509_AUTHORITY_KEY_ID:
4208 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4210 case (WORD)X509_ALTERNATE_NAME:
4211 decodeFunc = CRYPT_AsnDecodeAltName;
4213 case (WORD)X509_BASIC_CONSTRAINTS:
4214 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4216 case (WORD)X509_BASIC_CONSTRAINTS2:
4217 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4219 case (WORD)RSA_CSP_PUBLICKEYBLOB:
4220 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
4222 case (WORD)X509_UNICODE_NAME:
4223 decodeFunc = CRYPT_AsnDecodeUnicodeName;
4225 case (WORD)PKCS_ATTRIBUTE:
4226 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
4228 case (WORD)X509_UNICODE_NAME_VALUE:
4229 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
4231 case (WORD)X509_OCTET_STRING:
4232 decodeFunc = CRYPT_AsnDecodeOctets;
4234 case (WORD)X509_BITS:
4235 case (WORD)X509_KEY_USAGE:
4236 decodeFunc = CRYPT_AsnDecodeBits;
4238 case (WORD)X509_INTEGER:
4239 decodeFunc = CRYPT_AsnDecodeInt;
4241 case (WORD)X509_MULTI_BYTE_INTEGER:
4242 decodeFunc = CRYPT_AsnDecodeInteger;
4244 case (WORD)X509_MULTI_BYTE_UINT:
4245 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
4247 case (WORD)X509_ENUMERATED:
4248 decodeFunc = CRYPT_AsnDecodeEnumerated;
4250 case (WORD)X509_CHOICE_OF_TIME:
4251 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
4253 case (WORD)X509_AUTHORITY_KEY_ID2:
4254 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4256 case (WORD)PKCS_CONTENT_INFO:
4257 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
4259 case (WORD)X509_SEQUENCE_OF_ANY:
4260 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
4262 case (WORD)PKCS_UTC_TIME:
4263 decodeFunc = CRYPT_AsnDecodeUtcTime;
4265 case (WORD)X509_CRL_DIST_POINTS:
4266 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4268 case (WORD)X509_ENHANCED_KEY_USAGE:
4269 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4271 case (WORD)PKCS_ATTRIBUTES:
4272 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
4274 case (WORD)X509_ISSUING_DIST_POINT:
4275 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4277 case (WORD)PKCS7_SIGNER_INFO:
4278 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
4282 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4283 decodeFunc = CRYPT_AsnDecodeExtensions;
4284 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4285 decodeFunc = CRYPT_AsnDecodeUtcTime;
4286 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4287 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4288 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4289 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4290 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4291 decodeFunc = CRYPT_AsnDecodeEnumerated;
4292 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4293 decodeFunc = CRYPT_AsnDecodeBits;
4294 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4295 decodeFunc = CRYPT_AsnDecodeOctets;
4296 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4297 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4298 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4299 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4300 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4301 decodeFunc = CRYPT_AsnDecodeAltName;
4302 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4303 decodeFunc = CRYPT_AsnDecodeAltName;
4304 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4305 decodeFunc = CRYPT_AsnDecodeAltName;
4306 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4307 decodeFunc = CRYPT_AsnDecodeAltName;
4308 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4309 decodeFunc = CRYPT_AsnDecodeAltName;
4310 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4311 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4312 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4313 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4314 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4315 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4319 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
4320 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4322 static HCRYPTOIDFUNCSET set = NULL;
4323 CryptDecodeObjectFunc decodeFunc = NULL;
4326 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
4327 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4328 (void **)&decodeFunc, hFunc);
4332 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
4333 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4335 static HCRYPTOIDFUNCSET set = NULL;
4336 CryptDecodeObjectExFunc decodeFunc = NULL;
4339 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
4340 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4341 (void **)&decodeFunc, hFunc);
4345 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4346 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
4347 DWORD *pcbStructInfo)
4350 CryptDecodeObjectFunc pCryptDecodeObject = NULL;
4351 CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
4352 HCRYPTOIDFUNCADDR hFunc = NULL;
4354 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
4355 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
4356 pvStructInfo, pcbStructInfo);
4358 if (!pvStructInfo && !pcbStructInfo)
4360 SetLastError(ERROR_INVALID_PARAMETER);
4365 SetLastError(CRYPT_E_ASN1_EOD);
4368 if (cbEncoded > MAX_ENCODED_LEN)
4370 SetLastError(CRYPT_E_ASN1_LARGE);
4374 if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
4377 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4378 debugstr_a(lpszStructType));
4379 pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
4380 lpszStructType, &hFunc);
4381 if (!pCryptDecodeObject)
4382 pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
4383 lpszStructType, &hFunc);
4385 if (pCryptDecodeObject)
4386 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4387 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4388 else if (pCryptDecodeObjectEx)
4389 ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
4390 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
4391 pvStructInfo, pcbStructInfo);
4393 CryptFreeOIDFunctionAddress(hFunc, 0);
4394 TRACE_(crypt)("returning %d\n", ret);
4398 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4399 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4400 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4403 CryptDecodeObjectExFunc decodeFunc;
4404 HCRYPTOIDFUNCADDR hFunc = NULL;
4406 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
4407 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
4408 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4410 if (!pvStructInfo && !pcbStructInfo)
4412 SetLastError(ERROR_INVALID_PARAMETER);
4417 SetLastError(CRYPT_E_ASN1_EOD);
4420 if (cbEncoded > MAX_ENCODED_LEN)
4422 SetLastError(CRYPT_E_ASN1_LARGE);
4426 SetLastError(NOERROR);
4427 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
4428 *(BYTE **)pvStructInfo = NULL;
4429 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
4432 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4433 debugstr_a(lpszStructType));
4434 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
4438 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
4439 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4442 CryptDecodeObjectFunc pCryptDecodeObject =
4443 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
4445 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
4446 * directly, as that could cause an infinite loop.
4448 if (pCryptDecodeObject)
4450 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4452 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4453 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
4454 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4455 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
4456 ret = pCryptDecodeObject(dwCertEncodingType,
4457 lpszStructType, pbEncoded, cbEncoded, dwFlags,
4458 *(BYTE **)pvStructInfo, pcbStructInfo);
4461 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4462 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4466 CryptFreeOIDFunctionAddress(hFunc, 0);
4467 TRACE_(crypt)("returning %d\n", ret);