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;
470 BOOL indefinite = FALSE;
472 cbEncoded -= 1 + lenBytes;
473 if (dataLen == CMSG_INDEFINITE_LENGTH)
478 else if (cbEncoded < dataLen)
480 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
482 SetLastError(CRYPT_E_ASN1_CORRUPT);
487 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
488 ptr, dataLen, dwFlags, NULL, NULL, &cbDecoded);
489 if (ret && dataLen == CMSG_INDEFINITE_LENGTH)
491 if (cbDecoded > cbEncoded - 2)
493 /* Not enough space for 0 TLV */
494 SetLastError(CRYPT_E_ASN1_CORRUPT);
497 else if (*(ptr + cbDecoded) != 0 ||
498 *(ptr + cbDecoded + 1) != 0)
500 TRACE("expected 0 TLV\n");
501 SetLastError(CRYPT_E_ASN1_CORRUPT);
508 if (ret && !indefinite && cbDecoded != dataLen)
510 TRACE("expected %d decoded, got %d, failing\n", dataLen,
512 SetLastError(CRYPT_E_ASN1_CORRUPT);
517 DWORD i, bytesNeeded = 0, structSize = 0;
519 for (i = 0; i < cItem; i++)
521 bytesNeeded += items[i].size;
522 structSize += items[i].minSize;
525 *pcbDecoded = 1 + lenBytes + cbDecoded;
527 *pcbStructInfo = bytesNeeded;
528 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
529 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
533 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
534 pvStructInfo = *(BYTE **)pvStructInfo;
536 nextData = (BYTE *)startingPointer;
538 nextData = (BYTE *)pvStructInfo + structSize;
539 memset(pvStructInfo, 0, structSize);
540 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
541 ptr, dataLen, dwFlags, pvStructInfo, nextData,
549 SetLastError(CRYPT_E_ASN1_BADTAG);
552 TRACE("returning %d (%08x)\n", ret, GetLastError());
557 * The expected tag of the entire encoded array (usually a variant
558 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
559 * regardless of the tag seen.
561 * used to decode each item in the array
563 * is the minimum size of each decoded item
565 * indicates whether each item has a dynamic pointer
567 * indicates the offset within itemSize at which the pointer exists
569 struct AsnArrayDescriptor
572 InternalDecodeFunc decodeFunc;
578 struct AsnArrayItemSize
584 /* Decodes an array of like types into a struct GenericArray.
585 * The layout and decoding of the array are described by a struct
586 * AsnArrayDescriptor.
588 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
589 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
590 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
591 DWORD *pcbDecoded, void *startingPointer)
595 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
596 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
599 if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
603 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
605 DWORD bytesNeeded, cItems = 0, decoded;
606 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
607 /* There can be arbitrarily many items, but there is often only one.
609 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
611 decoded = 1 + lenBytes;
612 bytesNeeded = sizeof(struct GenericArray);
616 BOOL doneDecoding = FALSE;
618 for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
622 itemLenBytes = GET_LEN_BYTES(ptr[1]);
623 if (dataLen == CMSG_INDEFINITE_LENGTH)
628 if (itemLenBytes != 1 || ptr[1] != 0)
630 SetLastError(CRYPT_E_ASN1_CORRUPT);
637 else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
641 DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
643 /* Each item decoded may not tolerate extraneous bytes,
644 * so get the length of the next element if known.
646 if ((ret = CRYPT_GetLengthIndefinite(ptr,
647 cbEncoded - (ptr - pbEncoded), &itemDataLen)))
649 if (itemDataLen == CMSG_INDEFINITE_LENGTH)
650 itemEncoded = cbEncoded - (ptr - pbEncoded);
652 itemEncoded = 1 + itemLenBytes + itemDataLen;
655 ret = arrayDesc->decodeFunc(ptr, itemEncoded,
656 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size,
661 if (itemSizes != &itemSize)
662 itemSizes = CryptMemRealloc(itemSizes,
663 cItems * sizeof(struct AsnArrayItemSize));
668 cItems * sizeof(struct AsnArrayItemSize));
670 memcpy(itemSizes, &itemSize,
675 decoded += itemDecoded;
676 itemSizes[cItems - 1].encodedLen = itemEncoded;
677 itemSizes[cItems - 1].size = size;
690 *pcbDecoded = decoded;
692 *pcbStructInfo = bytesNeeded;
693 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
694 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
699 struct GenericArray *array;
701 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
702 pvStructInfo = *(BYTE **)pvStructInfo;
703 array = (struct GenericArray *)pvStructInfo;
704 array->cItems = cItems;
706 array->rgItems = startingPointer;
708 array->rgItems = (BYTE *)array +
709 sizeof(struct GenericArray);
710 nextData = (BYTE *)array->rgItems +
711 array->cItems * arrayDesc->itemSize;
712 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
713 i < cItems && ptr - pbEncoded - 1 - lenBytes <
718 if (arrayDesc->hasPointer)
719 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
720 + arrayDesc->pointerOffset) = nextData;
721 ret = arrayDesc->decodeFunc(ptr,
722 itemSizes[i].encodedLen,
723 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
724 array->rgItems + i * arrayDesc->itemSize,
725 &itemSizes[i].size, &itemDecoded);
728 nextData += itemSizes[i].size - arrayDesc->itemSize;
734 if (itemSizes != &itemSize)
735 CryptMemFree(itemSizes);
740 SetLastError(CRYPT_E_ASN1_BADTAG);
746 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
747 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
748 * to CRYPT_E_ASN1_CORRUPT.
749 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
752 static BOOL CRYPT_AsnDecodeDerBlob(const BYTE *pbEncoded, DWORD cbEncoded,
753 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
758 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
760 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
761 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
763 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
764 bytesNeeded += 1 + lenBytes + dataLen;
767 *pcbDecoded = 1 + lenBytes + dataLen;
769 *pcbStructInfo = bytesNeeded;
770 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded)))
772 CRYPT_DER_BLOB *blob;
774 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
775 pvStructInfo = *(BYTE **)pvStructInfo;
776 blob = (CRYPT_DER_BLOB *)pvStructInfo;
777 blob->cbData = 1 + lenBytes + dataLen;
780 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
781 blob->pbData = (BYTE *)pbEncoded;
784 assert(blob->pbData);
785 memcpy(blob->pbData, pbEncoded, blob->cbData);
790 SetLastError(CRYPT_E_ASN1_CORRUPT);
798 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
799 static BOOL CRYPT_AsnDecodeBitsSwapBytes(const BYTE *pbEncoded,
800 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
805 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
806 pvStructInfo, *pcbStructInfo, pcbDecoded);
808 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
811 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
812 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
814 if (ret && pvStructInfo)
816 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
823 for (i = 0; i < blob->cbData / 2; i++)
825 temp = blob->pbData[i];
826 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
827 blob->pbData[blob->cbData - i - 1] = temp;
831 TRACE("returning %d (%08x)\n", ret, GetLastError());
835 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
836 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
837 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
841 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
842 pDecodePara, pvStructInfo, *pcbStructInfo);
846 struct AsnDecodeSequenceItem items[] = {
847 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
848 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
849 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
850 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
851 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
852 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
853 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
854 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
855 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
856 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
859 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
860 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
861 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
862 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
863 pcbStructInfo, NULL, NULL);
867 SetLastError(STATUS_ACCESS_VIOLATION);
872 TRACE("Returning %d (%08x)\n", ret, GetLastError());
876 static BOOL CRYPT_AsnDecodeCertVersion(const BYTE *pbEncoded, DWORD cbEncoded,
877 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
882 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
884 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
886 ret = CRYPT_AsnDecodeIntInternal(pbEncoded + 1 + lenBytes, dataLen,
887 dwFlags, pvStructInfo, pcbStructInfo, NULL);
889 *pcbDecoded = 1 + lenBytes + dataLen;
894 static BOOL CRYPT_AsnDecodeValidity(const BYTE *pbEncoded, DWORD cbEncoded,
895 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
899 struct AsnDecodeSequenceItem items[] = {
900 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
901 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
902 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
903 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
906 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
907 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
912 static BOOL CRYPT_AsnDecodeCertExtensions(const BYTE *pbEncoded,
913 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
919 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
921 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
923 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded + 1 + lenBytes,
924 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
925 if (ret && pcbDecoded)
926 *pcbDecoded = 1 + lenBytes + dataLen;
931 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
932 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
933 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
936 struct AsnDecodeSequenceItem items[] = {
937 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
938 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
939 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
940 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
941 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
942 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
943 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
944 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
945 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
946 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
948 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
949 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
951 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
952 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
954 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
955 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
956 FALSE, TRUE, offsetof(CERT_INFO,
957 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
958 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
959 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
960 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
961 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
962 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
963 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
964 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
965 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
966 offsetof(CERT_INFO, rgExtension), 0 },
969 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
970 pDecodePara, pvStructInfo, *pcbStructInfo);
972 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
973 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
975 if (ret && pvStructInfo)
979 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
980 info = *(CERT_INFO **)pvStructInfo;
982 info = (CERT_INFO *)pvStructInfo;
983 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
984 !info->Subject.cbData)
986 SetLastError(CRYPT_E_ASN1_CORRUPT);
987 /* Don't need to deallocate, because it should have failed on the
988 * first pass (and no memory was allocated.)
994 TRACE("Returning %d (%08x)\n", ret, GetLastError());
998 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
999 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1000 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1004 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1005 pDecodePara, pvStructInfo, *pcbStructInfo);
1011 /* Unless told not to, first try to decode it as a signed cert. */
1012 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1014 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
1016 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1017 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1018 (BYTE *)&signedCert, &size);
1022 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1023 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
1024 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
1025 pvStructInfo, pcbStructInfo);
1026 LocalFree(signedCert);
1029 /* Failing that, try it as an unsigned cert */
1033 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1034 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
1035 pDecodePara, pvStructInfo, pcbStructInfo);
1040 SetLastError(STATUS_ACCESS_VIOLATION);
1044 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1048 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
1049 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1052 struct AsnDecodeSequenceItem items[] = {
1053 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
1054 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
1055 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
1056 { 0, offsetof(CRL_ENTRY, RevocationDate),
1057 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
1058 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
1059 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1060 offsetof(CRL_ENTRY, rgExtension), 0 },
1062 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
1064 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
1067 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1068 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, pcbDecoded,
1069 entry ? entry->SerialNumber.pbData : NULL);
1073 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
1074 * been set prior to calling.
1076 static BOOL CRYPT_AsnDecodeCRLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
1077 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1080 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1081 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
1082 offsetof(CRL_ENTRY, SerialNumber.pbData) };
1083 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
1085 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1086 pvStructInfo, *pcbStructInfo, pcbDecoded);
1088 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1089 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1090 entries ? entries->rgItems : NULL);
1091 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1095 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1096 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1097 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1099 struct AsnDecodeSequenceItem items[] = {
1100 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1101 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1102 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1103 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1104 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1105 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1106 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1108 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1109 sizeof(FILETIME), FALSE, FALSE, 0 },
1110 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1111 sizeof(FILETIME), TRUE, FALSE, 0 },
1112 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1113 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
1114 offsetof(CRL_INFO, rgCRLEntry), 0 },
1115 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1116 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1117 offsetof(CRL_INFO, rgExtension), 0 },
1121 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1122 pDecodePara, pvStructInfo, *pcbStructInfo);
1124 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1125 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
1128 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1132 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1133 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1134 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1138 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1139 pDecodePara, pvStructInfo, *pcbStructInfo);
1145 /* Unless told not to, first try to decode it as a signed crl. */
1146 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1148 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1150 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1151 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1152 (BYTE *)&signedCrl, &size);
1156 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1157 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1158 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1159 pvStructInfo, pcbStructInfo);
1160 LocalFree(signedCrl);
1163 /* Failing that, try it as an unsigned crl */
1167 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1168 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1169 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1174 SetLastError(STATUS_ACCESS_VIOLATION);
1178 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1182 static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded,
1183 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1188 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1189 pvStructInfo, *pcbStructInfo);
1191 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1193 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1194 DWORD bytesNeeded = sizeof(LPSTR);
1198 /* The largest possible string for the first two components
1199 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1204 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1205 pbEncoded[1 + lenBytes] / 40,
1206 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1208 bytesNeeded += strlen(firstTwo) + 1;
1209 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1210 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1212 /* large enough for ".4000000" */
1216 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1223 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1226 SetLastError(CRYPT_E_ASN1_CORRUPT);
1233 snprintf(str, sizeof(str), ".%d", val);
1234 bytesNeeded += strlen(str);
1239 *pcbDecoded = 1 + lenBytes + dataLen;
1241 *pcbStructInfo = bytesNeeded;
1242 else if (*pcbStructInfo < bytesNeeded)
1244 *pcbStructInfo = bytesNeeded;
1245 SetLastError(ERROR_MORE_DATA);
1253 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1256 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1257 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1259 pszObjId += strlen(pszObjId);
1260 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1261 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1265 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1274 sprintf(pszObjId, ".%d", val);
1275 pszObjId += strlen(pszObjId);
1279 *(LPSTR *)pvStructInfo = NULL;
1280 *pcbStructInfo = bytesNeeded;
1286 static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded,
1287 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1291 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1292 pvStructInfo, *pcbStructInfo);
1294 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1295 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1296 pvStructInfo, pcbStructInfo, pcbDecoded);
1299 SetLastError(CRYPT_E_ASN1_BADTAG);
1305 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1308 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
1309 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1311 struct AsnDecodeSequenceItem items[] = {
1312 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1313 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1314 offsetof(CERT_EXTENSION, pszObjId), 0 },
1315 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1316 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1317 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1318 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1319 offsetof(CERT_EXTENSION, Value.pbData) },
1322 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1324 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1328 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1329 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1330 pbEncoded, cbEncoded, dwFlags, NULL, ext, pcbStructInfo,
1331 pcbDecoded, ext ? ext->pszObjId : NULL);
1333 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1334 debugstr_a(ext->pszObjId));
1335 TRACE("returning %d (%08x)\n", ret, GetLastError());
1339 static BOOL CRYPT_AsnDecodeExtensionsInternal(const BYTE *pbEncoded,
1340 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1344 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1345 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1346 offsetof(CERT_EXTENSION, pszObjId) };
1347 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1349 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1350 pvStructInfo, *pcbStructInfo, pcbDecoded);
1352 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1353 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1354 exts ? exts->rgExtension : NULL);
1358 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1359 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1360 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1366 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
1367 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1368 if (ret && pvStructInfo)
1370 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1371 pcbStructInfo, *pcbStructInfo);
1374 CERT_EXTENSIONS *exts;
1376 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1377 pvStructInfo = *(BYTE **)pvStructInfo;
1378 exts = (CERT_EXTENSIONS *)pvStructInfo;
1379 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1380 sizeof(CERT_EXTENSIONS));
1381 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
1382 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1383 pcbStructInfo, NULL);
1389 SetLastError(STATUS_ACCESS_VIOLATION);
1396 /* Warning: this assumes the address of value->Value.pbData is already set, in
1397 * order to avoid overwriting memory. (In some cases, it may change it, if it
1398 * doesn't copy anything to memory.) Be sure to set it correctly!
1400 static BOOL CRYPT_AsnDecodeNameValueInternal(const BYTE *pbEncoded,
1401 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1406 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1408 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1410 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1411 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1413 switch (pbEncoded[0])
1415 case ASN_OCTETSTRING:
1416 valueType = CERT_RDN_OCTET_STRING;
1417 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1418 bytesNeeded += dataLen;
1420 case ASN_NUMERICSTRING:
1421 valueType = CERT_RDN_NUMERIC_STRING;
1422 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1423 bytesNeeded += dataLen;
1425 case ASN_PRINTABLESTRING:
1426 valueType = CERT_RDN_PRINTABLE_STRING;
1427 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1428 bytesNeeded += dataLen;
1431 valueType = CERT_RDN_IA5_STRING;
1432 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1433 bytesNeeded += dataLen;
1436 valueType = CERT_RDN_T61_STRING;
1437 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1438 bytesNeeded += dataLen;
1440 case ASN_VIDEOTEXSTRING:
1441 valueType = CERT_RDN_VIDEOTEX_STRING;
1442 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1443 bytesNeeded += dataLen;
1445 case ASN_GRAPHICSTRING:
1446 valueType = CERT_RDN_GRAPHIC_STRING;
1447 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1448 bytesNeeded += dataLen;
1450 case ASN_VISIBLESTRING:
1451 valueType = CERT_RDN_VISIBLE_STRING;
1452 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1453 bytesNeeded += dataLen;
1455 case ASN_GENERALSTRING:
1456 valueType = CERT_RDN_GENERAL_STRING;
1457 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1458 bytesNeeded += dataLen;
1460 case ASN_UNIVERSALSTRING:
1461 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1462 SetLastError(CRYPT_E_ASN1_BADTAG);
1465 valueType = CERT_RDN_BMP_STRING;
1466 bytesNeeded += dataLen;
1468 case ASN_UTF8STRING:
1469 valueType = CERT_RDN_UTF8_STRING;
1470 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1471 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1474 SetLastError(CRYPT_E_ASN1_BADTAG);
1479 *pcbDecoded = 1 + lenBytes + dataLen;
1481 *pcbStructInfo = bytesNeeded;
1482 else if (*pcbStructInfo < bytesNeeded)
1484 *pcbStructInfo = bytesNeeded;
1485 SetLastError(ERROR_MORE_DATA);
1490 *pcbStructInfo = bytesNeeded;
1491 value->dwValueType = valueType;
1496 assert(value->Value.pbData);
1497 switch (pbEncoded[0])
1499 case ASN_OCTETSTRING:
1500 case ASN_NUMERICSTRING:
1501 case ASN_PRINTABLESTRING:
1504 case ASN_VIDEOTEXSTRING:
1505 case ASN_GRAPHICSTRING:
1506 case ASN_VISIBLESTRING:
1507 case ASN_GENERALSTRING:
1508 value->Value.cbData = dataLen;
1511 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1512 memcpy(value->Value.pbData,
1513 pbEncoded + 1 + lenBytes, dataLen);
1515 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1521 LPWSTR str = (LPWSTR)value->Value.pbData;
1523 value->Value.cbData = dataLen;
1524 for (i = 0; i < dataLen / 2; i++)
1525 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1526 pbEncoded[1 + lenBytes + 2 * i + 1];
1529 case ASN_UTF8STRING:
1531 LPWSTR str = (LPWSTR)value->Value.pbData;
1533 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1534 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1535 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1542 value->Value.cbData = 0;
1543 value->Value.pbData = NULL;
1550 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1551 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1552 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1558 ret = CRYPT_AsnDecodeNameValueInternal(pbEncoded, cbEncoded,
1559 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1560 if (ret && pvStructInfo)
1562 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1563 pcbStructInfo, *pcbStructInfo);
1566 CERT_NAME_VALUE *value;
1568 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1569 pvStructInfo = *(BYTE **)pvStructInfo;
1570 value = (CERT_NAME_VALUE *)pvStructInfo;
1571 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1572 ret = CRYPT_AsnDecodeNameValueInternal( pbEncoded, cbEncoded,
1573 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1574 pcbStructInfo, NULL);
1580 SetLastError(STATUS_ACCESS_VIOLATION);
1587 static BOOL CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE *pbEncoded,
1588 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1593 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1595 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1597 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1598 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1600 switch (pbEncoded[0])
1602 case ASN_NUMERICSTRING:
1603 valueType = CERT_RDN_NUMERIC_STRING;
1604 bytesNeeded += dataLen * 2;
1606 case ASN_PRINTABLESTRING:
1607 valueType = CERT_RDN_PRINTABLE_STRING;
1608 bytesNeeded += dataLen * 2;
1611 valueType = CERT_RDN_IA5_STRING;
1612 bytesNeeded += dataLen * 2;
1615 valueType = CERT_RDN_T61_STRING;
1616 bytesNeeded += dataLen * 2;
1618 case ASN_VIDEOTEXSTRING:
1619 valueType = CERT_RDN_VIDEOTEX_STRING;
1620 bytesNeeded += dataLen * 2;
1622 case ASN_GRAPHICSTRING:
1623 valueType = CERT_RDN_GRAPHIC_STRING;
1624 bytesNeeded += dataLen * 2;
1626 case ASN_VISIBLESTRING:
1627 valueType = CERT_RDN_VISIBLE_STRING;
1628 bytesNeeded += dataLen * 2;
1630 case ASN_GENERALSTRING:
1631 valueType = CERT_RDN_GENERAL_STRING;
1632 bytesNeeded += dataLen * 2;
1634 case ASN_UNIVERSALSTRING:
1635 valueType = CERT_RDN_UNIVERSAL_STRING;
1636 bytesNeeded += dataLen / 2;
1639 valueType = CERT_RDN_BMP_STRING;
1640 bytesNeeded += dataLen;
1642 case ASN_UTF8STRING:
1643 valueType = CERT_RDN_UTF8_STRING;
1644 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1645 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1648 SetLastError(CRYPT_E_ASN1_BADTAG);
1653 *pcbDecoded = 1 + lenBytes + dataLen;
1655 *pcbStructInfo = bytesNeeded;
1656 else if (*pcbStructInfo < bytesNeeded)
1658 *pcbStructInfo = bytesNeeded;
1659 SetLastError(ERROR_MORE_DATA);
1664 *pcbStructInfo = bytesNeeded;
1665 value->dwValueType = valueType;
1669 LPWSTR str = (LPWSTR)value->Value.pbData;
1671 assert(value->Value.pbData);
1672 switch (pbEncoded[0])
1674 case ASN_NUMERICSTRING:
1675 case ASN_PRINTABLESTRING:
1678 case ASN_VIDEOTEXSTRING:
1679 case ASN_GRAPHICSTRING:
1680 case ASN_VISIBLESTRING:
1681 case ASN_GENERALSTRING:
1682 value->Value.cbData = dataLen * 2;
1683 for (i = 0; i < dataLen; i++)
1684 str[i] = pbEncoded[1 + lenBytes + i];
1686 case ASN_UNIVERSALSTRING:
1687 value->Value.cbData = dataLen / 2;
1688 for (i = 0; i < dataLen / 4; i++)
1689 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1690 | pbEncoded[1 + lenBytes + 2 * i + 3];
1693 value->Value.cbData = dataLen;
1694 for (i = 0; i < dataLen / 2; i++)
1695 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1696 pbEncoded[1 + lenBytes + 2 * i + 1];
1698 case ASN_UTF8STRING:
1699 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1700 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1701 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1707 value->Value.cbData = 0;
1708 value->Value.pbData = NULL;
1715 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1716 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1717 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1723 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded, cbEncoded,
1724 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1725 if (ret && pvStructInfo)
1727 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1728 pcbStructInfo, *pcbStructInfo);
1731 CERT_NAME_VALUE *value;
1733 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1734 pvStructInfo = *(BYTE **)pvStructInfo;
1735 value = (CERT_NAME_VALUE *)pvStructInfo;
1736 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1737 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded,
1738 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1739 pcbStructInfo, NULL);
1745 SetLastError(STATUS_ACCESS_VIOLATION);
1752 static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
1753 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1756 struct AsnDecodeSequenceItem items[] = {
1757 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1758 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1759 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1760 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1761 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1762 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1764 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1766 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1767 pvStructInfo, *pcbStructInfo);
1770 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1771 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1772 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1773 attr ? attr->pszObjId : NULL);
1776 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1777 debugstr_a(attr->pszObjId));
1778 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1780 TRACE("returning %d (%08x)\n", ret, GetLastError());
1784 static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1785 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1788 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1789 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1790 offsetof(CERT_RDN_ATTR, pszObjId) };
1791 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1793 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1794 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1795 rdn ? rdn->rgRDNAttr : NULL);
1799 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1800 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1801 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1807 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1808 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1809 offsetof(CERT_RDN, rgRDNAttr) };
1811 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1812 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1816 SetLastError(STATUS_ACCESS_VIOLATION);
1823 static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
1824 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1828 struct AsnDecodeSequenceItem items[] = {
1829 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1830 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1831 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1832 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1833 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1834 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1836 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1838 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1839 pvStructInfo, *pcbStructInfo);
1842 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1843 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1844 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1845 attr ? attr->pszObjId : NULL);
1848 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1849 debugstr_a(attr->pszObjId));
1850 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1852 TRACE("returning %d (%08x)\n", ret, GetLastError());
1856 static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1857 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1860 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1861 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1862 offsetof(CERT_RDN_ATTR, pszObjId) };
1863 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1865 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1866 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1867 rdn ? rdn->rgRDNAttr : NULL);
1871 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1872 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1873 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1879 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1880 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1881 offsetof(CERT_RDN, rgRDNAttr) };
1883 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1884 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1888 SetLastError(STATUS_ACCESS_VIOLATION);
1895 static BOOL CRYPT_FindEncodedLen(const BYTE *pbEncoded, DWORD cbEncoded,
1898 BOOL ret = TRUE, done = FALSE;
1899 DWORD indefiniteNestingLevels = 0, decoded = 0;
1901 TRACE("(%p, %d)\n", pbEncoded, cbEncoded);
1908 else if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded,
1911 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1913 if (dataLen == CMSG_INDEFINITE_LENGTH)
1915 indefiniteNestingLevels++;
1916 pbEncoded += 1 + lenBytes;
1917 cbEncoded -= 1 + lenBytes;
1918 decoded += 1 + lenBytes;
1919 TRACE("indefiniteNestingLevels = %d\n",
1920 indefiniteNestingLevels);
1924 if (pbEncoded[0] == 0 && pbEncoded[1] == 0 &&
1925 indefiniteNestingLevels)
1927 indefiniteNestingLevels--;
1928 TRACE("indefiniteNestingLevels = %d\n",
1929 indefiniteNestingLevels);
1931 pbEncoded += 1 + lenBytes + dataLen;
1932 cbEncoded -= 1 + lenBytes + dataLen;
1933 decoded += 1 + lenBytes + dataLen;
1934 if (!indefiniteNestingLevels)
1938 } while (ret && !done);
1939 /* If we haven't found all 0 TLVs, we haven't found the end */
1940 if (ret && indefiniteNestingLevels)
1942 SetLastError(CRYPT_E_ASN1_EOD);
1946 *pcbDecoded = decoded;
1947 TRACE("returning %d (%d)\n", ret, ret ? *pcbDecoded : 0);
1951 static BOOL CRYPT_AsnDecodeCopyBytes(const BYTE *pbEncoded,
1952 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1956 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB), encodedLen = 0;
1958 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1959 pvStructInfo, *pcbStructInfo);
1961 if ((ret = CRYPT_FindEncodedLen(pbEncoded, cbEncoded, &encodedLen)))
1963 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1964 bytesNeeded += encodedLen;
1966 *pcbStructInfo = bytesNeeded;
1967 else if (*pcbStructInfo < bytesNeeded)
1969 SetLastError(ERROR_MORE_DATA);
1970 *pcbStructInfo = bytesNeeded;
1975 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1977 *pcbStructInfo = bytesNeeded;
1978 blob->cbData = encodedLen;
1979 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1980 blob->pbData = (LPBYTE)pbEncoded;
1983 assert(blob->pbData);
1984 memcpy(blob->pbData, pbEncoded, blob->cbData);
1988 *pcbDecoded = encodedLen;
1993 static BOOL CRYPT_DecodeDERArray(const BYTE *pbEncoded, DWORD cbEncoded,
1994 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1997 struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytes,
1998 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
1999 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
2001 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2002 pvStructInfo, *pcbStructInfo, pcbDecoded);
2004 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2005 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2006 array ? array->rgItems : NULL);
2010 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
2011 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2015 struct AsnDecodeSequenceItem items[] = {
2016 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
2017 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2018 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
2019 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
2020 CRYPT_DecodeDERArray, sizeof(struct GenericArray), FALSE, TRUE,
2021 offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
2023 PCRYPT_ATTRIBUTE attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
2025 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2026 pvStructInfo, *pcbStructInfo);
2028 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2029 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2030 pcbDecoded, attr ? attr->pszObjId : NULL);
2031 TRACE("returning %d\n", ret);
2035 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
2036 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2037 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2041 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2042 pDecodePara, pvStructInfo, *pcbStructInfo);
2048 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2049 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
2053 *pcbStructInfo = bytesNeeded;
2054 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2055 pvStructInfo, pcbStructInfo, bytesNeeded)))
2057 PCRYPT_ATTRIBUTE attr;
2059 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2060 pvStructInfo = *(BYTE **)pvStructInfo;
2061 attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
2062 attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
2063 sizeof(CRYPT_ATTRIBUTE));
2064 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2065 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
2072 SetLastError(STATUS_ACCESS_VIOLATION);
2075 TRACE("returning %d\n", ret);
2079 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
2080 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2083 struct AsnArrayDescriptor arrayDesc = { 0,
2084 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2085 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2086 PCRYPT_ATTRIBUTES attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
2089 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2090 NULL, pvStructInfo, pcbStructInfo, pcbDecoded, attrs ? attrs->rgAttr :
2095 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
2096 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2097 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2101 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2102 pDecodePara, pvStructInfo, *pcbStructInfo);
2109 SetLastError(CRYPT_E_ASN1_EOD);
2110 else if (pbEncoded[0] != (ASN_CONSTRUCTOR | ASN_SETOF))
2111 SetLastError(CRYPT_E_ASN1_CORRUPT);
2112 else if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
2113 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2117 *pcbStructInfo = bytesNeeded;
2118 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2119 pvStructInfo, pcbStructInfo, bytesNeeded)))
2121 PCRYPT_ATTRIBUTES attrs;
2123 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2124 pvStructInfo = *(BYTE **)pvStructInfo;
2125 attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
2126 attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
2127 sizeof(CRYPT_ATTRIBUTES));
2128 ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
2129 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2130 &bytesNeeded, NULL);
2136 SetLastError(STATUS_ACCESS_VIOLATION);
2139 TRACE("returning %d\n", ret);
2143 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
2144 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2146 CRYPT_ALGORITHM_IDENTIFIER *algo =
2147 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
2149 struct AsnDecodeSequenceItem items[] = {
2150 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
2151 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2152 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
2153 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
2154 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2155 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
2158 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2159 pvStructInfo, *pcbStructInfo, pcbDecoded);
2161 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2162 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2163 pcbDecoded, algo ? algo->pszObjId : NULL);
2164 if (ret && pvStructInfo)
2166 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
2167 debugstr_a(algo->pszObjId));
2172 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
2173 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2177 struct AsnDecodeSequenceItem items[] = {
2178 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
2179 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2180 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
2181 Algorithm.pszObjId) },
2182 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
2183 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2184 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
2186 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2188 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2189 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2190 pcbDecoded, info ? info->Algorithm.Parameters.pbData : NULL);
2194 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2195 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2196 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2204 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2205 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2208 *pcbStructInfo = bytesNeeded;
2209 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2210 pvStructInfo, pcbStructInfo, bytesNeeded)))
2212 PCERT_PUBLIC_KEY_INFO info;
2214 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2215 pvStructInfo = *(BYTE **)pvStructInfo;
2216 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2217 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2218 sizeof(CERT_PUBLIC_KEY_INFO);
2219 ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2220 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2221 &bytesNeeded, NULL);
2227 SetLastError(STATUS_ACCESS_VIOLATION);
2234 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
2235 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2241 SetLastError(CRYPT_E_ASN1_CORRUPT);
2244 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2246 SetLastError(CRYPT_E_ASN1_CORRUPT);
2249 if (pbEncoded[1] > 1)
2251 SetLastError(CRYPT_E_ASN1_CORRUPT);
2258 *pcbStructInfo = sizeof(BOOL);
2261 else if (*pcbStructInfo < sizeof(BOOL))
2263 *pcbStructInfo = sizeof(BOOL);
2264 SetLastError(ERROR_MORE_DATA);
2269 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2272 TRACE("returning %d (%08x)\n", ret, GetLastError());
2276 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2277 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2279 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
2280 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2283 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2284 pvStructInfo, *pcbStructInfo);
2288 SetLastError(CRYPT_E_ASN1_CORRUPT);
2291 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2292 if (1 + lenBytes > cbEncoded)
2294 SetLastError(CRYPT_E_ASN1_CORRUPT);
2297 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2299 switch (pbEncoded[0] & ASN_TYPE_MASK)
2301 case 1: /* rfc822Name */
2302 case 2: /* dNSName */
2303 case 6: /* uniformResourceIdentifier */
2304 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
2306 case 4: /* directoryName */
2307 case 7: /* iPAddress */
2308 bytesNeeded += dataLen;
2310 case 8: /* registeredID */
2311 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
2315 /* FIXME: ugly, shouldn't need to know internals of OID decode
2316 * function to use it.
2318 bytesNeeded += dataLen - sizeof(LPSTR);
2321 case 0: /* otherName */
2322 FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
2323 SetLastError(CRYPT_E_ASN1_BADTAG);
2326 case 3: /* x400Address, unimplemented */
2327 case 5: /* ediPartyName, unimplemented */
2328 TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
2329 SetLastError(CRYPT_E_ASN1_BADTAG);
2333 TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
2334 SetLastError(CRYPT_E_ASN1_CORRUPT);
2340 *pcbDecoded = 1 + lenBytes + dataLen;
2342 *pcbStructInfo = bytesNeeded;
2343 else if (*pcbStructInfo < bytesNeeded)
2345 *pcbStructInfo = bytesNeeded;
2346 SetLastError(ERROR_MORE_DATA);
2351 *pcbStructInfo = bytesNeeded;
2352 /* MS used values one greater than the asn1 ones.. sigh */
2353 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
2354 switch (pbEncoded[0] & ASN_TYPE_MASK)
2356 case 1: /* rfc822Name */
2357 case 2: /* dNSName */
2358 case 6: /* uniformResourceIdentifier */
2362 for (i = 0; i < dataLen; i++)
2363 entry->u.pwszURL[i] =
2364 (WCHAR)pbEncoded[1 + lenBytes + i];
2365 entry->u.pwszURL[i] = 0;
2366 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2367 debugstr_w(entry->u.pwszURL));
2370 case 4: /* directoryName */
2371 entry->dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
2372 /* The data are memory-equivalent with the IPAddress case,
2375 case 7: /* iPAddress */
2376 /* The next data pointer is in the pwszURL spot, that is,
2377 * the first 4 bytes. Need to move it to the next spot.
2379 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2380 entry->u.IPAddress.cbData = dataLen;
2381 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2384 case 8: /* registeredID */
2385 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
2386 &entry->u.pszRegisteredID, &dataLen, NULL);
2395 static BOOL CRYPT_AsnDecodeAltNameInternal(const BYTE *pbEncoded,
2396 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2400 struct AsnArrayDescriptor arrayDesc = { 0,
2401 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2402 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2403 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
2405 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2406 pvStructInfo, *pcbStructInfo, pcbDecoded);
2409 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2410 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2411 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2412 info ? info->rgAltEntry : NULL);
2416 /* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */
2417 static BOOL CRYPT_AsnDecodeIntegerSwapBytes(const BYTE *pbEncoded,
2418 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2423 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
2424 pvStructInfo, *pcbStructInfo, pcbDecoded);
2426 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2429 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
2430 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
2432 if (ret && pvStructInfo)
2434 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2441 for (i = 0; i < blob->cbData / 2; i++)
2443 temp = blob->pbData[i];
2444 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
2445 blob->pbData[blob->cbData - i - 1] = temp;
2449 TRACE("returning %d (%08x)\n", ret, GetLastError());
2453 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
2454 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2455 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2461 struct AsnDecodeSequenceItem items[] = {
2462 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
2463 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2464 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
2465 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2466 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
2467 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
2468 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
2469 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
2470 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2471 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2472 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
2475 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2476 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2477 pcbStructInfo, NULL, NULL);
2481 SetLastError(STATUS_ACCESS_VIOLATION);
2488 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
2489 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2490 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2496 struct AsnDecodeSequenceItem items[] = {
2497 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
2498 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2499 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
2500 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2501 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
2502 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
2503 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2504 AuthorityCertIssuer.rgAltEntry), 0 },
2505 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2506 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2507 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2508 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2509 AuthorityCertSerialNumber.pbData), 0 },
2512 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2513 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2514 pcbStructInfo, NULL, NULL);
2518 SetLastError(STATUS_ACCESS_VIOLATION);
2525 static BOOL CRYPT_AsnDecodePKCSContent(const BYTE *pbEncoded, DWORD cbEncoded,
2526 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2531 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2532 pvStructInfo, *pcbStructInfo, pcbDecoded);
2534 /* The caller has already checked the tag, no need to check it again.
2535 * Check the outer length is valid:
2537 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
2539 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2542 pbEncoded += 1 + lenBytes;
2543 cbEncoded -= 1 + lenBytes;
2544 if (dataLen == CMSG_INDEFINITE_LENGTH)
2545 cbEncoded -= 2; /* space for 0 TLV */
2546 /* Check the inner length is valid: */
2547 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &innerLen)))
2551 ret = CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags,
2552 pvStructInfo, pcbStructInfo, &decodedLen);
2553 if (dataLen == CMSG_INDEFINITE_LENGTH)
2555 if (*(pbEncoded + decodedLen) != 0 ||
2556 *(pbEncoded + decodedLen + 1) != 0)
2558 TRACE("expected 0 TLV, got {%02x,%02x}\n",
2559 *(pbEncoded + decodedLen),
2560 *(pbEncoded + decodedLen + 1));
2561 SetLastError(CRYPT_E_ASN1_CORRUPT);
2567 if (ret && pcbDecoded)
2569 *pcbDecoded = 1 + lenBytes + decodedLen;
2570 TRACE("decoded %d bytes\n", *pcbDecoded);
2577 static BOOL CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE *pbEncoded,
2578 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2581 CRYPT_CONTENT_INFO *info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2582 struct AsnDecodeSequenceItem items[] = {
2583 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
2584 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2585 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
2586 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
2587 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
2588 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
2589 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
2593 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2594 pvStructInfo, *pcbStructInfo, pcbDecoded);
2596 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2597 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2598 pcbDecoded, info ? info->pszObjId : NULL);
2602 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
2603 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2604 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2608 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2609 pDecodePara, pvStructInfo, *pcbStructInfo);
2613 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, cbEncoded,
2614 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
2615 if (ret && pvStructInfo)
2617 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
2618 pcbStructInfo, *pcbStructInfo);
2621 CRYPT_CONTENT_INFO *info;
2623 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2624 pvStructInfo = *(BYTE **)pvStructInfo;
2625 info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2626 info->pszObjId = (LPSTR)((BYTE *)info +
2627 sizeof(CRYPT_CONTENT_INFO));
2628 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded,
2629 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2630 pcbStructInfo, NULL);
2636 SetLastError(STATUS_ACCESS_VIOLATION);
2642 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
2643 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2644 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
2647 struct AsnDecodeSequenceItem items[] = {
2648 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version),
2649 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2650 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
2651 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2652 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
2654 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
2655 CRYPT_AsnDecodePKCSContentInfoInternal,
2656 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
2657 ContentInfo.pszObjId), 0 },
2658 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
2659 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
2660 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
2663 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2664 pbEncoded, cbEncoded, dwFlags, pDecodePara, digestedData, pcbDigestedData,
2669 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
2670 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2671 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2675 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2676 pDecodePara, pvStructInfo, *pcbStructInfo);
2682 if ((ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
2683 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2686 *pcbStructInfo = bytesNeeded;
2687 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2688 pvStructInfo, pcbStructInfo, bytesNeeded)))
2690 CERT_ALT_NAME_INFO *name;
2692 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2693 pvStructInfo = *(BYTE **)pvStructInfo;
2694 name = (CERT_ALT_NAME_INFO *)pvStructInfo;
2695 name->rgAltEntry = (PCERT_ALT_NAME_ENTRY)
2696 ((BYTE *)pvStructInfo + sizeof(CERT_ALT_NAME_INFO));
2697 ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
2698 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2699 &bytesNeeded, NULL);
2705 SetLastError(STATUS_ACCESS_VIOLATION);
2712 struct PATH_LEN_CONSTRAINT
2714 BOOL fPathLenConstraint;
2715 DWORD dwPathLenConstraint;
2718 static BOOL CRYPT_AsnDecodePathLenConstraint(const BYTE *pbEncoded,
2719 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2723 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT), size;
2725 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2726 pvStructInfo, *pcbStructInfo, pcbDecoded);
2730 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, NULL,
2732 *pcbStructInfo = bytesNeeded;
2734 else if (*pcbStructInfo < bytesNeeded)
2736 SetLastError(ERROR_MORE_DATA);
2737 *pcbStructInfo = bytesNeeded;
2742 struct PATH_LEN_CONSTRAINT *constraint =
2743 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
2745 size = sizeof(constraint->dwPathLenConstraint);
2746 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
2747 &constraint->dwPathLenConstraint, &size, pcbDecoded);
2749 constraint->fPathLenConstraint = TRUE;
2750 TRACE("got an int, dwPathLenConstraint is %d\n",
2751 constraint->dwPathLenConstraint);
2753 TRACE("returning %d (%08x)\n", ret, GetLastError());
2757 static BOOL CRYPT_AsnDecodeSubtreeConstraints(const BYTE *pbEncoded,
2758 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2762 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2763 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
2764 offsetof(CERT_NAME_BLOB, pbData) };
2765 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2767 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2768 pvStructInfo, *pcbStructInfo, pcbDecoded);
2770 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2771 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2772 entries ? entries->rgItems : NULL);
2773 TRACE("Returning %d (%08x)\n", ret, GetLastError());
2777 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
2778 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2779 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2785 struct AsnDecodeSequenceItem items[] = {
2786 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
2787 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2788 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
2789 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2790 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2791 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2792 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2793 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
2794 sizeof(struct GenericArray), TRUE, TRUE,
2795 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
2798 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2799 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2800 pcbStructInfo, NULL, NULL);
2804 SetLastError(STATUS_ACCESS_VIOLATION);
2811 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
2812 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2813 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2819 struct AsnDecodeSequenceItem items[] = {
2820 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
2821 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
2822 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
2823 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2824 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2827 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2828 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2829 pcbStructInfo, NULL, NULL);
2833 SetLastError(STATUS_ACCESS_VIOLATION);
2840 #define RSA1_MAGIC 0x31415352
2842 struct DECODED_RSA_PUB_KEY
2845 CRYPT_INTEGER_BLOB modulus;
2848 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
2849 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2850 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2856 struct AsnDecodeSequenceItem items[] = {
2857 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
2858 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2859 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
2861 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
2862 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2864 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
2867 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2868 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
2872 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2873 decodedKey->modulus.cbData;
2877 *pcbStructInfo = bytesNeeded;
2880 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2881 pvStructInfo, pcbStructInfo, bytesNeeded)))
2884 RSAPUBKEY *rsaPubKey;
2886 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2887 pvStructInfo = *(BYTE **)pvStructInfo;
2888 hdr = (BLOBHEADER *)pvStructInfo;
2889 hdr->bType = PUBLICKEYBLOB;
2890 hdr->bVersion = CUR_BLOB_VERSION;
2892 hdr->aiKeyAlg = CALG_RSA_KEYX;
2893 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
2894 sizeof(BLOBHEADER));
2895 rsaPubKey->magic = RSA1_MAGIC;
2896 rsaPubKey->pubexp = decodedKey->pubexp;
2897 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
2898 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
2899 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
2900 decodedKey->modulus.cbData);
2902 LocalFree(decodedKey);
2907 SetLastError(STATUS_ACCESS_VIOLATION);
2914 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
2915 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2919 DWORD bytesNeeded, dataLen;
2921 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2922 pvStructInfo, *pcbStructInfo, pcbDecoded);
2924 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2926 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2928 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2929 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
2931 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
2933 *pcbDecoded = 1 + lenBytes + dataLen;
2935 *pcbStructInfo = bytesNeeded;
2936 else if (*pcbStructInfo < bytesNeeded)
2938 SetLastError(ERROR_MORE_DATA);
2939 *pcbStructInfo = bytesNeeded;
2944 CRYPT_DATA_BLOB *blob;
2946 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2947 blob->cbData = dataLen;
2948 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2949 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
2952 assert(blob->pbData);
2954 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
2962 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
2963 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2964 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2968 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2969 pDecodePara, pvStructInfo, *pcbStructInfo);
2977 SetLastError(CRYPT_E_ASN1_CORRUPT);
2980 else if (pbEncoded[0] != ASN_OCTETSTRING)
2982 SetLastError(CRYPT_E_ASN1_BADTAG);
2985 else if ((ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
2986 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2989 *pcbStructInfo = bytesNeeded;
2990 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2991 pvStructInfo, pcbStructInfo, bytesNeeded)))
2993 CRYPT_DATA_BLOB *blob;
2995 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2996 pvStructInfo = *(BYTE **)pvStructInfo;
2997 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2998 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
2999 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
3000 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3001 &bytesNeeded, NULL);
3007 SetLastError(STATUS_ACCESS_VIOLATION);
3014 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3015 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3019 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
3020 pvStructInfo, *pcbStructInfo, pcbDecoded);
3022 if (pbEncoded[0] == ASN_BITSTRING)
3024 DWORD bytesNeeded, dataLen;
3025 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3027 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3029 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3030 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
3032 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
3034 *pcbDecoded = 1 + lenBytes + dataLen;
3036 *pcbStructInfo = bytesNeeded;
3037 else if (*pcbStructInfo < bytesNeeded)
3039 *pcbStructInfo = bytesNeeded;
3040 SetLastError(ERROR_MORE_DATA);
3045 CRYPT_BIT_BLOB *blob;
3047 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
3048 blob->cbData = dataLen - 1;
3049 blob->cUnusedBits = *(pbEncoded + 1 + lenBytes);
3050 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3052 blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes;
3056 assert(blob->pbData);
3059 BYTE mask = 0xff << blob->cUnusedBits;
3061 memcpy(blob->pbData, pbEncoded + 2 + lenBytes,
3063 blob->pbData[blob->cbData - 1] &= mask;
3071 SetLastError(CRYPT_E_ASN1_BADTAG);
3074 TRACE("returning %d (%08x)\n", ret, GetLastError());
3078 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
3079 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3080 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3084 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
3085 pDecodePara, pvStructInfo, pcbStructInfo);
3091 if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3092 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3095 *pcbStructInfo = bytesNeeded;
3096 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3097 pvStructInfo, pcbStructInfo, bytesNeeded)))
3099 CRYPT_BIT_BLOB *blob;
3101 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3102 pvStructInfo = *(BYTE **)pvStructInfo;
3103 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
3104 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
3105 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3106 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3107 &bytesNeeded, NULL);
3113 SetLastError(STATUS_ACCESS_VIOLATION);
3117 TRACE("returning %d (%08x)\n", ret, GetLastError());
3121 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3122 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3125 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
3126 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
3127 DWORD size = sizeof(buf);
3129 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
3130 if (pbEncoded[0] != ASN_INTEGER)
3132 SetLastError(CRYPT_E_ASN1_BADTAG);
3136 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded, 0, &buf,
3141 *pcbStructInfo = sizeof(int);
3142 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int))))
3146 if (blob->pbData[blob->cbData - 1] & 0x80)
3148 /* initialize to a negative value to sign-extend */
3153 for (i = 0; i < blob->cbData; i++)
3156 val |= blob->pbData[blob->cbData - i - 1];
3158 memcpy(pvStructInfo, &val, sizeof(int));
3161 else if (GetLastError() == ERROR_MORE_DATA)
3162 SetLastError(CRYPT_E_ASN1_LARGE);
3166 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
3167 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3168 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3176 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3177 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3181 *pcbStructInfo = bytesNeeded;
3182 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3183 pvStructInfo, pcbStructInfo, bytesNeeded)))
3185 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3186 pvStructInfo = *(BYTE **)pvStructInfo;
3187 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3188 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3189 &bytesNeeded, NULL);
3195 SetLastError(STATUS_ACCESS_VIOLATION);
3202 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
3203 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3207 DWORD bytesNeeded, dataLen;
3209 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3211 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3213 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3215 *pcbDecoded = 1 + lenBytes + dataLen;
3217 *pcbStructInfo = bytesNeeded;
3218 else if (*pcbStructInfo < bytesNeeded)
3220 *pcbStructInfo = bytesNeeded;
3221 SetLastError(ERROR_MORE_DATA);
3226 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3228 blob->cbData = dataLen;
3229 assert(blob->pbData);
3234 for (i = 0; i < blob->cbData; i++)
3236 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3245 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
3246 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3247 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3255 if (pbEncoded[0] != ASN_INTEGER)
3257 SetLastError(CRYPT_E_ASN1_BADTAG);
3261 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3262 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3266 *pcbStructInfo = bytesNeeded;
3267 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3268 pvStructInfo, pcbStructInfo, bytesNeeded)))
3270 CRYPT_INTEGER_BLOB *blob;
3272 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3273 pvStructInfo = *(BYTE **)pvStructInfo;
3274 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3275 blob->pbData = (BYTE *)pvStructInfo +
3276 sizeof(CRYPT_INTEGER_BLOB);
3277 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3278 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
3279 &bytesNeeded, NULL);
3285 SetLastError(STATUS_ACCESS_VIOLATION);
3292 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
3293 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3298 if (pbEncoded[0] == ASN_INTEGER)
3300 DWORD bytesNeeded, dataLen;
3302 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3304 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3307 *pcbDecoded = 1 + lenBytes + dataLen;
3308 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3310 *pcbStructInfo = bytesNeeded;
3311 else if (*pcbStructInfo < bytesNeeded)
3313 *pcbStructInfo = bytesNeeded;
3314 SetLastError(ERROR_MORE_DATA);
3319 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3321 blob->cbData = dataLen;
3322 assert(blob->pbData);
3323 /* remove leading zero byte if it exists */
3324 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
3333 for (i = 0; i < blob->cbData; i++)
3335 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3344 SetLastError(CRYPT_E_ASN1_BADTAG);
3350 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
3351 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3352 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3360 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded,
3361 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3364 *pcbStructInfo = bytesNeeded;
3365 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3366 pvStructInfo, pcbStructInfo, bytesNeeded)))
3368 CRYPT_INTEGER_BLOB *blob;
3370 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3371 pvStructInfo = *(BYTE **)pvStructInfo;
3372 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3373 blob->pbData = (BYTE *)pvStructInfo +
3374 sizeof(CRYPT_INTEGER_BLOB);
3375 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded,
3376 cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
3377 &bytesNeeded, NULL);
3383 SetLastError(STATUS_ACCESS_VIOLATION);
3390 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
3391 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3392 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3398 *pcbStructInfo = sizeof(int);
3403 if (pbEncoded[0] == ASN_ENUMERATED)
3405 unsigned int val = 0, i;
3409 SetLastError(CRYPT_E_ASN1_EOD);
3412 else if (pbEncoded[1] == 0)
3414 SetLastError(CRYPT_E_ASN1_CORRUPT);
3419 /* A little strange looking, but we have to accept a sign byte:
3420 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
3421 * assuming a small length is okay here, it has to be in short
3424 if (pbEncoded[1] > sizeof(unsigned int) + 1)
3426 SetLastError(CRYPT_E_ASN1_LARGE);
3429 for (i = 0; i < pbEncoded[1]; i++)
3432 val |= pbEncoded[2 + i];
3434 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3435 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
3437 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3438 pvStructInfo = *(BYTE **)pvStructInfo;
3439 memcpy(pvStructInfo, &val, sizeof(unsigned int));
3445 SetLastError(CRYPT_E_ASN1_BADTAG);
3451 SetLastError(STATUS_ACCESS_VIOLATION);
3458 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
3461 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
3466 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
3468 if (!isdigit(*(pbEncoded))) \
3470 SetLastError(CRYPT_E_ASN1_CORRUPT); \
3476 (word) += *(pbEncoded)++ - '0'; \
3481 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
3482 SYSTEMTIME *sysTime)
3486 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
3488 WORD hours, minutes = 0;
3489 BYTE sign = *pbEncoded++;
3492 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
3493 if (ret && hours >= 24)
3495 SetLastError(CRYPT_E_ASN1_CORRUPT);
3500 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
3501 if (ret && minutes >= 60)
3503 SetLastError(CRYPT_E_ASN1_CORRUPT);
3511 sysTime->wHour += hours;
3512 sysTime->wMinute += minutes;
3516 if (hours > sysTime->wHour)
3519 sysTime->wHour = 24 - (hours - sysTime->wHour);
3522 sysTime->wHour -= hours;
3523 if (minutes > sysTime->wMinute)
3526 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
3529 sysTime->wMinute -= minutes;
3536 #define MIN_ENCODED_TIME_LENGTH 10
3538 static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
3539 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3544 if (pbEncoded[0] == ASN_UTCTIME)
3547 SetLastError(CRYPT_E_ASN1_EOD);
3548 else if (pbEncoded[1] > 0x7f)
3550 /* long-form date strings really can't be valid */
3551 SetLastError(CRYPT_E_ASN1_CORRUPT);
3555 SYSTEMTIME sysTime = { 0 };
3556 BYTE len = pbEncoded[1];
3558 if (len < MIN_ENCODED_TIME_LENGTH)
3559 SetLastError(CRYPT_E_ASN1_CORRUPT);
3564 *pcbDecoded = 2 + len;
3566 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
3567 if (sysTime.wYear >= 50)
3568 sysTime.wYear += 1900;
3570 sysTime.wYear += 2000;
3571 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3572 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3573 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3574 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
3577 if (len >= 2 && isdigit(*pbEncoded) &&
3578 isdigit(*(pbEncoded + 1)))
3579 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3581 else if (isdigit(*pbEncoded))
3582 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
3585 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3591 *pcbStructInfo = sizeof(FILETIME);
3592 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
3594 ret = SystemTimeToFileTime(&sysTime,
3595 (FILETIME *)pvStructInfo);
3601 SetLastError(CRYPT_E_ASN1_BADTAG);
3605 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
3606 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3607 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3615 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
3616 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3620 *pcbStructInfo = bytesNeeded;
3621 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
3622 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
3624 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3625 pvStructInfo = *(BYTE **)pvStructInfo;
3626 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
3627 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3628 &bytesNeeded, NULL);
3634 SetLastError(STATUS_ACCESS_VIOLATION);
3640 static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
3641 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3646 if (pbEncoded[0] == ASN_GENERALTIME)
3649 SetLastError(CRYPT_E_ASN1_EOD);
3650 else if (pbEncoded[1] > 0x7f)
3652 /* long-form date strings really can't be valid */
3653 SetLastError(CRYPT_E_ASN1_CORRUPT);
3657 BYTE len = pbEncoded[1];
3659 if (len < MIN_ENCODED_TIME_LENGTH)
3660 SetLastError(CRYPT_E_ASN1_CORRUPT);
3663 SYSTEMTIME sysTime = { 0 };
3667 *pcbDecoded = 2 + len;
3669 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
3670 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3671 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3672 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3675 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3678 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3680 if (ret && len > 0 && (*pbEncoded == '.' ||
3687 /* workaround macro weirdness */
3688 digits = min(len, 3);
3689 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
3690 sysTime.wMilliseconds);
3693 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3699 *pcbStructInfo = sizeof(FILETIME);
3700 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
3702 ret = SystemTimeToFileTime(&sysTime,
3703 (FILETIME *)pvStructInfo);
3709 SetLastError(CRYPT_E_ASN1_BADTAG);
3713 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
3714 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3718 InternalDecodeFunc decode = NULL;
3720 if (pbEncoded[0] == ASN_UTCTIME)
3721 decode = CRYPT_AsnDecodeUtcTimeInternal;
3722 else if (pbEncoded[0] == ASN_GENERALTIME)
3723 decode = CRYPT_AsnDecodeGeneralizedTime;
3725 ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
3726 pcbStructInfo, pcbDecoded);
3729 SetLastError(CRYPT_E_ASN1_BADTAG);
3735 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
3736 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3737 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3745 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
3746 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3750 *pcbStructInfo = bytesNeeded;
3751 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3752 pvStructInfo, pcbStructInfo, bytesNeeded)))
3754 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3755 pvStructInfo = *(BYTE **)pvStructInfo;
3756 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
3757 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3758 &bytesNeeded, NULL);
3764 SetLastError(STATUS_ACCESS_VIOLATION);
3771 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
3772 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3773 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3779 if (pbEncoded[0] == ASN_SEQUENCEOF)
3781 DWORD bytesNeeded, dataLen, remainingLen, cValue;
3783 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3788 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3789 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
3791 ptr = pbEncoded + 1 + lenBytes;
3792 remainingLen = dataLen;
3793 while (ret && remainingLen)
3797 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3800 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3802 remainingLen -= 1 + nextLenBytes + nextLen;
3803 ptr += 1 + nextLenBytes + nextLen;
3804 bytesNeeded += sizeof(CRYPT_DER_BLOB);
3805 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3806 bytesNeeded += 1 + nextLenBytes + nextLen;
3812 CRYPT_SEQUENCE_OF_ANY *seq;
3816 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3817 pvStructInfo, pcbStructInfo, bytesNeeded)))
3819 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3820 pvStructInfo = *(BYTE **)pvStructInfo;
3821 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
3822 seq->cValue = cValue;
3823 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
3825 nextPtr = (BYTE *)seq->rgValue +
3826 cValue * sizeof(CRYPT_DER_BLOB);
3827 ptr = pbEncoded + 1 + lenBytes;
3828 remainingLen = dataLen;
3830 while (ret && remainingLen)
3834 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3837 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3839 seq->rgValue[i].cbData = 1 + nextLenBytes +
3841 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3842 seq->rgValue[i].pbData = (BYTE *)ptr;
3845 seq->rgValue[i].pbData = nextPtr;
3846 memcpy(nextPtr, ptr, 1 + nextLenBytes +
3848 nextPtr += 1 + nextLenBytes + nextLen;
3850 remainingLen -= 1 + nextLenBytes + nextLen;
3851 ptr += 1 + nextLenBytes + nextLen;
3861 SetLastError(CRYPT_E_ASN1_BADTAG);
3867 SetLastError(STATUS_ACCESS_VIOLATION);
3874 static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded,
3875 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3880 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
3882 DWORD bytesNeeded, dataLen;
3884 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3886 struct AsnArrayDescriptor arrayDesc = {
3887 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
3888 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3889 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3890 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3896 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3897 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3898 0, NULL, NULL, &nameLen, NULL, NULL);
3899 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen;
3902 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
3904 *pcbDecoded = 1 + lenBytes + dataLen;
3906 *pcbStructInfo = bytesNeeded;
3907 else if (*pcbStructInfo < bytesNeeded)
3909 *pcbStructInfo = bytesNeeded;
3910 SetLastError(ERROR_MORE_DATA);
3915 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
3919 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3920 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3921 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3922 0, NULL, &name->u.FullName, pcbStructInfo, NULL,
3923 name->u.FullName.rgAltEntry);
3926 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3932 SetLastError(CRYPT_E_ASN1_BADTAG);
3938 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
3939 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3941 struct AsnDecodeSequenceItem items[] = {
3942 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
3943 DistPointName), CRYPT_AsnDecodeDistPointName,
3944 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
3945 DistPointName.u.FullName.rgAltEntry), 0 },
3946 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
3947 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
3948 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
3949 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
3950 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
3951 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
3955 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3956 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3961 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
3962 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3963 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3967 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3968 pDecodePara, pvStructInfo, *pcbStructInfo);
3972 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3973 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
3974 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
3976 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3977 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
3981 SetLastError(STATUS_ACCESS_VIOLATION);
3988 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3989 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3990 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3994 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3995 pDecodePara, pvStructInfo, *pcbStructInfo);
3999 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
4000 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
4002 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4003 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
4007 SetLastError(STATUS_ACCESS_VIOLATION);
4014 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
4015 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4016 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4020 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4021 pDecodePara, pvStructInfo, *pcbStructInfo);
4025 struct AsnDecodeSequenceItem items[] = {
4026 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
4027 DistPointName), CRYPT_AsnDecodeDistPointName,
4028 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
4029 offsetof(CRL_ISSUING_DIST_POINT,
4030 DistPointName.u.FullName.rgAltEntry), 0 },
4031 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
4032 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4034 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
4035 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4037 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
4038 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
4039 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
4040 OnlySomeReasonFlags.pbData), 0 },
4041 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
4042 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
4045 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4046 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
4047 pcbStructInfo, NULL, NULL);
4051 SetLastError(STATUS_ACCESS_VIOLATION);
4058 static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded,
4059 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4063 struct AsnDecodeSequenceItem items[] = {
4064 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
4065 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
4067 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
4068 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
4069 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
4071 CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
4072 (CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
4074 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4075 pvStructInfo, *pcbStructInfo, pcbDecoded);
4077 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4078 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4079 pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL);
4080 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
4082 SetLastError(CRYPT_E_ASN1_CORRUPT);
4085 TRACE("returning %d\n", ret);
4089 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
4090 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4093 CMSG_SIGNER_INFO *info = (CMSG_SIGNER_INFO *)pvStructInfo;
4094 struct AsnDecodeSequenceItem items[] = {
4095 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
4096 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4097 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
4098 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
4099 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
4100 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
4101 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4102 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
4103 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4104 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
4105 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4106 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
4107 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
4108 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4109 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
4110 HashEncryptionAlgorithm.pszObjId), 0 },
4111 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
4112 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
4113 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
4114 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4115 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
4116 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4117 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
4121 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4122 pvStructInfo, *pcbStructInfo);
4124 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4125 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4126 pcbDecoded, info ? info->Issuer.pbData : NULL);
4130 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
4131 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4132 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4136 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4137 pDecodePara, pvStructInfo, *pcbStructInfo);
4141 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
4142 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
4143 if (ret && pvStructInfo)
4145 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
4146 pcbStructInfo, *pcbStructInfo);
4149 CMSG_SIGNER_INFO *info;
4151 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4152 pvStructInfo = *(BYTE **)pvStructInfo;
4153 info = (CMSG_SIGNER_INFO *)pvStructInfo;
4154 info->Issuer.pbData = ((BYTE *)info +
4155 sizeof(CMSG_SIGNER_INFO));
4156 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
4157 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4158 pcbStructInfo, NULL);
4164 SetLastError(STATUS_ACCESS_VIOLATION);
4167 TRACE("returning %d\n", ret);
4171 static BOOL CRYPT_DecodeSignerArray(const BYTE *pbEncoded, DWORD cbEncoded,
4172 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4175 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
4176 CRYPT_AsnDecodePKCSSignerInfoInternal, sizeof(CMSG_SIGNER_INFO), TRUE,
4177 offsetof(CMSG_SIGNER_INFO, Issuer.pbData) };
4178 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
4180 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4181 pvStructInfo, *pcbStructInfo, pcbDecoded);
4183 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4184 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
4185 array ? array->rgItems : NULL);
4189 BOOL CRYPT_AsnDecodePKCSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
4190 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
4191 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
4194 struct AsnDecodeSequenceItem items[] = {
4195 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version),
4196 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4197 /* Placeholder for the hash algorithms - redundant with those in the
4198 * signers, so just ignore them.
4200 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
4201 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
4202 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
4203 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
4204 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4205 offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
4206 CRYPT_DecodeDERArray, sizeof(struct GenericArray), TRUE, TRUE,
4207 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
4208 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4209 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_DecodeDERArray,
4210 sizeof(struct GenericArray), TRUE, TRUE,
4211 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
4212 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
4213 CRYPT_DecodeSignerArray, sizeof(struct GenericArray), TRUE, TRUE,
4214 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
4217 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4218 pDecodePara, signedInfo, *pcbSignedInfo);
4220 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4221 pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo,
4223 TRACE("returning %d\n", ret);
4227 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
4228 LPCSTR lpszStructType)
4230 CryptDecodeObjectExFunc decodeFunc = NULL;
4232 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
4233 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
4235 SetLastError(ERROR_FILE_NOT_FOUND);
4238 if (!HIWORD(lpszStructType))
4240 switch (LOWORD(lpszStructType))
4242 case (WORD)X509_CERT:
4243 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
4245 case (WORD)X509_CERT_TO_BE_SIGNED:
4246 decodeFunc = CRYPT_AsnDecodeCert;
4248 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
4249 decodeFunc = CRYPT_AsnDecodeCRL;
4251 case (WORD)X509_EXTENSIONS:
4252 decodeFunc = CRYPT_AsnDecodeExtensions;
4254 case (WORD)X509_NAME_VALUE:
4255 decodeFunc = CRYPT_AsnDecodeNameValue;
4257 case (WORD)X509_NAME:
4258 decodeFunc = CRYPT_AsnDecodeName;
4260 case (WORD)X509_PUBLIC_KEY_INFO:
4261 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
4263 case (WORD)X509_AUTHORITY_KEY_ID:
4264 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4266 case (WORD)X509_ALTERNATE_NAME:
4267 decodeFunc = CRYPT_AsnDecodeAltName;
4269 case (WORD)X509_BASIC_CONSTRAINTS:
4270 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4272 case (WORD)X509_BASIC_CONSTRAINTS2:
4273 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4275 case (WORD)RSA_CSP_PUBLICKEYBLOB:
4276 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
4278 case (WORD)X509_UNICODE_NAME:
4279 decodeFunc = CRYPT_AsnDecodeUnicodeName;
4281 case (WORD)PKCS_ATTRIBUTE:
4282 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
4284 case (WORD)X509_UNICODE_NAME_VALUE:
4285 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
4287 case (WORD)X509_OCTET_STRING:
4288 decodeFunc = CRYPT_AsnDecodeOctets;
4290 case (WORD)X509_BITS:
4291 case (WORD)X509_KEY_USAGE:
4292 decodeFunc = CRYPT_AsnDecodeBits;
4294 case (WORD)X509_INTEGER:
4295 decodeFunc = CRYPT_AsnDecodeInt;
4297 case (WORD)X509_MULTI_BYTE_INTEGER:
4298 decodeFunc = CRYPT_AsnDecodeInteger;
4300 case (WORD)X509_MULTI_BYTE_UINT:
4301 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
4303 case (WORD)X509_ENUMERATED:
4304 decodeFunc = CRYPT_AsnDecodeEnumerated;
4306 case (WORD)X509_CHOICE_OF_TIME:
4307 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
4309 case (WORD)X509_AUTHORITY_KEY_ID2:
4310 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4312 case (WORD)PKCS_CONTENT_INFO:
4313 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
4315 case (WORD)X509_SEQUENCE_OF_ANY:
4316 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
4318 case (WORD)PKCS_UTC_TIME:
4319 decodeFunc = CRYPT_AsnDecodeUtcTime;
4321 case (WORD)X509_CRL_DIST_POINTS:
4322 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4324 case (WORD)X509_ENHANCED_KEY_USAGE:
4325 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4327 case (WORD)PKCS_ATTRIBUTES:
4328 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
4330 case (WORD)X509_ISSUING_DIST_POINT:
4331 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4333 case (WORD)PKCS7_SIGNER_INFO:
4334 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
4338 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4339 decodeFunc = CRYPT_AsnDecodeExtensions;
4340 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4341 decodeFunc = CRYPT_AsnDecodeUtcTime;
4342 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4343 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4344 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4345 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4346 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4347 decodeFunc = CRYPT_AsnDecodeEnumerated;
4348 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4349 decodeFunc = CRYPT_AsnDecodeBits;
4350 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4351 decodeFunc = CRYPT_AsnDecodeOctets;
4352 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4353 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4354 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4355 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4356 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4357 decodeFunc = CRYPT_AsnDecodeAltName;
4358 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4359 decodeFunc = CRYPT_AsnDecodeAltName;
4360 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4361 decodeFunc = CRYPT_AsnDecodeAltName;
4362 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4363 decodeFunc = CRYPT_AsnDecodeAltName;
4364 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4365 decodeFunc = CRYPT_AsnDecodeAltName;
4366 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4367 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4368 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4369 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4370 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4371 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4375 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
4376 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4378 static HCRYPTOIDFUNCSET set = NULL;
4379 CryptDecodeObjectFunc decodeFunc = NULL;
4382 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
4383 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4384 (void **)&decodeFunc, hFunc);
4388 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
4389 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4391 static HCRYPTOIDFUNCSET set = NULL;
4392 CryptDecodeObjectExFunc decodeFunc = NULL;
4395 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
4396 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4397 (void **)&decodeFunc, hFunc);
4401 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4402 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
4403 DWORD *pcbStructInfo)
4406 CryptDecodeObjectFunc pCryptDecodeObject = NULL;
4407 CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
4408 HCRYPTOIDFUNCADDR hFunc = NULL;
4410 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
4411 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
4412 pvStructInfo, pcbStructInfo);
4414 if (!pvStructInfo && !pcbStructInfo)
4416 SetLastError(ERROR_INVALID_PARAMETER);
4421 SetLastError(CRYPT_E_ASN1_EOD);
4424 if (cbEncoded > MAX_ENCODED_LEN)
4426 SetLastError(CRYPT_E_ASN1_LARGE);
4430 if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
4433 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4434 debugstr_a(lpszStructType));
4435 pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
4436 lpszStructType, &hFunc);
4437 if (!pCryptDecodeObject)
4438 pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
4439 lpszStructType, &hFunc);
4441 if (pCryptDecodeObject)
4442 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4443 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4444 else if (pCryptDecodeObjectEx)
4445 ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
4446 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
4447 pvStructInfo, pcbStructInfo);
4449 CryptFreeOIDFunctionAddress(hFunc, 0);
4450 TRACE_(crypt)("returning %d\n", ret);
4454 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4455 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4456 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4459 CryptDecodeObjectExFunc decodeFunc;
4460 HCRYPTOIDFUNCADDR hFunc = NULL;
4462 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
4463 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
4464 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4466 if (!pvStructInfo && !pcbStructInfo)
4468 SetLastError(ERROR_INVALID_PARAMETER);
4473 SetLastError(CRYPT_E_ASN1_EOD);
4476 if (cbEncoded > MAX_ENCODED_LEN)
4478 SetLastError(CRYPT_E_ASN1_LARGE);
4482 SetLastError(NOERROR);
4483 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
4484 *(BYTE **)pvStructInfo = NULL;
4485 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
4488 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4489 debugstr_a(lpszStructType));
4490 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
4494 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
4495 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4498 CryptDecodeObjectFunc pCryptDecodeObject =
4499 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
4501 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
4502 * directly, as that could cause an infinite loop.
4504 if (pCryptDecodeObject)
4506 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4508 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4509 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
4510 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4511 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
4512 ret = pCryptDecodeObject(dwCertEncodingType,
4513 lpszStructType, pbEncoded, cbEncoded, dwFlags,
4514 *(BYTE **)pvStructInfo, pcbStructInfo);
4517 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4518 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4522 CryptFreeOIDFunctionAddress(hFunc, 0);
4523 TRACE_(crypt)("returning %d\n", ret);