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);
365 decoded += itemDecoded;
366 TRACE("item %d: decoded %d bytes\n", i,
370 else if (items[i].optional &&
371 GetLastError() == CRYPT_E_ASN1_BADTAG)
373 TRACE("skipping optional item %d\n", i);
374 items[i].size = items[i].minSize;
375 SetLastError(NOERROR);
379 TRACE("item %d failed: %08x\n", i,
382 else if (itemLen == CMSG_INDEFINITE_LENGTH)
384 ERR("can't use indefinite length encoding without a decoder\n");
385 SetLastError(CRYPT_E_ASN1_CORRUPT);
390 TRACE("item %d: decoded %d bytes\n", i, itemEncodedLen);
391 ptr += itemEncodedLen;
392 decoded += itemEncodedLen;
393 items[i].size = items[i].minSize;
396 else if (items[i].optional)
398 TRACE("skipping optional item %d\n", i);
399 items[i].size = items[i].minSize;
403 TRACE("item %d: tag %02x doesn't match expected %02x\n",
404 i, ptr[0], items[i].tag);
405 SetLastError(CRYPT_E_ASN1_BADTAG);
410 else if (items[i].optional)
412 TRACE("missing optional item %d, skipping\n", i);
413 items[i].size = items[i].minSize;
417 TRACE("not enough bytes for item %d, failing\n", i);
418 SetLastError(CRYPT_E_ASN1_CORRUPT);
423 *cbDecoded = decoded;
424 TRACE("returning %d\n", ret);
428 /* This decodes an arbitrary sequence into a contiguous block of memory
429 * (basically, a struct.) Each element being decoded is described by a struct
430 * AsnDecodeSequenceItem, see above.
431 * startingPointer is an optional pointer to the first place where dynamic
432 * data will be stored. If you know the starting offset, you may pass it
433 * here. Otherwise, pass NULL, and one will be inferred from the items.
435 static BOOL CRYPT_AsnDecodeSequence(struct AsnDecodeSequenceItem items[],
436 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
437 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
438 DWORD *pcbDecoded, void *startingPointer)
442 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
443 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
446 if (pbEncoded[0] == ASN_SEQUENCE)
450 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
452 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
453 const BYTE *ptr = pbEncoded + 1 + lenBytes;
455 cbEncoded -= 1 + lenBytes;
456 if (dataLen == CMSG_INDEFINITE_LENGTH)
458 else if (cbEncoded < dataLen)
460 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
462 SetLastError(CRYPT_E_ASN1_CORRUPT);
467 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
468 ptr, dataLen, dwFlags, NULL, NULL, &cbDecoded);
469 if (ret && dataLen == CMSG_INDEFINITE_LENGTH)
471 if (cbDecoded > cbEncoded - 2)
473 /* Not enough space for 0 TLV */
474 SetLastError(CRYPT_E_ASN1_CORRUPT);
477 else if (*(ptr + cbDecoded) != 0 ||
478 *(ptr + cbDecoded + 1) != 0)
480 TRACE("expected 0 TLV\n");
481 SetLastError(CRYPT_E_ASN1_CORRUPT);
488 if (ret && cbDecoded != dataLen)
490 TRACE("expected %d decoded, got %d, failing\n", dataLen,
492 SetLastError(CRYPT_E_ASN1_CORRUPT);
497 DWORD i, bytesNeeded = 0, structSize = 0;
499 for (i = 0; i < cItem; i++)
501 bytesNeeded += items[i].size;
502 structSize += items[i].minSize;
504 if (ret && pcbDecoded)
505 *pcbDecoded = 1 + lenBytes + cbDecoded;
507 *pcbStructInfo = bytesNeeded;
508 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
509 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
513 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
514 pvStructInfo = *(BYTE **)pvStructInfo;
516 nextData = (BYTE *)startingPointer;
518 nextData = (BYTE *)pvStructInfo + structSize;
519 memset(pvStructInfo, 0, structSize);
520 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
521 ptr, dataLen, dwFlags, pvStructInfo, nextData,
529 SetLastError(CRYPT_E_ASN1_BADTAG);
532 TRACE("returning %d (%08x)\n", ret, GetLastError());
537 * The expected tag of the entire encoded array (usually a variant
538 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
539 * regardless of the tag seen.
541 * used to decode each item in the array
543 * is the minimum size of each decoded item
545 * indicates whether each item has a dynamic pointer
547 * indicates the offset within itemSize at which the pointer exists
549 struct AsnArrayDescriptor
552 InternalDecodeFunc decodeFunc;
558 struct AsnArrayItemSize
564 /* Decodes an array of like types into a struct GenericArray.
565 * The layout and decoding of the array are described by a struct
566 * AsnArrayDescriptor.
568 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
569 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
570 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
571 DWORD *pcbDecoded, void *startingPointer)
575 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
576 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
579 if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
583 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
585 DWORD bytesNeeded, cItems = 0, decoded;
586 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
587 /* There can be arbitrarily many items, but there is often only one.
589 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
591 decoded = 1 + lenBytes;
592 bytesNeeded = sizeof(struct GenericArray);
596 BOOL doneDecoding = FALSE;
598 for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
602 itemLenBytes = GET_LEN_BYTES(ptr[1]);
603 if (dataLen == CMSG_INDEFINITE_LENGTH)
608 if (itemLenBytes != 1 || ptr[1] != 0)
610 SetLastError(CRYPT_E_ASN1_CORRUPT);
617 else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
621 DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
623 /* Each item decoded may not tolerate extraneous bytes,
624 * so get the length of the next element if known.
626 if ((ret = CRYPT_GetLengthIndefinite(ptr,
627 cbEncoded - (ptr - pbEncoded), &itemDataLen)))
629 if (itemDataLen == CMSG_INDEFINITE_LENGTH)
630 itemEncoded = cbEncoded - (ptr - pbEncoded);
632 itemEncoded = 1 + itemLenBytes + itemDataLen;
635 ret = arrayDesc->decodeFunc(ptr, itemEncoded,
636 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size,
641 if (itemSizes != &itemSize)
642 itemSizes = CryptMemRealloc(itemSizes,
643 cItems * sizeof(struct AsnArrayItemSize));
648 cItems * sizeof(struct AsnArrayItemSize));
650 memcpy(itemSizes, &itemSize,
655 decoded += itemDecoded;
656 itemSizes[cItems - 1].encodedLen = itemEncoded;
657 itemSizes[cItems - 1].size = size;
670 *pcbDecoded = decoded;
672 *pcbStructInfo = bytesNeeded;
673 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
674 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
679 struct GenericArray *array;
681 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
682 pvStructInfo = *(BYTE **)pvStructInfo;
683 array = (struct GenericArray *)pvStructInfo;
684 array->cItems = cItems;
686 array->rgItems = startingPointer;
688 array->rgItems = (BYTE *)array +
689 sizeof(struct GenericArray);
690 nextData = (BYTE *)array->rgItems +
691 array->cItems * arrayDesc->itemSize;
692 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
693 i < cItems && ptr - pbEncoded - 1 - lenBytes <
696 if (arrayDesc->hasPointer)
697 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
698 + arrayDesc->pointerOffset) = nextData;
699 ret = arrayDesc->decodeFunc(ptr,
700 itemSizes[i].encodedLen,
701 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
702 array->rgItems + i * arrayDesc->itemSize,
703 &itemSizes[i].size, NULL);
708 nextData += itemSizes[i].size - arrayDesc->itemSize;
709 ret = CRYPT_GetLen(ptr,
710 cbEncoded - (ptr - pbEncoded), &nextLen);
712 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
717 if (itemSizes != &itemSize)
718 CryptMemFree(itemSizes);
723 SetLastError(CRYPT_E_ASN1_BADTAG);
729 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
730 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
731 * to CRYPT_E_ASN1_CORRUPT.
732 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
735 static BOOL CRYPT_AsnDecodeDerBlob(const BYTE *pbEncoded, DWORD cbEncoded,
736 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
741 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
743 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
744 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
746 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
747 bytesNeeded += 1 + lenBytes + dataLen;
750 *pcbDecoded = 1 + lenBytes + dataLen;
752 *pcbStructInfo = bytesNeeded;
753 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded)))
755 CRYPT_DER_BLOB *blob;
757 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
758 pvStructInfo = *(BYTE **)pvStructInfo;
759 blob = (CRYPT_DER_BLOB *)pvStructInfo;
760 blob->cbData = 1 + lenBytes + dataLen;
763 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
764 blob->pbData = (BYTE *)pbEncoded;
767 assert(blob->pbData);
768 memcpy(blob->pbData, pbEncoded, blob->cbData);
773 SetLastError(CRYPT_E_ASN1_CORRUPT);
781 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
782 static BOOL CRYPT_AsnDecodeBitsSwapBytes(const BYTE *pbEncoded,
783 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
788 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
789 pvStructInfo, *pcbStructInfo, pcbDecoded);
791 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
794 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
795 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
797 if (ret && pvStructInfo)
799 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
806 for (i = 0; i < blob->cbData / 2; i++)
808 temp = blob->pbData[i];
809 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
810 blob->pbData[blob->cbData - i - 1] = temp;
814 TRACE("returning %d (%08x)\n", ret, GetLastError());
818 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
819 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
820 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
824 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
825 pDecodePara, pvStructInfo, *pcbStructInfo);
829 struct AsnDecodeSequenceItem items[] = {
830 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
831 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
832 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
833 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
834 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
835 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
836 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
837 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
838 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
839 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
842 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
843 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
844 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
845 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
846 pcbStructInfo, NULL, NULL);
850 SetLastError(STATUS_ACCESS_VIOLATION);
855 TRACE("Returning %d (%08x)\n", ret, GetLastError());
859 static BOOL CRYPT_AsnDecodeCertVersion(const BYTE *pbEncoded, DWORD cbEncoded,
860 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
865 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
867 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
869 ret = CRYPT_AsnDecodeIntInternal(pbEncoded + 1 + lenBytes, dataLen,
870 dwFlags, pvStructInfo, pcbStructInfo, NULL);
872 *pcbDecoded = 1 + lenBytes + dataLen;
877 static BOOL CRYPT_AsnDecodeValidity(const BYTE *pbEncoded, DWORD cbEncoded,
878 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
882 struct AsnDecodeSequenceItem items[] = {
883 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
884 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
885 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
886 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
889 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
890 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
895 static BOOL CRYPT_AsnDecodeCertExtensions(const BYTE *pbEncoded,
896 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
902 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
904 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
906 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded + 1 + lenBytes,
907 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
908 if (ret && pcbDecoded)
909 *pcbDecoded = 1 + lenBytes + dataLen;
914 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
915 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
916 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
919 struct AsnDecodeSequenceItem items[] = {
920 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
921 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
922 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
923 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
924 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
925 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
926 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
927 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
928 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
929 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
931 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
932 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
934 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
935 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
937 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
938 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
939 FALSE, TRUE, offsetof(CERT_INFO,
940 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
941 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
942 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
943 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
944 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
945 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
946 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
947 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
948 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
949 offsetof(CERT_INFO, rgExtension), 0 },
952 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
953 pDecodePara, pvStructInfo, *pcbStructInfo);
955 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
956 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
958 if (ret && pvStructInfo)
962 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
963 info = *(CERT_INFO **)pvStructInfo;
965 info = (CERT_INFO *)pvStructInfo;
966 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
967 !info->Subject.cbData)
969 SetLastError(CRYPT_E_ASN1_CORRUPT);
970 /* Don't need to deallocate, because it should have failed on the
971 * first pass (and no memory was allocated.)
977 TRACE("Returning %d (%08x)\n", ret, GetLastError());
981 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
982 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
983 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
987 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
988 pDecodePara, pvStructInfo, *pcbStructInfo);
994 /* Unless told not to, first try to decode it as a signed cert. */
995 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
997 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
999 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1000 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1001 (BYTE *)&signedCert, &size);
1005 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1006 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
1007 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
1008 pvStructInfo, pcbStructInfo);
1009 LocalFree(signedCert);
1012 /* Failing that, try it as an unsigned cert */
1016 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1017 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
1018 pDecodePara, pvStructInfo, pcbStructInfo);
1023 SetLastError(STATUS_ACCESS_VIOLATION);
1027 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1031 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
1032 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1035 struct AsnDecodeSequenceItem items[] = {
1036 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
1037 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
1038 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
1039 { 0, offsetof(CRL_ENTRY, RevocationDate),
1040 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
1041 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
1042 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1043 offsetof(CRL_ENTRY, rgExtension), 0 },
1045 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
1047 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
1050 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1051 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, pcbDecoded,
1052 entry ? entry->SerialNumber.pbData : NULL);
1056 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
1057 * been set prior to calling.
1059 static BOOL CRYPT_AsnDecodeCRLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
1060 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1063 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1064 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
1065 offsetof(CRL_ENTRY, SerialNumber.pbData) };
1066 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
1068 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1069 pvStructInfo, *pcbStructInfo, pcbDecoded);
1071 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1072 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1073 entries ? entries->rgItems : NULL);
1074 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1078 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1079 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1080 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1082 struct AsnDecodeSequenceItem items[] = {
1083 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1084 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1085 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1086 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1087 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1088 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1089 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1091 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1092 sizeof(FILETIME), FALSE, FALSE, 0 },
1093 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1094 sizeof(FILETIME), TRUE, FALSE, 0 },
1095 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1096 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
1097 offsetof(CRL_INFO, rgCRLEntry), 0 },
1098 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1099 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1100 offsetof(CRL_INFO, rgExtension), 0 },
1104 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1105 pDecodePara, pvStructInfo, *pcbStructInfo);
1107 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1108 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
1111 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1115 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1116 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1117 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1121 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1122 pDecodePara, pvStructInfo, *pcbStructInfo);
1128 /* Unless told not to, first try to decode it as a signed crl. */
1129 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1131 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1133 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1134 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1135 (BYTE *)&signedCrl, &size);
1139 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1140 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1141 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1142 pvStructInfo, pcbStructInfo);
1143 LocalFree(signedCrl);
1146 /* Failing that, try it as an unsigned crl */
1150 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1151 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1152 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1157 SetLastError(STATUS_ACCESS_VIOLATION);
1161 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1165 static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded,
1166 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1171 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1172 pvStructInfo, *pcbStructInfo);
1174 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1176 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1177 DWORD bytesNeeded = sizeof(LPSTR);
1181 /* The largest possible string for the first two components
1182 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1187 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1188 pbEncoded[1 + lenBytes] / 40,
1189 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1191 bytesNeeded += strlen(firstTwo) + 1;
1192 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1193 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1195 /* large enough for ".4000000" */
1199 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1206 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1209 SetLastError(CRYPT_E_ASN1_CORRUPT);
1216 snprintf(str, sizeof(str), ".%d", val);
1217 bytesNeeded += strlen(str);
1222 *pcbDecoded = 1 + lenBytes + dataLen;
1224 *pcbStructInfo = bytesNeeded;
1225 else if (*pcbStructInfo < bytesNeeded)
1227 *pcbStructInfo = bytesNeeded;
1228 SetLastError(ERROR_MORE_DATA);
1236 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1239 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1240 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1242 pszObjId += strlen(pszObjId);
1243 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1244 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1248 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1257 sprintf(pszObjId, ".%d", val);
1258 pszObjId += strlen(pszObjId);
1262 *(LPSTR *)pvStructInfo = NULL;
1263 *pcbStructInfo = bytesNeeded;
1269 static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded,
1270 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1274 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1275 pvStructInfo, *pcbStructInfo);
1277 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1278 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1279 pvStructInfo, pcbStructInfo, pcbDecoded);
1282 SetLastError(CRYPT_E_ASN1_BADTAG);
1288 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1291 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
1292 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1294 struct AsnDecodeSequenceItem items[] = {
1295 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1296 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1297 offsetof(CERT_EXTENSION, pszObjId), 0 },
1298 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1299 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1300 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1301 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1302 offsetof(CERT_EXTENSION, Value.pbData) },
1305 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1307 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1311 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1312 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1313 pbEncoded, cbEncoded, dwFlags, NULL, ext, pcbStructInfo,
1314 pcbDecoded, ext ? ext->pszObjId : NULL);
1316 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1317 debugstr_a(ext->pszObjId));
1318 TRACE("returning %d (%08x)\n", ret, GetLastError());
1322 static BOOL CRYPT_AsnDecodeExtensionsInternal(const BYTE *pbEncoded,
1323 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1327 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1328 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1329 offsetof(CERT_EXTENSION, pszObjId) };
1330 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1332 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1333 pvStructInfo, *pcbStructInfo, pcbDecoded);
1335 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1336 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1337 exts ? exts->rgExtension : NULL);
1341 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1342 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1343 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1349 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
1350 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1351 if (ret && pvStructInfo)
1353 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1354 pcbStructInfo, *pcbStructInfo);
1357 CERT_EXTENSIONS *exts;
1359 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1360 pvStructInfo = *(BYTE **)pvStructInfo;
1361 exts = (CERT_EXTENSIONS *)pvStructInfo;
1362 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1363 sizeof(CERT_EXTENSIONS));
1364 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
1365 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1366 pcbStructInfo, NULL);
1372 SetLastError(STATUS_ACCESS_VIOLATION);
1379 /* Warning: this assumes the address of value->Value.pbData is already set, in
1380 * order to avoid overwriting memory. (In some cases, it may change it, if it
1381 * doesn't copy anything to memory.) Be sure to set it correctly!
1383 static BOOL CRYPT_AsnDecodeNameValueInternal(const BYTE *pbEncoded,
1384 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1389 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1391 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1393 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1394 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1396 switch (pbEncoded[0])
1398 case ASN_OCTETSTRING:
1399 valueType = CERT_RDN_OCTET_STRING;
1400 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1401 bytesNeeded += dataLen;
1403 case ASN_NUMERICSTRING:
1404 valueType = CERT_RDN_NUMERIC_STRING;
1405 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1406 bytesNeeded += dataLen;
1408 case ASN_PRINTABLESTRING:
1409 valueType = CERT_RDN_PRINTABLE_STRING;
1410 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1411 bytesNeeded += dataLen;
1414 valueType = CERT_RDN_IA5_STRING;
1415 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1416 bytesNeeded += dataLen;
1419 valueType = CERT_RDN_T61_STRING;
1420 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1421 bytesNeeded += dataLen;
1423 case ASN_VIDEOTEXSTRING:
1424 valueType = CERT_RDN_VIDEOTEX_STRING;
1425 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1426 bytesNeeded += dataLen;
1428 case ASN_GRAPHICSTRING:
1429 valueType = CERT_RDN_GRAPHIC_STRING;
1430 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1431 bytesNeeded += dataLen;
1433 case ASN_VISIBLESTRING:
1434 valueType = CERT_RDN_VISIBLE_STRING;
1435 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1436 bytesNeeded += dataLen;
1438 case ASN_GENERALSTRING:
1439 valueType = CERT_RDN_GENERAL_STRING;
1440 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1441 bytesNeeded += dataLen;
1443 case ASN_UNIVERSALSTRING:
1444 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1445 SetLastError(CRYPT_E_ASN1_BADTAG);
1448 valueType = CERT_RDN_BMP_STRING;
1449 bytesNeeded += dataLen;
1451 case ASN_UTF8STRING:
1452 valueType = CERT_RDN_UTF8_STRING;
1453 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1454 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1457 SetLastError(CRYPT_E_ASN1_BADTAG);
1462 *pcbDecoded = 1 + lenBytes + dataLen;
1464 *pcbStructInfo = bytesNeeded;
1465 else if (*pcbStructInfo < bytesNeeded)
1467 *pcbStructInfo = bytesNeeded;
1468 SetLastError(ERROR_MORE_DATA);
1473 *pcbStructInfo = bytesNeeded;
1474 value->dwValueType = valueType;
1479 assert(value->Value.pbData);
1480 switch (pbEncoded[0])
1482 case ASN_OCTETSTRING:
1483 case ASN_NUMERICSTRING:
1484 case ASN_PRINTABLESTRING:
1487 case ASN_VIDEOTEXSTRING:
1488 case ASN_GRAPHICSTRING:
1489 case ASN_VISIBLESTRING:
1490 case ASN_GENERALSTRING:
1491 value->Value.cbData = dataLen;
1494 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1495 memcpy(value->Value.pbData,
1496 pbEncoded + 1 + lenBytes, dataLen);
1498 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1504 LPWSTR str = (LPWSTR)value->Value.pbData;
1506 value->Value.cbData = dataLen;
1507 for (i = 0; i < dataLen / 2; i++)
1508 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1509 pbEncoded[1 + lenBytes + 2 * i + 1];
1512 case ASN_UTF8STRING:
1514 LPWSTR str = (LPWSTR)value->Value.pbData;
1516 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1517 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1518 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1525 value->Value.cbData = 0;
1526 value->Value.pbData = NULL;
1533 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1534 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1535 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1541 ret = CRYPT_AsnDecodeNameValueInternal(pbEncoded, cbEncoded,
1542 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1543 if (ret && pvStructInfo)
1545 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1546 pcbStructInfo, *pcbStructInfo);
1549 CERT_NAME_VALUE *value;
1551 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1552 pvStructInfo = *(BYTE **)pvStructInfo;
1553 value = (CERT_NAME_VALUE *)pvStructInfo;
1554 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1555 ret = CRYPT_AsnDecodeNameValueInternal( pbEncoded, cbEncoded,
1556 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1557 pcbStructInfo, NULL);
1563 SetLastError(STATUS_ACCESS_VIOLATION);
1570 static BOOL CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE *pbEncoded,
1571 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1576 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1578 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1580 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1581 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1583 switch (pbEncoded[0])
1585 case ASN_NUMERICSTRING:
1586 valueType = CERT_RDN_NUMERIC_STRING;
1587 bytesNeeded += dataLen * 2;
1589 case ASN_PRINTABLESTRING:
1590 valueType = CERT_RDN_PRINTABLE_STRING;
1591 bytesNeeded += dataLen * 2;
1594 valueType = CERT_RDN_IA5_STRING;
1595 bytesNeeded += dataLen * 2;
1598 valueType = CERT_RDN_T61_STRING;
1599 bytesNeeded += dataLen * 2;
1601 case ASN_VIDEOTEXSTRING:
1602 valueType = CERT_RDN_VIDEOTEX_STRING;
1603 bytesNeeded += dataLen * 2;
1605 case ASN_GRAPHICSTRING:
1606 valueType = CERT_RDN_GRAPHIC_STRING;
1607 bytesNeeded += dataLen * 2;
1609 case ASN_VISIBLESTRING:
1610 valueType = CERT_RDN_VISIBLE_STRING;
1611 bytesNeeded += dataLen * 2;
1613 case ASN_GENERALSTRING:
1614 valueType = CERT_RDN_GENERAL_STRING;
1615 bytesNeeded += dataLen * 2;
1617 case ASN_UNIVERSALSTRING:
1618 valueType = CERT_RDN_UNIVERSAL_STRING;
1619 bytesNeeded += dataLen / 2;
1622 valueType = CERT_RDN_BMP_STRING;
1623 bytesNeeded += dataLen;
1625 case ASN_UTF8STRING:
1626 valueType = CERT_RDN_UTF8_STRING;
1627 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1628 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1631 SetLastError(CRYPT_E_ASN1_BADTAG);
1636 *pcbDecoded = 1 + lenBytes + dataLen;
1638 *pcbStructInfo = bytesNeeded;
1639 else if (*pcbStructInfo < bytesNeeded)
1641 *pcbStructInfo = bytesNeeded;
1642 SetLastError(ERROR_MORE_DATA);
1647 *pcbStructInfo = bytesNeeded;
1648 value->dwValueType = valueType;
1652 LPWSTR str = (LPWSTR)value->Value.pbData;
1654 assert(value->Value.pbData);
1655 switch (pbEncoded[0])
1657 case ASN_NUMERICSTRING:
1658 case ASN_PRINTABLESTRING:
1661 case ASN_VIDEOTEXSTRING:
1662 case ASN_GRAPHICSTRING:
1663 case ASN_VISIBLESTRING:
1664 case ASN_GENERALSTRING:
1665 value->Value.cbData = dataLen * 2;
1666 for (i = 0; i < dataLen; i++)
1667 str[i] = pbEncoded[1 + lenBytes + i];
1669 case ASN_UNIVERSALSTRING:
1670 value->Value.cbData = dataLen / 2;
1671 for (i = 0; i < dataLen / 4; i++)
1672 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1673 | pbEncoded[1 + lenBytes + 2 * i + 3];
1676 value->Value.cbData = dataLen;
1677 for (i = 0; i < dataLen / 2; i++)
1678 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1679 pbEncoded[1 + lenBytes + 2 * i + 1];
1681 case ASN_UTF8STRING:
1682 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1683 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1684 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1690 value->Value.cbData = 0;
1691 value->Value.pbData = NULL;
1698 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1699 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1700 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1706 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded, cbEncoded,
1707 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1708 if (ret && pvStructInfo)
1710 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1711 pcbStructInfo, *pcbStructInfo);
1714 CERT_NAME_VALUE *value;
1716 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1717 pvStructInfo = *(BYTE **)pvStructInfo;
1718 value = (CERT_NAME_VALUE *)pvStructInfo;
1719 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1720 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded,
1721 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1722 pcbStructInfo, NULL);
1728 SetLastError(STATUS_ACCESS_VIOLATION);
1735 static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
1736 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1739 struct AsnDecodeSequenceItem items[] = {
1740 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1741 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1742 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1743 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1744 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1745 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1747 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1749 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1750 pvStructInfo, *pcbStructInfo);
1753 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1754 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1755 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1756 attr ? attr->pszObjId : NULL);
1759 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1760 debugstr_a(attr->pszObjId));
1761 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1763 TRACE("returning %d (%08x)\n", ret, GetLastError());
1767 static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1768 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1771 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1772 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1773 offsetof(CERT_RDN_ATTR, pszObjId) };
1774 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1776 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1777 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1778 rdn ? rdn->rgRDNAttr : NULL);
1782 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1783 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1784 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1790 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1791 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1792 offsetof(CERT_RDN, rgRDNAttr) };
1794 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1795 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1799 SetLastError(STATUS_ACCESS_VIOLATION);
1806 static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
1807 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1811 struct AsnDecodeSequenceItem items[] = {
1812 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1813 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1814 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1815 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1816 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1817 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1819 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1821 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1822 pvStructInfo, *pcbStructInfo);
1825 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1826 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1827 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1828 attr ? attr->pszObjId : NULL);
1831 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1832 debugstr_a(attr->pszObjId));
1833 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1835 TRACE("returning %d (%08x)\n", ret, GetLastError());
1839 static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1840 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1843 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1844 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1845 offsetof(CERT_RDN_ATTR, pszObjId) };
1846 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1848 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1849 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1850 rdn ? rdn->rgRDNAttr : NULL);
1854 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1855 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1856 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1862 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1863 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1864 offsetof(CERT_RDN, rgRDNAttr) };
1866 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1867 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1871 SetLastError(STATUS_ACCESS_VIOLATION);
1878 static BOOL CRYPT_AsnDecodeCopyBytes(const BYTE *pbEncoded,
1879 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1883 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1885 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1886 pvStructInfo, *pcbStructInfo);
1888 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1889 bytesNeeded += cbEncoded;
1891 *pcbDecoded = cbEncoded;
1893 *pcbStructInfo = bytesNeeded;
1894 else if (*pcbStructInfo < bytesNeeded)
1896 SetLastError(ERROR_MORE_DATA);
1897 *pcbStructInfo = bytesNeeded;
1902 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1904 *pcbStructInfo = bytesNeeded;
1905 blob->cbData = cbEncoded;
1906 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1907 blob->pbData = (LPBYTE)pbEncoded;
1910 assert(blob->pbData);
1911 memcpy(blob->pbData, pbEncoded, blob->cbData);
1917 static BOOL CRYPT_DecodeDERArray(const BYTE *pbEncoded, DWORD cbEncoded,
1918 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1921 struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytes,
1922 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
1923 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
1925 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1926 pvStructInfo, *pcbStructInfo, pcbDecoded);
1928 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1929 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1930 array ? array->rgItems : NULL);
1934 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
1935 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1939 struct AsnDecodeSequenceItem items[] = {
1940 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
1941 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1942 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
1943 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
1944 CRYPT_DecodeDERArray, sizeof(struct GenericArray), FALSE, TRUE,
1945 offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
1947 PCRYPT_ATTRIBUTE attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
1949 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1950 pvStructInfo, *pcbStructInfo);
1952 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1953 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
1954 pcbDecoded, attr ? attr->pszObjId : NULL);
1955 TRACE("returning %d\n", ret);
1959 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
1960 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1961 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1965 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1966 pDecodePara, pvStructInfo, *pcbStructInfo);
1972 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
1973 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
1977 *pcbStructInfo = bytesNeeded;
1978 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1979 pvStructInfo, pcbStructInfo, bytesNeeded)))
1981 PCRYPT_ATTRIBUTE attr;
1983 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1984 pvStructInfo = *(BYTE **)pvStructInfo;
1985 attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
1986 attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
1987 sizeof(CRYPT_ATTRIBUTE));
1988 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
1989 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
1996 SetLastError(STATUS_ACCESS_VIOLATION);
1999 TRACE("returning %d\n", ret);
2003 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
2004 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2007 struct AsnArrayDescriptor arrayDesc = { 0,
2008 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2009 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2010 PCRYPT_ATTRIBUTES attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
2013 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2014 NULL, pvStructInfo, pcbStructInfo, pcbDecoded, attrs ? attrs->rgAttr :
2019 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
2020 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2021 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2025 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2026 pDecodePara, pvStructInfo, *pcbStructInfo);
2033 SetLastError(CRYPT_E_ASN1_EOD);
2034 else if (pbEncoded[0] != (ASN_CONSTRUCTOR | ASN_SETOF))
2035 SetLastError(CRYPT_E_ASN1_CORRUPT);
2036 else if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
2037 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2041 *pcbStructInfo = bytesNeeded;
2042 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2043 pvStructInfo, pcbStructInfo, bytesNeeded)))
2045 PCRYPT_ATTRIBUTES attrs;
2047 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2048 pvStructInfo = *(BYTE **)pvStructInfo;
2049 attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
2050 attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
2051 sizeof(CRYPT_ATTRIBUTES));
2052 ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
2053 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2054 &bytesNeeded, NULL);
2060 SetLastError(STATUS_ACCESS_VIOLATION);
2063 TRACE("returning %d\n", ret);
2067 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
2068 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2070 CRYPT_ALGORITHM_IDENTIFIER *algo =
2071 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
2073 struct AsnDecodeSequenceItem items[] = {
2074 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
2075 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2076 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
2077 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
2078 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2079 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
2082 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2083 pvStructInfo, *pcbStructInfo, pcbDecoded);
2085 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2086 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2087 pcbDecoded, algo ? algo->pszObjId : NULL);
2088 if (ret && pvStructInfo)
2090 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
2091 debugstr_a(algo->pszObjId));
2096 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
2097 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2101 struct AsnDecodeSequenceItem items[] = {
2102 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
2103 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2104 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
2105 Algorithm.pszObjId) },
2106 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
2107 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2108 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
2110 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2112 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2113 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2114 pcbDecoded, info ? info->Algorithm.Parameters.pbData : NULL);
2118 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2119 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2120 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2128 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2129 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2132 *pcbStructInfo = bytesNeeded;
2133 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2134 pvStructInfo, pcbStructInfo, bytesNeeded)))
2136 PCERT_PUBLIC_KEY_INFO info;
2138 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2139 pvStructInfo = *(BYTE **)pvStructInfo;
2140 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2141 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2142 sizeof(CERT_PUBLIC_KEY_INFO);
2143 ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2144 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2145 &bytesNeeded, NULL);
2151 SetLastError(STATUS_ACCESS_VIOLATION);
2158 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
2159 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2165 SetLastError(CRYPT_E_ASN1_CORRUPT);
2168 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2170 SetLastError(CRYPT_E_ASN1_CORRUPT);
2173 if (pbEncoded[1] > 1)
2175 SetLastError(CRYPT_E_ASN1_CORRUPT);
2182 *pcbStructInfo = sizeof(BOOL);
2185 else if (*pcbStructInfo < sizeof(BOOL))
2187 *pcbStructInfo = sizeof(BOOL);
2188 SetLastError(ERROR_MORE_DATA);
2193 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2196 TRACE("returning %d (%08x)\n", ret, GetLastError());
2200 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2201 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2203 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
2204 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2207 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2208 pvStructInfo, *pcbStructInfo);
2212 SetLastError(CRYPT_E_ASN1_CORRUPT);
2215 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2216 if (1 + lenBytes > cbEncoded)
2218 SetLastError(CRYPT_E_ASN1_CORRUPT);
2221 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2223 switch (pbEncoded[0] & ASN_TYPE_MASK)
2225 case 1: /* rfc822Name */
2226 case 2: /* dNSName */
2227 case 6: /* uniformResourceIdentifier */
2228 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
2230 case 4: /* directoryName */
2231 case 7: /* iPAddress */
2232 bytesNeeded += dataLen;
2234 case 8: /* registeredID */
2235 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
2239 /* FIXME: ugly, shouldn't need to know internals of OID decode
2240 * function to use it.
2242 bytesNeeded += dataLen - sizeof(LPSTR);
2245 case 0: /* otherName */
2246 FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
2247 SetLastError(CRYPT_E_ASN1_BADTAG);
2250 case 3: /* x400Address, unimplemented */
2251 case 5: /* ediPartyName, unimplemented */
2252 TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
2253 SetLastError(CRYPT_E_ASN1_BADTAG);
2257 TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
2258 SetLastError(CRYPT_E_ASN1_CORRUPT);
2264 *pcbDecoded = 1 + lenBytes + dataLen;
2266 *pcbStructInfo = bytesNeeded;
2267 else if (*pcbStructInfo < bytesNeeded)
2269 *pcbStructInfo = bytesNeeded;
2270 SetLastError(ERROR_MORE_DATA);
2275 *pcbStructInfo = bytesNeeded;
2276 /* MS used values one greater than the asn1 ones.. sigh */
2277 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
2278 switch (pbEncoded[0] & ASN_TYPE_MASK)
2280 case 1: /* rfc822Name */
2281 case 2: /* dNSName */
2282 case 6: /* uniformResourceIdentifier */
2286 for (i = 0; i < dataLen; i++)
2287 entry->u.pwszURL[i] =
2288 (WCHAR)pbEncoded[1 + lenBytes + i];
2289 entry->u.pwszURL[i] = 0;
2290 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2291 debugstr_w(entry->u.pwszURL));
2294 case 4: /* directoryName */
2295 entry->dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
2296 /* The data are memory-equivalent with the IPAddress case,
2299 case 7: /* iPAddress */
2300 /* The next data pointer is in the pwszURL spot, that is,
2301 * the first 4 bytes. Need to move it to the next spot.
2303 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2304 entry->u.IPAddress.cbData = dataLen;
2305 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2308 case 8: /* registeredID */
2309 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
2310 &entry->u.pszRegisteredID, &dataLen, NULL);
2319 static BOOL CRYPT_AsnDecodeAltNameInternal(const BYTE *pbEncoded,
2320 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2324 struct AsnArrayDescriptor arrayDesc = { 0,
2325 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2326 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2327 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
2329 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2330 pvStructInfo, *pcbStructInfo, pcbDecoded);
2333 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2334 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2335 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2336 info ? info->rgAltEntry : NULL);
2340 /* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */
2341 static BOOL CRYPT_AsnDecodeIntegerSwapBytes(const BYTE *pbEncoded,
2342 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2347 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
2348 pvStructInfo, *pcbStructInfo, pcbDecoded);
2350 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2353 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
2354 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
2356 if (ret && pvStructInfo)
2358 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2365 for (i = 0; i < blob->cbData / 2; i++)
2367 temp = blob->pbData[i];
2368 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
2369 blob->pbData[blob->cbData - i - 1] = temp;
2373 TRACE("returning %d (%08x)\n", ret, GetLastError());
2377 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
2378 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2379 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2385 struct AsnDecodeSequenceItem items[] = {
2386 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
2387 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2388 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
2389 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2390 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
2391 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
2392 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
2393 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
2394 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2395 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2396 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
2399 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2400 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2401 pcbStructInfo, NULL, NULL);
2405 SetLastError(STATUS_ACCESS_VIOLATION);
2412 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
2413 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2414 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2420 struct AsnDecodeSequenceItem items[] = {
2421 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
2422 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2423 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
2424 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2425 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
2426 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
2427 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2428 AuthorityCertIssuer.rgAltEntry), 0 },
2429 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2430 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2431 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2432 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2433 AuthorityCertSerialNumber.pbData), 0 },
2436 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2437 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2438 pcbStructInfo, NULL, NULL);
2442 SetLastError(STATUS_ACCESS_VIOLATION);
2449 static BOOL CRYPT_AsnDecodePKCSContent(const BYTE *pbEncoded, DWORD cbEncoded,
2450 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2455 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2456 pvStructInfo, *pcbStructInfo, pcbDecoded);
2458 /* The caller has already checked the tag, no need to check it again.
2459 * Check the outer length is valid by calling CRYPT_GetLen:
2461 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2463 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2466 pbEncoded += 1 + lenBytes;
2467 /* Check the inner length is valid by calling CRYPT_GetLen again: */
2468 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &innerLen)))
2470 ret = CRYPT_AsnDecodeCopyBytes(pbEncoded, dataLen, dwFlags,
2471 pvStructInfo, pcbStructInfo, NULL);
2473 *pcbDecoded = 1 + lenBytes + dataLen;
2479 static BOOL CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE *pbEncoded,
2480 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2483 CRYPT_CONTENT_INFO *info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2484 struct AsnDecodeSequenceItem items[] = {
2485 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
2486 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2487 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
2488 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
2489 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
2490 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
2491 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
2495 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2496 pvStructInfo, *pcbStructInfo, pcbDecoded);
2498 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2499 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2500 pcbDecoded, info ? info->pszObjId : NULL);
2504 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
2505 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2506 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2510 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2511 pDecodePara, pvStructInfo, *pcbStructInfo);
2515 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, cbEncoded,
2516 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
2517 if (ret && pvStructInfo)
2519 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
2520 pcbStructInfo, *pcbStructInfo);
2523 CRYPT_CONTENT_INFO *info;
2525 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2526 pvStructInfo = *(BYTE **)pvStructInfo;
2527 info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2528 info->pszObjId = (LPSTR)((BYTE *)info +
2529 sizeof(CRYPT_CONTENT_INFO));
2530 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded,
2531 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2532 pcbStructInfo, NULL);
2538 SetLastError(STATUS_ACCESS_VIOLATION);
2544 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
2545 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2546 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
2549 struct AsnDecodeSequenceItem items[] = {
2550 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version),
2551 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2552 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
2553 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2554 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
2556 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
2557 CRYPT_AsnDecodePKCSContentInfoInternal,
2558 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
2559 ContentInfo.pszObjId), 0 },
2560 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
2561 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
2562 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
2565 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2566 pbEncoded, cbEncoded, dwFlags, pDecodePara, digestedData, pcbDigestedData,
2571 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
2572 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2573 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2577 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2578 pDecodePara, pvStructInfo, *pcbStructInfo);
2584 if ((ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
2585 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2588 *pcbStructInfo = bytesNeeded;
2589 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2590 pvStructInfo, pcbStructInfo, bytesNeeded)))
2592 CERT_ALT_NAME_INFO *name;
2594 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2595 pvStructInfo = *(BYTE **)pvStructInfo;
2596 name = (CERT_ALT_NAME_INFO *)pvStructInfo;
2597 name->rgAltEntry = (PCERT_ALT_NAME_ENTRY)
2598 ((BYTE *)pvStructInfo + sizeof(CERT_ALT_NAME_INFO));
2599 ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
2600 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2601 &bytesNeeded, NULL);
2607 SetLastError(STATUS_ACCESS_VIOLATION);
2614 struct PATH_LEN_CONSTRAINT
2616 BOOL fPathLenConstraint;
2617 DWORD dwPathLenConstraint;
2620 static BOOL CRYPT_AsnDecodePathLenConstraint(const BYTE *pbEncoded,
2621 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2625 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT), size;
2627 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2628 pvStructInfo, *pcbStructInfo, pcbDecoded);
2632 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, NULL,
2634 *pcbStructInfo = bytesNeeded;
2636 else if (*pcbStructInfo < bytesNeeded)
2638 SetLastError(ERROR_MORE_DATA);
2639 *pcbStructInfo = bytesNeeded;
2644 struct PATH_LEN_CONSTRAINT *constraint =
2645 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
2647 size = sizeof(constraint->dwPathLenConstraint);
2648 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
2649 &constraint->dwPathLenConstraint, &size, pcbDecoded);
2651 constraint->fPathLenConstraint = TRUE;
2652 TRACE("got an int, dwPathLenConstraint is %d\n",
2653 constraint->dwPathLenConstraint);
2655 TRACE("returning %d (%08x)\n", ret, GetLastError());
2659 static BOOL CRYPT_AsnDecodeSubtreeConstraints(const BYTE *pbEncoded,
2660 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2664 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2665 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
2666 offsetof(CERT_NAME_BLOB, pbData) };
2667 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2669 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2670 pvStructInfo, *pcbStructInfo, pcbDecoded);
2672 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2673 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2674 entries ? entries->rgItems : NULL);
2675 TRACE("Returning %d (%08x)\n", ret, GetLastError());
2679 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
2680 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2681 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2687 struct AsnDecodeSequenceItem items[] = {
2688 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
2689 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2690 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
2691 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2692 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2693 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2694 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2695 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
2696 sizeof(struct GenericArray), TRUE, TRUE,
2697 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
2700 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2701 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2702 pcbStructInfo, NULL, NULL);
2706 SetLastError(STATUS_ACCESS_VIOLATION);
2713 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
2714 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2715 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2721 struct AsnDecodeSequenceItem items[] = {
2722 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
2723 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
2724 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
2725 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2726 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2729 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2730 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2731 pcbStructInfo, NULL, NULL);
2735 SetLastError(STATUS_ACCESS_VIOLATION);
2742 #define RSA1_MAGIC 0x31415352
2744 struct DECODED_RSA_PUB_KEY
2747 CRYPT_INTEGER_BLOB modulus;
2750 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
2751 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2752 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2758 struct AsnDecodeSequenceItem items[] = {
2759 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
2760 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2761 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
2763 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
2764 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2766 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
2769 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2770 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
2774 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2775 decodedKey->modulus.cbData;
2779 *pcbStructInfo = bytesNeeded;
2782 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2783 pvStructInfo, pcbStructInfo, bytesNeeded)))
2786 RSAPUBKEY *rsaPubKey;
2788 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2789 pvStructInfo = *(BYTE **)pvStructInfo;
2790 hdr = (BLOBHEADER *)pvStructInfo;
2791 hdr->bType = PUBLICKEYBLOB;
2792 hdr->bVersion = CUR_BLOB_VERSION;
2794 hdr->aiKeyAlg = CALG_RSA_KEYX;
2795 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
2796 sizeof(BLOBHEADER));
2797 rsaPubKey->magic = RSA1_MAGIC;
2798 rsaPubKey->pubexp = decodedKey->pubexp;
2799 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
2800 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
2801 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
2802 decodedKey->modulus.cbData);
2804 LocalFree(decodedKey);
2809 SetLastError(STATUS_ACCESS_VIOLATION);
2816 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
2817 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2821 DWORD bytesNeeded, dataLen;
2823 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2824 pvStructInfo, *pcbStructInfo, pcbDecoded);
2826 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2828 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2830 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2831 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
2833 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
2835 *pcbDecoded = 1 + lenBytes + dataLen;
2837 *pcbStructInfo = bytesNeeded;
2838 else if (*pcbStructInfo < bytesNeeded)
2840 SetLastError(ERROR_MORE_DATA);
2841 *pcbStructInfo = bytesNeeded;
2846 CRYPT_DATA_BLOB *blob;
2848 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2849 blob->cbData = dataLen;
2850 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2851 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
2854 assert(blob->pbData);
2856 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
2864 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
2865 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2866 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2870 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2871 pDecodePara, pvStructInfo, *pcbStructInfo);
2879 SetLastError(CRYPT_E_ASN1_CORRUPT);
2882 else if (pbEncoded[0] != ASN_OCTETSTRING)
2884 SetLastError(CRYPT_E_ASN1_BADTAG);
2887 else if ((ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
2888 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2891 *pcbStructInfo = bytesNeeded;
2892 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2893 pvStructInfo, pcbStructInfo, bytesNeeded)))
2895 CRYPT_DATA_BLOB *blob;
2897 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2898 pvStructInfo = *(BYTE **)pvStructInfo;
2899 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2900 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
2901 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
2902 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2903 &bytesNeeded, NULL);
2909 SetLastError(STATUS_ACCESS_VIOLATION);
2916 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
2917 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2921 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
2922 pvStructInfo, *pcbStructInfo, pcbDecoded);
2924 if (pbEncoded[0] == ASN_BITSTRING)
2926 DWORD bytesNeeded, dataLen;
2927 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2929 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2931 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2932 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
2934 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
2936 *pcbDecoded = 1 + lenBytes + dataLen;
2938 *pcbStructInfo = bytesNeeded;
2939 else if (*pcbStructInfo < bytesNeeded)
2941 *pcbStructInfo = bytesNeeded;
2942 SetLastError(ERROR_MORE_DATA);
2947 CRYPT_BIT_BLOB *blob;
2949 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2950 blob->cbData = dataLen - 1;
2951 blob->cUnusedBits = *(pbEncoded + 1 + lenBytes);
2952 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2954 blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes;
2958 assert(blob->pbData);
2961 BYTE mask = 0xff << blob->cUnusedBits;
2963 memcpy(blob->pbData, pbEncoded + 2 + lenBytes,
2965 blob->pbData[blob->cbData - 1] &= mask;
2973 SetLastError(CRYPT_E_ASN1_BADTAG);
2976 TRACE("returning %d (%08x)\n", ret, GetLastError());
2980 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
2981 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2982 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2986 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
2987 pDecodePara, pvStructInfo, pcbStructInfo);
2993 if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
2994 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2997 *pcbStructInfo = bytesNeeded;
2998 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2999 pvStructInfo, pcbStructInfo, bytesNeeded)))
3001 CRYPT_BIT_BLOB *blob;
3003 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3004 pvStructInfo = *(BYTE **)pvStructInfo;
3005 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
3006 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
3007 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3008 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3009 &bytesNeeded, NULL);
3015 SetLastError(STATUS_ACCESS_VIOLATION);
3019 TRACE("returning %d (%08x)\n", ret, GetLastError());
3023 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3024 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3027 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
3028 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
3029 DWORD size = sizeof(buf);
3031 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
3032 if (pbEncoded[0] != ASN_INTEGER)
3034 SetLastError(CRYPT_E_ASN1_BADTAG);
3038 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded, 0, &buf,
3043 *pcbStructInfo = sizeof(int);
3044 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int))))
3048 if (blob->pbData[blob->cbData - 1] & 0x80)
3050 /* initialize to a negative value to sign-extend */
3055 for (i = 0; i < blob->cbData; i++)
3058 val |= blob->pbData[blob->cbData - i - 1];
3060 memcpy(pvStructInfo, &val, sizeof(int));
3063 else if (GetLastError() == ERROR_MORE_DATA)
3064 SetLastError(CRYPT_E_ASN1_LARGE);
3068 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
3069 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3070 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3078 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3079 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3083 *pcbStructInfo = bytesNeeded;
3084 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3085 pvStructInfo, pcbStructInfo, bytesNeeded)))
3087 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3088 pvStructInfo = *(BYTE **)pvStructInfo;
3089 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3090 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3091 &bytesNeeded, NULL);
3097 SetLastError(STATUS_ACCESS_VIOLATION);
3104 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
3105 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3109 DWORD bytesNeeded, dataLen;
3111 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3113 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3115 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3117 *pcbDecoded = 1 + lenBytes + dataLen;
3119 *pcbStructInfo = bytesNeeded;
3120 else if (*pcbStructInfo < bytesNeeded)
3122 *pcbStructInfo = bytesNeeded;
3123 SetLastError(ERROR_MORE_DATA);
3128 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3130 blob->cbData = dataLen;
3131 assert(blob->pbData);
3136 for (i = 0; i < blob->cbData; i++)
3138 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3147 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
3148 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3149 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3157 if (pbEncoded[0] != ASN_INTEGER)
3159 SetLastError(CRYPT_E_ASN1_BADTAG);
3163 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3164 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3168 *pcbStructInfo = bytesNeeded;
3169 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3170 pvStructInfo, pcbStructInfo, bytesNeeded)))
3172 CRYPT_INTEGER_BLOB *blob;
3174 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3175 pvStructInfo = *(BYTE **)pvStructInfo;
3176 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3177 blob->pbData = (BYTE *)pvStructInfo +
3178 sizeof(CRYPT_INTEGER_BLOB);
3179 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3180 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
3181 &bytesNeeded, NULL);
3187 SetLastError(STATUS_ACCESS_VIOLATION);
3194 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
3195 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3200 if (pbEncoded[0] == ASN_INTEGER)
3202 DWORD bytesNeeded, dataLen;
3204 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3206 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3209 *pcbDecoded = 1 + lenBytes + dataLen;
3210 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3212 *pcbStructInfo = bytesNeeded;
3213 else if (*pcbStructInfo < bytesNeeded)
3215 *pcbStructInfo = bytesNeeded;
3216 SetLastError(ERROR_MORE_DATA);
3221 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3223 blob->cbData = dataLen;
3224 assert(blob->pbData);
3225 /* remove leading zero byte if it exists */
3226 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
3235 for (i = 0; i < blob->cbData; i++)
3237 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3246 SetLastError(CRYPT_E_ASN1_BADTAG);
3252 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
3253 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3254 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3262 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded,
3263 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_AsnDecodeUnsignedIntegerInternal(pbEncoded,
3278 cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
3279 &bytesNeeded, NULL);
3285 SetLastError(STATUS_ACCESS_VIOLATION);
3292 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
3293 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3294 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3300 *pcbStructInfo = sizeof(int);
3305 if (pbEncoded[0] == ASN_ENUMERATED)
3307 unsigned int val = 0, i;
3311 SetLastError(CRYPT_E_ASN1_EOD);
3314 else if (pbEncoded[1] == 0)
3316 SetLastError(CRYPT_E_ASN1_CORRUPT);
3321 /* A little strange looking, but we have to accept a sign byte:
3322 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
3323 * assuming a small length is okay here, it has to be in short
3326 if (pbEncoded[1] > sizeof(unsigned int) + 1)
3328 SetLastError(CRYPT_E_ASN1_LARGE);
3331 for (i = 0; i < pbEncoded[1]; i++)
3334 val |= pbEncoded[2 + i];
3336 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3337 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
3339 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3340 pvStructInfo = *(BYTE **)pvStructInfo;
3341 memcpy(pvStructInfo, &val, sizeof(unsigned int));
3347 SetLastError(CRYPT_E_ASN1_BADTAG);
3353 SetLastError(STATUS_ACCESS_VIOLATION);
3360 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
3363 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
3368 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
3370 if (!isdigit(*(pbEncoded))) \
3372 SetLastError(CRYPT_E_ASN1_CORRUPT); \
3378 (word) += *(pbEncoded)++ - '0'; \
3383 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
3384 SYSTEMTIME *sysTime)
3388 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
3390 WORD hours, minutes = 0;
3391 BYTE sign = *pbEncoded++;
3394 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
3395 if (ret && hours >= 24)
3397 SetLastError(CRYPT_E_ASN1_CORRUPT);
3402 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
3403 if (ret && minutes >= 60)
3405 SetLastError(CRYPT_E_ASN1_CORRUPT);
3413 sysTime->wHour += hours;
3414 sysTime->wMinute += minutes;
3418 if (hours > sysTime->wHour)
3421 sysTime->wHour = 24 - (hours - sysTime->wHour);
3424 sysTime->wHour -= hours;
3425 if (minutes > sysTime->wMinute)
3428 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
3431 sysTime->wMinute -= minutes;
3438 #define MIN_ENCODED_TIME_LENGTH 10
3440 static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
3441 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3446 if (pbEncoded[0] == ASN_UTCTIME)
3449 SetLastError(CRYPT_E_ASN1_EOD);
3450 else if (pbEncoded[1] > 0x7f)
3452 /* long-form date strings really can't be valid */
3453 SetLastError(CRYPT_E_ASN1_CORRUPT);
3457 SYSTEMTIME sysTime = { 0 };
3458 BYTE len = pbEncoded[1];
3460 if (len < MIN_ENCODED_TIME_LENGTH)
3461 SetLastError(CRYPT_E_ASN1_CORRUPT);
3466 *pcbDecoded = 2 + len;
3468 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
3469 if (sysTime.wYear >= 50)
3470 sysTime.wYear += 1900;
3472 sysTime.wYear += 2000;
3473 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3474 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3475 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3476 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
3479 if (len >= 2 && isdigit(*pbEncoded) &&
3480 isdigit(*(pbEncoded + 1)))
3481 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3483 else if (isdigit(*pbEncoded))
3484 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
3487 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3493 *pcbStructInfo = sizeof(FILETIME);
3494 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
3496 ret = SystemTimeToFileTime(&sysTime,
3497 (FILETIME *)pvStructInfo);
3503 SetLastError(CRYPT_E_ASN1_BADTAG);
3507 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
3508 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3509 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3517 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
3518 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3522 *pcbStructInfo = bytesNeeded;
3523 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
3524 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
3526 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3527 pvStructInfo = *(BYTE **)pvStructInfo;
3528 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
3529 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3530 &bytesNeeded, NULL);
3536 SetLastError(STATUS_ACCESS_VIOLATION);
3542 static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
3543 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3548 if (pbEncoded[0] == ASN_GENERALTIME)
3551 SetLastError(CRYPT_E_ASN1_EOD);
3552 else if (pbEncoded[1] > 0x7f)
3554 /* long-form date strings really can't be valid */
3555 SetLastError(CRYPT_E_ASN1_CORRUPT);
3559 BYTE len = pbEncoded[1];
3561 if (len < MIN_ENCODED_TIME_LENGTH)
3562 SetLastError(CRYPT_E_ASN1_CORRUPT);
3565 SYSTEMTIME sysTime = { 0 };
3569 *pcbDecoded = 2 + len;
3571 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
3572 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3573 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3574 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3577 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3580 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3582 if (ret && len > 0 && (*pbEncoded == '.' ||
3589 /* workaround macro weirdness */
3590 digits = min(len, 3);
3591 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
3592 sysTime.wMilliseconds);
3595 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3601 *pcbStructInfo = sizeof(FILETIME);
3602 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
3604 ret = SystemTimeToFileTime(&sysTime,
3605 (FILETIME *)pvStructInfo);
3611 SetLastError(CRYPT_E_ASN1_BADTAG);
3615 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
3616 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3620 InternalDecodeFunc decode = NULL;
3622 if (pbEncoded[0] == ASN_UTCTIME)
3623 decode = CRYPT_AsnDecodeUtcTimeInternal;
3624 else if (pbEncoded[0] == ASN_GENERALTIME)
3625 decode = CRYPT_AsnDecodeGeneralizedTime;
3627 ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
3628 pcbStructInfo, pcbDecoded);
3631 SetLastError(CRYPT_E_ASN1_BADTAG);
3637 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
3638 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3639 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3647 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
3648 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3652 *pcbStructInfo = bytesNeeded;
3653 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3654 pvStructInfo, pcbStructInfo, bytesNeeded)))
3656 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3657 pvStructInfo = *(BYTE **)pvStructInfo;
3658 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
3659 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3660 &bytesNeeded, NULL);
3666 SetLastError(STATUS_ACCESS_VIOLATION);
3673 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
3674 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3675 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3681 if (pbEncoded[0] == ASN_SEQUENCEOF)
3683 DWORD bytesNeeded, dataLen, remainingLen, cValue;
3685 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3690 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3691 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
3693 ptr = pbEncoded + 1 + lenBytes;
3694 remainingLen = dataLen;
3695 while (ret && remainingLen)
3699 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3702 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3704 remainingLen -= 1 + nextLenBytes + nextLen;
3705 ptr += 1 + nextLenBytes + nextLen;
3706 bytesNeeded += sizeof(CRYPT_DER_BLOB);
3707 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3708 bytesNeeded += 1 + nextLenBytes + nextLen;
3714 CRYPT_SEQUENCE_OF_ANY *seq;
3718 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3719 pvStructInfo, pcbStructInfo, bytesNeeded)))
3721 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3722 pvStructInfo = *(BYTE **)pvStructInfo;
3723 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
3724 seq->cValue = cValue;
3725 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
3727 nextPtr = (BYTE *)seq->rgValue +
3728 cValue * sizeof(CRYPT_DER_BLOB);
3729 ptr = pbEncoded + 1 + lenBytes;
3730 remainingLen = dataLen;
3732 while (ret && remainingLen)
3736 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3739 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3741 seq->rgValue[i].cbData = 1 + nextLenBytes +
3743 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3744 seq->rgValue[i].pbData = (BYTE *)ptr;
3747 seq->rgValue[i].pbData = nextPtr;
3748 memcpy(nextPtr, ptr, 1 + nextLenBytes +
3750 nextPtr += 1 + nextLenBytes + nextLen;
3752 remainingLen -= 1 + nextLenBytes + nextLen;
3753 ptr += 1 + nextLenBytes + nextLen;
3763 SetLastError(CRYPT_E_ASN1_BADTAG);
3769 SetLastError(STATUS_ACCESS_VIOLATION);
3776 static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded,
3777 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3782 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
3784 DWORD bytesNeeded, dataLen;
3786 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3788 struct AsnArrayDescriptor arrayDesc = {
3789 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
3790 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3791 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3792 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3798 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3799 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3800 0, NULL, NULL, &nameLen, NULL, NULL);
3801 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen;
3804 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
3806 *pcbDecoded = 1 + lenBytes + dataLen;
3808 *pcbStructInfo = bytesNeeded;
3809 else if (*pcbStructInfo < bytesNeeded)
3811 *pcbStructInfo = bytesNeeded;
3812 SetLastError(ERROR_MORE_DATA);
3817 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
3821 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3822 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3823 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3824 0, NULL, &name->u.FullName, pcbStructInfo, NULL,
3825 name->u.FullName.rgAltEntry);
3828 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3834 SetLastError(CRYPT_E_ASN1_BADTAG);
3840 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
3841 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3843 struct AsnDecodeSequenceItem items[] = {
3844 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
3845 DistPointName), CRYPT_AsnDecodeDistPointName,
3846 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
3847 DistPointName.u.FullName.rgAltEntry), 0 },
3848 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
3849 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
3850 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
3851 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
3852 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
3853 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
3857 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3858 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3863 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
3864 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3865 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3869 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3870 pDecodePara, pvStructInfo, *pcbStructInfo);
3874 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3875 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
3876 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
3878 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3879 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
3883 SetLastError(STATUS_ACCESS_VIOLATION);
3890 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3891 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3892 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3896 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3897 pDecodePara, pvStructInfo, *pcbStructInfo);
3901 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3902 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
3904 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3905 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
3909 SetLastError(STATUS_ACCESS_VIOLATION);
3916 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
3917 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3918 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3922 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3923 pDecodePara, pvStructInfo, *pcbStructInfo);
3927 struct AsnDecodeSequenceItem items[] = {
3928 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
3929 DistPointName), CRYPT_AsnDecodeDistPointName,
3930 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
3931 offsetof(CRL_ISSUING_DIST_POINT,
3932 DistPointName.u.FullName.rgAltEntry), 0 },
3933 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
3934 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3936 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
3937 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3939 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
3940 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
3941 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
3942 OnlySomeReasonFlags.pbData), 0 },
3943 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
3944 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
3947 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3948 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3949 pcbStructInfo, NULL, NULL);
3953 SetLastError(STATUS_ACCESS_VIOLATION);
3960 static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded,
3961 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3965 struct AsnDecodeSequenceItem items[] = {
3966 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
3967 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
3969 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
3970 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
3971 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
3973 CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
3974 (CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
3976 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3977 pvStructInfo, *pcbStructInfo, pcbDecoded);
3979 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3980 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3981 pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL);
3982 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
3984 SetLastError(CRYPT_E_ASN1_CORRUPT);
3987 TRACE("returning %d\n", ret);
3991 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
3992 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3995 CMSG_SIGNER_INFO *info = (CMSG_SIGNER_INFO *)pvStructInfo;
3996 struct AsnDecodeSequenceItem items[] = {
3997 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
3998 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3999 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
4000 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
4001 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
4002 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
4003 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4004 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
4005 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4006 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
4007 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4008 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
4009 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
4010 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4011 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
4012 HashEncryptionAlgorithm.pszObjId), 0 },
4013 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
4014 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
4015 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
4016 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4017 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
4018 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4019 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
4023 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4024 pvStructInfo, *pcbStructInfo);
4026 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4027 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4028 pcbDecoded, info ? info->Issuer.pbData : NULL);
4032 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
4033 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4034 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4038 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4039 pDecodePara, pvStructInfo, *pcbStructInfo);
4043 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
4044 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
4045 if (ret && pvStructInfo)
4047 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
4048 pcbStructInfo, *pcbStructInfo);
4051 CMSG_SIGNER_INFO *info;
4053 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4054 pvStructInfo = *(BYTE **)pvStructInfo;
4055 info = (CMSG_SIGNER_INFO *)pvStructInfo;
4056 info->Issuer.pbData = ((BYTE *)info +
4057 sizeof(CMSG_SIGNER_INFO));
4058 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
4059 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4060 pcbStructInfo, NULL);
4066 SetLastError(STATUS_ACCESS_VIOLATION);
4069 TRACE("returning %d\n", ret);
4073 static BOOL CRYPT_DecodeSignerArray(const BYTE *pbEncoded, DWORD cbEncoded,
4074 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4077 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
4078 CRYPT_AsnDecodePKCSSignerInfoInternal, sizeof(CMSG_SIGNER_INFO), TRUE,
4079 offsetof(CMSG_SIGNER_INFO, Issuer.pbData) };
4080 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
4082 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4083 pvStructInfo, *pcbStructInfo, pcbDecoded);
4085 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4086 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
4087 array ? array->rgItems : NULL);
4091 BOOL CRYPT_AsnDecodePKCSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
4092 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
4093 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
4096 struct AsnDecodeSequenceItem items[] = {
4097 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version),
4098 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4099 /* Placeholder for the hash algorithms - redundant with those in the
4100 * signers, so just ignore them.
4102 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
4103 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
4104 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
4105 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
4106 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4107 offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
4108 CRYPT_DecodeDERArray, sizeof(struct GenericArray), TRUE, TRUE,
4109 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
4110 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4111 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_DecodeDERArray,
4112 sizeof(struct GenericArray), TRUE, TRUE,
4113 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
4114 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
4115 CRYPT_DecodeSignerArray, sizeof(struct GenericArray), TRUE, TRUE,
4116 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
4119 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4120 pDecodePara, signedInfo, *pcbSignedInfo);
4122 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4123 pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo,
4125 TRACE("returning %d\n", ret);
4129 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
4130 LPCSTR lpszStructType)
4132 CryptDecodeObjectExFunc decodeFunc = NULL;
4134 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
4135 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
4137 SetLastError(ERROR_FILE_NOT_FOUND);
4140 if (!HIWORD(lpszStructType))
4142 switch (LOWORD(lpszStructType))
4144 case (WORD)X509_CERT:
4145 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
4147 case (WORD)X509_CERT_TO_BE_SIGNED:
4148 decodeFunc = CRYPT_AsnDecodeCert;
4150 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
4151 decodeFunc = CRYPT_AsnDecodeCRL;
4153 case (WORD)X509_EXTENSIONS:
4154 decodeFunc = CRYPT_AsnDecodeExtensions;
4156 case (WORD)X509_NAME_VALUE:
4157 decodeFunc = CRYPT_AsnDecodeNameValue;
4159 case (WORD)X509_NAME:
4160 decodeFunc = CRYPT_AsnDecodeName;
4162 case (WORD)X509_PUBLIC_KEY_INFO:
4163 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
4165 case (WORD)X509_AUTHORITY_KEY_ID:
4166 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4168 case (WORD)X509_ALTERNATE_NAME:
4169 decodeFunc = CRYPT_AsnDecodeAltName;
4171 case (WORD)X509_BASIC_CONSTRAINTS:
4172 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4174 case (WORD)X509_BASIC_CONSTRAINTS2:
4175 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4177 case (WORD)RSA_CSP_PUBLICKEYBLOB:
4178 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
4180 case (WORD)X509_UNICODE_NAME:
4181 decodeFunc = CRYPT_AsnDecodeUnicodeName;
4183 case (WORD)PKCS_ATTRIBUTE:
4184 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
4186 case (WORD)X509_UNICODE_NAME_VALUE:
4187 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
4189 case (WORD)X509_OCTET_STRING:
4190 decodeFunc = CRYPT_AsnDecodeOctets;
4192 case (WORD)X509_BITS:
4193 case (WORD)X509_KEY_USAGE:
4194 decodeFunc = CRYPT_AsnDecodeBits;
4196 case (WORD)X509_INTEGER:
4197 decodeFunc = CRYPT_AsnDecodeInt;
4199 case (WORD)X509_MULTI_BYTE_INTEGER:
4200 decodeFunc = CRYPT_AsnDecodeInteger;
4202 case (WORD)X509_MULTI_BYTE_UINT:
4203 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
4205 case (WORD)X509_ENUMERATED:
4206 decodeFunc = CRYPT_AsnDecodeEnumerated;
4208 case (WORD)X509_CHOICE_OF_TIME:
4209 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
4211 case (WORD)X509_AUTHORITY_KEY_ID2:
4212 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4214 case (WORD)PKCS_CONTENT_INFO:
4215 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
4217 case (WORD)X509_SEQUENCE_OF_ANY:
4218 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
4220 case (WORD)PKCS_UTC_TIME:
4221 decodeFunc = CRYPT_AsnDecodeUtcTime;
4223 case (WORD)X509_CRL_DIST_POINTS:
4224 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4226 case (WORD)X509_ENHANCED_KEY_USAGE:
4227 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4229 case (WORD)PKCS_ATTRIBUTES:
4230 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
4232 case (WORD)X509_ISSUING_DIST_POINT:
4233 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4235 case (WORD)PKCS7_SIGNER_INFO:
4236 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
4240 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4241 decodeFunc = CRYPT_AsnDecodeExtensions;
4242 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4243 decodeFunc = CRYPT_AsnDecodeUtcTime;
4244 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4245 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4246 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4247 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4248 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4249 decodeFunc = CRYPT_AsnDecodeEnumerated;
4250 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4251 decodeFunc = CRYPT_AsnDecodeBits;
4252 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4253 decodeFunc = CRYPT_AsnDecodeOctets;
4254 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4255 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4256 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4257 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4258 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4259 decodeFunc = CRYPT_AsnDecodeAltName;
4260 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4261 decodeFunc = CRYPT_AsnDecodeAltName;
4262 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4263 decodeFunc = CRYPT_AsnDecodeAltName;
4264 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4265 decodeFunc = CRYPT_AsnDecodeAltName;
4266 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4267 decodeFunc = CRYPT_AsnDecodeAltName;
4268 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4269 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4270 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4271 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4272 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4273 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4277 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
4278 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4280 static HCRYPTOIDFUNCSET set = NULL;
4281 CryptDecodeObjectFunc decodeFunc = NULL;
4284 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
4285 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4286 (void **)&decodeFunc, hFunc);
4290 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
4291 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4293 static HCRYPTOIDFUNCSET set = NULL;
4294 CryptDecodeObjectExFunc decodeFunc = NULL;
4297 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
4298 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4299 (void **)&decodeFunc, hFunc);
4303 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4304 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
4305 DWORD *pcbStructInfo)
4308 CryptDecodeObjectFunc pCryptDecodeObject = NULL;
4309 CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
4310 HCRYPTOIDFUNCADDR hFunc = NULL;
4312 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
4313 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
4314 pvStructInfo, pcbStructInfo);
4316 if (!pvStructInfo && !pcbStructInfo)
4318 SetLastError(ERROR_INVALID_PARAMETER);
4323 SetLastError(CRYPT_E_ASN1_EOD);
4326 if (cbEncoded > MAX_ENCODED_LEN)
4328 SetLastError(CRYPT_E_ASN1_LARGE);
4332 if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
4335 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4336 debugstr_a(lpszStructType));
4337 pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
4338 lpszStructType, &hFunc);
4339 if (!pCryptDecodeObject)
4340 pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
4341 lpszStructType, &hFunc);
4343 if (pCryptDecodeObject)
4344 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4345 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4346 else if (pCryptDecodeObjectEx)
4347 ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
4348 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
4349 pvStructInfo, pcbStructInfo);
4351 CryptFreeOIDFunctionAddress(hFunc, 0);
4352 TRACE_(crypt)("returning %d\n", ret);
4356 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4357 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4358 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4361 CryptDecodeObjectExFunc decodeFunc;
4362 HCRYPTOIDFUNCADDR hFunc = NULL;
4364 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
4365 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
4366 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4368 if (!pvStructInfo && !pcbStructInfo)
4370 SetLastError(ERROR_INVALID_PARAMETER);
4375 SetLastError(CRYPT_E_ASN1_EOD);
4378 if (cbEncoded > MAX_ENCODED_LEN)
4380 SetLastError(CRYPT_E_ASN1_LARGE);
4384 SetLastError(NOERROR);
4385 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
4386 *(BYTE **)pvStructInfo = NULL;
4387 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
4390 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4391 debugstr_a(lpszStructType));
4392 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
4396 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
4397 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4400 CryptDecodeObjectFunc pCryptDecodeObject =
4401 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
4403 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
4404 * directly, as that could cause an infinite loop.
4406 if (pCryptDecodeObject)
4408 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4410 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4411 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
4412 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4413 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
4414 ret = pCryptDecodeObject(dwCertEncodingType,
4415 lpszStructType, pbEncoded, cbEncoded, dwFlags,
4416 *(BYTE **)pvStructInfo, pcbStructInfo);
4419 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4420 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4424 CryptFreeOIDFunctionAddress(hFunc, 0);
4425 TRACE_(crypt)("returning %d\n", ret);