2 * Copyright 2005-2007 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 * This file implements ASN.1 DER decoding of a limited set of types.
19 * It isn't a full ASN.1 implementation. Microsoft implements BER
20 * encoding of many of the basic types in msasn1.dll, but that interface isn't
21 * implemented, so I implement them here.
24 * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
25 * (available online, look for a PDF copy as the HTML versions tend to have
26 * translation errors.)
28 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
30 * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject"
38 #define NONAMELESSUNION
45 #include "wine/debug.h"
46 #include "wine/exception.h"
47 #include "crypt32_private.h"
49 /* This is a bit arbitrary, but to set some limit: */
50 #define MAX_ENCODED_LEN 0x02000000
52 #define ASN_FLAGS_MASK 0xe0
53 #define ASN_TYPE_MASK 0x1f
55 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
56 WINE_DECLARE_DEBUG_CHANNEL(crypt);
64 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
65 DWORD, DWORD, void *, DWORD *);
66 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
67 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
69 /* Internal decoders don't do memory allocation or exception handling, and
70 * they report how many bytes they decoded.
72 typedef BOOL (*InternalDecodeFunc)(const BYTE *pbEncoded, DWORD cbEncoded,
73 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
75 /* Prototypes for built-in decoders. They follow the Ex style prototypes.
76 * The dwCertEncodingType and lpszStructType are ignored by the built-in
77 * functions, but the parameters are retained to simplify CryptDecodeObjectEx,
78 * since it must call functions in external DLLs that follow these signatures.
80 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
81 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
82 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
83 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
84 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
85 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
86 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
87 * time, doesn't do memory allocation, and doesn't do exception handling.
88 * (This isn't intended to be the externally-called one.)
90 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
91 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
92 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
93 /* Assumes algo->Parameters.pbData is set ahead of time. Internal func. */
94 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
95 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
96 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
97 /* Internal function */
98 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
99 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
100 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
101 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
102 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
103 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
104 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
105 /* Like CRYPT_AsnDecodeBits, but assumes the CRYPT_INTEGER_BLOB's pbData
106 * member has been initialized, doesn't do exception handling, and doesn't do
109 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
110 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
111 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
112 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
113 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
114 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
115 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
116 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
117 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
118 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
119 * member has been initialized, doesn't do exception handling, and doesn't do
120 * memory allocation. Also doesn't check tag, assumes the caller has checked
123 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
124 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
125 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
126 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
127 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
128 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
129 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
130 void *pvStructInfo, DWORD *pcbStructInfo);
132 /* Gets the number of length bytes from the given (leading) length byte */
133 #define GET_LEN_BYTES(b) ((b) <= 0x80 ? 1 : 1 + ((b) & 0x7f))
135 /* Helper function to get the encoded length of the data starting at pbEncoded,
136 * where pbEncoded[0] is the tag. If the data are too short to contain a
137 * length or if the length is too large for cbEncoded, sets an appropriate
138 * error code and returns FALSE.
140 static BOOL WINAPI CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded,
147 SetLastError(CRYPT_E_ASN1_CORRUPT);
150 else if (pbEncoded[1] <= 0x7f)
152 if (pbEncoded[1] + 1 > cbEncoded)
154 SetLastError(CRYPT_E_ASN1_EOD);
163 else if (pbEncoded[1] == 0x80)
165 FIXME("unimplemented for indefinite-length encoding\n");
166 SetLastError(CRYPT_E_ASN1_CORRUPT);
171 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
173 if (lenLen > sizeof(DWORD) + 1)
175 SetLastError(CRYPT_E_ASN1_LARGE);
178 else if (lenLen + 2 > cbEncoded)
180 SetLastError(CRYPT_E_ASN1_CORRUPT);
193 if (out + lenLen + 1 > cbEncoded)
195 SetLastError(CRYPT_E_ASN1_EOD);
208 /* Helper function to check *pcbStructInfo, set it to the required size, and
209 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
210 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
211 * pointer to the newly allocated memory.
213 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
214 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
219 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
221 if (pDecodePara && pDecodePara->pfnAlloc)
222 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
224 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
225 if (!*(BYTE **)pvStructInfo)
228 *pcbStructInfo = bytesNeeded;
230 else if (*pcbStructInfo < bytesNeeded)
232 *pcbStructInfo = bytesNeeded;
233 SetLastError(ERROR_MORE_DATA);
240 * The expected tag of the item. If tag is 0, decodeFunc is called
241 * regardless of the tag value seen.
243 * A sequence is decoded into a struct. The offset member is the
244 * offset of this item within that struct.
246 * The decoder function to use. If this is NULL, then the member isn't
247 * decoded, but minSize space is reserved for it.
249 * The minimum amount of space occupied after decoding. You must set this.
251 * If true, and the tag doesn't match the expected tag for this item,
252 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
253 * filled with 0 for this member.
254 * hasPointer, pointerOffset:
255 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
256 * the offset within the struct of the data pointer (or to the
257 * first data pointer, if more than one exist).
259 * Used by CRYPT_AsnDecodeSequence, not for your use.
261 struct AsnDecodeSequenceItem
265 CryptDecodeObjectExFunc decodeFunc;
273 /* Decodes the items in a sequence, where the items are described in items,
274 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
275 * pvStructInfo. nextData is a pointer to the memory location at which the
276 * first decoded item with a dynamic pointer should point.
277 * Upon decoding, *cbDecoded is the total number of bytes decoded.
279 static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
280 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
281 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData,
285 DWORD i, decoded = 0;
286 const BYTE *ptr = pbEncoded;
288 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
289 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
291 for (i = 0, ret = TRUE; ret && i < cItem; i++)
293 if (cbEncoded - (ptr - pbEncoded) != 0)
297 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
300 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
302 if (ptr[0] == items[i].tag || !items[i].tag)
304 if (nextData && pvStructInfo && items[i].hasPointer)
306 TRACE("Setting next pointer to %p\n",
308 *(BYTE **)((BYTE *)pvStructInfo +
309 items[i].pointerOffset) = nextData;
311 if (items[i].decodeFunc)
314 TRACE("decoding item %d\n", i);
316 TRACE("sizing item %d\n", i);
317 ret = items[i].decodeFunc(dwCertEncodingType,
318 NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
319 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
320 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
321 : NULL, &items[i].size);
324 /* Account for alignment padding */
325 if (items[i].size % sizeof(DWORD_PTR))
326 items[i].size += sizeof(DWORD_PTR) -
327 items[i].size % sizeof(DWORD_PTR);
328 TRACE("item %d size: %d\n", i, items[i].size);
329 if (nextData && items[i].hasPointer &&
330 items[i].size > items[i].minSize)
331 nextData += items[i].size - items[i].minSize;
332 ptr += 1 + nextItemLenBytes + nextItemLen;
333 decoded += 1 + nextItemLenBytes + nextItemLen;
334 TRACE("item %d: decoded %d bytes\n", i,
335 1 + nextItemLenBytes + nextItemLen);
337 else if (items[i].optional &&
338 GetLastError() == CRYPT_E_ASN1_BADTAG)
340 TRACE("skipping optional item %d\n", i);
341 items[i].size = items[i].minSize;
342 SetLastError(NOERROR);
346 TRACE("item %d failed: %08x\n", i,
351 TRACE("item %d: decoded %d bytes\n", i,
352 1 + nextItemLenBytes + nextItemLen);
353 ptr += 1 + nextItemLenBytes + nextItemLen;
354 decoded += 1 + nextItemLenBytes + nextItemLen;
355 items[i].size = items[i].minSize;
358 else if (items[i].optional)
360 TRACE("skipping optional item %d\n", i);
361 items[i].size = items[i].minSize;
365 TRACE("item %d: tag %02x doesn't match expected %02x\n",
366 i, ptr[0], items[i].tag);
367 SetLastError(CRYPT_E_ASN1_BADTAG);
372 else if (items[i].optional)
374 TRACE("missing optional item %d, skipping\n", i);
375 items[i].size = items[i].minSize;
379 TRACE("not enough bytes for item %d, failing\n", i);
380 SetLastError(CRYPT_E_ASN1_CORRUPT);
385 *cbDecoded = decoded;
386 TRACE("returning %d\n", ret);
390 /* This decodes an arbitrary sequence into a contiguous block of memory
391 * (basically, a struct.) Each element being decoded is described by a struct
392 * AsnDecodeSequenceItem, see above.
393 * startingPointer is an optional pointer to the first place where dynamic
394 * data will be stored. If you know the starting offset, you may pass it
395 * here. Otherwise, pass NULL, and one will be inferred from the items.
396 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
398 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
399 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
400 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
401 void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded,
402 void *startingPointer)
406 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
407 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
410 if (pbEncoded[0] == ASN_SEQUENCE)
414 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
416 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
417 const BYTE *ptr = pbEncoded + 1 + lenBytes;
419 cbEncoded -= 1 + lenBytes;
420 if (cbEncoded < dataLen)
422 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
424 SetLastError(CRYPT_E_ASN1_CORRUPT);
428 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, ptr,
429 cbEncoded, dwFlags, NULL, NULL, &cbDecoded);
430 if (ret && cbDecoded != dataLen)
432 TRACE("expected %d decoded, got %d, failing\n", dataLen,
434 SetLastError(CRYPT_E_ASN1_CORRUPT);
439 DWORD i, bytesNeeded = 0, structSize = 0;
441 for (i = 0; i < cItem; i++)
443 bytesNeeded += items[i].size;
444 structSize += items[i].minSize;
447 *pcbStructInfo = bytesNeeded;
448 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
449 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
453 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
454 pvStructInfo = *(BYTE **)pvStructInfo;
456 nextData = (BYTE *)startingPointer;
458 nextData = (BYTE *)pvStructInfo + structSize;
459 memset(pvStructInfo, 0, structSize);
460 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
461 ptr, cbEncoded, dwFlags, pvStructInfo, nextData,
463 if (ret && pcbDecoded)
464 *pcbDecoded = 1 + lenBytes + cbDecoded;
471 SetLastError(CRYPT_E_ASN1_BADTAG);
474 TRACE("returning %d (%08x)\n", ret, GetLastError());
479 * The expected tag of the entire encoded array (usually a variant
480 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
481 * regardless of the tag seen.
483 * used to decode each item in the array
485 * is the minimum size of each decoded item
487 * indicates whether each item has a dynamic pointer
489 * indicates the offset within itemSize at which the pointer exists
491 struct AsnArrayDescriptor
494 InternalDecodeFunc decodeFunc;
500 struct AsnArrayItemSize
506 /* Decodes an array of like types into a struct GenericArray.
507 * The layout and decoding of the array are described by a struct
508 * AsnArrayDescriptor.
510 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
511 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
512 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
513 void *startingPointer)
517 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
518 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
521 if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
525 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
527 DWORD bytesNeeded, cItems = 0;
528 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
529 /* There can be arbitrarily many items, but there is often only one.
531 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
533 bytesNeeded = sizeof(struct GenericArray);
538 for (ptr = pbEncoded + 1 + lenBytes; ret &&
539 ptr - pbEncoded - 1 - lenBytes < dataLen; )
541 DWORD itemLenBytes, itemDataLen, size = 0;
543 itemLenBytes = GET_LEN_BYTES(ptr[1]);
544 /* Each item decoded may not tolerate extraneous bytes, so
545 * get the length of the next element and pass it directly.
547 ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
550 ret = arrayDesc->decodeFunc(ptr,
551 1 + itemLenBytes + itemDataLen,
552 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size, NULL);
558 if (itemSizes != &itemSize)
559 itemSizes = CryptMemRealloc(itemSizes,
560 cItems * sizeof(struct AsnArrayItemSize));
565 cItems * sizeof(struct AsnArrayItemSize));
567 memcpy(itemSizes, &itemSize, sizeof(itemSize));
571 itemSizes[cItems - 1].encodedLen = 1 + itemLenBytes
573 itemSizes[cItems - 1].size = size;
575 ret = CRYPT_GetLen(ptr,
576 cbEncoded - (ptr - pbEncoded), &nextLen);
578 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
588 *pcbStructInfo = bytesNeeded;
589 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
590 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
595 struct GenericArray *array;
597 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
598 pvStructInfo = *(BYTE **)pvStructInfo;
599 array = (struct GenericArray *)pvStructInfo;
600 array->cItems = cItems;
602 array->rgItems = startingPointer;
604 array->rgItems = (BYTE *)array +
605 sizeof(struct GenericArray);
606 nextData = (BYTE *)array->rgItems +
607 array->cItems * arrayDesc->itemSize;
608 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
609 i < cItems && ptr - pbEncoded - 1 - lenBytes <
612 if (arrayDesc->hasPointer)
613 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
614 + arrayDesc->pointerOffset) = nextData;
615 ret = arrayDesc->decodeFunc(ptr,
616 itemSizes[i].encodedLen,
617 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
618 array->rgItems + i * arrayDesc->itemSize,
619 &itemSizes[i].size, NULL);
624 nextData += itemSizes[i].size - arrayDesc->itemSize;
625 ret = CRYPT_GetLen(ptr,
626 cbEncoded - (ptr - pbEncoded), &nextLen);
628 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
633 if (itemSizes != &itemSize)
634 CryptMemFree(itemSizes);
639 SetLastError(CRYPT_E_ASN1_BADTAG);
645 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
646 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
647 * to CRYPT_E_ASN1_CORRUPT.
648 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
651 static BOOL WINAPI CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType,
652 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
653 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
658 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
660 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
661 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
663 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
664 bytesNeeded += 1 + lenBytes + dataLen;
667 *pcbStructInfo = bytesNeeded;
668 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
669 pvStructInfo, pcbStructInfo, bytesNeeded)))
671 CRYPT_DER_BLOB *blob;
673 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
674 pvStructInfo = *(BYTE **)pvStructInfo;
675 blob = (CRYPT_DER_BLOB *)pvStructInfo;
676 blob->cbData = 1 + lenBytes + dataLen;
679 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
680 blob->pbData = (BYTE *)pbEncoded;
683 assert(blob->pbData);
684 memcpy(blob->pbData, pbEncoded, blob->cbData);
689 SetLastError(CRYPT_E_ASN1_CORRUPT);
697 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
698 static BOOL WINAPI CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType,
699 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
700 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
704 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
705 pDecodePara, pvStructInfo, *pcbStructInfo);
707 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
710 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType, lpszStructType,
711 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
712 pvStructInfo, pcbStructInfo);
713 if (ret && pvStructInfo)
715 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
722 for (i = 0; i < blob->cbData / 2; i++)
724 temp = blob->pbData[i];
725 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
726 blob->pbData[blob->cbData - i - 1] = temp;
730 TRACE("returning %d (%08x)\n", ret, GetLastError());
734 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
735 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
736 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
740 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
741 pDecodePara, pvStructInfo, *pcbStructInfo);
745 struct AsnDecodeSequenceItem items[] = {
746 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
747 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
748 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
749 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
750 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
751 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
752 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
753 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
754 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
755 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
758 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
759 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
760 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
761 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
762 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
766 SetLastError(STATUS_ACCESS_VIOLATION);
771 TRACE("Returning %d (%08x)\n", ret, GetLastError());
775 /* Internal function */
776 static BOOL WINAPI CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType,
777 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
778 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
783 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
785 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
787 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
788 pbEncoded + 1 + lenBytes, dataLen, dwFlags, pDecodePara,
789 pvStructInfo, pcbStructInfo);
794 static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
795 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
796 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
800 struct AsnDecodeSequenceItem items[] = {
801 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
802 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
803 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
804 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
807 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
808 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
809 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
813 /* Internal function */
814 static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType,
815 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
816 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
821 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
823 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
825 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
826 X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
827 pDecodePara, pvStructInfo, pcbStructInfo);
832 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
833 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
834 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
837 struct AsnDecodeSequenceItem items[] = {
838 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
839 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
840 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
841 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
842 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
843 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
844 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
845 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
846 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
847 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
849 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
850 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
852 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
853 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
855 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
856 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
857 FALSE, TRUE, offsetof(CERT_INFO,
858 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
859 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
860 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
861 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
862 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
863 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
864 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
865 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
866 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
867 offsetof(CERT_INFO, rgExtension), 0 },
870 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
871 pDecodePara, pvStructInfo, *pcbStructInfo);
873 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
874 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
875 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
876 if (ret && pvStructInfo)
880 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
881 info = *(CERT_INFO **)pvStructInfo;
883 info = (CERT_INFO *)pvStructInfo;
884 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
885 !info->Subject.cbData)
887 SetLastError(CRYPT_E_ASN1_CORRUPT);
888 /* Don't need to deallocate, because it should have failed on the
889 * first pass (and no memory was allocated.)
895 TRACE("Returning %d (%08x)\n", ret, GetLastError());
899 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
900 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
901 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
905 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
906 pDecodePara, pvStructInfo, *pcbStructInfo);
912 /* Unless told not to, first try to decode it as a signed cert. */
913 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
915 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
917 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
918 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
919 (BYTE *)&signedCert, &size);
923 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
924 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
925 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
926 pvStructInfo, pcbStructInfo);
927 LocalFree(signedCert);
930 /* Failing that, try it as an unsigned cert */
934 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
935 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
936 pDecodePara, pvStructInfo, pcbStructInfo);
941 SetLastError(STATUS_ACCESS_VIOLATION);
945 TRACE("Returning %d (%08x)\n", ret, GetLastError());
949 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
950 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
953 struct AsnDecodeSequenceItem items[] = {
954 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
955 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
956 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
957 { 0, offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime,
958 sizeof(FILETIME), FALSE, FALSE, 0 },
959 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
960 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
961 offsetof(CRL_ENTRY, rgExtension), 0 },
963 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
965 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
968 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
969 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
970 NULL, entry, pcbStructInfo, pcbDecoded,
971 entry ? entry->SerialNumber.pbData : NULL);
975 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
976 * been set prior to calling.
978 static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType,
979 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
980 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
983 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
984 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
985 offsetof(CRL_ENTRY, SerialNumber.pbData) };
986 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
988 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
989 pDecodePara, pvStructInfo, *pcbStructInfo);
991 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
992 pDecodePara, pvStructInfo, pcbStructInfo,
993 entries ? entries->rgItems : NULL);
994 TRACE("Returning %d (%08x)\n", ret, GetLastError());
998 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
999 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1000 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1002 struct AsnDecodeSequenceItem items[] = {
1003 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1004 CRYPT_AsnDecodeInt, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1005 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1006 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1007 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1008 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1009 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1011 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime,
1012 sizeof(FILETIME), FALSE, FALSE, 0 },
1013 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime,
1014 sizeof(FILETIME), TRUE, FALSE, 0 },
1015 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1016 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
1017 offsetof(CRL_INFO, rgCRLEntry), 0 },
1018 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1019 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1020 offsetof(CRL_INFO, rgExtension), 0 },
1024 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1025 pDecodePara, pvStructInfo, *pcbStructInfo);
1027 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1028 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1029 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1031 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1035 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1036 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1037 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1041 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1042 pDecodePara, pvStructInfo, *pcbStructInfo);
1048 /* Unless told not to, first try to decode it as a signed crl. */
1049 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1051 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1053 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1054 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1055 (BYTE *)&signedCrl, &size);
1059 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1060 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1061 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1062 pvStructInfo, pcbStructInfo);
1063 LocalFree(signedCrl);
1066 /* Failing that, try it as an unsigned crl */
1070 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1071 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1072 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1077 SetLastError(STATUS_ACCESS_VIOLATION);
1081 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1085 static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded,
1086 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1091 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1092 pvStructInfo, *pcbStructInfo);
1094 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1096 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1097 DWORD bytesNeeded = sizeof(LPSTR);
1101 /* The largest possible string for the first two components
1102 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1107 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1108 pbEncoded[1 + lenBytes] / 40,
1109 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1111 bytesNeeded += strlen(firstTwo) + 1;
1112 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1113 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1115 /* large enough for ".4000000" */
1119 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1126 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1129 SetLastError(CRYPT_E_ASN1_CORRUPT);
1136 snprintf(str, sizeof(str), ".%d", val);
1137 bytesNeeded += strlen(str);
1142 *pcbStructInfo = bytesNeeded;
1143 else if (*pcbStructInfo < bytesNeeded)
1145 *pcbStructInfo = bytesNeeded;
1146 SetLastError(ERROR_MORE_DATA);
1154 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1157 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1158 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1160 pszObjId += strlen(pszObjId);
1161 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1162 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1166 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1175 sprintf(pszObjId, ".%d", val);
1176 pszObjId += strlen(pszObjId);
1180 *(LPSTR *)pvStructInfo = NULL;
1181 *pcbStructInfo = bytesNeeded;
1183 *pcbDecoded = 1 + lenBytes + dataLen;
1189 static BOOL WINAPI CRYPT_AsnDecodeOidIgnoreTagWrap(DWORD dwCertEncodingType,
1190 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1191 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1193 return CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1194 pvStructInfo, pcbStructInfo, NULL);
1197 static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded,
1198 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1202 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1203 pvStructInfo, *pcbStructInfo);
1205 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1206 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1207 pvStructInfo, pcbStructInfo, pcbDecoded);
1210 SetLastError(CRYPT_E_ASN1_BADTAG);
1216 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1219 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
1220 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1222 struct AsnDecodeSequenceItem items[] = {
1223 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1224 CRYPT_AsnDecodeOidIgnoreTagWrap, sizeof(LPSTR), FALSE, TRUE,
1225 offsetof(CERT_EXTENSION, pszObjId), 0 },
1226 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1227 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1228 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1229 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1230 offsetof(CERT_EXTENSION, Value.pbData) },
1233 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1235 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1239 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1240 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1241 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1242 ext, pcbStructInfo, pcbDecoded, ext ? ext->pszObjId : NULL);
1244 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1245 debugstr_a(ext->pszObjId));
1246 TRACE("returning %d (%08x)\n", ret, GetLastError());
1250 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
1251 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1252 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1255 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1256 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1257 offsetof(CERT_EXTENSION, pszObjId) };
1258 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1260 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1261 pDecodePara, pvStructInfo, *pcbStructInfo);
1263 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1264 pDecodePara, pvStructInfo, pcbStructInfo, exts ? exts->rgExtension : NULL);
1268 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1269 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1270 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1276 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1277 lpszStructType, pbEncoded, cbEncoded,
1278 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1279 if (ret && pvStructInfo)
1281 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1282 pcbStructInfo, *pcbStructInfo);
1285 CERT_EXTENSIONS *exts;
1287 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1288 pvStructInfo = *(BYTE **)pvStructInfo;
1289 exts = (CERT_EXTENSIONS *)pvStructInfo;
1290 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1291 sizeof(CERT_EXTENSIONS));
1292 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1293 lpszStructType, pbEncoded, cbEncoded,
1294 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1301 SetLastError(STATUS_ACCESS_VIOLATION);
1308 /* Warning: this assumes the address of value->Value.pbData is already set, in
1309 * order to avoid overwriting memory. (In some cases, it may change it, if it
1310 * doesn't copy anything to memory.) Be sure to set it correctly!
1312 static BOOL WINAPI CRYPT_AsnDecodeNameValueInternal(DWORD dwCertEncodingType,
1313 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1314 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1318 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1320 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1322 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1323 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1325 switch (pbEncoded[0])
1327 case ASN_OCTETSTRING:
1328 valueType = CERT_RDN_OCTET_STRING;
1329 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1330 bytesNeeded += dataLen;
1332 case ASN_NUMERICSTRING:
1333 valueType = CERT_RDN_NUMERIC_STRING;
1334 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1335 bytesNeeded += dataLen;
1337 case ASN_PRINTABLESTRING:
1338 valueType = CERT_RDN_PRINTABLE_STRING;
1339 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1340 bytesNeeded += dataLen;
1343 valueType = CERT_RDN_IA5_STRING;
1344 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1345 bytesNeeded += dataLen;
1348 valueType = CERT_RDN_T61_STRING;
1349 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1350 bytesNeeded += dataLen;
1352 case ASN_VIDEOTEXSTRING:
1353 valueType = CERT_RDN_VIDEOTEX_STRING;
1354 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1355 bytesNeeded += dataLen;
1357 case ASN_GRAPHICSTRING:
1358 valueType = CERT_RDN_GRAPHIC_STRING;
1359 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1360 bytesNeeded += dataLen;
1362 case ASN_VISIBLESTRING:
1363 valueType = CERT_RDN_VISIBLE_STRING;
1364 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1365 bytesNeeded += dataLen;
1367 case ASN_GENERALSTRING:
1368 valueType = CERT_RDN_GENERAL_STRING;
1369 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1370 bytesNeeded += dataLen;
1372 case ASN_UNIVERSALSTRING:
1373 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1374 SetLastError(CRYPT_E_ASN1_BADTAG);
1377 valueType = CERT_RDN_BMP_STRING;
1378 bytesNeeded += dataLen;
1380 case ASN_UTF8STRING:
1381 valueType = CERT_RDN_UTF8_STRING;
1382 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1383 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1386 SetLastError(CRYPT_E_ASN1_BADTAG);
1391 *pcbStructInfo = bytesNeeded;
1392 else if (*pcbStructInfo < bytesNeeded)
1394 *pcbStructInfo = bytesNeeded;
1395 SetLastError(ERROR_MORE_DATA);
1400 *pcbStructInfo = bytesNeeded;
1401 value->dwValueType = valueType;
1406 assert(value->Value.pbData);
1407 switch (pbEncoded[0])
1409 case ASN_OCTETSTRING:
1410 case ASN_NUMERICSTRING:
1411 case ASN_PRINTABLESTRING:
1414 case ASN_VIDEOTEXSTRING:
1415 case ASN_GRAPHICSTRING:
1416 case ASN_VISIBLESTRING:
1417 case ASN_GENERALSTRING:
1418 value->Value.cbData = dataLen;
1421 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1422 memcpy(value->Value.pbData,
1423 pbEncoded + 1 + lenBytes, dataLen);
1425 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1431 LPWSTR str = (LPWSTR)value->Value.pbData;
1433 value->Value.cbData = dataLen;
1434 for (i = 0; i < dataLen / 2; i++)
1435 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1436 pbEncoded[1 + lenBytes + 2 * i + 1];
1439 case ASN_UTF8STRING:
1441 LPWSTR str = (LPWSTR)value->Value.pbData;
1443 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1444 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1445 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1452 value->Value.cbData = 0;
1453 value->Value.pbData = NULL;
1460 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1461 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1462 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1468 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1469 lpszStructType, pbEncoded, cbEncoded,
1470 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1471 if (ret && pvStructInfo)
1473 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1474 pcbStructInfo, *pcbStructInfo);
1477 CERT_NAME_VALUE *value;
1479 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1480 pvStructInfo = *(BYTE **)pvStructInfo;
1481 value = (CERT_NAME_VALUE *)pvStructInfo;
1482 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1483 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1484 lpszStructType, pbEncoded, cbEncoded,
1485 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1492 SetLastError(STATUS_ACCESS_VIOLATION);
1499 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValueInternal(
1500 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
1501 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
1502 void *pvStructInfo, DWORD *pcbStructInfo)
1506 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1508 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1510 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1511 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1513 switch (pbEncoded[0])
1515 case ASN_NUMERICSTRING:
1516 valueType = CERT_RDN_NUMERIC_STRING;
1517 bytesNeeded += dataLen * 2;
1519 case ASN_PRINTABLESTRING:
1520 valueType = CERT_RDN_PRINTABLE_STRING;
1521 bytesNeeded += dataLen * 2;
1524 valueType = CERT_RDN_IA5_STRING;
1525 bytesNeeded += dataLen * 2;
1528 valueType = CERT_RDN_T61_STRING;
1529 bytesNeeded += dataLen * 2;
1531 case ASN_VIDEOTEXSTRING:
1532 valueType = CERT_RDN_VIDEOTEX_STRING;
1533 bytesNeeded += dataLen * 2;
1535 case ASN_GRAPHICSTRING:
1536 valueType = CERT_RDN_GRAPHIC_STRING;
1537 bytesNeeded += dataLen * 2;
1539 case ASN_VISIBLESTRING:
1540 valueType = CERT_RDN_VISIBLE_STRING;
1541 bytesNeeded += dataLen * 2;
1543 case ASN_GENERALSTRING:
1544 valueType = CERT_RDN_GENERAL_STRING;
1545 bytesNeeded += dataLen * 2;
1547 case ASN_UNIVERSALSTRING:
1548 valueType = CERT_RDN_UNIVERSAL_STRING;
1549 bytesNeeded += dataLen / 2;
1552 valueType = CERT_RDN_BMP_STRING;
1553 bytesNeeded += dataLen;
1555 case ASN_UTF8STRING:
1556 valueType = CERT_RDN_UTF8_STRING;
1557 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1558 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1561 SetLastError(CRYPT_E_ASN1_BADTAG);
1566 *pcbStructInfo = bytesNeeded;
1567 else if (*pcbStructInfo < bytesNeeded)
1569 *pcbStructInfo = bytesNeeded;
1570 SetLastError(ERROR_MORE_DATA);
1575 *pcbStructInfo = bytesNeeded;
1576 value->dwValueType = valueType;
1580 LPWSTR str = (LPWSTR)value->Value.pbData;
1582 assert(value->Value.pbData);
1583 switch (pbEncoded[0])
1585 case ASN_NUMERICSTRING:
1586 case ASN_PRINTABLESTRING:
1589 case ASN_VIDEOTEXSTRING:
1590 case ASN_GRAPHICSTRING:
1591 case ASN_VISIBLESTRING:
1592 case ASN_GENERALSTRING:
1593 value->Value.cbData = dataLen * 2;
1594 for (i = 0; i < dataLen; i++)
1595 str[i] = pbEncoded[1 + lenBytes + i];
1597 case ASN_UNIVERSALSTRING:
1598 value->Value.cbData = dataLen / 2;
1599 for (i = 0; i < dataLen / 4; i++)
1600 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1601 | pbEncoded[1 + lenBytes + 2 * i + 3];
1604 value->Value.cbData = dataLen;
1605 for (i = 0; i < dataLen / 2; i++)
1606 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1607 pbEncoded[1 + lenBytes + 2 * i + 1];
1609 case ASN_UTF8STRING:
1610 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1611 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1612 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1618 value->Value.cbData = 0;
1619 value->Value.pbData = NULL;
1626 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1627 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1628 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1634 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(dwCertEncodingType,
1635 lpszStructType, pbEncoded, cbEncoded,
1636 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1637 if (ret && pvStructInfo)
1639 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1640 pcbStructInfo, *pcbStructInfo);
1643 CERT_NAME_VALUE *value;
1645 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1646 pvStructInfo = *(BYTE **)pvStructInfo;
1647 value = (CERT_NAME_VALUE *)pvStructInfo;
1648 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1649 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(
1650 dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded,
1651 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1658 SetLastError(STATUS_ACCESS_VIOLATION);
1665 static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
1666 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1669 struct AsnDecodeSequenceItem items[] = {
1670 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1671 CRYPT_AsnDecodeOidIgnoreTagWrap, sizeof(LPSTR), FALSE, TRUE,
1672 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1673 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1674 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1675 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1677 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1679 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1680 pvStructInfo, *pcbStructInfo);
1683 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1684 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1685 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1686 attr, pcbStructInfo, pcbDecoded, attr ? attr->pszObjId : NULL);
1689 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1690 debugstr_a(attr->pszObjId));
1691 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1693 TRACE("returning %d (%08x)\n", ret, GetLastError());
1697 static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1698 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1701 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1702 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1703 offsetof(CERT_RDN_ATTR, pszObjId) };
1704 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1706 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1707 NULL, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1711 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1712 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1713 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1719 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1720 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1721 offsetof(CERT_RDN, rgRDNAttr) };
1723 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1724 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1728 SetLastError(STATUS_ACCESS_VIOLATION);
1735 static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
1736 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1740 struct AsnDecodeSequenceItem items[] = {
1741 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1742 CRYPT_AsnDecodeOidIgnoreTagWrap, sizeof(LPSTR), FALSE, TRUE,
1743 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1744 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1745 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1746 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1748 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1750 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1751 pvStructInfo, *pcbStructInfo);
1754 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1755 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1756 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1757 attr, pcbStructInfo, pcbDecoded, attr ? attr->pszObjId : NULL);
1760 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1761 debugstr_a(attr->pszObjId));
1762 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1764 TRACE("returning %d (%08x)\n", ret, GetLastError());
1768 static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1769 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1772 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1773 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1774 offsetof(CERT_RDN_ATTR, pszObjId) };
1775 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1777 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1778 NULL, pvStructInfo, pcbStructInfo, rdn ? rdn->rgRDNAttr : NULL);
1782 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(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_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1792 offsetof(CERT_RDN, rgRDNAttr) };
1794 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1795 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1799 SetLastError(STATUS_ACCESS_VIOLATION);
1806 static BOOL CRYPT_AsnDecodeCopyBytesInternal(const BYTE *pbEncoded,
1807 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1811 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1813 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1814 pvStructInfo, *pcbStructInfo);
1816 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1817 bytesNeeded += cbEncoded;
1819 *pcbStructInfo = bytesNeeded;
1820 else if (*pcbStructInfo < bytesNeeded)
1822 SetLastError(ERROR_MORE_DATA);
1823 *pcbStructInfo = bytesNeeded;
1828 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1830 *pcbStructInfo = bytesNeeded;
1831 blob->cbData = cbEncoded;
1832 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1833 blob->pbData = (LPBYTE)pbEncoded;
1836 assert(blob->pbData);
1837 memcpy(blob->pbData, pbEncoded, blob->cbData);
1840 *pcbDecoded = cbEncoded;
1845 static BOOL WINAPI CRYPT_DecodeDERArray(DWORD dwCertEncodingType,
1846 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1847 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1850 struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytesInternal,
1851 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
1852 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
1854 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1855 pDecodePara, pvStructInfo, *pcbStructInfo);
1857 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1858 pDecodePara, pvStructInfo, pcbStructInfo, array ? array->rgItems : NULL);
1862 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
1863 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1867 struct AsnDecodeSequenceItem items[] = {
1868 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
1869 CRYPT_AsnDecodeOidIgnoreTagWrap, sizeof(LPSTR), FALSE, TRUE,
1870 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
1871 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
1872 CRYPT_DecodeDERArray, sizeof(struct GenericArray), FALSE, TRUE,
1873 offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
1875 PCRYPT_ATTRIBUTE attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
1877 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1878 pvStructInfo, *pcbStructInfo);
1880 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1881 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1882 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1883 attr ? attr->pszObjId : NULL);
1884 TRACE("returning %d\n", ret);
1888 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
1889 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1890 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1894 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1895 pDecodePara, pvStructInfo, *pcbStructInfo);
1901 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
1902 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
1906 *pcbStructInfo = bytesNeeded;
1907 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1908 pvStructInfo, pcbStructInfo, bytesNeeded)))
1910 PCRYPT_ATTRIBUTE attr;
1912 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1913 pvStructInfo = *(BYTE **)pvStructInfo;
1914 attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
1915 attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
1916 sizeof(CRYPT_ATTRIBUTE));
1917 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
1918 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
1925 SetLastError(STATUS_ACCESS_VIOLATION);
1928 TRACE("returning %d\n", ret);
1932 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributesInternal(
1933 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
1934 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
1935 void *pvStructInfo, DWORD *pcbStructInfo)
1937 struct AsnArrayDescriptor arrayDesc = { 0,
1938 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
1939 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
1940 PCRYPT_ATTRIBUTES attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
1943 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1944 pDecodePara, pvStructInfo, pcbStructInfo, attrs ? attrs->rgAttr :
1949 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
1950 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1951 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1955 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1956 pDecodePara, pvStructInfo, *pcbStructInfo);
1963 SetLastError(CRYPT_E_ASN1_EOD);
1964 else if (pbEncoded[0] != (ASN_CONSTRUCTOR | ASN_SETOF))
1965 SetLastError(CRYPT_E_ASN1_CORRUPT);
1966 else if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(
1967 dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded,
1968 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
1971 *pcbStructInfo = bytesNeeded;
1972 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1973 pvStructInfo, pcbStructInfo, bytesNeeded)))
1975 PCRYPT_ATTRIBUTES attrs;
1977 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1978 pvStructInfo = *(BYTE **)pvStructInfo;
1979 attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
1980 attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
1981 sizeof(CRYPT_ATTRIBUTES));
1982 ret = CRYPT_AsnDecodePKCSAttributesInternal(dwCertEncodingType,
1983 lpszStructType, pbEncoded, cbEncoded,
1984 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1991 SetLastError(STATUS_ACCESS_VIOLATION);
1994 TRACE("returning %d\n", ret);
1998 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
1999 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2000 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2003 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
2005 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2006 pDecodePara, pvStructInfo, *pcbStructInfo);
2008 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
2009 bytesNeeded += cbEncoded;
2011 *pcbStructInfo = bytesNeeded;
2012 else if (*pcbStructInfo < bytesNeeded)
2014 SetLastError(ERROR_MORE_DATA);
2015 *pcbStructInfo = bytesNeeded;
2020 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
2022 *pcbStructInfo = bytesNeeded;
2023 blob->cbData = cbEncoded;
2024 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2025 blob->pbData = (LPBYTE)pbEncoded;
2028 assert(blob->pbData);
2029 memcpy(blob->pbData, pbEncoded, blob->cbData);
2035 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
2036 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2037 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2039 CRYPT_ALGORITHM_IDENTIFIER *algo =
2040 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
2042 struct AsnDecodeSequenceItem items[] = {
2043 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
2044 CRYPT_AsnDecodeOidIgnoreTagWrap, sizeof(LPSTR), FALSE, TRUE,
2045 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
2046 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
2047 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2048 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
2051 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2052 pDecodePara, pvStructInfo, *pcbStructInfo);
2054 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2055 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2056 pDecodePara, pvStructInfo, pcbStructInfo, NULL,
2057 algo ? algo->pszObjId : NULL);
2058 if (ret && pvStructInfo)
2060 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
2061 debugstr_a(algo->pszObjId));
2066 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
2067 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2068 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2071 struct AsnDecodeSequenceItem items[] = {
2072 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
2073 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2074 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
2075 Algorithm.pszObjId) },
2076 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
2077 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2078 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
2080 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2082 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2083 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2084 pDecodePara, pvStructInfo, pcbStructInfo, NULL, info ?
2085 info->Algorithm.Parameters.pbData : NULL);
2089 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2090 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2091 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2099 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
2100 lpszStructType, pbEncoded, cbEncoded,
2101 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2104 *pcbStructInfo = bytesNeeded;
2105 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2106 pvStructInfo, pcbStructInfo, bytesNeeded)))
2108 PCERT_PUBLIC_KEY_INFO info;
2110 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2111 pvStructInfo = *(BYTE **)pvStructInfo;
2112 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2113 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2114 sizeof(CERT_PUBLIC_KEY_INFO);
2115 ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
2116 lpszStructType, pbEncoded, cbEncoded,
2117 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2124 SetLastError(STATUS_ACCESS_VIOLATION);
2131 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
2132 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2133 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2139 SetLastError(CRYPT_E_ASN1_CORRUPT);
2142 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2144 SetLastError(CRYPT_E_ASN1_CORRUPT);
2147 if (pbEncoded[1] > 1)
2149 SetLastError(CRYPT_E_ASN1_CORRUPT);
2154 *pcbStructInfo = sizeof(BOOL);
2157 else if (*pcbStructInfo < sizeof(BOOL))
2159 *pcbStructInfo = sizeof(BOOL);
2160 SetLastError(ERROR_MORE_DATA);
2165 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2168 TRACE("returning %d (%08x)\n", ret, GetLastError());
2172 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2173 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2175 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
2176 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2179 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2180 pvStructInfo, *pcbStructInfo);
2184 SetLastError(CRYPT_E_ASN1_CORRUPT);
2187 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2188 if (1 + lenBytes > cbEncoded)
2190 SetLastError(CRYPT_E_ASN1_CORRUPT);
2193 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2195 switch (pbEncoded[0] & ASN_TYPE_MASK)
2197 case 1: /* rfc822Name */
2198 case 2: /* dNSName */
2199 case 6: /* uniformResourceIdentifier */
2200 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
2202 case 4: /* directoryName */
2203 case 7: /* iPAddress */
2204 bytesNeeded += dataLen;
2206 case 8: /* registeredID */
2207 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
2211 /* FIXME: ugly, shouldn't need to know internals of OID decode
2212 * function to use it.
2214 bytesNeeded += dataLen - sizeof(LPSTR);
2217 case 0: /* otherName */
2218 FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
2219 SetLastError(CRYPT_E_ASN1_BADTAG);
2222 case 3: /* x400Address, unimplemented */
2223 case 5: /* ediPartyName, unimplemented */
2224 TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
2225 SetLastError(CRYPT_E_ASN1_BADTAG);
2229 TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
2230 SetLastError(CRYPT_E_ASN1_CORRUPT);
2236 *pcbStructInfo = bytesNeeded;
2237 else if (*pcbStructInfo < bytesNeeded)
2239 *pcbStructInfo = bytesNeeded;
2240 SetLastError(ERROR_MORE_DATA);
2245 *pcbStructInfo = bytesNeeded;
2246 /* MS used values one greater than the asn1 ones.. sigh */
2247 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
2248 switch (pbEncoded[0] & ASN_TYPE_MASK)
2250 case 1: /* rfc822Name */
2251 case 2: /* dNSName */
2252 case 6: /* uniformResourceIdentifier */
2256 for (i = 0; i < dataLen; i++)
2257 entry->u.pwszURL[i] =
2258 (WCHAR)pbEncoded[1 + lenBytes + i];
2259 entry->u.pwszURL[i] = 0;
2260 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2261 debugstr_w(entry->u.pwszURL));
2264 case 4: /* directoryName */
2265 entry->dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
2266 /* The data are memory-equivalent with the IPAddress case,
2269 case 7: /* iPAddress */
2270 /* The next data pointer is in the pwszURL spot, that is,
2271 * the first 4 bytes. Need to move it to the next spot.
2273 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2274 entry->u.IPAddress.cbData = dataLen;
2275 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2278 case 8: /* registeredID */
2279 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
2280 &entry->u.pszRegisteredID, &dataLen, NULL);
2289 static BOOL WINAPI CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType,
2290 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2291 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2294 struct AsnArrayDescriptor arrayDesc = { 0,
2295 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2296 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2297 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
2299 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2300 pDecodePara, pvStructInfo, *pcbStructInfo);
2303 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2304 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2305 pDecodePara, pvStructInfo, pcbStructInfo, info ? info->rgAltEntry : NULL);
2309 /* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */
2310 static BOOL WINAPI CRYPT_AsnDecodeIntegerSwapBytes(DWORD dwCertEncodingType,
2311 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2312 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2316 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2317 pDecodePara, pvStructInfo, *pcbStructInfo);
2319 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2322 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType, lpszStructType,
2323 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
2324 pvStructInfo, pcbStructInfo);
2325 if (ret && pvStructInfo)
2327 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2334 for (i = 0; i < blob->cbData / 2; i++)
2336 temp = blob->pbData[i];
2337 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
2338 blob->pbData[blob->cbData - i - 1] = temp;
2342 TRACE("returning %d (%08x)\n", ret, GetLastError());
2346 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
2347 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2348 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2354 struct AsnDecodeSequenceItem items[] = {
2355 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
2356 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2357 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
2358 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2359 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
2360 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
2361 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
2362 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
2363 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2364 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2365 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
2368 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2369 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2370 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
2374 SetLastError(STATUS_ACCESS_VIOLATION);
2381 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
2382 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2383 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2389 struct AsnDecodeSequenceItem items[] = {
2390 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
2391 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2392 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
2393 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2394 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
2395 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
2396 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2397 AuthorityCertIssuer.rgAltEntry), 0 },
2398 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2399 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2400 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2401 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2402 AuthorityCertSerialNumber.pbData), 0 },
2405 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2406 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2407 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
2411 SetLastError(STATUS_ACCESS_VIOLATION);
2418 static BOOL WINAPI CRYPT_AsnDecodePKCSContent(DWORD dwCertEncodingType,
2419 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2420 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2425 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2426 pDecodePara, pvStructInfo, *pcbStructInfo);
2428 /* The caller has already checked the tag, no need to check it again.
2429 * Check the outer length is valid by calling CRYPT_GetLen:
2431 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2433 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2436 pbEncoded += 1 + lenBytes;
2437 /* Check the inner length is valid by calling CRYPT_GetLen again: */
2438 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &innerLen)))
2440 ret = CRYPT_AsnDecodeCopyBytes(dwCertEncodingType, NULL,
2441 pbEncoded, dataLen, dwFlags, pDecodePara, pvStructInfo,
2448 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfoInternal(
2449 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2450 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2451 void *pvStructInfo, DWORD *pcbStructInfo)
2453 CRYPT_CONTENT_INFO *info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2454 struct AsnDecodeSequenceItem items[] = {
2455 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
2456 CRYPT_AsnDecodeOidIgnoreTagWrap, sizeof(LPSTR), FALSE, TRUE,
2457 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
2458 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
2459 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
2460 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
2461 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
2465 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2466 pDecodePara, pvStructInfo, *pcbStructInfo);
2468 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2469 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2470 pDecodePara, pvStructInfo, pcbStructInfo, NULL,
2471 info ? info->pszObjId : NULL);
2475 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
2476 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2477 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2481 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2482 pDecodePara, pvStructInfo, *pcbStructInfo);
2486 ret = CRYPT_AsnDecodePKCSContentInfoInternal(dwCertEncodingType,
2487 lpszStructType, pbEncoded, cbEncoded,
2488 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
2489 if (ret && pvStructInfo)
2491 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
2492 pcbStructInfo, *pcbStructInfo);
2495 CRYPT_CONTENT_INFO *info;
2497 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2498 pvStructInfo = *(BYTE **)pvStructInfo;
2499 info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2500 info->pszObjId = (LPSTR)((BYTE *)info +
2501 sizeof(CRYPT_CONTENT_INFO));
2502 ret = CRYPT_AsnDecodePKCSContentInfoInternal(dwCertEncodingType,
2503 lpszStructType, pbEncoded, cbEncoded,
2504 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2511 SetLastError(STATUS_ACCESS_VIOLATION);
2517 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
2518 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2519 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
2522 struct AsnDecodeSequenceItem items[] = {
2523 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version), CRYPT_AsnDecodeInt,
2524 sizeof(DWORD), FALSE, FALSE, 0, 0 },
2525 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
2526 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2527 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
2529 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
2530 CRYPT_AsnDecodePKCSContentInfoInternal,
2531 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
2532 ContentInfo.pszObjId), 0 },
2533 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
2534 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
2535 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
2538 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
2539 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2540 pDecodePara, digestedData, pcbDigestedData, NULL, NULL);
2544 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
2545 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2546 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2550 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2551 pDecodePara, pvStructInfo, *pcbStructInfo);
2555 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2556 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2557 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2559 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2560 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2564 SetLastError(STATUS_ACCESS_VIOLATION);
2571 struct PATH_LEN_CONSTRAINT
2573 BOOL fPathLenConstraint;
2574 DWORD dwPathLenConstraint;
2577 static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
2578 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2579 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2583 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2584 pvStructInfo, *pcbStructInfo);
2588 if (pbEncoded[0] == ASN_INTEGER)
2590 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT);
2593 *pcbStructInfo = bytesNeeded;
2594 else if (*pcbStructInfo < bytesNeeded)
2596 SetLastError(ERROR_MORE_DATA);
2597 *pcbStructInfo = bytesNeeded;
2602 struct PATH_LEN_CONSTRAINT *constraint =
2603 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
2604 DWORD size = sizeof(constraint->dwPathLenConstraint);
2606 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
2607 pbEncoded, cbEncoded, 0, NULL,
2608 &constraint->dwPathLenConstraint, &size);
2610 constraint->fPathLenConstraint = TRUE;
2611 TRACE("got an int, dwPathLenConstraint is %d\n",
2612 constraint->dwPathLenConstraint);
2617 SetLastError(CRYPT_E_ASN1_CORRUPT);
2621 TRACE("returning %d (%08x)\n", ret, GetLastError());
2625 static BOOL WINAPI CRYPT_AsnDecodeSubtreeConstraints(DWORD dwCertEncodingType,
2626 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2627 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2630 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2631 CRYPT_AsnDecodeCopyBytesInternal, sizeof(CERT_NAME_BLOB), TRUE,
2632 offsetof(CERT_NAME_BLOB, pbData) };
2633 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2635 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2636 pDecodePara, pvStructInfo, *pcbStructInfo);
2638 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2639 pDecodePara, pvStructInfo, pcbStructInfo,
2640 entries ? entries->rgItems : NULL);
2641 TRACE("Returning %d (%08x)\n", ret, GetLastError());
2645 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
2646 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2647 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2653 struct AsnDecodeSequenceItem items[] = {
2654 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
2655 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2656 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
2657 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2658 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2659 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2660 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2661 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
2662 sizeof(struct GenericArray), TRUE, TRUE,
2663 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
2666 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2667 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2668 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
2672 SetLastError(STATUS_ACCESS_VIOLATION);
2679 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(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_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
2689 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
2690 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
2691 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2692 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2695 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2696 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2697 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
2701 SetLastError(STATUS_ACCESS_VIOLATION);
2708 #define RSA1_MAGIC 0x31415352
2710 struct DECODED_RSA_PUB_KEY
2713 CRYPT_INTEGER_BLOB modulus;
2716 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
2717 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2718 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2724 struct AsnDecodeSequenceItem items[] = {
2725 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
2726 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2727 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
2729 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
2730 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2732 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
2735 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2736 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
2737 CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, &size, NULL, NULL);
2740 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2741 decodedKey->modulus.cbData;
2745 *pcbStructInfo = bytesNeeded;
2748 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2749 pvStructInfo, pcbStructInfo, bytesNeeded)))
2752 RSAPUBKEY *rsaPubKey;
2754 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2755 pvStructInfo = *(BYTE **)pvStructInfo;
2756 hdr = (BLOBHEADER *)pvStructInfo;
2757 hdr->bType = PUBLICKEYBLOB;
2758 hdr->bVersion = CUR_BLOB_VERSION;
2760 hdr->aiKeyAlg = CALG_RSA_KEYX;
2761 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
2762 sizeof(BLOBHEADER));
2763 rsaPubKey->magic = RSA1_MAGIC;
2764 rsaPubKey->pubexp = decodedKey->pubexp;
2765 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
2766 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
2767 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
2768 decodedKey->modulus.cbData);
2770 LocalFree(decodedKey);
2775 SetLastError(STATUS_ACCESS_VIOLATION);
2782 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
2783 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2784 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2787 DWORD bytesNeeded, dataLen;
2789 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2790 pDecodePara, pvStructInfo, *pcbStructInfo);
2792 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2794 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2795 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
2797 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
2799 *pcbStructInfo = bytesNeeded;
2800 else if (*pcbStructInfo < bytesNeeded)
2802 SetLastError(ERROR_MORE_DATA);
2803 *pcbStructInfo = bytesNeeded;
2808 CRYPT_DATA_BLOB *blob;
2809 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2811 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2812 blob->cbData = dataLen;
2813 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2814 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
2817 assert(blob->pbData);
2819 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
2827 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
2828 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2829 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2833 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2834 pDecodePara, pvStructInfo, *pcbStructInfo);
2842 SetLastError(CRYPT_E_ASN1_CORRUPT);
2845 else if (pbEncoded[0] != ASN_OCTETSTRING)
2847 SetLastError(CRYPT_E_ASN1_BADTAG);
2850 else if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2851 lpszStructType, pbEncoded, cbEncoded,
2852 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2855 *pcbStructInfo = bytesNeeded;
2856 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2857 pvStructInfo, pcbStructInfo, bytesNeeded)))
2859 CRYPT_DATA_BLOB *blob;
2861 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2862 pvStructInfo = *(BYTE **)pvStructInfo;
2863 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2864 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
2865 ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2866 lpszStructType, pbEncoded, cbEncoded,
2867 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2874 SetLastError(STATUS_ACCESS_VIOLATION);
2881 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
2882 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2883 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2887 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2888 pDecodePara, pvStructInfo, *pcbStructInfo);
2890 if (pbEncoded[0] == ASN_BITSTRING)
2892 DWORD bytesNeeded, dataLen;
2894 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2896 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2897 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
2899 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
2901 *pcbStructInfo = bytesNeeded;
2902 else if (*pcbStructInfo < bytesNeeded)
2904 *pcbStructInfo = bytesNeeded;
2905 SetLastError(ERROR_MORE_DATA);
2910 CRYPT_BIT_BLOB *blob;
2912 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2913 blob->cbData = dataLen - 1;
2914 blob->cUnusedBits = *(pbEncoded + 1 +
2915 GET_LEN_BYTES(pbEncoded[1]));
2916 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2918 blob->pbData = (BYTE *)pbEncoded + 2 +
2919 GET_LEN_BYTES(pbEncoded[1]);
2923 assert(blob->pbData);
2926 BYTE mask = 0xff << blob->cUnusedBits;
2928 memcpy(blob->pbData, pbEncoded + 2 +
2929 GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
2930 blob->pbData[blob->cbData - 1] &= mask;
2938 SetLastError(CRYPT_E_ASN1_BADTAG);
2941 TRACE("returning %d (%08x)\n", ret, GetLastError());
2945 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
2946 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2947 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2951 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
2952 pDecodePara, pvStructInfo, pcbStructInfo);
2958 if ((ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2959 lpszStructType, pbEncoded, cbEncoded,
2960 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2963 *pcbStructInfo = bytesNeeded;
2964 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2965 pvStructInfo, pcbStructInfo, bytesNeeded)))
2967 CRYPT_BIT_BLOB *blob;
2969 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2970 pvStructInfo = *(BYTE **)pvStructInfo;
2971 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2972 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
2973 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2974 lpszStructType, pbEncoded, cbEncoded,
2975 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2982 SetLastError(STATUS_ACCESS_VIOLATION);
2986 TRACE("returning %d (%08x)\n", ret, GetLastError());
2990 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
2991 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2992 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2998 *pcbStructInfo = sizeof(int);
3003 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
3004 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
3005 DWORD size = sizeof(buf);
3007 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
3008 if (pbEncoded[0] != ASN_INTEGER)
3010 SetLastError(CRYPT_E_ASN1_BADTAG);
3014 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
3015 X509_MULTI_BYTE_INTEGER, pbEncoded, cbEncoded, 0, NULL, &buf,
3019 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3020 pvStructInfo, pcbStructInfo, sizeof(int))))
3024 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3025 pvStructInfo = *(BYTE **)pvStructInfo;
3026 if (blob->pbData[blob->cbData - 1] & 0x80)
3028 /* initialize to a negative value to sign-extend */
3033 for (i = 0; i < blob->cbData; i++)
3036 val |= blob->pbData[blob->cbData - i - 1];
3038 memcpy(pvStructInfo, &val, sizeof(int));
3041 else if (GetLastError() == ERROR_MORE_DATA)
3042 SetLastError(CRYPT_E_ASN1_LARGE);
3046 SetLastError(STATUS_ACCESS_VIOLATION);
3053 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
3054 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3055 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3058 DWORD bytesNeeded, dataLen;
3060 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3062 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3064 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3066 *pcbStructInfo = bytesNeeded;
3067 else if (*pcbStructInfo < bytesNeeded)
3069 *pcbStructInfo = bytesNeeded;
3070 SetLastError(ERROR_MORE_DATA);
3075 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3077 blob->cbData = dataLen;
3078 assert(blob->pbData);
3083 for (i = 0; i < blob->cbData; i++)
3085 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3094 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
3095 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3096 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3104 if (pbEncoded[0] != ASN_INTEGER)
3106 SetLastError(CRYPT_E_ASN1_BADTAG);
3110 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
3111 lpszStructType, pbEncoded, cbEncoded,
3112 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded);
3116 *pcbStructInfo = bytesNeeded;
3117 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3118 pvStructInfo, pcbStructInfo, bytesNeeded)))
3120 CRYPT_INTEGER_BLOB *blob;
3122 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3123 pvStructInfo = *(BYTE **)pvStructInfo;
3124 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3125 blob->pbData = (BYTE *)pvStructInfo +
3126 sizeof(CRYPT_INTEGER_BLOB);
3127 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
3128 lpszStructType, pbEncoded, cbEncoded,
3129 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
3136 SetLastError(STATUS_ACCESS_VIOLATION);
3143 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
3144 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
3145 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3146 void *pvStructInfo, DWORD *pcbStructInfo)
3150 if (pbEncoded[0] == ASN_INTEGER)
3152 DWORD bytesNeeded, dataLen;
3154 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3156 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3158 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3160 *pcbStructInfo = bytesNeeded;
3161 else if (*pcbStructInfo < bytesNeeded)
3163 *pcbStructInfo = bytesNeeded;
3164 SetLastError(ERROR_MORE_DATA);
3169 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3171 blob->cbData = dataLen;
3172 assert(blob->pbData);
3173 /* remove leading zero byte if it exists */
3174 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
3183 for (i = 0; i < blob->cbData; i++)
3185 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3194 SetLastError(CRYPT_E_ASN1_BADTAG);
3200 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
3201 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3202 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3210 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
3211 lpszStructType, pbEncoded, cbEncoded,
3212 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
3215 *pcbStructInfo = bytesNeeded;
3216 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3217 pvStructInfo, pcbStructInfo, bytesNeeded)))
3219 CRYPT_INTEGER_BLOB *blob;
3221 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3222 pvStructInfo = *(BYTE **)pvStructInfo;
3223 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3224 blob->pbData = (BYTE *)pvStructInfo +
3225 sizeof(CRYPT_INTEGER_BLOB);
3226 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
3227 lpszStructType, pbEncoded, cbEncoded,
3228 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
3235 SetLastError(STATUS_ACCESS_VIOLATION);
3242 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
3243 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3244 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3250 *pcbStructInfo = sizeof(int);
3255 if (pbEncoded[0] == ASN_ENUMERATED)
3257 unsigned int val = 0, i;
3261 SetLastError(CRYPT_E_ASN1_EOD);
3264 else if (pbEncoded[1] == 0)
3266 SetLastError(CRYPT_E_ASN1_CORRUPT);
3271 /* A little strange looking, but we have to accept a sign byte:
3272 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
3273 * assuming a small length is okay here, it has to be in short
3276 if (pbEncoded[1] > sizeof(unsigned int) + 1)
3278 SetLastError(CRYPT_E_ASN1_LARGE);
3281 for (i = 0; i < pbEncoded[1]; i++)
3284 val |= pbEncoded[2 + i];
3286 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3287 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
3289 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3290 pvStructInfo = *(BYTE **)pvStructInfo;
3291 memcpy(pvStructInfo, &val, sizeof(unsigned int));
3297 SetLastError(CRYPT_E_ASN1_BADTAG);
3303 SetLastError(STATUS_ACCESS_VIOLATION);
3310 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
3313 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
3318 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
3320 if (!isdigit(*(pbEncoded))) \
3322 SetLastError(CRYPT_E_ASN1_CORRUPT); \
3328 (word) += *(pbEncoded)++ - '0'; \
3333 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
3334 SYSTEMTIME *sysTime)
3341 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
3343 WORD hours, minutes = 0;
3344 BYTE sign = *pbEncoded++;
3347 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
3348 if (ret && hours >= 24)
3350 SetLastError(CRYPT_E_ASN1_CORRUPT);
3355 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
3356 if (ret && minutes >= 60)
3358 SetLastError(CRYPT_E_ASN1_CORRUPT);
3366 sysTime->wHour += hours;
3367 sysTime->wMinute += minutes;
3371 if (hours > sysTime->wHour)
3374 sysTime->wHour = 24 - (hours - sysTime->wHour);
3377 sysTime->wHour -= hours;
3378 if (minutes > sysTime->wMinute)
3381 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
3384 sysTime->wMinute -= minutes;
3391 SetLastError(STATUS_ACCESS_VIOLATION);
3398 #define MIN_ENCODED_TIME_LENGTH 10
3400 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
3401 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3402 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3408 *pcbStructInfo = sizeof(FILETIME);
3414 if (pbEncoded[0] == ASN_UTCTIME)
3418 SetLastError(CRYPT_E_ASN1_EOD);
3421 else if (pbEncoded[1] > 0x7f)
3423 /* long-form date strings really can't be valid */
3424 SetLastError(CRYPT_E_ASN1_CORRUPT);
3429 SYSTEMTIME sysTime = { 0 };
3430 BYTE len = pbEncoded[1];
3432 if (len < MIN_ENCODED_TIME_LENGTH)
3434 SetLastError(CRYPT_E_ASN1_CORRUPT);
3440 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
3441 if (sysTime.wYear >= 50)
3442 sysTime.wYear += 1900;
3444 sysTime.wYear += 2000;
3445 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3446 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3447 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3448 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
3451 if (len >= 2 && isdigit(*pbEncoded) &&
3452 isdigit(*(pbEncoded + 1)))
3453 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3455 else if (isdigit(*pbEncoded))
3456 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
3459 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3462 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
3463 pDecodePara, pvStructInfo, pcbStructInfo,
3466 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3467 pvStructInfo = *(BYTE **)pvStructInfo;
3468 ret = SystemTimeToFileTime(&sysTime,
3469 (FILETIME *)pvStructInfo);
3476 SetLastError(CRYPT_E_ASN1_BADTAG);
3482 SetLastError(STATUS_ACCESS_VIOLATION);
3489 static BOOL WINAPI CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType,
3490 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3491 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3497 *pcbStructInfo = sizeof(FILETIME);
3503 if (pbEncoded[0] == ASN_GENERALTIME)
3507 SetLastError(CRYPT_E_ASN1_EOD);
3510 else if (pbEncoded[1] > 0x7f)
3512 /* long-form date strings really can't be valid */
3513 SetLastError(CRYPT_E_ASN1_CORRUPT);
3518 BYTE len = pbEncoded[1];
3520 if (len < MIN_ENCODED_TIME_LENGTH)
3522 SetLastError(CRYPT_E_ASN1_CORRUPT);
3527 SYSTEMTIME sysTime = { 0 };
3530 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
3531 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3532 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3533 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3536 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3539 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3541 if (ret && len > 0 && (*pbEncoded == '.' ||
3548 /* workaround macro weirdness */
3549 digits = min(len, 3);
3550 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
3551 sysTime.wMilliseconds);
3554 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3557 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
3558 pDecodePara, pvStructInfo, pcbStructInfo,
3561 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3562 pvStructInfo = *(BYTE **)pvStructInfo;
3563 ret = SystemTimeToFileTime(&sysTime,
3564 (FILETIME *)pvStructInfo);
3571 SetLastError(CRYPT_E_ASN1_BADTAG);
3577 SetLastError(STATUS_ACCESS_VIOLATION);
3584 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
3585 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3586 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3592 if (pbEncoded[0] == ASN_UTCTIME)
3593 ret = CRYPT_AsnDecodeUtcTime(dwCertEncodingType, lpszStructType,
3594 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3596 else if (pbEncoded[0] == ASN_GENERALTIME)
3597 ret = CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType,
3598 lpszStructType, pbEncoded, cbEncoded, dwFlags, pDecodePara,
3599 pvStructInfo, pcbStructInfo);
3602 SetLastError(CRYPT_E_ASN1_BADTAG);
3608 SetLastError(STATUS_ACCESS_VIOLATION);
3615 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
3616 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3617 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3623 if (pbEncoded[0] == ASN_SEQUENCEOF)
3625 DWORD bytesNeeded, dataLen, remainingLen, cValue;
3627 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3632 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3633 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
3635 ptr = pbEncoded + 1 + lenBytes;
3636 remainingLen = dataLen;
3637 while (ret && remainingLen)
3641 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3644 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3646 remainingLen -= 1 + nextLenBytes + nextLen;
3647 ptr += 1 + nextLenBytes + nextLen;
3648 bytesNeeded += sizeof(CRYPT_DER_BLOB);
3649 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3650 bytesNeeded += 1 + nextLenBytes + nextLen;
3656 CRYPT_SEQUENCE_OF_ANY *seq;
3660 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3661 pvStructInfo, pcbStructInfo, bytesNeeded)))
3663 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3664 pvStructInfo = *(BYTE **)pvStructInfo;
3665 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
3666 seq->cValue = cValue;
3667 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
3669 nextPtr = (BYTE *)seq->rgValue +
3670 cValue * sizeof(CRYPT_DER_BLOB);
3671 ptr = pbEncoded + 1 + lenBytes;
3672 remainingLen = dataLen;
3674 while (ret && remainingLen)
3678 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3681 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3683 seq->rgValue[i].cbData = 1 + nextLenBytes +
3685 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3686 seq->rgValue[i].pbData = (BYTE *)ptr;
3689 seq->rgValue[i].pbData = nextPtr;
3690 memcpy(nextPtr, ptr, 1 + nextLenBytes +
3692 nextPtr += 1 + nextLenBytes + nextLen;
3694 remainingLen -= 1 + nextLenBytes + nextLen;
3695 ptr += 1 + nextLenBytes + nextLen;
3705 SetLastError(CRYPT_E_ASN1_BADTAG);
3711 SetLastError(STATUS_ACCESS_VIOLATION);
3718 static BOOL WINAPI CRYPT_AsnDecodeDistPointName(DWORD dwCertEncodingType,
3719 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3720 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3724 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
3726 DWORD bytesNeeded, dataLen;
3728 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3730 struct AsnArrayDescriptor arrayDesc = {
3731 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
3732 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3733 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3734 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3740 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3741 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3742 0, NULL, NULL, &nameLen, NULL);
3743 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen;
3746 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
3748 *pcbStructInfo = bytesNeeded;
3749 else if (*pcbStructInfo < bytesNeeded)
3751 *pcbStructInfo = bytesNeeded;
3752 SetLastError(ERROR_MORE_DATA);
3757 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
3761 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3762 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3763 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3764 0, NULL, &name->u.FullName, pcbStructInfo,
3765 name->u.FullName.rgAltEntry);
3768 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3774 SetLastError(CRYPT_E_ASN1_BADTAG);
3780 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
3781 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3783 struct AsnDecodeSequenceItem items[] = {
3784 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
3785 DistPointName), CRYPT_AsnDecodeDistPointName,
3786 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
3787 DistPointName.u.FullName.rgAltEntry), 0 },
3788 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
3789 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
3790 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
3791 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
3792 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
3793 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
3797 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
3798 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3799 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded, NULL);
3803 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
3804 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3805 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3809 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3810 pDecodePara, pvStructInfo, *pcbStructInfo);
3814 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3815 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
3816 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
3818 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3819 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3823 SetLastError(STATUS_ACCESS_VIOLATION);
3830 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3831 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3832 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3836 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3837 pDecodePara, pvStructInfo, *pcbStructInfo);
3841 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3842 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
3844 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3845 pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3849 SetLastError(STATUS_ACCESS_VIOLATION);
3856 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
3857 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3858 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3862 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3863 pDecodePara, pvStructInfo, *pcbStructInfo);
3867 struct AsnDecodeSequenceItem items[] = {
3868 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
3869 DistPointName), CRYPT_AsnDecodeDistPointName,
3870 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
3871 offsetof(CRL_ISSUING_DIST_POINT,
3872 DistPointName.u.FullName.rgAltEntry), 0 },
3873 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
3874 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3876 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
3877 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3879 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
3880 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
3881 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
3882 OnlySomeReasonFlags.pbData), 0 },
3883 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
3884 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
3887 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3888 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3889 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
3893 SetLastError(STATUS_ACCESS_VIOLATION);
3900 static BOOL WINAPI CRYPT_AsnDecodeIssuerSerialNumber(DWORD dwCertEncodingType,
3901 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3902 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3905 struct AsnDecodeSequenceItem items[] = {
3906 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
3907 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
3909 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
3910 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
3911 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
3913 CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
3914 (CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
3916 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3917 pDecodePara, pvStructInfo, *pcbStructInfo);
3919 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3920 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3921 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL,
3922 issuerSerial ? issuerSerial->Issuer.pbData : NULL);
3923 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
3925 SetLastError(CRYPT_E_ASN1_CORRUPT);
3928 TRACE("returning %d\n", ret);
3932 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
3933 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3936 CMSG_SIGNER_INFO *info = (CMSG_SIGNER_INFO *)pvStructInfo;
3937 struct AsnDecodeSequenceItem items[] = {
3938 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
3939 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3940 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
3941 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
3942 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
3943 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
3944 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3945 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
3946 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
3947 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
3948 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
3949 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
3950 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
3951 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3952 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
3953 HashEncryptionAlgorithm.pszObjId), 0 },
3954 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
3955 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
3956 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
3957 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
3958 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
3959 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
3960 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
3964 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3965 pvStructInfo, *pcbStructInfo);
3967 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
3968 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3969 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
3970 info ? info->Issuer.pbData : NULL);
3974 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
3975 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3976 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3980 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3981 pDecodePara, pvStructInfo, *pcbStructInfo);
3985 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
3986 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
3987 if (ret && pvStructInfo)
3989 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
3990 pcbStructInfo, *pcbStructInfo);
3993 CMSG_SIGNER_INFO *info;
3995 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3996 pvStructInfo = *(BYTE **)pvStructInfo;
3997 info = (CMSG_SIGNER_INFO *)pvStructInfo;
3998 info->Issuer.pbData = ((BYTE *)info +
3999 sizeof(CMSG_SIGNER_INFO));
4000 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
4001 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4002 pcbStructInfo, NULL);
4008 SetLastError(STATUS_ACCESS_VIOLATION);
4011 TRACE("returning %d\n", ret);
4015 static BOOL WINAPI CRYPT_DecodeSignerArray(DWORD dwCertEncodingType,
4016 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4017 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4020 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
4021 CRYPT_AsnDecodePKCSSignerInfoInternal, sizeof(CMSG_SIGNER_INFO), TRUE,
4022 offsetof(CMSG_SIGNER_INFO, Issuer.pbData) };
4023 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
4025 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4026 pDecodePara, pvStructInfo, *pcbStructInfo);
4028 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4029 pDecodePara, pvStructInfo, pcbStructInfo, array ? array->rgItems : NULL);
4033 BOOL CRYPT_AsnDecodePKCSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
4034 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
4035 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
4038 struct AsnDecodeSequenceItem items[] = {
4039 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version), CRYPT_AsnDecodeInt,
4040 sizeof(DWORD), FALSE, FALSE, 0, 0 },
4041 /* Placeholder for the hash algorithms - redundant with those in the
4042 * signers, so just ignore them.
4044 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
4045 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
4046 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
4047 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
4048 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4049 offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
4050 CRYPT_DecodeDERArray, sizeof(struct GenericArray), TRUE, TRUE,
4051 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
4052 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4053 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_DecodeDERArray,
4054 sizeof(struct GenericArray), TRUE, TRUE,
4055 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
4056 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
4057 CRYPT_DecodeSignerArray, sizeof(struct GenericArray), TRUE, TRUE,
4058 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
4061 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4062 pDecodePara, signedInfo, *pcbSignedInfo);
4064 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
4065 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
4066 pDecodePara, signedInfo, pcbSignedInfo, NULL, NULL);
4067 TRACE("returning %d\n", ret);
4071 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
4072 LPCSTR lpszStructType)
4074 CryptDecodeObjectExFunc decodeFunc = NULL;
4076 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
4077 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
4079 SetLastError(ERROR_FILE_NOT_FOUND);
4082 if (!HIWORD(lpszStructType))
4084 switch (LOWORD(lpszStructType))
4086 case (WORD)X509_CERT:
4087 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
4089 case (WORD)X509_CERT_TO_BE_SIGNED:
4090 decodeFunc = CRYPT_AsnDecodeCert;
4092 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
4093 decodeFunc = CRYPT_AsnDecodeCRL;
4095 case (WORD)X509_EXTENSIONS:
4096 decodeFunc = CRYPT_AsnDecodeExtensions;
4098 case (WORD)X509_NAME_VALUE:
4099 decodeFunc = CRYPT_AsnDecodeNameValue;
4101 case (WORD)X509_NAME:
4102 decodeFunc = CRYPT_AsnDecodeName;
4104 case (WORD)X509_PUBLIC_KEY_INFO:
4105 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
4107 case (WORD)X509_AUTHORITY_KEY_ID:
4108 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4110 case (WORD)X509_ALTERNATE_NAME:
4111 decodeFunc = CRYPT_AsnDecodeAltName;
4113 case (WORD)X509_BASIC_CONSTRAINTS:
4114 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4116 case (WORD)X509_BASIC_CONSTRAINTS2:
4117 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4119 case (WORD)RSA_CSP_PUBLICKEYBLOB:
4120 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
4122 case (WORD)X509_UNICODE_NAME:
4123 decodeFunc = CRYPT_AsnDecodeUnicodeName;
4125 case (WORD)PKCS_ATTRIBUTE:
4126 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
4128 case (WORD)X509_UNICODE_NAME_VALUE:
4129 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
4131 case (WORD)X509_OCTET_STRING:
4132 decodeFunc = CRYPT_AsnDecodeOctets;
4134 case (WORD)X509_BITS:
4135 case (WORD)X509_KEY_USAGE:
4136 decodeFunc = CRYPT_AsnDecodeBits;
4138 case (WORD)X509_INTEGER:
4139 decodeFunc = CRYPT_AsnDecodeInt;
4141 case (WORD)X509_MULTI_BYTE_INTEGER:
4142 decodeFunc = CRYPT_AsnDecodeInteger;
4144 case (WORD)X509_MULTI_BYTE_UINT:
4145 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
4147 case (WORD)X509_ENUMERATED:
4148 decodeFunc = CRYPT_AsnDecodeEnumerated;
4150 case (WORD)X509_CHOICE_OF_TIME:
4151 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
4153 case (WORD)X509_AUTHORITY_KEY_ID2:
4154 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4156 case (WORD)PKCS_CONTENT_INFO:
4157 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
4159 case (WORD)X509_SEQUENCE_OF_ANY:
4160 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
4162 case (WORD)PKCS_UTC_TIME:
4163 decodeFunc = CRYPT_AsnDecodeUtcTime;
4165 case (WORD)X509_CRL_DIST_POINTS:
4166 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4168 case (WORD)X509_ENHANCED_KEY_USAGE:
4169 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4171 case (WORD)PKCS_ATTRIBUTES:
4172 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
4174 case (WORD)X509_ISSUING_DIST_POINT:
4175 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4177 case (WORD)PKCS7_SIGNER_INFO:
4178 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
4182 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4183 decodeFunc = CRYPT_AsnDecodeExtensions;
4184 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4185 decodeFunc = CRYPT_AsnDecodeUtcTime;
4186 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4187 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4188 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4189 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4190 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4191 decodeFunc = CRYPT_AsnDecodeEnumerated;
4192 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4193 decodeFunc = CRYPT_AsnDecodeBits;
4194 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4195 decodeFunc = CRYPT_AsnDecodeOctets;
4196 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4197 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4198 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4199 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4200 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4201 decodeFunc = CRYPT_AsnDecodeAltName;
4202 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4203 decodeFunc = CRYPT_AsnDecodeAltName;
4204 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4205 decodeFunc = CRYPT_AsnDecodeAltName;
4206 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4207 decodeFunc = CRYPT_AsnDecodeAltName;
4208 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4209 decodeFunc = CRYPT_AsnDecodeAltName;
4210 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4211 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4212 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4213 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4214 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4215 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4219 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
4220 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4222 static HCRYPTOIDFUNCSET set = NULL;
4223 CryptDecodeObjectFunc decodeFunc = NULL;
4226 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
4227 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4228 (void **)&decodeFunc, hFunc);
4232 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
4233 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4235 static HCRYPTOIDFUNCSET set = NULL;
4236 CryptDecodeObjectExFunc decodeFunc = NULL;
4239 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
4240 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4241 (void **)&decodeFunc, hFunc);
4245 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4246 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
4247 DWORD *pcbStructInfo)
4250 CryptDecodeObjectFunc pCryptDecodeObject = NULL;
4251 CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
4252 HCRYPTOIDFUNCADDR hFunc = NULL;
4254 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
4255 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
4256 pvStructInfo, pcbStructInfo);
4258 if (!pvStructInfo && !pcbStructInfo)
4260 SetLastError(ERROR_INVALID_PARAMETER);
4265 SetLastError(CRYPT_E_ASN1_EOD);
4268 if (cbEncoded > MAX_ENCODED_LEN)
4270 SetLastError(CRYPT_E_ASN1_LARGE);
4274 if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
4277 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4278 debugstr_a(lpszStructType));
4279 pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
4280 lpszStructType, &hFunc);
4281 if (!pCryptDecodeObject)
4282 pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
4283 lpszStructType, &hFunc);
4285 if (pCryptDecodeObject)
4286 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4287 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4288 else if (pCryptDecodeObjectEx)
4289 ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
4290 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
4291 pvStructInfo, pcbStructInfo);
4293 CryptFreeOIDFunctionAddress(hFunc, 0);
4294 TRACE_(crypt)("returning %d\n", ret);
4298 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4299 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4300 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4303 CryptDecodeObjectExFunc decodeFunc;
4304 HCRYPTOIDFUNCADDR hFunc = NULL;
4306 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
4307 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
4308 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4310 if (!pvStructInfo && !pcbStructInfo)
4312 SetLastError(ERROR_INVALID_PARAMETER);
4317 SetLastError(CRYPT_E_ASN1_EOD);
4320 if (cbEncoded > MAX_ENCODED_LEN)
4322 SetLastError(CRYPT_E_ASN1_LARGE);
4326 SetLastError(NOERROR);
4327 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
4328 *(BYTE **)pvStructInfo = NULL;
4329 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
4332 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4333 debugstr_a(lpszStructType));
4334 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
4338 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
4339 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4342 CryptDecodeObjectFunc pCryptDecodeObject =
4343 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
4345 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
4346 * directly, as that could cause an infinite loop.
4348 if (pCryptDecodeObject)
4350 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4352 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4353 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
4354 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4355 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
4356 ret = pCryptDecodeObject(dwCertEncodingType,
4357 lpszStructType, pbEncoded, cbEncoded, dwFlags,
4358 *(BYTE **)pvStructInfo, pcbStructInfo);
4361 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4362 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4366 CryptFreeOIDFunctionAddress(hFunc, 0);
4367 TRACE_(crypt)("returning %d\n", ret);