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 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
76 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
78 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
79 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
81 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
82 * time, doesn't do memory allocation, and doesn't do exception handling.
84 static BOOL CRYPT_AsnDecodeExtensionsInternal(const BYTE *pbEncoded,
85 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
87 /* Assumes algo->Parameters.pbData is set ahead of time. */
88 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
89 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
90 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
91 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
92 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
93 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
94 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
96 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
97 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
98 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
99 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
100 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
101 * member has been initialized, doesn't do exception handling, and doesn't do
102 * memory allocation. Also doesn't check tag, assumes the caller has checked
105 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
106 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
108 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
109 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
110 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
113 /* Gets the number of length bytes from the given (leading) length byte */
114 #define GET_LEN_BYTES(b) ((b) <= 0x80 ? 1 : 1 + ((b) & 0x7f))
116 /* Helper function to get the encoded length of the data starting at pbEncoded,
117 * where pbEncoded[0] is the tag. If the data are too short to contain a
118 * length or if the length is too large for cbEncoded, sets an appropriate
119 * error code and returns FALSE. If the encoded length is unknown due to
120 * indefinite length encoding, *len is set to CMSG_INDEFINITE_LENGTH.
122 static BOOL CRYPT_GetLengthIndefinite(const BYTE *pbEncoded, DWORD cbEncoded,
129 SetLastError(CRYPT_E_ASN1_CORRUPT);
132 else if (pbEncoded[1] <= 0x7f)
134 if (pbEncoded[1] + 1 > cbEncoded)
136 SetLastError(CRYPT_E_ASN1_EOD);
145 else if (pbEncoded[1] == 0x80)
147 *len = CMSG_INDEFINITE_LENGTH;
152 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
154 if (lenLen > sizeof(DWORD) + 1)
156 SetLastError(CRYPT_E_ASN1_LARGE);
159 else if (lenLen + 2 > cbEncoded)
161 SetLastError(CRYPT_E_ASN1_CORRUPT);
174 if (out + lenLen + 1 > cbEncoded)
176 SetLastError(CRYPT_E_ASN1_EOD);
189 /* Like CRYPT_GetLengthIndefinite, but disallows indefinite-length encoding. */
190 static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
194 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, len)) &&
195 *len == CMSG_INDEFINITE_LENGTH)
197 SetLastError(CRYPT_E_ASN1_CORRUPT);
203 /* Helper function to check *pcbStructInfo, set it to the required size, and
204 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
205 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
206 * pointer to the newly allocated memory.
208 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
209 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
214 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
216 if (pDecodePara && pDecodePara->pfnAlloc)
217 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
219 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
220 if (!*(BYTE **)pvStructInfo)
223 *pcbStructInfo = bytesNeeded;
225 else if (*pcbStructInfo < bytesNeeded)
227 *pcbStructInfo = bytesNeeded;
228 SetLastError(ERROR_MORE_DATA);
234 /* Helper function to check *pcbStructInfo and set it to the required size.
235 * Assumes pvStructInfo is not NULL.
237 static BOOL CRYPT_DecodeCheckSpace(DWORD *pcbStructInfo, DWORD bytesNeeded)
241 if (*pcbStructInfo < bytesNeeded)
243 *pcbStructInfo = bytesNeeded;
244 SetLastError(ERROR_MORE_DATA);
249 *pcbStructInfo = bytesNeeded;
256 * The expected tag of the item. If tag is 0, decodeFunc is called
257 * regardless of the tag value seen.
259 * A sequence is decoded into a struct. The offset member is the
260 * offset of this item within that struct.
262 * The decoder function to use. If this is NULL, then the member isn't
263 * decoded, but minSize space is reserved for it.
265 * The minimum amount of space occupied after decoding. You must set this.
267 * If true, and the tag doesn't match the expected tag for this item,
268 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
269 * filled with 0 for this member.
270 * hasPointer, pointerOffset:
271 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
272 * the offset within the struct of the data pointer (or to the
273 * first data pointer, if more than one exist).
275 * Used by CRYPT_AsnDecodeSequence, not for your use.
277 struct AsnDecodeSequenceItem
281 InternalDecodeFunc decodeFunc;
289 /* Decodes the items in a sequence, where the items are described in items,
290 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
291 * pvStructInfo. nextData is a pointer to the memory location at which the
292 * first decoded item with a dynamic pointer should point.
293 * Upon decoding, *cbDecoded is the total number of bytes decoded.
294 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
296 static BOOL CRYPT_AsnDecodeSequenceItems(struct AsnDecodeSequenceItem items[],
297 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
298 void *pvStructInfo, BYTE *nextData, DWORD *cbDecoded)
301 DWORD i, decoded = 0;
302 const BYTE *ptr = pbEncoded;
304 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
305 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
307 for (i = 0, ret = TRUE; ret && i < cItem; i++)
309 if (cbEncoded - (ptr - pbEncoded) != 0)
313 if ((ret = CRYPT_GetLengthIndefinite(ptr,
314 cbEncoded - (ptr - pbEncoded), &itemLen)))
316 BYTE itemLenBytes = GET_LEN_BYTES(ptr[1]);
318 if (ptr[0] == items[i].tag || !items[i].tag)
320 DWORD itemEncodedLen;
322 if (itemLen == CMSG_INDEFINITE_LENGTH)
323 itemEncodedLen = cbEncoded - (ptr - pbEncoded);
325 itemEncodedLen = 1 + itemLenBytes + itemLen;
326 if (nextData && pvStructInfo && items[i].hasPointer)
328 TRACE("Setting next pointer to %p\n",
330 *(BYTE **)((BYTE *)pvStructInfo +
331 items[i].pointerOffset) = nextData;
333 if (items[i].decodeFunc)
338 TRACE("decoding item %d\n", i);
340 TRACE("sizing item %d\n", i);
341 ret = items[i].decodeFunc(ptr, itemEncodedLen,
342 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
343 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
344 : NULL, &items[i].size, &itemDecoded);
347 /* Account for alignment padding */
348 if (items[i].size % sizeof(DWORD_PTR))
349 items[i].size += sizeof(DWORD_PTR) -
350 items[i].size % sizeof(DWORD_PTR);
351 TRACE("item %d size: %d\n", i, items[i].size);
352 if (nextData && items[i].hasPointer &&
353 items[i].size > items[i].minSize)
354 nextData += items[i].size - items[i].minSize;
355 if (itemDecoded > itemEncodedLen)
357 WARN("decoded length %d exceeds encoded %d\n",
358 itemDecoded, itemEncodedLen);
359 SetLastError(CRYPT_E_ASN1_CORRUPT);
364 if (itemLen == CMSG_INDEFINITE_LENGTH)
366 if (itemDecoded > itemEncodedLen - 2 ||
367 *(ptr + itemDecoded) != 0 ||
368 *(ptr + itemDecoded + 1) != 0)
370 TRACE("expected 0 TLV\n");
371 SetLastError(CRYPT_E_ASN1_CORRUPT);
380 decoded += itemDecoded;
381 TRACE("item %d: decoded %d bytes\n", i,
386 else if (items[i].optional &&
387 GetLastError() == CRYPT_E_ASN1_BADTAG)
389 TRACE("skipping optional item %d\n", i);
390 items[i].size = items[i].minSize;
391 SetLastError(NOERROR);
395 TRACE("item %d failed: %08x\n", i,
398 else if (itemLen == CMSG_INDEFINITE_LENGTH)
400 ERR("can't use indefinite length encoding without a decoder\n");
401 SetLastError(CRYPT_E_ASN1_CORRUPT);
406 TRACE("item %d: decoded %d bytes\n", i, itemEncodedLen);
407 ptr += itemEncodedLen;
408 decoded += itemEncodedLen;
409 items[i].size = items[i].minSize;
412 else if (items[i].optional)
414 TRACE("skipping optional item %d\n", i);
415 items[i].size = items[i].minSize;
419 TRACE("item %d: tag %02x doesn't match expected %02x\n",
420 i, ptr[0], items[i].tag);
421 SetLastError(CRYPT_E_ASN1_BADTAG);
426 else if (items[i].optional)
428 TRACE("missing optional item %d, skipping\n", i);
429 items[i].size = items[i].minSize;
433 TRACE("not enough bytes for item %d, failing\n", i);
434 SetLastError(CRYPT_E_ASN1_CORRUPT);
439 *cbDecoded = decoded;
440 TRACE("returning %d\n", ret);
444 /* This decodes an arbitrary sequence into a contiguous block of memory
445 * (basically, a struct.) Each element being decoded is described by a struct
446 * AsnDecodeSequenceItem, see above.
447 * startingPointer is an optional pointer to the first place where dynamic
448 * data will be stored. If you know the starting offset, you may pass it
449 * here. Otherwise, pass NULL, and one will be inferred from the items.
451 static BOOL CRYPT_AsnDecodeSequence(struct AsnDecodeSequenceItem items[],
452 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
453 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
454 DWORD *pcbDecoded, void *startingPointer)
458 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
459 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
462 if (pbEncoded[0] == ASN_SEQUENCE)
466 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
468 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
469 const BYTE *ptr = pbEncoded + 1 + lenBytes;
471 cbEncoded -= 1 + lenBytes;
472 if (dataLen == CMSG_INDEFINITE_LENGTH)
474 else if (cbEncoded < dataLen)
476 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
478 SetLastError(CRYPT_E_ASN1_CORRUPT);
483 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
484 ptr, dataLen, dwFlags, NULL, NULL, &cbDecoded);
485 if (ret && dataLen == CMSG_INDEFINITE_LENGTH)
487 if (cbDecoded > cbEncoded - 2)
489 /* Not enough space for 0 TLV */
490 SetLastError(CRYPT_E_ASN1_CORRUPT);
493 else if (*(ptr + cbDecoded) != 0 ||
494 *(ptr + cbDecoded + 1) != 0)
496 TRACE("expected 0 TLV\n");
497 SetLastError(CRYPT_E_ASN1_CORRUPT);
504 if (ret && cbDecoded != dataLen)
506 TRACE("expected %d decoded, got %d, failing\n", dataLen,
508 SetLastError(CRYPT_E_ASN1_CORRUPT);
513 DWORD i, bytesNeeded = 0, structSize = 0;
515 for (i = 0; i < cItem; i++)
517 bytesNeeded += items[i].size;
518 structSize += items[i].minSize;
521 *pcbDecoded = 1 + lenBytes + cbDecoded;
523 *pcbStructInfo = bytesNeeded;
524 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
525 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
529 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
530 pvStructInfo = *(BYTE **)pvStructInfo;
532 nextData = (BYTE *)startingPointer;
534 nextData = (BYTE *)pvStructInfo + structSize;
535 memset(pvStructInfo, 0, structSize);
536 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
537 ptr, dataLen, dwFlags, pvStructInfo, nextData,
545 SetLastError(CRYPT_E_ASN1_BADTAG);
548 TRACE("returning %d (%08x)\n", ret, GetLastError());
553 * The expected tag of the entire encoded array (usually a variant
554 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
555 * regardless of the tag seen.
557 * used to decode each item in the array
559 * is the minimum size of each decoded item
561 * indicates whether each item has a dynamic pointer
563 * indicates the offset within itemSize at which the pointer exists
565 struct AsnArrayDescriptor
568 InternalDecodeFunc decodeFunc;
574 struct AsnArrayItemSize
580 /* Decodes an array of like types into a struct GenericArray.
581 * The layout and decoding of the array are described by a struct
582 * AsnArrayDescriptor.
584 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
585 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
586 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
587 DWORD *pcbDecoded, void *startingPointer)
591 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
592 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
595 if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
599 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
601 DWORD bytesNeeded, cItems = 0, decoded;
602 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
603 /* There can be arbitrarily many items, but there is often only one.
605 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
607 decoded = 1 + lenBytes;
608 bytesNeeded = sizeof(struct GenericArray);
612 BOOL doneDecoding = FALSE;
614 for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
618 itemLenBytes = GET_LEN_BYTES(ptr[1]);
619 if (dataLen == CMSG_INDEFINITE_LENGTH)
624 if (itemLenBytes != 1 || ptr[1] != 0)
626 SetLastError(CRYPT_E_ASN1_CORRUPT);
633 else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
637 DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
639 /* Each item decoded may not tolerate extraneous bytes,
640 * so get the length of the next element if known.
642 if ((ret = CRYPT_GetLengthIndefinite(ptr,
643 cbEncoded - (ptr - pbEncoded), &itemDataLen)))
645 if (itemDataLen == CMSG_INDEFINITE_LENGTH)
646 itemEncoded = cbEncoded - (ptr - pbEncoded);
648 itemEncoded = 1 + itemLenBytes + itemDataLen;
651 ret = arrayDesc->decodeFunc(ptr, itemEncoded,
652 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size,
657 if (itemSizes != &itemSize)
658 itemSizes = CryptMemRealloc(itemSizes,
659 cItems * sizeof(struct AsnArrayItemSize));
664 cItems * sizeof(struct AsnArrayItemSize));
666 memcpy(itemSizes, &itemSize,
671 decoded += itemDecoded;
672 itemSizes[cItems - 1].encodedLen = itemEncoded;
673 itemSizes[cItems - 1].size = size;
686 *pcbDecoded = decoded;
688 *pcbStructInfo = bytesNeeded;
689 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
690 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
695 struct GenericArray *array;
697 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
698 pvStructInfo = *(BYTE **)pvStructInfo;
699 array = (struct GenericArray *)pvStructInfo;
700 array->cItems = cItems;
702 array->rgItems = startingPointer;
704 array->rgItems = (BYTE *)array +
705 sizeof(struct GenericArray);
706 nextData = (BYTE *)array->rgItems +
707 array->cItems * arrayDesc->itemSize;
708 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
709 i < cItems && ptr - pbEncoded - 1 - lenBytes <
712 if (arrayDesc->hasPointer)
713 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
714 + arrayDesc->pointerOffset) = nextData;
715 ret = arrayDesc->decodeFunc(ptr,
716 itemSizes[i].encodedLen,
717 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
718 array->rgItems + i * arrayDesc->itemSize,
719 &itemSizes[i].size, NULL);
724 nextData += itemSizes[i].size - arrayDesc->itemSize;
725 ret = CRYPT_GetLen(ptr,
726 cbEncoded - (ptr - pbEncoded), &nextLen);
728 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
733 if (itemSizes != &itemSize)
734 CryptMemFree(itemSizes);
739 SetLastError(CRYPT_E_ASN1_BADTAG);
745 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
746 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
747 * to CRYPT_E_ASN1_CORRUPT.
748 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
751 static BOOL CRYPT_AsnDecodeDerBlob(const BYTE *pbEncoded, DWORD cbEncoded,
752 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
757 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
759 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
760 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
762 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
763 bytesNeeded += 1 + lenBytes + dataLen;
766 *pcbDecoded = 1 + lenBytes + dataLen;
768 *pcbStructInfo = bytesNeeded;
769 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded)))
771 CRYPT_DER_BLOB *blob;
773 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
774 pvStructInfo = *(BYTE **)pvStructInfo;
775 blob = (CRYPT_DER_BLOB *)pvStructInfo;
776 blob->cbData = 1 + lenBytes + dataLen;
779 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
780 blob->pbData = (BYTE *)pbEncoded;
783 assert(blob->pbData);
784 memcpy(blob->pbData, pbEncoded, blob->cbData);
789 SetLastError(CRYPT_E_ASN1_CORRUPT);
797 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
798 static BOOL CRYPT_AsnDecodeBitsSwapBytes(const BYTE *pbEncoded,
799 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
804 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
805 pvStructInfo, *pcbStructInfo, pcbDecoded);
807 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
810 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
811 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
813 if (ret && pvStructInfo)
815 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
822 for (i = 0; i < blob->cbData / 2; i++)
824 temp = blob->pbData[i];
825 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
826 blob->pbData[blob->cbData - i - 1] = temp;
830 TRACE("returning %d (%08x)\n", ret, GetLastError());
834 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
835 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
836 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
840 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
841 pDecodePara, pvStructInfo, *pcbStructInfo);
845 struct AsnDecodeSequenceItem items[] = {
846 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
847 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
848 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
849 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
850 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
851 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
852 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
853 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
854 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
855 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
858 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
859 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
860 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
861 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
862 pcbStructInfo, NULL, NULL);
866 SetLastError(STATUS_ACCESS_VIOLATION);
871 TRACE("Returning %d (%08x)\n", ret, GetLastError());
875 static BOOL CRYPT_AsnDecodeCertVersion(const BYTE *pbEncoded, DWORD cbEncoded,
876 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
881 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
883 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
885 ret = CRYPT_AsnDecodeIntInternal(pbEncoded + 1 + lenBytes, dataLen,
886 dwFlags, pvStructInfo, pcbStructInfo, NULL);
888 *pcbDecoded = 1 + lenBytes + dataLen;
893 static BOOL CRYPT_AsnDecodeValidity(const BYTE *pbEncoded, DWORD cbEncoded,
894 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
898 struct AsnDecodeSequenceItem items[] = {
899 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
900 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
901 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
902 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
905 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
906 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
911 static BOOL CRYPT_AsnDecodeCertExtensions(const BYTE *pbEncoded,
912 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
918 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
920 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
922 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded + 1 + lenBytes,
923 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
924 if (ret && pcbDecoded)
925 *pcbDecoded = 1 + lenBytes + dataLen;
930 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
931 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
932 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
935 struct AsnDecodeSequenceItem items[] = {
936 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
937 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
938 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
939 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
940 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
941 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
942 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
943 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
944 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
945 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
947 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
948 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
950 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
951 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
953 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
954 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
955 FALSE, TRUE, offsetof(CERT_INFO,
956 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
957 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
958 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
959 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
960 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
961 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
962 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
963 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
964 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
965 offsetof(CERT_INFO, rgExtension), 0 },
968 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
969 pDecodePara, pvStructInfo, *pcbStructInfo);
971 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
972 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
974 if (ret && pvStructInfo)
978 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
979 info = *(CERT_INFO **)pvStructInfo;
981 info = (CERT_INFO *)pvStructInfo;
982 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
983 !info->Subject.cbData)
985 SetLastError(CRYPT_E_ASN1_CORRUPT);
986 /* Don't need to deallocate, because it should have failed on the
987 * first pass (and no memory was allocated.)
993 TRACE("Returning %d (%08x)\n", ret, GetLastError());
997 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
998 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
999 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1003 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1004 pDecodePara, pvStructInfo, *pcbStructInfo);
1010 /* Unless told not to, first try to decode it as a signed cert. */
1011 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1013 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
1015 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1016 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1017 (BYTE *)&signedCert, &size);
1021 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1022 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
1023 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
1024 pvStructInfo, pcbStructInfo);
1025 LocalFree(signedCert);
1028 /* Failing that, try it as an unsigned cert */
1032 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1033 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
1034 pDecodePara, pvStructInfo, pcbStructInfo);
1039 SetLastError(STATUS_ACCESS_VIOLATION);
1043 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1047 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
1048 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1051 struct AsnDecodeSequenceItem items[] = {
1052 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
1053 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
1054 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
1055 { 0, offsetof(CRL_ENTRY, RevocationDate),
1056 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
1057 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
1058 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1059 offsetof(CRL_ENTRY, rgExtension), 0 },
1061 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
1063 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
1066 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1067 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, pcbDecoded,
1068 entry ? entry->SerialNumber.pbData : NULL);
1072 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
1073 * been set prior to calling.
1075 static BOOL CRYPT_AsnDecodeCRLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
1076 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1079 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1080 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
1081 offsetof(CRL_ENTRY, SerialNumber.pbData) };
1082 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
1084 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1085 pvStructInfo, *pcbStructInfo, pcbDecoded);
1087 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1088 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1089 entries ? entries->rgItems : NULL);
1090 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1094 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1095 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1096 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1098 struct AsnDecodeSequenceItem items[] = {
1099 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1100 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1101 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1102 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1103 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1104 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1105 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1107 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1108 sizeof(FILETIME), FALSE, FALSE, 0 },
1109 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1110 sizeof(FILETIME), TRUE, FALSE, 0 },
1111 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1112 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
1113 offsetof(CRL_INFO, rgCRLEntry), 0 },
1114 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1115 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1116 offsetof(CRL_INFO, rgExtension), 0 },
1120 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1121 pDecodePara, pvStructInfo, *pcbStructInfo);
1123 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1124 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
1127 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1131 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1132 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1133 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1137 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1138 pDecodePara, pvStructInfo, *pcbStructInfo);
1144 /* Unless told not to, first try to decode it as a signed crl. */
1145 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1147 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1149 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1150 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1151 (BYTE *)&signedCrl, &size);
1155 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1156 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1157 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1158 pvStructInfo, pcbStructInfo);
1159 LocalFree(signedCrl);
1162 /* Failing that, try it as an unsigned crl */
1166 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1167 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1168 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1173 SetLastError(STATUS_ACCESS_VIOLATION);
1177 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1181 static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded,
1182 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1187 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1188 pvStructInfo, *pcbStructInfo);
1190 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1192 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1193 DWORD bytesNeeded = sizeof(LPSTR);
1197 /* The largest possible string for the first two components
1198 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1203 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1204 pbEncoded[1 + lenBytes] / 40,
1205 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1207 bytesNeeded += strlen(firstTwo) + 1;
1208 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1209 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1211 /* large enough for ".4000000" */
1215 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1222 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1225 SetLastError(CRYPT_E_ASN1_CORRUPT);
1232 snprintf(str, sizeof(str), ".%d", val);
1233 bytesNeeded += strlen(str);
1238 *pcbDecoded = 1 + lenBytes + dataLen;
1240 *pcbStructInfo = bytesNeeded;
1241 else if (*pcbStructInfo < bytesNeeded)
1243 *pcbStructInfo = bytesNeeded;
1244 SetLastError(ERROR_MORE_DATA);
1252 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1255 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1256 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1258 pszObjId += strlen(pszObjId);
1259 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1260 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1264 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1273 sprintf(pszObjId, ".%d", val);
1274 pszObjId += strlen(pszObjId);
1278 *(LPSTR *)pvStructInfo = NULL;
1279 *pcbStructInfo = bytesNeeded;
1285 static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded,
1286 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1290 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1291 pvStructInfo, *pcbStructInfo);
1293 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1294 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1295 pvStructInfo, pcbStructInfo, pcbDecoded);
1298 SetLastError(CRYPT_E_ASN1_BADTAG);
1304 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1307 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
1308 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1310 struct AsnDecodeSequenceItem items[] = {
1311 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1312 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1313 offsetof(CERT_EXTENSION, pszObjId), 0 },
1314 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1315 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1316 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1317 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1318 offsetof(CERT_EXTENSION, Value.pbData) },
1321 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1323 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1327 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1328 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1329 pbEncoded, cbEncoded, dwFlags, NULL, ext, pcbStructInfo,
1330 pcbDecoded, ext ? ext->pszObjId : NULL);
1332 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1333 debugstr_a(ext->pszObjId));
1334 TRACE("returning %d (%08x)\n", ret, GetLastError());
1338 static BOOL CRYPT_AsnDecodeExtensionsInternal(const BYTE *pbEncoded,
1339 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1343 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1344 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1345 offsetof(CERT_EXTENSION, pszObjId) };
1346 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1348 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1349 pvStructInfo, *pcbStructInfo, pcbDecoded);
1351 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1352 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1353 exts ? exts->rgExtension : NULL);
1357 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1358 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1359 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1365 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
1366 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1367 if (ret && pvStructInfo)
1369 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1370 pcbStructInfo, *pcbStructInfo);
1373 CERT_EXTENSIONS *exts;
1375 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1376 pvStructInfo = *(BYTE **)pvStructInfo;
1377 exts = (CERT_EXTENSIONS *)pvStructInfo;
1378 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1379 sizeof(CERT_EXTENSIONS));
1380 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
1381 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1382 pcbStructInfo, NULL);
1388 SetLastError(STATUS_ACCESS_VIOLATION);
1395 /* Warning: this assumes the address of value->Value.pbData is already set, in
1396 * order to avoid overwriting memory. (In some cases, it may change it, if it
1397 * doesn't copy anything to memory.) Be sure to set it correctly!
1399 static BOOL CRYPT_AsnDecodeNameValueInternal(const BYTE *pbEncoded,
1400 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1405 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1407 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1409 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1410 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1412 switch (pbEncoded[0])
1414 case ASN_OCTETSTRING:
1415 valueType = CERT_RDN_OCTET_STRING;
1416 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1417 bytesNeeded += dataLen;
1419 case ASN_NUMERICSTRING:
1420 valueType = CERT_RDN_NUMERIC_STRING;
1421 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1422 bytesNeeded += dataLen;
1424 case ASN_PRINTABLESTRING:
1425 valueType = CERT_RDN_PRINTABLE_STRING;
1426 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1427 bytesNeeded += dataLen;
1430 valueType = CERT_RDN_IA5_STRING;
1431 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1432 bytesNeeded += dataLen;
1435 valueType = CERT_RDN_T61_STRING;
1436 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1437 bytesNeeded += dataLen;
1439 case ASN_VIDEOTEXSTRING:
1440 valueType = CERT_RDN_VIDEOTEX_STRING;
1441 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1442 bytesNeeded += dataLen;
1444 case ASN_GRAPHICSTRING:
1445 valueType = CERT_RDN_GRAPHIC_STRING;
1446 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1447 bytesNeeded += dataLen;
1449 case ASN_VISIBLESTRING:
1450 valueType = CERT_RDN_VISIBLE_STRING;
1451 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1452 bytesNeeded += dataLen;
1454 case ASN_GENERALSTRING:
1455 valueType = CERT_RDN_GENERAL_STRING;
1456 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1457 bytesNeeded += dataLen;
1459 case ASN_UNIVERSALSTRING:
1460 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1461 SetLastError(CRYPT_E_ASN1_BADTAG);
1464 valueType = CERT_RDN_BMP_STRING;
1465 bytesNeeded += dataLen;
1467 case ASN_UTF8STRING:
1468 valueType = CERT_RDN_UTF8_STRING;
1469 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1470 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1473 SetLastError(CRYPT_E_ASN1_BADTAG);
1478 *pcbDecoded = 1 + lenBytes + dataLen;
1480 *pcbStructInfo = bytesNeeded;
1481 else if (*pcbStructInfo < bytesNeeded)
1483 *pcbStructInfo = bytesNeeded;
1484 SetLastError(ERROR_MORE_DATA);
1489 *pcbStructInfo = bytesNeeded;
1490 value->dwValueType = valueType;
1495 assert(value->Value.pbData);
1496 switch (pbEncoded[0])
1498 case ASN_OCTETSTRING:
1499 case ASN_NUMERICSTRING:
1500 case ASN_PRINTABLESTRING:
1503 case ASN_VIDEOTEXSTRING:
1504 case ASN_GRAPHICSTRING:
1505 case ASN_VISIBLESTRING:
1506 case ASN_GENERALSTRING:
1507 value->Value.cbData = dataLen;
1510 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1511 memcpy(value->Value.pbData,
1512 pbEncoded + 1 + lenBytes, dataLen);
1514 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1520 LPWSTR str = (LPWSTR)value->Value.pbData;
1522 value->Value.cbData = dataLen;
1523 for (i = 0; i < dataLen / 2; i++)
1524 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1525 pbEncoded[1 + lenBytes + 2 * i + 1];
1528 case ASN_UTF8STRING:
1530 LPWSTR str = (LPWSTR)value->Value.pbData;
1532 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1533 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1534 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1541 value->Value.cbData = 0;
1542 value->Value.pbData = NULL;
1549 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1550 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1551 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1557 ret = CRYPT_AsnDecodeNameValueInternal(pbEncoded, cbEncoded,
1558 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1559 if (ret && pvStructInfo)
1561 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1562 pcbStructInfo, *pcbStructInfo);
1565 CERT_NAME_VALUE *value;
1567 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1568 pvStructInfo = *(BYTE **)pvStructInfo;
1569 value = (CERT_NAME_VALUE *)pvStructInfo;
1570 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1571 ret = CRYPT_AsnDecodeNameValueInternal( pbEncoded, cbEncoded,
1572 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1573 pcbStructInfo, NULL);
1579 SetLastError(STATUS_ACCESS_VIOLATION);
1586 static BOOL CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE *pbEncoded,
1587 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1592 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1594 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1596 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1597 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1599 switch (pbEncoded[0])
1601 case ASN_NUMERICSTRING:
1602 valueType = CERT_RDN_NUMERIC_STRING;
1603 bytesNeeded += dataLen * 2;
1605 case ASN_PRINTABLESTRING:
1606 valueType = CERT_RDN_PRINTABLE_STRING;
1607 bytesNeeded += dataLen * 2;
1610 valueType = CERT_RDN_IA5_STRING;
1611 bytesNeeded += dataLen * 2;
1614 valueType = CERT_RDN_T61_STRING;
1615 bytesNeeded += dataLen * 2;
1617 case ASN_VIDEOTEXSTRING:
1618 valueType = CERT_RDN_VIDEOTEX_STRING;
1619 bytesNeeded += dataLen * 2;
1621 case ASN_GRAPHICSTRING:
1622 valueType = CERT_RDN_GRAPHIC_STRING;
1623 bytesNeeded += dataLen * 2;
1625 case ASN_VISIBLESTRING:
1626 valueType = CERT_RDN_VISIBLE_STRING;
1627 bytesNeeded += dataLen * 2;
1629 case ASN_GENERALSTRING:
1630 valueType = CERT_RDN_GENERAL_STRING;
1631 bytesNeeded += dataLen * 2;
1633 case ASN_UNIVERSALSTRING:
1634 valueType = CERT_RDN_UNIVERSAL_STRING;
1635 bytesNeeded += dataLen / 2;
1638 valueType = CERT_RDN_BMP_STRING;
1639 bytesNeeded += dataLen;
1641 case ASN_UTF8STRING:
1642 valueType = CERT_RDN_UTF8_STRING;
1643 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1644 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1647 SetLastError(CRYPT_E_ASN1_BADTAG);
1652 *pcbDecoded = 1 + lenBytes + dataLen;
1654 *pcbStructInfo = bytesNeeded;
1655 else if (*pcbStructInfo < bytesNeeded)
1657 *pcbStructInfo = bytesNeeded;
1658 SetLastError(ERROR_MORE_DATA);
1663 *pcbStructInfo = bytesNeeded;
1664 value->dwValueType = valueType;
1668 LPWSTR str = (LPWSTR)value->Value.pbData;
1670 assert(value->Value.pbData);
1671 switch (pbEncoded[0])
1673 case ASN_NUMERICSTRING:
1674 case ASN_PRINTABLESTRING:
1677 case ASN_VIDEOTEXSTRING:
1678 case ASN_GRAPHICSTRING:
1679 case ASN_VISIBLESTRING:
1680 case ASN_GENERALSTRING:
1681 value->Value.cbData = dataLen * 2;
1682 for (i = 0; i < dataLen; i++)
1683 str[i] = pbEncoded[1 + lenBytes + i];
1685 case ASN_UNIVERSALSTRING:
1686 value->Value.cbData = dataLen / 2;
1687 for (i = 0; i < dataLen / 4; i++)
1688 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1689 | pbEncoded[1 + lenBytes + 2 * i + 3];
1692 value->Value.cbData = dataLen;
1693 for (i = 0; i < dataLen / 2; i++)
1694 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1695 pbEncoded[1 + lenBytes + 2 * i + 1];
1697 case ASN_UTF8STRING:
1698 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1699 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1700 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1706 value->Value.cbData = 0;
1707 value->Value.pbData = NULL;
1714 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1715 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1716 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1722 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded, cbEncoded,
1723 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1724 if (ret && pvStructInfo)
1726 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1727 pcbStructInfo, *pcbStructInfo);
1730 CERT_NAME_VALUE *value;
1732 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1733 pvStructInfo = *(BYTE **)pvStructInfo;
1734 value = (CERT_NAME_VALUE *)pvStructInfo;
1735 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1736 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded,
1737 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1738 pcbStructInfo, NULL);
1744 SetLastError(STATUS_ACCESS_VIOLATION);
1751 static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
1752 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1755 struct AsnDecodeSequenceItem items[] = {
1756 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1757 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1758 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1759 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1760 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1761 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1763 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1765 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1766 pvStructInfo, *pcbStructInfo);
1769 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1770 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1771 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1772 attr ? attr->pszObjId : NULL);
1775 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1776 debugstr_a(attr->pszObjId));
1777 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1779 TRACE("returning %d (%08x)\n", ret, GetLastError());
1783 static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1784 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1787 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1788 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1789 offsetof(CERT_RDN_ATTR, pszObjId) };
1790 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1792 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1793 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1794 rdn ? rdn->rgRDNAttr : NULL);
1798 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1799 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1800 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1806 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1807 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1808 offsetof(CERT_RDN, rgRDNAttr) };
1810 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1811 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1815 SetLastError(STATUS_ACCESS_VIOLATION);
1822 static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
1823 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1827 struct AsnDecodeSequenceItem items[] = {
1828 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1829 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1830 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1831 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1832 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1833 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1835 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1837 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1838 pvStructInfo, *pcbStructInfo);
1841 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1842 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1843 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1844 attr ? attr->pszObjId : NULL);
1847 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1848 debugstr_a(attr->pszObjId));
1849 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1851 TRACE("returning %d (%08x)\n", ret, GetLastError());
1855 static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1856 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1859 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1860 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1861 offsetof(CERT_RDN_ATTR, pszObjId) };
1862 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1864 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1865 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1866 rdn ? rdn->rgRDNAttr : NULL);
1870 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1871 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1872 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1878 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1879 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1880 offsetof(CERT_RDN, rgRDNAttr) };
1882 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1883 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1887 SetLastError(STATUS_ACCESS_VIOLATION);
1894 static BOOL CRYPT_FindEncodedLen(const BYTE *pbEncoded, DWORD cbEncoded,
1897 BOOL ret = TRUE, done = FALSE;
1898 DWORD indefiniteNestingLevels = 0, decoded = 0;
1900 TRACE("(%p, %d)\n", pbEncoded, cbEncoded);
1907 else if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded,
1910 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1912 if (dataLen == CMSG_INDEFINITE_LENGTH)
1914 indefiniteNestingLevels++;
1915 pbEncoded += 1 + lenBytes;
1916 cbEncoded -= 1 + lenBytes;
1917 decoded += 1 + lenBytes;
1918 TRACE("indefiniteNestingLevels = %d\n",
1919 indefiniteNestingLevels);
1923 if (pbEncoded[0] == 0 && pbEncoded[1] == 0 &&
1924 indefiniteNestingLevels)
1926 indefiniteNestingLevels--;
1927 TRACE("indefiniteNestingLevels = %d\n",
1928 indefiniteNestingLevels);
1930 pbEncoded += 1 + lenBytes + dataLen;
1931 cbEncoded -= 1 + lenBytes + dataLen;
1932 decoded += 1 + lenBytes + dataLen;
1933 if (!indefiniteNestingLevels)
1937 } while (ret && !done);
1938 /* If we haven't found all 0 TLVs, we haven't found the end */
1939 if (ret && indefiniteNestingLevels)
1941 SetLastError(CRYPT_E_ASN1_EOD);
1945 *pcbDecoded = decoded;
1946 TRACE("returning %d (%d)\n", ret, ret ? *pcbDecoded : 0);
1950 static BOOL CRYPT_AsnDecodeCopyBytes(const BYTE *pbEncoded,
1951 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1955 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB), encodedLen = 0;
1957 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1958 pvStructInfo, *pcbStructInfo);
1960 if ((ret = CRYPT_FindEncodedLen(pbEncoded, cbEncoded, &encodedLen)))
1962 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1963 bytesNeeded += encodedLen;
1965 *pcbStructInfo = bytesNeeded;
1966 else if (*pcbStructInfo < bytesNeeded)
1968 SetLastError(ERROR_MORE_DATA);
1969 *pcbStructInfo = bytesNeeded;
1974 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1976 *pcbStructInfo = bytesNeeded;
1977 blob->cbData = encodedLen;
1978 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1979 blob->pbData = (LPBYTE)pbEncoded;
1982 assert(blob->pbData);
1983 memcpy(blob->pbData, pbEncoded, blob->cbData);
1987 *pcbDecoded = encodedLen;
1992 static BOOL CRYPT_DecodeDERArray(const BYTE *pbEncoded, DWORD cbEncoded,
1993 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1996 struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytes,
1997 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
1998 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
2000 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2001 pvStructInfo, *pcbStructInfo, pcbDecoded);
2003 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2004 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2005 array ? array->rgItems : NULL);
2009 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
2010 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2014 struct AsnDecodeSequenceItem items[] = {
2015 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
2016 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2017 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
2018 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
2019 CRYPT_DecodeDERArray, sizeof(struct GenericArray), FALSE, TRUE,
2020 offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
2022 PCRYPT_ATTRIBUTE attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
2024 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2025 pvStructInfo, *pcbStructInfo);
2027 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2028 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2029 pcbDecoded, attr ? attr->pszObjId : NULL);
2030 TRACE("returning %d\n", ret);
2034 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
2035 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2036 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2040 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2041 pDecodePara, pvStructInfo, *pcbStructInfo);
2047 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2048 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
2052 *pcbStructInfo = bytesNeeded;
2053 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2054 pvStructInfo, pcbStructInfo, bytesNeeded)))
2056 PCRYPT_ATTRIBUTE attr;
2058 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2059 pvStructInfo = *(BYTE **)pvStructInfo;
2060 attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
2061 attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
2062 sizeof(CRYPT_ATTRIBUTE));
2063 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2064 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
2071 SetLastError(STATUS_ACCESS_VIOLATION);
2074 TRACE("returning %d\n", ret);
2078 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
2079 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2082 struct AsnArrayDescriptor arrayDesc = { 0,
2083 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2084 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2085 PCRYPT_ATTRIBUTES attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
2088 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2089 NULL, pvStructInfo, pcbStructInfo, pcbDecoded, attrs ? attrs->rgAttr :
2094 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
2095 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2096 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2100 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2101 pDecodePara, pvStructInfo, *pcbStructInfo);
2108 SetLastError(CRYPT_E_ASN1_EOD);
2109 else if (pbEncoded[0] != (ASN_CONSTRUCTOR | ASN_SETOF))
2110 SetLastError(CRYPT_E_ASN1_CORRUPT);
2111 else if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
2112 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2116 *pcbStructInfo = bytesNeeded;
2117 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2118 pvStructInfo, pcbStructInfo, bytesNeeded)))
2120 PCRYPT_ATTRIBUTES attrs;
2122 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2123 pvStructInfo = *(BYTE **)pvStructInfo;
2124 attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
2125 attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
2126 sizeof(CRYPT_ATTRIBUTES));
2127 ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
2128 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2129 &bytesNeeded, NULL);
2135 SetLastError(STATUS_ACCESS_VIOLATION);
2138 TRACE("returning %d\n", ret);
2142 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
2143 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2145 CRYPT_ALGORITHM_IDENTIFIER *algo =
2146 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
2148 struct AsnDecodeSequenceItem items[] = {
2149 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
2150 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2151 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
2152 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
2153 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2154 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
2157 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2158 pvStructInfo, *pcbStructInfo, pcbDecoded);
2160 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2161 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2162 pcbDecoded, algo ? algo->pszObjId : NULL);
2163 if (ret && pvStructInfo)
2165 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
2166 debugstr_a(algo->pszObjId));
2171 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
2172 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2176 struct AsnDecodeSequenceItem items[] = {
2177 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
2178 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2179 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
2180 Algorithm.pszObjId) },
2181 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
2182 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2183 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
2185 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2187 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2188 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2189 pcbDecoded, info ? info->Algorithm.Parameters.pbData : NULL);
2193 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2194 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2195 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2203 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2204 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2207 *pcbStructInfo = bytesNeeded;
2208 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2209 pvStructInfo, pcbStructInfo, bytesNeeded)))
2211 PCERT_PUBLIC_KEY_INFO info;
2213 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2214 pvStructInfo = *(BYTE **)pvStructInfo;
2215 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2216 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2217 sizeof(CERT_PUBLIC_KEY_INFO);
2218 ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2219 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2220 &bytesNeeded, NULL);
2226 SetLastError(STATUS_ACCESS_VIOLATION);
2233 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
2234 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2240 SetLastError(CRYPT_E_ASN1_CORRUPT);
2243 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2245 SetLastError(CRYPT_E_ASN1_CORRUPT);
2248 if (pbEncoded[1] > 1)
2250 SetLastError(CRYPT_E_ASN1_CORRUPT);
2257 *pcbStructInfo = sizeof(BOOL);
2260 else if (*pcbStructInfo < sizeof(BOOL))
2262 *pcbStructInfo = sizeof(BOOL);
2263 SetLastError(ERROR_MORE_DATA);
2268 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2271 TRACE("returning %d (%08x)\n", ret, GetLastError());
2275 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2276 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2278 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
2279 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2282 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2283 pvStructInfo, *pcbStructInfo);
2287 SetLastError(CRYPT_E_ASN1_CORRUPT);
2290 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2291 if (1 + lenBytes > cbEncoded)
2293 SetLastError(CRYPT_E_ASN1_CORRUPT);
2296 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2298 switch (pbEncoded[0] & ASN_TYPE_MASK)
2300 case 1: /* rfc822Name */
2301 case 2: /* dNSName */
2302 case 6: /* uniformResourceIdentifier */
2303 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
2305 case 4: /* directoryName */
2306 case 7: /* iPAddress */
2307 bytesNeeded += dataLen;
2309 case 8: /* registeredID */
2310 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
2314 /* FIXME: ugly, shouldn't need to know internals of OID decode
2315 * function to use it.
2317 bytesNeeded += dataLen - sizeof(LPSTR);
2320 case 0: /* otherName */
2321 FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
2322 SetLastError(CRYPT_E_ASN1_BADTAG);
2325 case 3: /* x400Address, unimplemented */
2326 case 5: /* ediPartyName, unimplemented */
2327 TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
2328 SetLastError(CRYPT_E_ASN1_BADTAG);
2332 TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
2333 SetLastError(CRYPT_E_ASN1_CORRUPT);
2339 *pcbDecoded = 1 + lenBytes + dataLen;
2341 *pcbStructInfo = bytesNeeded;
2342 else if (*pcbStructInfo < bytesNeeded)
2344 *pcbStructInfo = bytesNeeded;
2345 SetLastError(ERROR_MORE_DATA);
2350 *pcbStructInfo = bytesNeeded;
2351 /* MS used values one greater than the asn1 ones.. sigh */
2352 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
2353 switch (pbEncoded[0] & ASN_TYPE_MASK)
2355 case 1: /* rfc822Name */
2356 case 2: /* dNSName */
2357 case 6: /* uniformResourceIdentifier */
2361 for (i = 0; i < dataLen; i++)
2362 entry->u.pwszURL[i] =
2363 (WCHAR)pbEncoded[1 + lenBytes + i];
2364 entry->u.pwszURL[i] = 0;
2365 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2366 debugstr_w(entry->u.pwszURL));
2369 case 4: /* directoryName */
2370 entry->dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
2371 /* The data are memory-equivalent with the IPAddress case,
2374 case 7: /* iPAddress */
2375 /* The next data pointer is in the pwszURL spot, that is,
2376 * the first 4 bytes. Need to move it to the next spot.
2378 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2379 entry->u.IPAddress.cbData = dataLen;
2380 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2383 case 8: /* registeredID */
2384 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
2385 &entry->u.pszRegisteredID, &dataLen, NULL);
2394 static BOOL CRYPT_AsnDecodeAltNameInternal(const BYTE *pbEncoded,
2395 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2399 struct AsnArrayDescriptor arrayDesc = { 0,
2400 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2401 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2402 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
2404 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2405 pvStructInfo, *pcbStructInfo, pcbDecoded);
2408 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2409 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2410 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2411 info ? info->rgAltEntry : NULL);
2415 /* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */
2416 static BOOL CRYPT_AsnDecodeIntegerSwapBytes(const BYTE *pbEncoded,
2417 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2422 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
2423 pvStructInfo, *pcbStructInfo, pcbDecoded);
2425 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2428 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
2429 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
2431 if (ret && pvStructInfo)
2433 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2440 for (i = 0; i < blob->cbData / 2; i++)
2442 temp = blob->pbData[i];
2443 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
2444 blob->pbData[blob->cbData - i - 1] = temp;
2448 TRACE("returning %d (%08x)\n", ret, GetLastError());
2452 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
2453 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2454 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2460 struct AsnDecodeSequenceItem items[] = {
2461 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
2462 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2463 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
2464 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2465 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
2466 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
2467 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
2468 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
2469 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2470 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2471 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
2474 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2475 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2476 pcbStructInfo, NULL, NULL);
2480 SetLastError(STATUS_ACCESS_VIOLATION);
2487 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
2488 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2489 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2495 struct AsnDecodeSequenceItem items[] = {
2496 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
2497 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2498 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
2499 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2500 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
2501 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
2502 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2503 AuthorityCertIssuer.rgAltEntry), 0 },
2504 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2505 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2506 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2507 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2508 AuthorityCertSerialNumber.pbData), 0 },
2511 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2512 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2513 pcbStructInfo, NULL, NULL);
2517 SetLastError(STATUS_ACCESS_VIOLATION);
2524 static BOOL CRYPT_AsnDecodePKCSContent(const BYTE *pbEncoded, DWORD cbEncoded,
2525 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2530 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2531 pvStructInfo, *pcbStructInfo, pcbDecoded);
2533 /* The caller has already checked the tag, no need to check it again.
2534 * Check the outer length is valid:
2536 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
2538 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2541 pbEncoded += 1 + lenBytes;
2542 cbEncoded -= 1 + lenBytes;
2543 if (dataLen == CMSG_INDEFINITE_LENGTH)
2544 cbEncoded -= 2; /* space for 0 TLV */
2545 /* Check the inner length is valid: */
2546 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &innerLen)))
2550 ret = CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags,
2551 pvStructInfo, pcbStructInfo, &decodedLen);
2552 if (dataLen == CMSG_INDEFINITE_LENGTH)
2554 if (*(pbEncoded + decodedLen) != 0 ||
2555 *(pbEncoded + decodedLen + 1) != 0)
2557 TRACE("expected 0 TLV, got {%02x,%02x}\n",
2558 *(pbEncoded + decodedLen),
2559 *(pbEncoded + decodedLen + 1));
2560 SetLastError(CRYPT_E_ASN1_CORRUPT);
2566 if (ret && pcbDecoded)
2568 *pcbDecoded = 1 + lenBytes + decodedLen;
2569 TRACE("decoded %d bytes\n", *pcbDecoded);
2576 static BOOL CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE *pbEncoded,
2577 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2580 CRYPT_CONTENT_INFO *info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2581 struct AsnDecodeSequenceItem items[] = {
2582 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
2583 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2584 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
2585 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
2586 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
2587 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
2588 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
2592 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2593 pvStructInfo, *pcbStructInfo, pcbDecoded);
2595 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2596 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2597 pcbDecoded, info ? info->pszObjId : NULL);
2601 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
2602 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2603 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2607 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2608 pDecodePara, pvStructInfo, *pcbStructInfo);
2612 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, cbEncoded,
2613 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
2614 if (ret && pvStructInfo)
2616 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
2617 pcbStructInfo, *pcbStructInfo);
2620 CRYPT_CONTENT_INFO *info;
2622 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2623 pvStructInfo = *(BYTE **)pvStructInfo;
2624 info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2625 info->pszObjId = (LPSTR)((BYTE *)info +
2626 sizeof(CRYPT_CONTENT_INFO));
2627 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded,
2628 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2629 pcbStructInfo, NULL);
2635 SetLastError(STATUS_ACCESS_VIOLATION);
2641 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
2642 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2643 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
2646 struct AsnDecodeSequenceItem items[] = {
2647 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version),
2648 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2649 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
2650 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2651 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
2653 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
2654 CRYPT_AsnDecodePKCSContentInfoInternal,
2655 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
2656 ContentInfo.pszObjId), 0 },
2657 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
2658 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
2659 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
2662 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2663 pbEncoded, cbEncoded, dwFlags, pDecodePara, digestedData, pcbDigestedData,
2668 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
2669 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2670 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2674 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2675 pDecodePara, pvStructInfo, *pcbStructInfo);
2681 if ((ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
2682 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2685 *pcbStructInfo = bytesNeeded;
2686 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2687 pvStructInfo, pcbStructInfo, bytesNeeded)))
2689 CERT_ALT_NAME_INFO *name;
2691 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2692 pvStructInfo = *(BYTE **)pvStructInfo;
2693 name = (CERT_ALT_NAME_INFO *)pvStructInfo;
2694 name->rgAltEntry = (PCERT_ALT_NAME_ENTRY)
2695 ((BYTE *)pvStructInfo + sizeof(CERT_ALT_NAME_INFO));
2696 ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
2697 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2698 &bytesNeeded, NULL);
2704 SetLastError(STATUS_ACCESS_VIOLATION);
2711 struct PATH_LEN_CONSTRAINT
2713 BOOL fPathLenConstraint;
2714 DWORD dwPathLenConstraint;
2717 static BOOL CRYPT_AsnDecodePathLenConstraint(const BYTE *pbEncoded,
2718 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2722 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT), size;
2724 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2725 pvStructInfo, *pcbStructInfo, pcbDecoded);
2729 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, NULL,
2731 *pcbStructInfo = bytesNeeded;
2733 else if (*pcbStructInfo < bytesNeeded)
2735 SetLastError(ERROR_MORE_DATA);
2736 *pcbStructInfo = bytesNeeded;
2741 struct PATH_LEN_CONSTRAINT *constraint =
2742 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
2744 size = sizeof(constraint->dwPathLenConstraint);
2745 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
2746 &constraint->dwPathLenConstraint, &size, pcbDecoded);
2748 constraint->fPathLenConstraint = TRUE;
2749 TRACE("got an int, dwPathLenConstraint is %d\n",
2750 constraint->dwPathLenConstraint);
2752 TRACE("returning %d (%08x)\n", ret, GetLastError());
2756 static BOOL CRYPT_AsnDecodeSubtreeConstraints(const BYTE *pbEncoded,
2757 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2761 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2762 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
2763 offsetof(CERT_NAME_BLOB, pbData) };
2764 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2766 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2767 pvStructInfo, *pcbStructInfo, pcbDecoded);
2769 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2770 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2771 entries ? entries->rgItems : NULL);
2772 TRACE("Returning %d (%08x)\n", ret, GetLastError());
2776 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
2777 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2778 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2784 struct AsnDecodeSequenceItem items[] = {
2785 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
2786 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2787 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
2788 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2789 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2790 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2791 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2792 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
2793 sizeof(struct GenericArray), TRUE, TRUE,
2794 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
2797 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2798 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2799 pcbStructInfo, NULL, NULL);
2803 SetLastError(STATUS_ACCESS_VIOLATION);
2810 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
2811 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2812 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2818 struct AsnDecodeSequenceItem items[] = {
2819 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
2820 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
2821 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
2822 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2823 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2826 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2827 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2828 pcbStructInfo, NULL, NULL);
2832 SetLastError(STATUS_ACCESS_VIOLATION);
2839 #define RSA1_MAGIC 0x31415352
2841 struct DECODED_RSA_PUB_KEY
2844 CRYPT_INTEGER_BLOB modulus;
2847 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
2848 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2849 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2855 struct AsnDecodeSequenceItem items[] = {
2856 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
2857 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2858 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
2860 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
2861 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2863 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
2866 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2867 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
2871 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2872 decodedKey->modulus.cbData;
2876 *pcbStructInfo = bytesNeeded;
2879 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2880 pvStructInfo, pcbStructInfo, bytesNeeded)))
2883 RSAPUBKEY *rsaPubKey;
2885 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2886 pvStructInfo = *(BYTE **)pvStructInfo;
2887 hdr = (BLOBHEADER *)pvStructInfo;
2888 hdr->bType = PUBLICKEYBLOB;
2889 hdr->bVersion = CUR_BLOB_VERSION;
2891 hdr->aiKeyAlg = CALG_RSA_KEYX;
2892 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
2893 sizeof(BLOBHEADER));
2894 rsaPubKey->magic = RSA1_MAGIC;
2895 rsaPubKey->pubexp = decodedKey->pubexp;
2896 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
2897 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
2898 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
2899 decodedKey->modulus.cbData);
2901 LocalFree(decodedKey);
2906 SetLastError(STATUS_ACCESS_VIOLATION);
2913 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
2914 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2918 DWORD bytesNeeded, dataLen;
2920 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2921 pvStructInfo, *pcbStructInfo, pcbDecoded);
2923 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2925 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2927 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2928 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
2930 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
2932 *pcbDecoded = 1 + lenBytes + dataLen;
2934 *pcbStructInfo = bytesNeeded;
2935 else if (*pcbStructInfo < bytesNeeded)
2937 SetLastError(ERROR_MORE_DATA);
2938 *pcbStructInfo = bytesNeeded;
2943 CRYPT_DATA_BLOB *blob;
2945 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2946 blob->cbData = dataLen;
2947 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2948 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
2951 assert(blob->pbData);
2953 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
2961 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
2962 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2963 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2967 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2968 pDecodePara, pvStructInfo, *pcbStructInfo);
2976 SetLastError(CRYPT_E_ASN1_CORRUPT);
2979 else if (pbEncoded[0] != ASN_OCTETSTRING)
2981 SetLastError(CRYPT_E_ASN1_BADTAG);
2984 else if ((ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
2985 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2988 *pcbStructInfo = bytesNeeded;
2989 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2990 pvStructInfo, pcbStructInfo, bytesNeeded)))
2992 CRYPT_DATA_BLOB *blob;
2994 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2995 pvStructInfo = *(BYTE **)pvStructInfo;
2996 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2997 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
2998 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
2999 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3000 &bytesNeeded, NULL);
3006 SetLastError(STATUS_ACCESS_VIOLATION);
3013 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3014 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3018 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
3019 pvStructInfo, *pcbStructInfo, pcbDecoded);
3021 if (pbEncoded[0] == ASN_BITSTRING)
3023 DWORD bytesNeeded, dataLen;
3024 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3026 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3028 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3029 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
3031 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
3033 *pcbDecoded = 1 + lenBytes + dataLen;
3035 *pcbStructInfo = bytesNeeded;
3036 else if (*pcbStructInfo < bytesNeeded)
3038 *pcbStructInfo = bytesNeeded;
3039 SetLastError(ERROR_MORE_DATA);
3044 CRYPT_BIT_BLOB *blob;
3046 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
3047 blob->cbData = dataLen - 1;
3048 blob->cUnusedBits = *(pbEncoded + 1 + lenBytes);
3049 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3051 blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes;
3055 assert(blob->pbData);
3058 BYTE mask = 0xff << blob->cUnusedBits;
3060 memcpy(blob->pbData, pbEncoded + 2 + lenBytes,
3062 blob->pbData[blob->cbData - 1] &= mask;
3070 SetLastError(CRYPT_E_ASN1_BADTAG);
3073 TRACE("returning %d (%08x)\n", ret, GetLastError());
3077 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
3078 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3079 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3083 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
3084 pDecodePara, pvStructInfo, pcbStructInfo);
3090 if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3091 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3094 *pcbStructInfo = bytesNeeded;
3095 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3096 pvStructInfo, pcbStructInfo, bytesNeeded)))
3098 CRYPT_BIT_BLOB *blob;
3100 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3101 pvStructInfo = *(BYTE **)pvStructInfo;
3102 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
3103 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
3104 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3105 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3106 &bytesNeeded, NULL);
3112 SetLastError(STATUS_ACCESS_VIOLATION);
3116 TRACE("returning %d (%08x)\n", ret, GetLastError());
3120 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3121 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3124 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
3125 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
3126 DWORD size = sizeof(buf);
3128 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
3129 if (pbEncoded[0] != ASN_INTEGER)
3131 SetLastError(CRYPT_E_ASN1_BADTAG);
3135 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded, 0, &buf,
3140 *pcbStructInfo = sizeof(int);
3141 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int))))
3145 if (blob->pbData[blob->cbData - 1] & 0x80)
3147 /* initialize to a negative value to sign-extend */
3152 for (i = 0; i < blob->cbData; i++)
3155 val |= blob->pbData[blob->cbData - i - 1];
3157 memcpy(pvStructInfo, &val, sizeof(int));
3160 else if (GetLastError() == ERROR_MORE_DATA)
3161 SetLastError(CRYPT_E_ASN1_LARGE);
3165 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
3166 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3167 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3175 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3176 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3180 *pcbStructInfo = bytesNeeded;
3181 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3182 pvStructInfo, pcbStructInfo, bytesNeeded)))
3184 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3185 pvStructInfo = *(BYTE **)pvStructInfo;
3186 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3187 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3188 &bytesNeeded, NULL);
3194 SetLastError(STATUS_ACCESS_VIOLATION);
3201 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
3202 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3206 DWORD bytesNeeded, dataLen;
3208 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3210 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3212 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3214 *pcbDecoded = 1 + lenBytes + dataLen;
3216 *pcbStructInfo = bytesNeeded;
3217 else if (*pcbStructInfo < bytesNeeded)
3219 *pcbStructInfo = bytesNeeded;
3220 SetLastError(ERROR_MORE_DATA);
3225 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3227 blob->cbData = dataLen;
3228 assert(blob->pbData);
3233 for (i = 0; i < blob->cbData; i++)
3235 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3244 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
3245 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3246 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3254 if (pbEncoded[0] != ASN_INTEGER)
3256 SetLastError(CRYPT_E_ASN1_BADTAG);
3260 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3261 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3265 *pcbStructInfo = bytesNeeded;
3266 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3267 pvStructInfo, pcbStructInfo, bytesNeeded)))
3269 CRYPT_INTEGER_BLOB *blob;
3271 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3272 pvStructInfo = *(BYTE **)pvStructInfo;
3273 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3274 blob->pbData = (BYTE *)pvStructInfo +
3275 sizeof(CRYPT_INTEGER_BLOB);
3276 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3277 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
3278 &bytesNeeded, NULL);
3284 SetLastError(STATUS_ACCESS_VIOLATION);
3291 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
3292 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3297 if (pbEncoded[0] == ASN_INTEGER)
3299 DWORD bytesNeeded, dataLen;
3301 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3303 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3306 *pcbDecoded = 1 + lenBytes + dataLen;
3307 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3309 *pcbStructInfo = bytesNeeded;
3310 else if (*pcbStructInfo < bytesNeeded)
3312 *pcbStructInfo = bytesNeeded;
3313 SetLastError(ERROR_MORE_DATA);
3318 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3320 blob->cbData = dataLen;
3321 assert(blob->pbData);
3322 /* remove leading zero byte if it exists */
3323 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
3332 for (i = 0; i < blob->cbData; i++)
3334 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3343 SetLastError(CRYPT_E_ASN1_BADTAG);
3349 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
3350 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3351 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3359 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded,
3360 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3363 *pcbStructInfo = bytesNeeded;
3364 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3365 pvStructInfo, pcbStructInfo, bytesNeeded)))
3367 CRYPT_INTEGER_BLOB *blob;
3369 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3370 pvStructInfo = *(BYTE **)pvStructInfo;
3371 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3372 blob->pbData = (BYTE *)pvStructInfo +
3373 sizeof(CRYPT_INTEGER_BLOB);
3374 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded,
3375 cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
3376 &bytesNeeded, NULL);
3382 SetLastError(STATUS_ACCESS_VIOLATION);
3389 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
3390 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3391 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3397 *pcbStructInfo = sizeof(int);
3402 if (pbEncoded[0] == ASN_ENUMERATED)
3404 unsigned int val = 0, i;
3408 SetLastError(CRYPT_E_ASN1_EOD);
3411 else if (pbEncoded[1] == 0)
3413 SetLastError(CRYPT_E_ASN1_CORRUPT);
3418 /* A little strange looking, but we have to accept a sign byte:
3419 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
3420 * assuming a small length is okay here, it has to be in short
3423 if (pbEncoded[1] > sizeof(unsigned int) + 1)
3425 SetLastError(CRYPT_E_ASN1_LARGE);
3428 for (i = 0; i < pbEncoded[1]; i++)
3431 val |= pbEncoded[2 + i];
3433 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3434 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
3436 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3437 pvStructInfo = *(BYTE **)pvStructInfo;
3438 memcpy(pvStructInfo, &val, sizeof(unsigned int));
3444 SetLastError(CRYPT_E_ASN1_BADTAG);
3450 SetLastError(STATUS_ACCESS_VIOLATION);
3457 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
3460 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
3465 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
3467 if (!isdigit(*(pbEncoded))) \
3469 SetLastError(CRYPT_E_ASN1_CORRUPT); \
3475 (word) += *(pbEncoded)++ - '0'; \
3480 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
3481 SYSTEMTIME *sysTime)
3485 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
3487 WORD hours, minutes = 0;
3488 BYTE sign = *pbEncoded++;
3491 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
3492 if (ret && hours >= 24)
3494 SetLastError(CRYPT_E_ASN1_CORRUPT);
3499 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
3500 if (ret && minutes >= 60)
3502 SetLastError(CRYPT_E_ASN1_CORRUPT);
3510 sysTime->wHour += hours;
3511 sysTime->wMinute += minutes;
3515 if (hours > sysTime->wHour)
3518 sysTime->wHour = 24 - (hours - sysTime->wHour);
3521 sysTime->wHour -= hours;
3522 if (minutes > sysTime->wMinute)
3525 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
3528 sysTime->wMinute -= minutes;
3535 #define MIN_ENCODED_TIME_LENGTH 10
3537 static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
3538 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3543 if (pbEncoded[0] == ASN_UTCTIME)
3546 SetLastError(CRYPT_E_ASN1_EOD);
3547 else if (pbEncoded[1] > 0x7f)
3549 /* long-form date strings really can't be valid */
3550 SetLastError(CRYPT_E_ASN1_CORRUPT);
3554 SYSTEMTIME sysTime = { 0 };
3555 BYTE len = pbEncoded[1];
3557 if (len < MIN_ENCODED_TIME_LENGTH)
3558 SetLastError(CRYPT_E_ASN1_CORRUPT);
3563 *pcbDecoded = 2 + len;
3565 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
3566 if (sysTime.wYear >= 50)
3567 sysTime.wYear += 1900;
3569 sysTime.wYear += 2000;
3570 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3571 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3572 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3573 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
3576 if (len >= 2 && isdigit(*pbEncoded) &&
3577 isdigit(*(pbEncoded + 1)))
3578 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3580 else if (isdigit(*pbEncoded))
3581 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
3584 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3590 *pcbStructInfo = sizeof(FILETIME);
3591 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
3593 ret = SystemTimeToFileTime(&sysTime,
3594 (FILETIME *)pvStructInfo);
3600 SetLastError(CRYPT_E_ASN1_BADTAG);
3604 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
3605 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3606 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3614 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
3615 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3619 *pcbStructInfo = bytesNeeded;
3620 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
3621 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
3623 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3624 pvStructInfo = *(BYTE **)pvStructInfo;
3625 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
3626 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3627 &bytesNeeded, NULL);
3633 SetLastError(STATUS_ACCESS_VIOLATION);
3639 static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
3640 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3645 if (pbEncoded[0] == ASN_GENERALTIME)
3648 SetLastError(CRYPT_E_ASN1_EOD);
3649 else if (pbEncoded[1] > 0x7f)
3651 /* long-form date strings really can't be valid */
3652 SetLastError(CRYPT_E_ASN1_CORRUPT);
3656 BYTE len = pbEncoded[1];
3658 if (len < MIN_ENCODED_TIME_LENGTH)
3659 SetLastError(CRYPT_E_ASN1_CORRUPT);
3662 SYSTEMTIME sysTime = { 0 };
3666 *pcbDecoded = 2 + len;
3668 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
3669 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3670 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3671 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3674 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3677 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3679 if (ret && len > 0 && (*pbEncoded == '.' ||
3686 /* workaround macro weirdness */
3687 digits = min(len, 3);
3688 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
3689 sysTime.wMilliseconds);
3692 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3698 *pcbStructInfo = sizeof(FILETIME);
3699 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
3701 ret = SystemTimeToFileTime(&sysTime,
3702 (FILETIME *)pvStructInfo);
3708 SetLastError(CRYPT_E_ASN1_BADTAG);
3712 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
3713 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3717 InternalDecodeFunc decode = NULL;
3719 if (pbEncoded[0] == ASN_UTCTIME)
3720 decode = CRYPT_AsnDecodeUtcTimeInternal;
3721 else if (pbEncoded[0] == ASN_GENERALTIME)
3722 decode = CRYPT_AsnDecodeGeneralizedTime;
3724 ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
3725 pcbStructInfo, pcbDecoded);
3728 SetLastError(CRYPT_E_ASN1_BADTAG);
3734 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
3735 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3736 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3744 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
3745 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3749 *pcbStructInfo = bytesNeeded;
3750 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3751 pvStructInfo, pcbStructInfo, bytesNeeded)))
3753 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3754 pvStructInfo = *(BYTE **)pvStructInfo;
3755 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
3756 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3757 &bytesNeeded, NULL);
3763 SetLastError(STATUS_ACCESS_VIOLATION);
3770 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
3771 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3772 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3778 if (pbEncoded[0] == ASN_SEQUENCEOF)
3780 DWORD bytesNeeded, dataLen, remainingLen, cValue;
3782 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3787 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3788 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
3790 ptr = pbEncoded + 1 + lenBytes;
3791 remainingLen = dataLen;
3792 while (ret && remainingLen)
3796 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3799 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3801 remainingLen -= 1 + nextLenBytes + nextLen;
3802 ptr += 1 + nextLenBytes + nextLen;
3803 bytesNeeded += sizeof(CRYPT_DER_BLOB);
3804 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3805 bytesNeeded += 1 + nextLenBytes + nextLen;
3811 CRYPT_SEQUENCE_OF_ANY *seq;
3815 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3816 pvStructInfo, pcbStructInfo, bytesNeeded)))
3818 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3819 pvStructInfo = *(BYTE **)pvStructInfo;
3820 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
3821 seq->cValue = cValue;
3822 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
3824 nextPtr = (BYTE *)seq->rgValue +
3825 cValue * sizeof(CRYPT_DER_BLOB);
3826 ptr = pbEncoded + 1 + lenBytes;
3827 remainingLen = dataLen;
3829 while (ret && remainingLen)
3833 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3836 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3838 seq->rgValue[i].cbData = 1 + nextLenBytes +
3840 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3841 seq->rgValue[i].pbData = (BYTE *)ptr;
3844 seq->rgValue[i].pbData = nextPtr;
3845 memcpy(nextPtr, ptr, 1 + nextLenBytes +
3847 nextPtr += 1 + nextLenBytes + nextLen;
3849 remainingLen -= 1 + nextLenBytes + nextLen;
3850 ptr += 1 + nextLenBytes + nextLen;
3860 SetLastError(CRYPT_E_ASN1_BADTAG);
3866 SetLastError(STATUS_ACCESS_VIOLATION);
3873 static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded,
3874 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3879 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
3881 DWORD bytesNeeded, dataLen;
3883 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3885 struct AsnArrayDescriptor arrayDesc = {
3886 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
3887 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3888 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3889 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3895 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3896 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3897 0, NULL, NULL, &nameLen, NULL, NULL);
3898 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen;
3901 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
3903 *pcbDecoded = 1 + lenBytes + dataLen;
3905 *pcbStructInfo = bytesNeeded;
3906 else if (*pcbStructInfo < bytesNeeded)
3908 *pcbStructInfo = bytesNeeded;
3909 SetLastError(ERROR_MORE_DATA);
3914 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
3918 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3919 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3920 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3921 0, NULL, &name->u.FullName, pcbStructInfo, NULL,
3922 name->u.FullName.rgAltEntry);
3925 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3931 SetLastError(CRYPT_E_ASN1_BADTAG);
3937 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
3938 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3940 struct AsnDecodeSequenceItem items[] = {
3941 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
3942 DistPointName), CRYPT_AsnDecodeDistPointName,
3943 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
3944 DistPointName.u.FullName.rgAltEntry), 0 },
3945 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
3946 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
3947 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
3948 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
3949 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
3950 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
3954 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3955 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3960 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
3961 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3962 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3966 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3967 pDecodePara, pvStructInfo, *pcbStructInfo);
3971 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3972 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
3973 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
3975 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3976 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
3980 SetLastError(STATUS_ACCESS_VIOLATION);
3987 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3988 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3989 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3993 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3994 pDecodePara, pvStructInfo, *pcbStructInfo);
3998 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3999 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
4001 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4002 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
4006 SetLastError(STATUS_ACCESS_VIOLATION);
4013 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
4014 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4015 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4019 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4020 pDecodePara, pvStructInfo, *pcbStructInfo);
4024 struct AsnDecodeSequenceItem items[] = {
4025 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
4026 DistPointName), CRYPT_AsnDecodeDistPointName,
4027 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
4028 offsetof(CRL_ISSUING_DIST_POINT,
4029 DistPointName.u.FullName.rgAltEntry), 0 },
4030 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
4031 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4033 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
4034 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4036 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
4037 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
4038 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
4039 OnlySomeReasonFlags.pbData), 0 },
4040 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
4041 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
4044 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4045 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
4046 pcbStructInfo, NULL, NULL);
4050 SetLastError(STATUS_ACCESS_VIOLATION);
4057 static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded,
4058 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4062 struct AsnDecodeSequenceItem items[] = {
4063 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
4064 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
4066 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
4067 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
4068 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
4070 CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
4071 (CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
4073 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4074 pvStructInfo, *pcbStructInfo, pcbDecoded);
4076 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4077 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4078 pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL);
4079 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
4081 SetLastError(CRYPT_E_ASN1_CORRUPT);
4084 TRACE("returning %d\n", ret);
4088 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
4089 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4092 CMSG_SIGNER_INFO *info = (CMSG_SIGNER_INFO *)pvStructInfo;
4093 struct AsnDecodeSequenceItem items[] = {
4094 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
4095 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4096 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
4097 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
4098 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
4099 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
4100 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4101 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
4102 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4103 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
4104 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4105 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
4106 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
4107 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4108 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
4109 HashEncryptionAlgorithm.pszObjId), 0 },
4110 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
4111 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
4112 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
4113 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4114 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
4115 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4116 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
4120 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4121 pvStructInfo, *pcbStructInfo);
4123 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4124 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4125 pcbDecoded, info ? info->Issuer.pbData : NULL);
4129 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
4130 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4131 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4135 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4136 pDecodePara, pvStructInfo, *pcbStructInfo);
4140 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
4141 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
4142 if (ret && pvStructInfo)
4144 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
4145 pcbStructInfo, *pcbStructInfo);
4148 CMSG_SIGNER_INFO *info;
4150 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4151 pvStructInfo = *(BYTE **)pvStructInfo;
4152 info = (CMSG_SIGNER_INFO *)pvStructInfo;
4153 info->Issuer.pbData = ((BYTE *)info +
4154 sizeof(CMSG_SIGNER_INFO));
4155 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
4156 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4157 pcbStructInfo, NULL);
4163 SetLastError(STATUS_ACCESS_VIOLATION);
4166 TRACE("returning %d\n", ret);
4170 static BOOL CRYPT_DecodeSignerArray(const BYTE *pbEncoded, DWORD cbEncoded,
4171 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4174 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
4175 CRYPT_AsnDecodePKCSSignerInfoInternal, sizeof(CMSG_SIGNER_INFO), TRUE,
4176 offsetof(CMSG_SIGNER_INFO, Issuer.pbData) };
4177 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
4179 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4180 pvStructInfo, *pcbStructInfo, pcbDecoded);
4182 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4183 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
4184 array ? array->rgItems : NULL);
4188 BOOL CRYPT_AsnDecodePKCSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
4189 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
4190 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
4193 struct AsnDecodeSequenceItem items[] = {
4194 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version),
4195 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4196 /* Placeholder for the hash algorithms - redundant with those in the
4197 * signers, so just ignore them.
4199 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
4200 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
4201 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
4202 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
4203 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4204 offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
4205 CRYPT_DecodeDERArray, sizeof(struct GenericArray), TRUE, TRUE,
4206 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
4207 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4208 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_DecodeDERArray,
4209 sizeof(struct GenericArray), TRUE, TRUE,
4210 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
4211 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
4212 CRYPT_DecodeSignerArray, sizeof(struct GenericArray), TRUE, TRUE,
4213 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
4216 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4217 pDecodePara, signedInfo, *pcbSignedInfo);
4219 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4220 pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo,
4222 TRACE("returning %d\n", ret);
4226 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
4227 LPCSTR lpszStructType)
4229 CryptDecodeObjectExFunc decodeFunc = NULL;
4231 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
4232 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
4234 SetLastError(ERROR_FILE_NOT_FOUND);
4237 if (!HIWORD(lpszStructType))
4239 switch (LOWORD(lpszStructType))
4241 case (WORD)X509_CERT:
4242 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
4244 case (WORD)X509_CERT_TO_BE_SIGNED:
4245 decodeFunc = CRYPT_AsnDecodeCert;
4247 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
4248 decodeFunc = CRYPT_AsnDecodeCRL;
4250 case (WORD)X509_EXTENSIONS:
4251 decodeFunc = CRYPT_AsnDecodeExtensions;
4253 case (WORD)X509_NAME_VALUE:
4254 decodeFunc = CRYPT_AsnDecodeNameValue;
4256 case (WORD)X509_NAME:
4257 decodeFunc = CRYPT_AsnDecodeName;
4259 case (WORD)X509_PUBLIC_KEY_INFO:
4260 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
4262 case (WORD)X509_AUTHORITY_KEY_ID:
4263 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4265 case (WORD)X509_ALTERNATE_NAME:
4266 decodeFunc = CRYPT_AsnDecodeAltName;
4268 case (WORD)X509_BASIC_CONSTRAINTS:
4269 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4271 case (WORD)X509_BASIC_CONSTRAINTS2:
4272 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4274 case (WORD)RSA_CSP_PUBLICKEYBLOB:
4275 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
4277 case (WORD)X509_UNICODE_NAME:
4278 decodeFunc = CRYPT_AsnDecodeUnicodeName;
4280 case (WORD)PKCS_ATTRIBUTE:
4281 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
4283 case (WORD)X509_UNICODE_NAME_VALUE:
4284 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
4286 case (WORD)X509_OCTET_STRING:
4287 decodeFunc = CRYPT_AsnDecodeOctets;
4289 case (WORD)X509_BITS:
4290 case (WORD)X509_KEY_USAGE:
4291 decodeFunc = CRYPT_AsnDecodeBits;
4293 case (WORD)X509_INTEGER:
4294 decodeFunc = CRYPT_AsnDecodeInt;
4296 case (WORD)X509_MULTI_BYTE_INTEGER:
4297 decodeFunc = CRYPT_AsnDecodeInteger;
4299 case (WORD)X509_MULTI_BYTE_UINT:
4300 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
4302 case (WORD)X509_ENUMERATED:
4303 decodeFunc = CRYPT_AsnDecodeEnumerated;
4305 case (WORD)X509_CHOICE_OF_TIME:
4306 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
4308 case (WORD)X509_AUTHORITY_KEY_ID2:
4309 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4311 case (WORD)PKCS_CONTENT_INFO:
4312 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
4314 case (WORD)X509_SEQUENCE_OF_ANY:
4315 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
4317 case (WORD)PKCS_UTC_TIME:
4318 decodeFunc = CRYPT_AsnDecodeUtcTime;
4320 case (WORD)X509_CRL_DIST_POINTS:
4321 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4323 case (WORD)X509_ENHANCED_KEY_USAGE:
4324 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4326 case (WORD)PKCS_ATTRIBUTES:
4327 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
4329 case (WORD)X509_ISSUING_DIST_POINT:
4330 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4332 case (WORD)PKCS7_SIGNER_INFO:
4333 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
4337 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4338 decodeFunc = CRYPT_AsnDecodeExtensions;
4339 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4340 decodeFunc = CRYPT_AsnDecodeUtcTime;
4341 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4342 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4343 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4344 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4345 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4346 decodeFunc = CRYPT_AsnDecodeEnumerated;
4347 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4348 decodeFunc = CRYPT_AsnDecodeBits;
4349 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4350 decodeFunc = CRYPT_AsnDecodeOctets;
4351 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4352 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4353 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4354 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4355 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4356 decodeFunc = CRYPT_AsnDecodeAltName;
4357 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4358 decodeFunc = CRYPT_AsnDecodeAltName;
4359 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4360 decodeFunc = CRYPT_AsnDecodeAltName;
4361 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4362 decodeFunc = CRYPT_AsnDecodeAltName;
4363 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4364 decodeFunc = CRYPT_AsnDecodeAltName;
4365 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4366 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4367 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4368 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4369 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4370 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4374 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
4375 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4377 static HCRYPTOIDFUNCSET set = NULL;
4378 CryptDecodeObjectFunc decodeFunc = NULL;
4381 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
4382 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4383 (void **)&decodeFunc, hFunc);
4387 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
4388 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4390 static HCRYPTOIDFUNCSET set = NULL;
4391 CryptDecodeObjectExFunc decodeFunc = NULL;
4394 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
4395 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4396 (void **)&decodeFunc, hFunc);
4400 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4401 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
4402 DWORD *pcbStructInfo)
4405 CryptDecodeObjectFunc pCryptDecodeObject = NULL;
4406 CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
4407 HCRYPTOIDFUNCADDR hFunc = NULL;
4409 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
4410 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
4411 pvStructInfo, pcbStructInfo);
4413 if (!pvStructInfo && !pcbStructInfo)
4415 SetLastError(ERROR_INVALID_PARAMETER);
4420 SetLastError(CRYPT_E_ASN1_EOD);
4423 if (cbEncoded > MAX_ENCODED_LEN)
4425 SetLastError(CRYPT_E_ASN1_LARGE);
4429 if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
4432 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4433 debugstr_a(lpszStructType));
4434 pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
4435 lpszStructType, &hFunc);
4436 if (!pCryptDecodeObject)
4437 pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
4438 lpszStructType, &hFunc);
4440 if (pCryptDecodeObject)
4441 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4442 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4443 else if (pCryptDecodeObjectEx)
4444 ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
4445 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
4446 pvStructInfo, pcbStructInfo);
4448 CryptFreeOIDFunctionAddress(hFunc, 0);
4449 TRACE_(crypt)("returning %d\n", ret);
4453 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4454 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4455 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4458 CryptDecodeObjectExFunc decodeFunc;
4459 HCRYPTOIDFUNCADDR hFunc = NULL;
4461 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
4462 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
4463 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4465 if (!pvStructInfo && !pcbStructInfo)
4467 SetLastError(ERROR_INVALID_PARAMETER);
4472 SetLastError(CRYPT_E_ASN1_EOD);
4475 if (cbEncoded > MAX_ENCODED_LEN)
4477 SetLastError(CRYPT_E_ASN1_LARGE);
4481 SetLastError(NOERROR);
4482 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
4483 *(BYTE **)pvStructInfo = NULL;
4484 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
4487 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4488 debugstr_a(lpszStructType));
4489 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
4493 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
4494 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4497 CryptDecodeObjectFunc pCryptDecodeObject =
4498 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
4500 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
4501 * directly, as that could cause an infinite loop.
4503 if (pCryptDecodeObject)
4505 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4507 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4508 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
4509 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4510 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
4511 ret = pCryptDecodeObject(dwCertEncodingType,
4512 lpszStructType, pbEncoded, cbEncoded, dwFlags,
4513 *(BYTE **)pvStructInfo, pcbStructInfo);
4516 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4517 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4521 CryptFreeOIDFunctionAddress(hFunc, 0);
4522 TRACE_(crypt)("returning %d\n", ret);