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 CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
146 SetLastError(CRYPT_E_ASN1_CORRUPT);
149 else if (pbEncoded[1] <= 0x7f)
151 if (pbEncoded[1] + 1 > cbEncoded)
153 SetLastError(CRYPT_E_ASN1_EOD);
162 else if (pbEncoded[1] == 0x80)
164 FIXME("unimplemented for indefinite-length encoding\n");
165 SetLastError(CRYPT_E_ASN1_CORRUPT);
170 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
172 if (lenLen > sizeof(DWORD) + 1)
174 SetLastError(CRYPT_E_ASN1_LARGE);
177 else if (lenLen + 2 > cbEncoded)
179 SetLastError(CRYPT_E_ASN1_CORRUPT);
192 if (out + lenLen + 1 > cbEncoded)
194 SetLastError(CRYPT_E_ASN1_EOD);
207 /* Helper function to check *pcbStructInfo, set it to the required size, and
208 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
209 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
210 * pointer to the newly allocated memory.
212 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
213 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
218 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
220 if (pDecodePara && pDecodePara->pfnAlloc)
221 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
223 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
224 if (!*(BYTE **)pvStructInfo)
227 *pcbStructInfo = bytesNeeded;
229 else if (*pcbStructInfo < bytesNeeded)
231 *pcbStructInfo = bytesNeeded;
232 SetLastError(ERROR_MORE_DATA);
239 * The expected tag of the item. If tag is 0, decodeFunc is called
240 * regardless of the tag value seen.
242 * A sequence is decoded into a struct. The offset member is the
243 * offset of this item within that struct.
245 * The decoder function to use. If this is NULL, then the member isn't
246 * decoded, but minSize space is reserved for it.
248 * The minimum amount of space occupied after decoding. You must set this.
250 * If true, and the tag doesn't match the expected tag for this item,
251 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
252 * filled with 0 for this member.
253 * hasPointer, pointerOffset:
254 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
255 * the offset within the struct of the data pointer (or to the
256 * first data pointer, if more than one exist).
258 * Used by CRYPT_AsnDecodeSequence, not for your use.
260 struct AsnDecodeSequenceItem
264 CryptDecodeObjectExFunc decodeFunc;
272 /* Decodes the items in a sequence, where the items are described in items,
273 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
274 * pvStructInfo. nextData is a pointer to the memory location at which the
275 * first decoded item with a dynamic pointer should point.
276 * Upon decoding, *cbDecoded is the total number of bytes decoded.
278 static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
279 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
280 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData,
284 DWORD i, decoded = 0;
285 const BYTE *ptr = pbEncoded;
287 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
288 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
290 for (i = 0, ret = TRUE; ret && i < cItem; i++)
292 if (cbEncoded - (ptr - pbEncoded) != 0)
296 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
299 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
301 if (ptr[0] == items[i].tag || !items[i].tag)
303 if (nextData && pvStructInfo && items[i].hasPointer)
305 TRACE("Setting next pointer to %p\n",
307 *(BYTE **)((BYTE *)pvStructInfo +
308 items[i].pointerOffset) = nextData;
310 if (items[i].decodeFunc)
313 TRACE("decoding item %d\n", i);
315 TRACE("sizing item %d\n", i);
316 ret = items[i].decodeFunc(dwCertEncodingType,
317 NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
318 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
319 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
320 : NULL, &items[i].size);
323 /* Account for alignment padding */
324 if (items[i].size % sizeof(DWORD_PTR))
325 items[i].size += sizeof(DWORD_PTR) -
326 items[i].size % sizeof(DWORD_PTR);
327 TRACE("item %d size: %d\n", i, items[i].size);
328 if (nextData && items[i].hasPointer &&
329 items[i].size > items[i].minSize)
330 nextData += items[i].size - items[i].minSize;
331 ptr += 1 + nextItemLenBytes + nextItemLen;
332 decoded += 1 + nextItemLenBytes + nextItemLen;
333 TRACE("item %d: decoded %d bytes\n", i,
334 1 + nextItemLenBytes + nextItemLen);
336 else if (items[i].optional &&
337 GetLastError() == CRYPT_E_ASN1_BADTAG)
339 TRACE("skipping optional item %d\n", i);
340 items[i].size = items[i].minSize;
341 SetLastError(NOERROR);
345 TRACE("item %d failed: %08x\n", i,
350 TRACE("item %d: decoded %d bytes\n", i,
351 1 + nextItemLenBytes + nextItemLen);
352 ptr += 1 + nextItemLenBytes + nextItemLen;
353 decoded += 1 + nextItemLenBytes + nextItemLen;
354 items[i].size = items[i].minSize;
357 else if (items[i].optional)
359 TRACE("skipping optional item %d\n", i);
360 items[i].size = items[i].minSize;
364 TRACE("item %d: tag %02x doesn't match expected %02x\n",
365 i, ptr[0], items[i].tag);
366 SetLastError(CRYPT_E_ASN1_BADTAG);
371 else if (items[i].optional)
373 TRACE("missing optional item %d, skipping\n", i);
374 items[i].size = items[i].minSize;
378 TRACE("not enough bytes for item %d, failing\n", i);
379 SetLastError(CRYPT_E_ASN1_CORRUPT);
384 *cbDecoded = decoded;
385 TRACE("returning %d\n", ret);
389 /* This decodes an arbitrary sequence into a contiguous block of memory
390 * (basically, a struct.) Each element being decoded is described by a struct
391 * AsnDecodeSequenceItem, see above.
392 * startingPointer is an optional pointer to the first place where dynamic
393 * data will be stored. If you know the starting offset, you may pass it
394 * here. Otherwise, pass NULL, and one will be inferred from the items.
395 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
397 static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
398 struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
399 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
400 void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded,
401 void *startingPointer)
405 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
406 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
409 if (pbEncoded[0] == ASN_SEQUENCE)
413 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
415 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
416 const BYTE *ptr = pbEncoded + 1 + lenBytes;
418 cbEncoded -= 1 + lenBytes;
419 if (cbEncoded < dataLen)
421 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
423 SetLastError(CRYPT_E_ASN1_CORRUPT);
427 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, ptr,
428 cbEncoded, dwFlags, NULL, NULL, &cbDecoded);
429 if (ret && cbDecoded != dataLen)
431 TRACE("expected %d decoded, got %d, failing\n", dataLen,
433 SetLastError(CRYPT_E_ASN1_CORRUPT);
438 DWORD i, bytesNeeded = 0, structSize = 0;
440 for (i = 0; i < cItem; i++)
442 bytesNeeded += items[i].size;
443 structSize += items[i].minSize;
446 *pcbStructInfo = bytesNeeded;
447 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
448 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
452 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
453 pvStructInfo = *(BYTE **)pvStructInfo;
455 nextData = (BYTE *)startingPointer;
457 nextData = (BYTE *)pvStructInfo + structSize;
458 memset(pvStructInfo, 0, structSize);
459 ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
460 ptr, cbEncoded, dwFlags, pvStructInfo, nextData,
462 if (ret && pcbDecoded)
463 *pcbDecoded = 1 + lenBytes + cbDecoded;
470 SetLastError(CRYPT_E_ASN1_BADTAG);
473 TRACE("returning %d (%08x)\n", ret, GetLastError());
478 * The expected tag of the entire encoded array (usually a variant
479 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
480 * regardless of the tag seen.
482 * used to decode each item in the array
484 * is the minimum size of each decoded item
486 * indicates whether each item has a dynamic pointer
488 * indicates the offset within itemSize at which the pointer exists
490 struct AsnArrayDescriptor
493 InternalDecodeFunc decodeFunc;
499 struct AsnArrayItemSize
505 /* Decodes an array of like types into a struct GenericArray.
506 * The layout and decoding of the array are described by a struct
507 * AsnArrayDescriptor.
509 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
510 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
511 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
512 DWORD *pcbDecoded, void *startingPointer)
516 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
517 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
520 if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
524 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
526 DWORD bytesNeeded, cItems = 0, decoded;
527 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
528 /* There can be arbitrarily many items, but there is often only one.
530 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
532 decoded = 1 + lenBytes;
533 bytesNeeded = sizeof(struct GenericArray);
538 for (ptr = pbEncoded + 1 + lenBytes; ret &&
539 ptr - pbEncoded - 1 - lenBytes < dataLen; )
541 DWORD itemLenBytes, itemDataLen, itemDecoded, 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,
559 if (itemSizes != &itemSize)
560 itemSizes = CryptMemRealloc(itemSizes,
561 cItems * sizeof(struct AsnArrayItemSize));
566 cItems * sizeof(struct AsnArrayItemSize));
568 memcpy(itemSizes, &itemSize, sizeof(itemSize));
572 decoded += itemDecoded;
573 itemSizes[cItems - 1].encodedLen = 1 + itemLenBytes
575 itemSizes[cItems - 1].size = size;
577 ret = CRYPT_GetLen(ptr,
578 cbEncoded - (ptr - pbEncoded), &nextLen);
580 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
590 *pcbStructInfo = bytesNeeded;
591 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
592 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
597 struct GenericArray *array;
600 *pcbDecoded = decoded;
601 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
602 pvStructInfo = *(BYTE **)pvStructInfo;
603 array = (struct GenericArray *)pvStructInfo;
604 array->cItems = cItems;
606 array->rgItems = startingPointer;
608 array->rgItems = (BYTE *)array +
609 sizeof(struct GenericArray);
610 nextData = (BYTE *)array->rgItems +
611 array->cItems * arrayDesc->itemSize;
612 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
613 i < cItems && ptr - pbEncoded - 1 - lenBytes <
616 if (arrayDesc->hasPointer)
617 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
618 + arrayDesc->pointerOffset) = nextData;
619 ret = arrayDesc->decodeFunc(ptr,
620 itemSizes[i].encodedLen,
621 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
622 array->rgItems + i * arrayDesc->itemSize,
623 &itemSizes[i].size, NULL);
628 nextData += itemSizes[i].size - arrayDesc->itemSize;
629 ret = CRYPT_GetLen(ptr,
630 cbEncoded - (ptr - pbEncoded), &nextLen);
632 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
637 if (itemSizes != &itemSize)
638 CryptMemFree(itemSizes);
643 SetLastError(CRYPT_E_ASN1_BADTAG);
649 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
650 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
651 * to CRYPT_E_ASN1_CORRUPT.
652 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
655 static BOOL WINAPI CRYPT_AsnDecodeDerBlob(DWORD dwCertEncodingType,
656 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
657 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
662 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
664 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
665 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
667 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
668 bytesNeeded += 1 + lenBytes + dataLen;
671 *pcbStructInfo = bytesNeeded;
672 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
673 pvStructInfo, pcbStructInfo, bytesNeeded)))
675 CRYPT_DER_BLOB *blob;
677 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
678 pvStructInfo = *(BYTE **)pvStructInfo;
679 blob = (CRYPT_DER_BLOB *)pvStructInfo;
680 blob->cbData = 1 + lenBytes + dataLen;
683 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
684 blob->pbData = (BYTE *)pbEncoded;
687 assert(blob->pbData);
688 memcpy(blob->pbData, pbEncoded, blob->cbData);
693 SetLastError(CRYPT_E_ASN1_CORRUPT);
701 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
702 static BOOL WINAPI CRYPT_AsnDecodeBitsSwapBytes(DWORD dwCertEncodingType,
703 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
704 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
708 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
709 pDecodePara, pvStructInfo, *pcbStructInfo);
711 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
714 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType, lpszStructType,
715 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
716 pvStructInfo, pcbStructInfo);
717 if (ret && pvStructInfo)
719 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
726 for (i = 0; i < blob->cbData / 2; i++)
728 temp = blob->pbData[i];
729 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
730 blob->pbData[blob->cbData - i - 1] = temp;
734 TRACE("returning %d (%08x)\n", ret, GetLastError());
738 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
739 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
740 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
744 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
745 pDecodePara, pvStructInfo, *pcbStructInfo);
749 struct AsnDecodeSequenceItem items[] = {
750 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
751 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
752 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
753 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
754 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
755 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
756 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
757 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
758 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
759 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
762 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
763 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
764 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
765 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
766 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
770 SetLastError(STATUS_ACCESS_VIOLATION);
775 TRACE("Returning %d (%08x)\n", ret, GetLastError());
779 /* Internal function */
780 static BOOL WINAPI CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType,
781 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
782 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
787 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
789 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
791 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
792 pbEncoded + 1 + lenBytes, dataLen, dwFlags, pDecodePara,
793 pvStructInfo, pcbStructInfo);
798 static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
799 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
800 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
804 struct AsnDecodeSequenceItem items[] = {
805 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
806 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
807 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
808 CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
811 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
812 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
813 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
817 /* Internal function */
818 static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType,
819 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
820 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
825 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
827 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
829 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
830 X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
831 pDecodePara, pvStructInfo, pcbStructInfo);
836 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
837 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
838 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
841 struct AsnDecodeSequenceItem items[] = {
842 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
843 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
844 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
845 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
846 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
847 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
848 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
849 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
850 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
851 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
853 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
854 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
856 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
857 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
859 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
860 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
861 FALSE, TRUE, offsetof(CERT_INFO,
862 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
863 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
864 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
865 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
866 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
867 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
868 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
869 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
870 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
871 offsetof(CERT_INFO, rgExtension), 0 },
874 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
875 pDecodePara, pvStructInfo, *pcbStructInfo);
877 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
878 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
879 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
880 if (ret && pvStructInfo)
884 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
885 info = *(CERT_INFO **)pvStructInfo;
887 info = (CERT_INFO *)pvStructInfo;
888 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
889 !info->Subject.cbData)
891 SetLastError(CRYPT_E_ASN1_CORRUPT);
892 /* Don't need to deallocate, because it should have failed on the
893 * first pass (and no memory was allocated.)
899 TRACE("Returning %d (%08x)\n", ret, GetLastError());
903 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
904 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
905 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
909 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
910 pDecodePara, pvStructInfo, *pcbStructInfo);
916 /* Unless told not to, first try to decode it as a signed cert. */
917 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
919 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
921 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
922 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
923 (BYTE *)&signedCert, &size);
927 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
928 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
929 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
930 pvStructInfo, pcbStructInfo);
931 LocalFree(signedCert);
934 /* Failing that, try it as an unsigned cert */
938 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
939 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
940 pDecodePara, pvStructInfo, pcbStructInfo);
945 SetLastError(STATUS_ACCESS_VIOLATION);
949 TRACE("Returning %d (%08x)\n", ret, GetLastError());
953 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
954 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
957 struct AsnDecodeSequenceItem items[] = {
958 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
959 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
960 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
961 { 0, offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime,
962 sizeof(FILETIME), FALSE, FALSE, 0 },
963 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
964 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
965 offsetof(CRL_ENTRY, rgExtension), 0 },
967 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
969 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
972 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
973 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
974 NULL, entry, pcbStructInfo, pcbDecoded,
975 entry ? entry->SerialNumber.pbData : NULL);
979 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
980 * been set prior to calling.
982 static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType,
983 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
984 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
987 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
988 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
989 offsetof(CRL_ENTRY, SerialNumber.pbData) };
990 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
992 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
993 pDecodePara, pvStructInfo, *pcbStructInfo);
995 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
996 pDecodePara, pvStructInfo, pcbStructInfo, NULL,
997 entries ? entries->rgItems : NULL);
998 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1002 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1003 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1004 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1006 struct AsnDecodeSequenceItem items[] = {
1007 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1008 CRYPT_AsnDecodeInt, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1009 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1010 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1011 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1012 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1013 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1015 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime,
1016 sizeof(FILETIME), FALSE, FALSE, 0 },
1017 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime,
1018 sizeof(FILETIME), TRUE, FALSE, 0 },
1019 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1020 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
1021 offsetof(CRL_INFO, rgCRLEntry), 0 },
1022 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1023 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1024 offsetof(CRL_INFO, rgExtension), 0 },
1028 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1029 pDecodePara, pvStructInfo, *pcbStructInfo);
1031 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
1032 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1033 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1035 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1039 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1040 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1041 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1045 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1046 pDecodePara, pvStructInfo, *pcbStructInfo);
1052 /* Unless told not to, first try to decode it as a signed crl. */
1053 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1055 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1057 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1058 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1059 (BYTE *)&signedCrl, &size);
1063 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1064 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1065 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1066 pvStructInfo, pcbStructInfo);
1067 LocalFree(signedCrl);
1070 /* Failing that, try it as an unsigned crl */
1074 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1075 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1076 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1081 SetLastError(STATUS_ACCESS_VIOLATION);
1085 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1089 static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded,
1090 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1095 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1096 pvStructInfo, *pcbStructInfo);
1098 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1100 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1101 DWORD bytesNeeded = sizeof(LPSTR);
1105 /* The largest possible string for the first two components
1106 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1111 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1112 pbEncoded[1 + lenBytes] / 40,
1113 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1115 bytesNeeded += strlen(firstTwo) + 1;
1116 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1117 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1119 /* large enough for ".4000000" */
1123 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1130 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1133 SetLastError(CRYPT_E_ASN1_CORRUPT);
1140 snprintf(str, sizeof(str), ".%d", val);
1141 bytesNeeded += strlen(str);
1146 *pcbStructInfo = bytesNeeded;
1147 else if (*pcbStructInfo < bytesNeeded)
1149 *pcbStructInfo = bytesNeeded;
1150 SetLastError(ERROR_MORE_DATA);
1158 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1161 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1162 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1164 pszObjId += strlen(pszObjId);
1165 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1166 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1170 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1179 sprintf(pszObjId, ".%d", val);
1180 pszObjId += strlen(pszObjId);
1184 *(LPSTR *)pvStructInfo = NULL;
1185 *pcbStructInfo = bytesNeeded;
1187 *pcbDecoded = 1 + lenBytes + dataLen;
1193 static BOOL WINAPI CRYPT_AsnDecodeOidIgnoreTagWrap(DWORD dwCertEncodingType,
1194 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1195 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1197 return CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1198 pvStructInfo, pcbStructInfo, NULL);
1201 static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded,
1202 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1206 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1207 pvStructInfo, *pcbStructInfo);
1209 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1210 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1211 pvStructInfo, pcbStructInfo, pcbDecoded);
1214 SetLastError(CRYPT_E_ASN1_BADTAG);
1220 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1223 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
1224 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1226 struct AsnDecodeSequenceItem items[] = {
1227 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1228 CRYPT_AsnDecodeOidIgnoreTagWrap, sizeof(LPSTR), FALSE, TRUE,
1229 offsetof(CERT_EXTENSION, pszObjId), 0 },
1230 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1231 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1232 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1233 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1234 offsetof(CERT_EXTENSION, Value.pbData) },
1237 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1239 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1243 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1244 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1245 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1246 ext, pcbStructInfo, pcbDecoded, ext ? ext->pszObjId : NULL);
1248 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1249 debugstr_a(ext->pszObjId));
1250 TRACE("returning %d (%08x)\n", ret, GetLastError());
1254 static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
1255 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1256 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1259 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1260 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1261 offsetof(CERT_EXTENSION, pszObjId) };
1262 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1264 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1265 pDecodePara, pvStructInfo, *pcbStructInfo);
1267 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1268 pDecodePara, pvStructInfo, pcbStructInfo, NULL,
1269 exts ? exts->rgExtension : NULL);
1273 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1274 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1275 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1281 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1282 lpszStructType, pbEncoded, cbEncoded,
1283 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1284 if (ret && pvStructInfo)
1286 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1287 pcbStructInfo, *pcbStructInfo);
1290 CERT_EXTENSIONS *exts;
1292 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1293 pvStructInfo = *(BYTE **)pvStructInfo;
1294 exts = (CERT_EXTENSIONS *)pvStructInfo;
1295 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1296 sizeof(CERT_EXTENSIONS));
1297 ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
1298 lpszStructType, pbEncoded, cbEncoded,
1299 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1306 SetLastError(STATUS_ACCESS_VIOLATION);
1313 /* Warning: this assumes the address of value->Value.pbData is already set, in
1314 * order to avoid overwriting memory. (In some cases, it may change it, if it
1315 * doesn't copy anything to memory.) Be sure to set it correctly!
1317 static BOOL WINAPI CRYPT_AsnDecodeNameValueInternal(DWORD dwCertEncodingType,
1318 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1319 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1323 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1325 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1327 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1328 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1330 switch (pbEncoded[0])
1332 case ASN_OCTETSTRING:
1333 valueType = CERT_RDN_OCTET_STRING;
1334 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1335 bytesNeeded += dataLen;
1337 case ASN_NUMERICSTRING:
1338 valueType = CERT_RDN_NUMERIC_STRING;
1339 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1340 bytesNeeded += dataLen;
1342 case ASN_PRINTABLESTRING:
1343 valueType = CERT_RDN_PRINTABLE_STRING;
1344 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1345 bytesNeeded += dataLen;
1348 valueType = CERT_RDN_IA5_STRING;
1349 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1350 bytesNeeded += dataLen;
1353 valueType = CERT_RDN_T61_STRING;
1354 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1355 bytesNeeded += dataLen;
1357 case ASN_VIDEOTEXSTRING:
1358 valueType = CERT_RDN_VIDEOTEX_STRING;
1359 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1360 bytesNeeded += dataLen;
1362 case ASN_GRAPHICSTRING:
1363 valueType = CERT_RDN_GRAPHIC_STRING;
1364 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1365 bytesNeeded += dataLen;
1367 case ASN_VISIBLESTRING:
1368 valueType = CERT_RDN_VISIBLE_STRING;
1369 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1370 bytesNeeded += dataLen;
1372 case ASN_GENERALSTRING:
1373 valueType = CERT_RDN_GENERAL_STRING;
1374 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1375 bytesNeeded += dataLen;
1377 case ASN_UNIVERSALSTRING:
1378 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1379 SetLastError(CRYPT_E_ASN1_BADTAG);
1382 valueType = CERT_RDN_BMP_STRING;
1383 bytesNeeded += dataLen;
1385 case ASN_UTF8STRING:
1386 valueType = CERT_RDN_UTF8_STRING;
1387 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1388 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1391 SetLastError(CRYPT_E_ASN1_BADTAG);
1396 *pcbStructInfo = bytesNeeded;
1397 else if (*pcbStructInfo < bytesNeeded)
1399 *pcbStructInfo = bytesNeeded;
1400 SetLastError(ERROR_MORE_DATA);
1405 *pcbStructInfo = bytesNeeded;
1406 value->dwValueType = valueType;
1411 assert(value->Value.pbData);
1412 switch (pbEncoded[0])
1414 case ASN_OCTETSTRING:
1415 case ASN_NUMERICSTRING:
1416 case ASN_PRINTABLESTRING:
1419 case ASN_VIDEOTEXSTRING:
1420 case ASN_GRAPHICSTRING:
1421 case ASN_VISIBLESTRING:
1422 case ASN_GENERALSTRING:
1423 value->Value.cbData = dataLen;
1426 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1427 memcpy(value->Value.pbData,
1428 pbEncoded + 1 + lenBytes, dataLen);
1430 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1436 LPWSTR str = (LPWSTR)value->Value.pbData;
1438 value->Value.cbData = dataLen;
1439 for (i = 0; i < dataLen / 2; i++)
1440 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1441 pbEncoded[1 + lenBytes + 2 * i + 1];
1444 case ASN_UTF8STRING:
1446 LPWSTR str = (LPWSTR)value->Value.pbData;
1448 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1449 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1450 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1457 value->Value.cbData = 0;
1458 value->Value.pbData = NULL;
1465 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1466 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1467 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1473 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1474 lpszStructType, pbEncoded, cbEncoded,
1475 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1476 if (ret && pvStructInfo)
1478 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1479 pcbStructInfo, *pcbStructInfo);
1482 CERT_NAME_VALUE *value;
1484 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1485 pvStructInfo = *(BYTE **)pvStructInfo;
1486 value = (CERT_NAME_VALUE *)pvStructInfo;
1487 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1488 ret = CRYPT_AsnDecodeNameValueInternal(dwCertEncodingType,
1489 lpszStructType, pbEncoded, cbEncoded,
1490 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1497 SetLastError(STATUS_ACCESS_VIOLATION);
1504 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValueInternal(
1505 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
1506 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
1507 void *pvStructInfo, DWORD *pcbStructInfo)
1511 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1513 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1515 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1516 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1518 switch (pbEncoded[0])
1520 case ASN_NUMERICSTRING:
1521 valueType = CERT_RDN_NUMERIC_STRING;
1522 bytesNeeded += dataLen * 2;
1524 case ASN_PRINTABLESTRING:
1525 valueType = CERT_RDN_PRINTABLE_STRING;
1526 bytesNeeded += dataLen * 2;
1529 valueType = CERT_RDN_IA5_STRING;
1530 bytesNeeded += dataLen * 2;
1533 valueType = CERT_RDN_T61_STRING;
1534 bytesNeeded += dataLen * 2;
1536 case ASN_VIDEOTEXSTRING:
1537 valueType = CERT_RDN_VIDEOTEX_STRING;
1538 bytesNeeded += dataLen * 2;
1540 case ASN_GRAPHICSTRING:
1541 valueType = CERT_RDN_GRAPHIC_STRING;
1542 bytesNeeded += dataLen * 2;
1544 case ASN_VISIBLESTRING:
1545 valueType = CERT_RDN_VISIBLE_STRING;
1546 bytesNeeded += dataLen * 2;
1548 case ASN_GENERALSTRING:
1549 valueType = CERT_RDN_GENERAL_STRING;
1550 bytesNeeded += dataLen * 2;
1552 case ASN_UNIVERSALSTRING:
1553 valueType = CERT_RDN_UNIVERSAL_STRING;
1554 bytesNeeded += dataLen / 2;
1557 valueType = CERT_RDN_BMP_STRING;
1558 bytesNeeded += dataLen;
1560 case ASN_UTF8STRING:
1561 valueType = CERT_RDN_UTF8_STRING;
1562 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1563 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1566 SetLastError(CRYPT_E_ASN1_BADTAG);
1571 *pcbStructInfo = bytesNeeded;
1572 else if (*pcbStructInfo < bytesNeeded)
1574 *pcbStructInfo = bytesNeeded;
1575 SetLastError(ERROR_MORE_DATA);
1580 *pcbStructInfo = bytesNeeded;
1581 value->dwValueType = valueType;
1585 LPWSTR str = (LPWSTR)value->Value.pbData;
1587 assert(value->Value.pbData);
1588 switch (pbEncoded[0])
1590 case ASN_NUMERICSTRING:
1591 case ASN_PRINTABLESTRING:
1594 case ASN_VIDEOTEXSTRING:
1595 case ASN_GRAPHICSTRING:
1596 case ASN_VISIBLESTRING:
1597 case ASN_GENERALSTRING:
1598 value->Value.cbData = dataLen * 2;
1599 for (i = 0; i < dataLen; i++)
1600 str[i] = pbEncoded[1 + lenBytes + i];
1602 case ASN_UNIVERSALSTRING:
1603 value->Value.cbData = dataLen / 2;
1604 for (i = 0; i < dataLen / 4; i++)
1605 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1606 | pbEncoded[1 + lenBytes + 2 * i + 3];
1609 value->Value.cbData = dataLen;
1610 for (i = 0; i < dataLen / 2; i++)
1611 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1612 pbEncoded[1 + lenBytes + 2 * i + 1];
1614 case ASN_UTF8STRING:
1615 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1616 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1617 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1623 value->Value.cbData = 0;
1624 value->Value.pbData = NULL;
1631 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1632 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1633 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1639 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(dwCertEncodingType,
1640 lpszStructType, pbEncoded, cbEncoded,
1641 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
1642 if (ret && pvStructInfo)
1644 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1645 pcbStructInfo, *pcbStructInfo);
1648 CERT_NAME_VALUE *value;
1650 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1651 pvStructInfo = *(BYTE **)pvStructInfo;
1652 value = (CERT_NAME_VALUE *)pvStructInfo;
1653 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1654 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(
1655 dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded,
1656 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1663 SetLastError(STATUS_ACCESS_VIOLATION);
1670 static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
1671 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1674 struct AsnDecodeSequenceItem items[] = {
1675 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1676 CRYPT_AsnDecodeOidIgnoreTagWrap, sizeof(LPSTR), FALSE, TRUE,
1677 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1678 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1679 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1680 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1682 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1684 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1685 pvStructInfo, *pcbStructInfo);
1688 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1689 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1690 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1691 attr, pcbStructInfo, pcbDecoded, attr ? attr->pszObjId : NULL);
1694 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1695 debugstr_a(attr->pszObjId));
1696 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1698 TRACE("returning %d (%08x)\n", ret, GetLastError());
1702 static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1703 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1706 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1707 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1708 offsetof(CERT_RDN_ATTR, pszObjId) };
1709 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1711 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1712 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1713 rdn ? rdn->rgRDNAttr : NULL);
1717 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1718 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1719 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1725 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1726 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1727 offsetof(CERT_RDN, rgRDNAttr) };
1729 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1730 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1734 SetLastError(STATUS_ACCESS_VIOLATION);
1741 static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
1742 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1746 struct AsnDecodeSequenceItem items[] = {
1747 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1748 CRYPT_AsnDecodeOidIgnoreTagWrap, sizeof(LPSTR), FALSE, TRUE,
1749 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1750 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1751 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1752 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1754 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1756 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1757 pvStructInfo, *pcbStructInfo);
1760 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1761 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1762 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags, NULL,
1763 attr, pcbStructInfo, pcbDecoded, attr ? attr->pszObjId : NULL);
1766 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1767 debugstr_a(attr->pszObjId));
1768 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1770 TRACE("returning %d (%08x)\n", ret, GetLastError());
1774 static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1775 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1778 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1779 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1780 offsetof(CERT_RDN_ATTR, pszObjId) };
1781 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1783 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1784 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1785 rdn ? rdn->rgRDNAttr : NULL);
1789 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1790 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1791 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1797 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1798 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1799 offsetof(CERT_RDN, rgRDNAttr) };
1801 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1802 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1806 SetLastError(STATUS_ACCESS_VIOLATION);
1813 static BOOL CRYPT_AsnDecodeCopyBytesInternal(const BYTE *pbEncoded,
1814 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1818 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1820 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1821 pvStructInfo, *pcbStructInfo);
1823 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1824 bytesNeeded += cbEncoded;
1826 *pcbStructInfo = bytesNeeded;
1827 else if (*pcbStructInfo < bytesNeeded)
1829 SetLastError(ERROR_MORE_DATA);
1830 *pcbStructInfo = bytesNeeded;
1835 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1837 *pcbStructInfo = bytesNeeded;
1838 blob->cbData = cbEncoded;
1839 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1840 blob->pbData = (LPBYTE)pbEncoded;
1843 assert(blob->pbData);
1844 memcpy(blob->pbData, pbEncoded, blob->cbData);
1847 *pcbDecoded = cbEncoded;
1852 static BOOL WINAPI CRYPT_DecodeDERArray(DWORD dwCertEncodingType,
1853 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1854 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1857 struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytesInternal,
1858 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
1859 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
1861 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1862 pDecodePara, pvStructInfo, *pcbStructInfo);
1864 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1865 pDecodePara, pvStructInfo, pcbStructInfo, NULL,
1866 array ? array->rgItems : NULL);
1870 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
1871 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1875 struct AsnDecodeSequenceItem items[] = {
1876 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
1877 CRYPT_AsnDecodeOidIgnoreTagWrap, sizeof(LPSTR), FALSE, TRUE,
1878 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
1879 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
1880 CRYPT_DecodeDERArray, sizeof(struct GenericArray), FALSE, TRUE,
1881 offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
1883 PCRYPT_ATTRIBUTE attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
1885 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1886 pvStructInfo, *pcbStructInfo);
1888 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
1889 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
1890 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1891 attr ? attr->pszObjId : NULL);
1892 TRACE("returning %d\n", ret);
1896 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
1897 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1898 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1902 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1903 pDecodePara, pvStructInfo, *pcbStructInfo);
1909 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
1910 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
1914 *pcbStructInfo = bytesNeeded;
1915 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1916 pvStructInfo, pcbStructInfo, bytesNeeded)))
1918 PCRYPT_ATTRIBUTE attr;
1920 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1921 pvStructInfo = *(BYTE **)pvStructInfo;
1922 attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
1923 attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
1924 sizeof(CRYPT_ATTRIBUTE));
1925 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
1926 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
1933 SetLastError(STATUS_ACCESS_VIOLATION);
1936 TRACE("returning %d\n", ret);
1940 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributesInternal(
1941 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
1942 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
1943 void *pvStructInfo, DWORD *pcbStructInfo)
1945 struct AsnArrayDescriptor arrayDesc = { 0,
1946 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
1947 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
1948 PCRYPT_ATTRIBUTES attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
1951 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1952 pDecodePara, pvStructInfo, pcbStructInfo, NULL, attrs ? attrs->rgAttr :
1957 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
1958 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1959 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1963 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1964 pDecodePara, pvStructInfo, *pcbStructInfo);
1971 SetLastError(CRYPT_E_ASN1_EOD);
1972 else if (pbEncoded[0] != (ASN_CONSTRUCTOR | ASN_SETOF))
1973 SetLastError(CRYPT_E_ASN1_CORRUPT);
1974 else if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(
1975 dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded,
1976 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
1979 *pcbStructInfo = bytesNeeded;
1980 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1981 pvStructInfo, pcbStructInfo, bytesNeeded)))
1983 PCRYPT_ATTRIBUTES attrs;
1985 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1986 pvStructInfo = *(BYTE **)pvStructInfo;
1987 attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
1988 attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
1989 sizeof(CRYPT_ATTRIBUTES));
1990 ret = CRYPT_AsnDecodePKCSAttributesInternal(dwCertEncodingType,
1991 lpszStructType, pbEncoded, cbEncoded,
1992 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1999 SetLastError(STATUS_ACCESS_VIOLATION);
2002 TRACE("returning %d\n", ret);
2006 static BOOL WINAPI CRYPT_AsnDecodeCopyBytes(DWORD dwCertEncodingType,
2007 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2008 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2011 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
2013 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2014 pDecodePara, pvStructInfo, *pcbStructInfo);
2016 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
2017 bytesNeeded += cbEncoded;
2019 *pcbStructInfo = bytesNeeded;
2020 else if (*pcbStructInfo < bytesNeeded)
2022 SetLastError(ERROR_MORE_DATA);
2023 *pcbStructInfo = bytesNeeded;
2028 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
2030 *pcbStructInfo = bytesNeeded;
2031 blob->cbData = cbEncoded;
2032 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2033 blob->pbData = (LPBYTE)pbEncoded;
2036 assert(blob->pbData);
2037 memcpy(blob->pbData, pbEncoded, blob->cbData);
2043 static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
2044 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2045 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2047 CRYPT_ALGORITHM_IDENTIFIER *algo =
2048 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
2050 struct AsnDecodeSequenceItem items[] = {
2051 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
2052 CRYPT_AsnDecodeOidIgnoreTagWrap, sizeof(LPSTR), FALSE, TRUE,
2053 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
2054 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
2055 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2056 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
2059 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2060 pDecodePara, pvStructInfo, *pcbStructInfo);
2062 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2063 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2064 pDecodePara, pvStructInfo, pcbStructInfo, NULL,
2065 algo ? algo->pszObjId : NULL);
2066 if (ret && pvStructInfo)
2068 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
2069 debugstr_a(algo->pszObjId));
2074 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfoInternal(DWORD dwCertEncodingType,
2075 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2076 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2079 struct AsnDecodeSequenceItem items[] = {
2080 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
2081 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2082 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
2083 Algorithm.pszObjId) },
2084 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
2085 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2086 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
2088 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2090 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2091 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2092 pDecodePara, pvStructInfo, pcbStructInfo, NULL, info ?
2093 info->Algorithm.Parameters.pbData : NULL);
2097 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2098 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2099 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2107 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
2108 lpszStructType, pbEncoded, cbEncoded,
2109 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2112 *pcbStructInfo = bytesNeeded;
2113 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2114 pvStructInfo, pcbStructInfo, bytesNeeded)))
2116 PCERT_PUBLIC_KEY_INFO info;
2118 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2119 pvStructInfo = *(BYTE **)pvStructInfo;
2120 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2121 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2122 sizeof(CERT_PUBLIC_KEY_INFO);
2123 ret = CRYPT_AsnDecodePubKeyInfoInternal(dwCertEncodingType,
2124 lpszStructType, pbEncoded, cbEncoded,
2125 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2132 SetLastError(STATUS_ACCESS_VIOLATION);
2139 static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
2140 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2141 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2147 SetLastError(CRYPT_E_ASN1_CORRUPT);
2150 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2152 SetLastError(CRYPT_E_ASN1_CORRUPT);
2155 if (pbEncoded[1] > 1)
2157 SetLastError(CRYPT_E_ASN1_CORRUPT);
2162 *pcbStructInfo = sizeof(BOOL);
2165 else if (*pcbStructInfo < sizeof(BOOL))
2167 *pcbStructInfo = sizeof(BOOL);
2168 SetLastError(ERROR_MORE_DATA);
2173 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2176 TRACE("returning %d (%08x)\n", ret, GetLastError());
2180 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2181 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2183 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
2184 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2187 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2188 pvStructInfo, *pcbStructInfo);
2192 SetLastError(CRYPT_E_ASN1_CORRUPT);
2195 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2196 if (1 + lenBytes > cbEncoded)
2198 SetLastError(CRYPT_E_ASN1_CORRUPT);
2201 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2203 switch (pbEncoded[0] & ASN_TYPE_MASK)
2205 case 1: /* rfc822Name */
2206 case 2: /* dNSName */
2207 case 6: /* uniformResourceIdentifier */
2208 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
2210 case 4: /* directoryName */
2211 case 7: /* iPAddress */
2212 bytesNeeded += dataLen;
2214 case 8: /* registeredID */
2215 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
2219 /* FIXME: ugly, shouldn't need to know internals of OID decode
2220 * function to use it.
2222 bytesNeeded += dataLen - sizeof(LPSTR);
2225 case 0: /* otherName */
2226 FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
2227 SetLastError(CRYPT_E_ASN1_BADTAG);
2230 case 3: /* x400Address, unimplemented */
2231 case 5: /* ediPartyName, unimplemented */
2232 TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
2233 SetLastError(CRYPT_E_ASN1_BADTAG);
2237 TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
2238 SetLastError(CRYPT_E_ASN1_CORRUPT);
2244 *pcbDecoded = 1 + lenBytes + dataLen;
2246 *pcbStructInfo = bytesNeeded;
2247 else if (*pcbStructInfo < bytesNeeded)
2249 *pcbStructInfo = bytesNeeded;
2250 SetLastError(ERROR_MORE_DATA);
2255 *pcbStructInfo = bytesNeeded;
2256 /* MS used values one greater than the asn1 ones.. sigh */
2257 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
2258 switch (pbEncoded[0] & ASN_TYPE_MASK)
2260 case 1: /* rfc822Name */
2261 case 2: /* dNSName */
2262 case 6: /* uniformResourceIdentifier */
2266 for (i = 0; i < dataLen; i++)
2267 entry->u.pwszURL[i] =
2268 (WCHAR)pbEncoded[1 + lenBytes + i];
2269 entry->u.pwszURL[i] = 0;
2270 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2271 debugstr_w(entry->u.pwszURL));
2274 case 4: /* directoryName */
2275 entry->dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
2276 /* The data are memory-equivalent with the IPAddress case,
2279 case 7: /* iPAddress */
2280 /* The next data pointer is in the pwszURL spot, that is,
2281 * the first 4 bytes. Need to move it to the next spot.
2283 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2284 entry->u.IPAddress.cbData = dataLen;
2285 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2288 case 8: /* registeredID */
2289 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
2290 &entry->u.pszRegisteredID, &dataLen, NULL);
2299 static BOOL WINAPI CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType,
2300 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2301 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2304 struct AsnArrayDescriptor arrayDesc = { 0,
2305 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2306 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2307 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
2309 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2310 pDecodePara, pvStructInfo, *pcbStructInfo);
2313 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2314 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2315 pDecodePara, pvStructInfo, pcbStructInfo, NULL,
2316 info ? info->rgAltEntry : NULL);
2320 /* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */
2321 static BOOL WINAPI CRYPT_AsnDecodeIntegerSwapBytes(DWORD dwCertEncodingType,
2322 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2323 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2327 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2328 pDecodePara, pvStructInfo, *pcbStructInfo);
2330 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2333 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType, lpszStructType,
2334 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pDecodePara,
2335 pvStructInfo, pcbStructInfo);
2336 if (ret && pvStructInfo)
2338 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2345 for (i = 0; i < blob->cbData / 2; i++)
2347 temp = blob->pbData[i];
2348 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
2349 blob->pbData[blob->cbData - i - 1] = temp;
2353 TRACE("returning %d (%08x)\n", ret, GetLastError());
2357 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
2358 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2359 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2365 struct AsnDecodeSequenceItem items[] = {
2366 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
2367 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2368 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
2369 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2370 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
2371 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
2372 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
2373 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
2374 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2375 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2376 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
2379 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2380 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2381 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
2385 SetLastError(STATUS_ACCESS_VIOLATION);
2392 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
2393 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2394 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2400 struct AsnDecodeSequenceItem items[] = {
2401 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
2402 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2403 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
2404 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2405 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
2406 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
2407 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2408 AuthorityCertIssuer.rgAltEntry), 0 },
2409 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2410 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2411 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2412 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2413 AuthorityCertSerialNumber.pbData), 0 },
2416 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2417 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2418 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
2422 SetLastError(STATUS_ACCESS_VIOLATION);
2429 static BOOL WINAPI CRYPT_AsnDecodePKCSContent(DWORD dwCertEncodingType,
2430 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2431 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2436 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2437 pDecodePara, pvStructInfo, *pcbStructInfo);
2439 /* The caller has already checked the tag, no need to check it again.
2440 * Check the outer length is valid by calling CRYPT_GetLen:
2442 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2444 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2447 pbEncoded += 1 + lenBytes;
2448 /* Check the inner length is valid by calling CRYPT_GetLen again: */
2449 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &innerLen)))
2451 ret = CRYPT_AsnDecodeCopyBytes(dwCertEncodingType, NULL,
2452 pbEncoded, dataLen, dwFlags, pDecodePara, pvStructInfo,
2459 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfoInternal(
2460 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2461 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2462 void *pvStructInfo, DWORD *pcbStructInfo)
2464 CRYPT_CONTENT_INFO *info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2465 struct AsnDecodeSequenceItem items[] = {
2466 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
2467 CRYPT_AsnDecodeOidIgnoreTagWrap, sizeof(LPSTR), FALSE, TRUE,
2468 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
2469 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
2470 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
2471 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
2472 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
2476 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2477 pDecodePara, pvStructInfo, *pcbStructInfo);
2479 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2480 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2481 pDecodePara, pvStructInfo, pcbStructInfo, NULL,
2482 info ? info->pszObjId : NULL);
2486 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
2487 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2488 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2492 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2493 pDecodePara, pvStructInfo, *pcbStructInfo);
2497 ret = CRYPT_AsnDecodePKCSContentInfoInternal(dwCertEncodingType,
2498 lpszStructType, pbEncoded, cbEncoded,
2499 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
2500 if (ret && pvStructInfo)
2502 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
2503 pcbStructInfo, *pcbStructInfo);
2506 CRYPT_CONTENT_INFO *info;
2508 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2509 pvStructInfo = *(BYTE **)pvStructInfo;
2510 info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2511 info->pszObjId = (LPSTR)((BYTE *)info +
2512 sizeof(CRYPT_CONTENT_INFO));
2513 ret = CRYPT_AsnDecodePKCSContentInfoInternal(dwCertEncodingType,
2514 lpszStructType, pbEncoded, cbEncoded,
2515 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2522 SetLastError(STATUS_ACCESS_VIOLATION);
2528 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
2529 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2530 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
2533 struct AsnDecodeSequenceItem items[] = {
2534 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version), CRYPT_AsnDecodeInt,
2535 sizeof(DWORD), FALSE, FALSE, 0, 0 },
2536 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
2537 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2538 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
2540 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
2541 CRYPT_AsnDecodePKCSContentInfoInternal,
2542 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
2543 ContentInfo.pszObjId), 0 },
2544 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
2545 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
2546 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
2549 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
2550 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2551 pDecodePara, digestedData, pcbDigestedData, NULL, NULL);
2555 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
2556 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2557 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2561 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2562 pDecodePara, pvStructInfo, *pcbStructInfo);
2566 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2567 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2568 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2570 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2571 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
2575 SetLastError(STATUS_ACCESS_VIOLATION);
2582 struct PATH_LEN_CONSTRAINT
2584 BOOL fPathLenConstraint;
2585 DWORD dwPathLenConstraint;
2588 static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
2589 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2590 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2594 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2595 pvStructInfo, *pcbStructInfo);
2599 if (pbEncoded[0] == ASN_INTEGER)
2601 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT);
2604 *pcbStructInfo = bytesNeeded;
2605 else if (*pcbStructInfo < bytesNeeded)
2607 SetLastError(ERROR_MORE_DATA);
2608 *pcbStructInfo = bytesNeeded;
2613 struct PATH_LEN_CONSTRAINT *constraint =
2614 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
2615 DWORD size = sizeof(constraint->dwPathLenConstraint);
2617 ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
2618 pbEncoded, cbEncoded, 0, NULL,
2619 &constraint->dwPathLenConstraint, &size);
2621 constraint->fPathLenConstraint = TRUE;
2622 TRACE("got an int, dwPathLenConstraint is %d\n",
2623 constraint->dwPathLenConstraint);
2628 SetLastError(CRYPT_E_ASN1_CORRUPT);
2632 TRACE("returning %d (%08x)\n", ret, GetLastError());
2636 static BOOL WINAPI CRYPT_AsnDecodeSubtreeConstraints(DWORD dwCertEncodingType,
2637 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2638 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2641 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2642 CRYPT_AsnDecodeCopyBytesInternal, sizeof(CERT_NAME_BLOB), TRUE,
2643 offsetof(CERT_NAME_BLOB, pbData) };
2644 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2646 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2647 pDecodePara, pvStructInfo, *pcbStructInfo);
2649 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2650 pDecodePara, pvStructInfo, pcbStructInfo, NULL,
2651 entries ? entries->rgItems : NULL);
2652 TRACE("Returning %d (%08x)\n", ret, GetLastError());
2656 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
2657 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2658 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2664 struct AsnDecodeSequenceItem items[] = {
2665 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
2666 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2667 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
2668 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2669 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2670 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2671 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2672 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
2673 sizeof(struct GenericArray), TRUE, TRUE,
2674 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
2677 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2678 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2679 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
2683 SetLastError(STATUS_ACCESS_VIOLATION);
2690 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
2691 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2692 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2698 struct AsnDecodeSequenceItem items[] = {
2699 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
2700 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
2701 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
2702 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2703 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2706 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2707 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2708 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
2712 SetLastError(STATUS_ACCESS_VIOLATION);
2719 #define RSA1_MAGIC 0x31415352
2721 struct DECODED_RSA_PUB_KEY
2724 CRYPT_INTEGER_BLOB modulus;
2727 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
2728 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2729 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2735 struct AsnDecodeSequenceItem items[] = {
2736 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
2737 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2738 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
2740 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
2741 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2743 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
2746 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
2747 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
2748 CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey, &size, NULL, NULL);
2751 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2752 decodedKey->modulus.cbData;
2756 *pcbStructInfo = bytesNeeded;
2759 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2760 pvStructInfo, pcbStructInfo, bytesNeeded)))
2763 RSAPUBKEY *rsaPubKey;
2765 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2766 pvStructInfo = *(BYTE **)pvStructInfo;
2767 hdr = (BLOBHEADER *)pvStructInfo;
2768 hdr->bType = PUBLICKEYBLOB;
2769 hdr->bVersion = CUR_BLOB_VERSION;
2771 hdr->aiKeyAlg = CALG_RSA_KEYX;
2772 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
2773 sizeof(BLOBHEADER));
2774 rsaPubKey->magic = RSA1_MAGIC;
2775 rsaPubKey->pubexp = decodedKey->pubexp;
2776 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
2777 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
2778 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
2779 decodedKey->modulus.cbData);
2781 LocalFree(decodedKey);
2786 SetLastError(STATUS_ACCESS_VIOLATION);
2793 static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
2794 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2795 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2798 DWORD bytesNeeded, dataLen;
2800 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2801 pDecodePara, pvStructInfo, *pcbStructInfo);
2803 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2805 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2806 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
2808 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
2810 *pcbStructInfo = bytesNeeded;
2811 else if (*pcbStructInfo < bytesNeeded)
2813 SetLastError(ERROR_MORE_DATA);
2814 *pcbStructInfo = bytesNeeded;
2819 CRYPT_DATA_BLOB *blob;
2820 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2822 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2823 blob->cbData = dataLen;
2824 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2825 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
2828 assert(blob->pbData);
2830 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
2838 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
2839 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2840 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2844 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2845 pDecodePara, pvStructInfo, *pcbStructInfo);
2853 SetLastError(CRYPT_E_ASN1_CORRUPT);
2856 else if (pbEncoded[0] != ASN_OCTETSTRING)
2858 SetLastError(CRYPT_E_ASN1_BADTAG);
2861 else if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2862 lpszStructType, pbEncoded, cbEncoded,
2863 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2866 *pcbStructInfo = bytesNeeded;
2867 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2868 pvStructInfo, pcbStructInfo, bytesNeeded)))
2870 CRYPT_DATA_BLOB *blob;
2872 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2873 pvStructInfo = *(BYTE **)pvStructInfo;
2874 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2875 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
2876 ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
2877 lpszStructType, pbEncoded, cbEncoded,
2878 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2885 SetLastError(STATUS_ACCESS_VIOLATION);
2892 static BOOL WINAPI CRYPT_AsnDecodeBitsInternal(DWORD dwCertEncodingType,
2893 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2894 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2898 TRACE("(%p, %d, 0x%08x, %p, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2899 pDecodePara, pvStructInfo, *pcbStructInfo);
2901 if (pbEncoded[0] == ASN_BITSTRING)
2903 DWORD bytesNeeded, dataLen;
2905 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2907 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2908 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
2910 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
2912 *pcbStructInfo = bytesNeeded;
2913 else if (*pcbStructInfo < bytesNeeded)
2915 *pcbStructInfo = bytesNeeded;
2916 SetLastError(ERROR_MORE_DATA);
2921 CRYPT_BIT_BLOB *blob;
2923 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2924 blob->cbData = dataLen - 1;
2925 blob->cUnusedBits = *(pbEncoded + 1 +
2926 GET_LEN_BYTES(pbEncoded[1]));
2927 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2929 blob->pbData = (BYTE *)pbEncoded + 2 +
2930 GET_LEN_BYTES(pbEncoded[1]);
2934 assert(blob->pbData);
2937 BYTE mask = 0xff << blob->cUnusedBits;
2939 memcpy(blob->pbData, pbEncoded + 2 +
2940 GET_LEN_BYTES(pbEncoded[1]), blob->cbData);
2941 blob->pbData[blob->cbData - 1] &= mask;
2949 SetLastError(CRYPT_E_ASN1_BADTAG);
2952 TRACE("returning %d (%08x)\n", ret, GetLastError());
2956 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
2957 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2958 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2962 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
2963 pDecodePara, pvStructInfo, pcbStructInfo);
2969 if ((ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2970 lpszStructType, pbEncoded, cbEncoded,
2971 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
2974 *pcbStructInfo = bytesNeeded;
2975 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2976 pvStructInfo, pcbStructInfo, bytesNeeded)))
2978 CRYPT_BIT_BLOB *blob;
2980 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2981 pvStructInfo = *(BYTE **)pvStructInfo;
2982 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2983 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
2984 ret = CRYPT_AsnDecodeBitsInternal(dwCertEncodingType,
2985 lpszStructType, pbEncoded, cbEncoded,
2986 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2993 SetLastError(STATUS_ACCESS_VIOLATION);
2997 TRACE("returning %d (%08x)\n", ret, GetLastError());
3001 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
3002 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3003 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3009 *pcbStructInfo = sizeof(int);
3014 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
3015 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
3016 DWORD size = sizeof(buf);
3018 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
3019 if (pbEncoded[0] != ASN_INTEGER)
3021 SetLastError(CRYPT_E_ASN1_BADTAG);
3025 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
3026 X509_MULTI_BYTE_INTEGER, pbEncoded, cbEncoded, 0, NULL, &buf,
3030 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3031 pvStructInfo, pcbStructInfo, sizeof(int))))
3035 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3036 pvStructInfo = *(BYTE **)pvStructInfo;
3037 if (blob->pbData[blob->cbData - 1] & 0x80)
3039 /* initialize to a negative value to sign-extend */
3044 for (i = 0; i < blob->cbData; i++)
3047 val |= blob->pbData[blob->cbData - i - 1];
3049 memcpy(pvStructInfo, &val, sizeof(int));
3052 else if (GetLastError() == ERROR_MORE_DATA)
3053 SetLastError(CRYPT_E_ASN1_LARGE);
3057 SetLastError(STATUS_ACCESS_VIOLATION);
3064 static BOOL WINAPI CRYPT_AsnDecodeIntegerInternal(DWORD dwCertEncodingType,
3065 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3066 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3069 DWORD bytesNeeded, dataLen;
3071 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3073 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3075 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3077 *pcbStructInfo = bytesNeeded;
3078 else if (*pcbStructInfo < bytesNeeded)
3080 *pcbStructInfo = bytesNeeded;
3081 SetLastError(ERROR_MORE_DATA);
3086 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3088 blob->cbData = dataLen;
3089 assert(blob->pbData);
3094 for (i = 0; i < blob->cbData; i++)
3096 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3105 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
3106 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3107 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3115 if (pbEncoded[0] != ASN_INTEGER)
3117 SetLastError(CRYPT_E_ASN1_BADTAG);
3121 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
3122 lpszStructType, pbEncoded, cbEncoded,
3123 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded);
3127 *pcbStructInfo = bytesNeeded;
3128 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3129 pvStructInfo, pcbStructInfo, bytesNeeded)))
3131 CRYPT_INTEGER_BLOB *blob;
3133 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3134 pvStructInfo = *(BYTE **)pvStructInfo;
3135 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3136 blob->pbData = (BYTE *)pvStructInfo +
3137 sizeof(CRYPT_INTEGER_BLOB);
3138 ret = CRYPT_AsnDecodeIntegerInternal(dwCertEncodingType,
3139 lpszStructType, pbEncoded, cbEncoded,
3140 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
3147 SetLastError(STATUS_ACCESS_VIOLATION);
3154 static BOOL WINAPI CRYPT_AsnDecodeUnsignedIntegerInternal(
3155 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
3156 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3157 void *pvStructInfo, DWORD *pcbStructInfo)
3161 if (pbEncoded[0] == ASN_INTEGER)
3163 DWORD bytesNeeded, dataLen;
3165 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3167 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3169 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3171 *pcbStructInfo = bytesNeeded;
3172 else if (*pcbStructInfo < bytesNeeded)
3174 *pcbStructInfo = bytesNeeded;
3175 SetLastError(ERROR_MORE_DATA);
3180 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3182 blob->cbData = dataLen;
3183 assert(blob->pbData);
3184 /* remove leading zero byte if it exists */
3185 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
3194 for (i = 0; i < blob->cbData; i++)
3196 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3205 SetLastError(CRYPT_E_ASN1_BADTAG);
3211 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
3212 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3213 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3221 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
3222 lpszStructType, pbEncoded, cbEncoded,
3223 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
3226 *pcbStructInfo = bytesNeeded;
3227 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3228 pvStructInfo, pcbStructInfo, bytesNeeded)))
3230 CRYPT_INTEGER_BLOB *blob;
3232 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3233 pvStructInfo = *(BYTE **)pvStructInfo;
3234 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3235 blob->pbData = (BYTE *)pvStructInfo +
3236 sizeof(CRYPT_INTEGER_BLOB);
3237 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(dwCertEncodingType,
3238 lpszStructType, pbEncoded, cbEncoded,
3239 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pvStructInfo,
3246 SetLastError(STATUS_ACCESS_VIOLATION);
3253 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
3254 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3255 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3261 *pcbStructInfo = sizeof(int);
3266 if (pbEncoded[0] == ASN_ENUMERATED)
3268 unsigned int val = 0, i;
3272 SetLastError(CRYPT_E_ASN1_EOD);
3275 else if (pbEncoded[1] == 0)
3277 SetLastError(CRYPT_E_ASN1_CORRUPT);
3282 /* A little strange looking, but we have to accept a sign byte:
3283 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
3284 * assuming a small length is okay here, it has to be in short
3287 if (pbEncoded[1] > sizeof(unsigned int) + 1)
3289 SetLastError(CRYPT_E_ASN1_LARGE);
3292 for (i = 0; i < pbEncoded[1]; i++)
3295 val |= pbEncoded[2 + i];
3297 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3298 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
3300 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3301 pvStructInfo = *(BYTE **)pvStructInfo;
3302 memcpy(pvStructInfo, &val, sizeof(unsigned int));
3308 SetLastError(CRYPT_E_ASN1_BADTAG);
3314 SetLastError(STATUS_ACCESS_VIOLATION);
3321 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
3324 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
3329 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
3331 if (!isdigit(*(pbEncoded))) \
3333 SetLastError(CRYPT_E_ASN1_CORRUPT); \
3339 (word) += *(pbEncoded)++ - '0'; \
3344 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
3345 SYSTEMTIME *sysTime)
3352 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
3354 WORD hours, minutes = 0;
3355 BYTE sign = *pbEncoded++;
3358 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
3359 if (ret && hours >= 24)
3361 SetLastError(CRYPT_E_ASN1_CORRUPT);
3366 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
3367 if (ret && minutes >= 60)
3369 SetLastError(CRYPT_E_ASN1_CORRUPT);
3377 sysTime->wHour += hours;
3378 sysTime->wMinute += minutes;
3382 if (hours > sysTime->wHour)
3385 sysTime->wHour = 24 - (hours - sysTime->wHour);
3388 sysTime->wHour -= hours;
3389 if (minutes > sysTime->wMinute)
3392 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
3395 sysTime->wMinute -= minutes;
3402 SetLastError(STATUS_ACCESS_VIOLATION);
3409 #define MIN_ENCODED_TIME_LENGTH 10
3411 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
3412 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3413 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3419 *pcbStructInfo = sizeof(FILETIME);
3425 if (pbEncoded[0] == ASN_UTCTIME)
3429 SetLastError(CRYPT_E_ASN1_EOD);
3432 else if (pbEncoded[1] > 0x7f)
3434 /* long-form date strings really can't be valid */
3435 SetLastError(CRYPT_E_ASN1_CORRUPT);
3440 SYSTEMTIME sysTime = { 0 };
3441 BYTE len = pbEncoded[1];
3443 if (len < MIN_ENCODED_TIME_LENGTH)
3445 SetLastError(CRYPT_E_ASN1_CORRUPT);
3451 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
3452 if (sysTime.wYear >= 50)
3453 sysTime.wYear += 1900;
3455 sysTime.wYear += 2000;
3456 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3457 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3458 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3459 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
3462 if (len >= 2 && isdigit(*pbEncoded) &&
3463 isdigit(*(pbEncoded + 1)))
3464 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3466 else if (isdigit(*pbEncoded))
3467 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
3470 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3473 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
3474 pDecodePara, pvStructInfo, pcbStructInfo,
3477 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3478 pvStructInfo = *(BYTE **)pvStructInfo;
3479 ret = SystemTimeToFileTime(&sysTime,
3480 (FILETIME *)pvStructInfo);
3487 SetLastError(CRYPT_E_ASN1_BADTAG);
3493 SetLastError(STATUS_ACCESS_VIOLATION);
3500 static BOOL WINAPI CRYPT_AsnDecodeGeneralizedTime(DWORD dwCertEncodingType,
3501 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3502 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3508 *pcbStructInfo = sizeof(FILETIME);
3514 if (pbEncoded[0] == ASN_GENERALTIME)
3518 SetLastError(CRYPT_E_ASN1_EOD);
3521 else if (pbEncoded[1] > 0x7f)
3523 /* long-form date strings really can't be valid */
3524 SetLastError(CRYPT_E_ASN1_CORRUPT);
3529 BYTE len = pbEncoded[1];
3531 if (len < MIN_ENCODED_TIME_LENGTH)
3533 SetLastError(CRYPT_E_ASN1_CORRUPT);
3538 SYSTEMTIME sysTime = { 0 };
3541 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
3542 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3543 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3544 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3547 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3550 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3552 if (ret && len > 0 && (*pbEncoded == '.' ||
3559 /* workaround macro weirdness */
3560 digits = min(len, 3);
3561 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
3562 sysTime.wMilliseconds);
3565 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3568 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags,
3569 pDecodePara, pvStructInfo, pcbStructInfo,
3572 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3573 pvStructInfo = *(BYTE **)pvStructInfo;
3574 ret = SystemTimeToFileTime(&sysTime,
3575 (FILETIME *)pvStructInfo);
3582 SetLastError(CRYPT_E_ASN1_BADTAG);
3588 SetLastError(STATUS_ACCESS_VIOLATION);
3595 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
3596 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3597 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3603 if (pbEncoded[0] == ASN_UTCTIME)
3604 ret = CRYPT_AsnDecodeUtcTime(dwCertEncodingType, lpszStructType,
3605 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3607 else if (pbEncoded[0] == ASN_GENERALTIME)
3608 ret = CRYPT_AsnDecodeGeneralizedTime(dwCertEncodingType,
3609 lpszStructType, pbEncoded, cbEncoded, dwFlags, pDecodePara,
3610 pvStructInfo, pcbStructInfo);
3613 SetLastError(CRYPT_E_ASN1_BADTAG);
3619 SetLastError(STATUS_ACCESS_VIOLATION);
3626 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
3627 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3628 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3634 if (pbEncoded[0] == ASN_SEQUENCEOF)
3636 DWORD bytesNeeded, dataLen, remainingLen, cValue;
3638 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3643 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3644 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
3646 ptr = pbEncoded + 1 + lenBytes;
3647 remainingLen = dataLen;
3648 while (ret && remainingLen)
3652 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3655 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3657 remainingLen -= 1 + nextLenBytes + nextLen;
3658 ptr += 1 + nextLenBytes + nextLen;
3659 bytesNeeded += sizeof(CRYPT_DER_BLOB);
3660 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3661 bytesNeeded += 1 + nextLenBytes + nextLen;
3667 CRYPT_SEQUENCE_OF_ANY *seq;
3671 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3672 pvStructInfo, pcbStructInfo, bytesNeeded)))
3674 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3675 pvStructInfo = *(BYTE **)pvStructInfo;
3676 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
3677 seq->cValue = cValue;
3678 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
3680 nextPtr = (BYTE *)seq->rgValue +
3681 cValue * sizeof(CRYPT_DER_BLOB);
3682 ptr = pbEncoded + 1 + lenBytes;
3683 remainingLen = dataLen;
3685 while (ret && remainingLen)
3689 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3692 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3694 seq->rgValue[i].cbData = 1 + nextLenBytes +
3696 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3697 seq->rgValue[i].pbData = (BYTE *)ptr;
3700 seq->rgValue[i].pbData = nextPtr;
3701 memcpy(nextPtr, ptr, 1 + nextLenBytes +
3703 nextPtr += 1 + nextLenBytes + nextLen;
3705 remainingLen -= 1 + nextLenBytes + nextLen;
3706 ptr += 1 + nextLenBytes + nextLen;
3716 SetLastError(CRYPT_E_ASN1_BADTAG);
3722 SetLastError(STATUS_ACCESS_VIOLATION);
3729 static BOOL WINAPI CRYPT_AsnDecodeDistPointName(DWORD dwCertEncodingType,
3730 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3731 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3735 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
3737 DWORD bytesNeeded, dataLen;
3739 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3741 struct AsnArrayDescriptor arrayDesc = {
3742 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
3743 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3744 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3745 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3751 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3752 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3753 0, NULL, NULL, &nameLen, NULL, NULL);
3754 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen;
3757 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
3759 *pcbStructInfo = bytesNeeded;
3760 else if (*pcbStructInfo < bytesNeeded)
3762 *pcbStructInfo = bytesNeeded;
3763 SetLastError(ERROR_MORE_DATA);
3768 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
3772 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3773 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3774 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3775 0, NULL, &name->u.FullName, pcbStructInfo, NULL,
3776 name->u.FullName.rgAltEntry);
3779 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3785 SetLastError(CRYPT_E_ASN1_BADTAG);
3791 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
3792 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3794 struct AsnDecodeSequenceItem items[] = {
3795 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
3796 DistPointName), CRYPT_AsnDecodeDistPointName,
3797 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
3798 DistPointName.u.FullName.rgAltEntry), 0 },
3799 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
3800 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
3801 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
3802 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
3803 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
3804 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
3808 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
3809 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3810 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded, NULL);
3814 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
3815 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3816 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3820 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3821 pDecodePara, pvStructInfo, *pcbStructInfo);
3825 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3826 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
3827 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
3829 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3830 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
3834 SetLastError(STATUS_ACCESS_VIOLATION);
3841 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3842 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3843 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3847 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3848 pDecodePara, pvStructInfo, *pcbStructInfo);
3852 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3853 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
3855 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3856 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
3860 SetLastError(STATUS_ACCESS_VIOLATION);
3867 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
3868 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3869 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3873 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3874 pDecodePara, pvStructInfo, *pcbStructInfo);
3878 struct AsnDecodeSequenceItem items[] = {
3879 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
3880 DistPointName), CRYPT_AsnDecodeDistPointName,
3881 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
3882 offsetof(CRL_ISSUING_DIST_POINT,
3883 DistPointName.u.FullName.rgAltEntry), 0 },
3884 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
3885 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3887 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
3888 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3890 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
3891 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
3892 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
3893 OnlySomeReasonFlags.pbData), 0 },
3894 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
3895 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
3898 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3899 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3900 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
3904 SetLastError(STATUS_ACCESS_VIOLATION);
3911 static BOOL WINAPI CRYPT_AsnDecodeIssuerSerialNumber(DWORD dwCertEncodingType,
3912 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3913 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3916 struct AsnDecodeSequenceItem items[] = {
3917 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
3918 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
3920 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
3921 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
3922 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
3924 CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
3925 (CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
3927 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3928 pDecodePara, pvStructInfo, *pcbStructInfo);
3930 ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
3931 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3932 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL,
3933 issuerSerial ? issuerSerial->Issuer.pbData : NULL);
3934 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
3936 SetLastError(CRYPT_E_ASN1_CORRUPT);
3939 TRACE("returning %d\n", ret);
3943 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
3944 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3947 CMSG_SIGNER_INFO *info = (CMSG_SIGNER_INFO *)pvStructInfo;
3948 struct AsnDecodeSequenceItem items[] = {
3949 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
3950 CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3951 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
3952 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
3953 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
3954 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
3955 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3956 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
3957 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
3958 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
3959 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
3960 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
3961 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
3962 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3963 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
3964 HashEncryptionAlgorithm.pszObjId), 0 },
3965 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
3966 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
3967 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
3968 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
3969 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
3970 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
3971 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
3975 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3976 pvStructInfo, *pcbStructInfo);
3978 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
3979 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
3980 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
3981 info ? info->Issuer.pbData : NULL);
3985 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
3986 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3987 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3991 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3992 pDecodePara, pvStructInfo, *pcbStructInfo);
3996 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
3997 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
3998 if (ret && pvStructInfo)
4000 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
4001 pcbStructInfo, *pcbStructInfo);
4004 CMSG_SIGNER_INFO *info;
4006 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4007 pvStructInfo = *(BYTE **)pvStructInfo;
4008 info = (CMSG_SIGNER_INFO *)pvStructInfo;
4009 info->Issuer.pbData = ((BYTE *)info +
4010 sizeof(CMSG_SIGNER_INFO));
4011 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
4012 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4013 pcbStructInfo, NULL);
4019 SetLastError(STATUS_ACCESS_VIOLATION);
4022 TRACE("returning %d\n", ret);
4026 static BOOL WINAPI CRYPT_DecodeSignerArray(DWORD dwCertEncodingType,
4027 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4028 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4031 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
4032 CRYPT_AsnDecodePKCSSignerInfoInternal, sizeof(CMSG_SIGNER_INFO), TRUE,
4033 offsetof(CMSG_SIGNER_INFO, Issuer.pbData) };
4034 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
4036 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4037 pDecodePara, pvStructInfo, *pcbStructInfo);
4039 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4040 pDecodePara, pvStructInfo, pcbStructInfo, NULL,
4041 array ? array->rgItems : NULL);
4045 BOOL CRYPT_AsnDecodePKCSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
4046 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
4047 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
4050 struct AsnDecodeSequenceItem items[] = {
4051 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version), CRYPT_AsnDecodeInt,
4052 sizeof(DWORD), FALSE, FALSE, 0, 0 },
4053 /* Placeholder for the hash algorithms - redundant with those in the
4054 * signers, so just ignore them.
4056 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
4057 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
4058 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
4059 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
4060 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4061 offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
4062 CRYPT_DecodeDERArray, sizeof(struct GenericArray), TRUE, TRUE,
4063 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
4064 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4065 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_DecodeDERArray,
4066 sizeof(struct GenericArray), TRUE, TRUE,
4067 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
4068 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
4069 CRYPT_DecodeSignerArray, sizeof(struct GenericArray), TRUE, TRUE,
4070 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
4073 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4074 pDecodePara, signedInfo, *pcbSignedInfo);
4076 ret = CRYPT_AsnDecodeSequence(X509_ASN_ENCODING, items,
4077 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
4078 pDecodePara, signedInfo, pcbSignedInfo, NULL, NULL);
4079 TRACE("returning %d\n", ret);
4083 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
4084 LPCSTR lpszStructType)
4086 CryptDecodeObjectExFunc decodeFunc = NULL;
4088 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
4089 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
4091 SetLastError(ERROR_FILE_NOT_FOUND);
4094 if (!HIWORD(lpszStructType))
4096 switch (LOWORD(lpszStructType))
4098 case (WORD)X509_CERT:
4099 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
4101 case (WORD)X509_CERT_TO_BE_SIGNED:
4102 decodeFunc = CRYPT_AsnDecodeCert;
4104 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
4105 decodeFunc = CRYPT_AsnDecodeCRL;
4107 case (WORD)X509_EXTENSIONS:
4108 decodeFunc = CRYPT_AsnDecodeExtensions;
4110 case (WORD)X509_NAME_VALUE:
4111 decodeFunc = CRYPT_AsnDecodeNameValue;
4113 case (WORD)X509_NAME:
4114 decodeFunc = CRYPT_AsnDecodeName;
4116 case (WORD)X509_PUBLIC_KEY_INFO:
4117 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
4119 case (WORD)X509_AUTHORITY_KEY_ID:
4120 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4122 case (WORD)X509_ALTERNATE_NAME:
4123 decodeFunc = CRYPT_AsnDecodeAltName;
4125 case (WORD)X509_BASIC_CONSTRAINTS:
4126 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4128 case (WORD)X509_BASIC_CONSTRAINTS2:
4129 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4131 case (WORD)RSA_CSP_PUBLICKEYBLOB:
4132 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
4134 case (WORD)X509_UNICODE_NAME:
4135 decodeFunc = CRYPT_AsnDecodeUnicodeName;
4137 case (WORD)PKCS_ATTRIBUTE:
4138 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
4140 case (WORD)X509_UNICODE_NAME_VALUE:
4141 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
4143 case (WORD)X509_OCTET_STRING:
4144 decodeFunc = CRYPT_AsnDecodeOctets;
4146 case (WORD)X509_BITS:
4147 case (WORD)X509_KEY_USAGE:
4148 decodeFunc = CRYPT_AsnDecodeBits;
4150 case (WORD)X509_INTEGER:
4151 decodeFunc = CRYPT_AsnDecodeInt;
4153 case (WORD)X509_MULTI_BYTE_INTEGER:
4154 decodeFunc = CRYPT_AsnDecodeInteger;
4156 case (WORD)X509_MULTI_BYTE_UINT:
4157 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
4159 case (WORD)X509_ENUMERATED:
4160 decodeFunc = CRYPT_AsnDecodeEnumerated;
4162 case (WORD)X509_CHOICE_OF_TIME:
4163 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
4165 case (WORD)X509_AUTHORITY_KEY_ID2:
4166 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4168 case (WORD)PKCS_CONTENT_INFO:
4169 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
4171 case (WORD)X509_SEQUENCE_OF_ANY:
4172 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
4174 case (WORD)PKCS_UTC_TIME:
4175 decodeFunc = CRYPT_AsnDecodeUtcTime;
4177 case (WORD)X509_CRL_DIST_POINTS:
4178 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4180 case (WORD)X509_ENHANCED_KEY_USAGE:
4181 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4183 case (WORD)PKCS_ATTRIBUTES:
4184 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
4186 case (WORD)X509_ISSUING_DIST_POINT:
4187 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4189 case (WORD)PKCS7_SIGNER_INFO:
4190 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
4194 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4195 decodeFunc = CRYPT_AsnDecodeExtensions;
4196 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4197 decodeFunc = CRYPT_AsnDecodeUtcTime;
4198 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4199 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4200 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4201 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4202 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4203 decodeFunc = CRYPT_AsnDecodeEnumerated;
4204 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4205 decodeFunc = CRYPT_AsnDecodeBits;
4206 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4207 decodeFunc = CRYPT_AsnDecodeOctets;
4208 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4209 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4210 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4211 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4212 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4213 decodeFunc = CRYPT_AsnDecodeAltName;
4214 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4215 decodeFunc = CRYPT_AsnDecodeAltName;
4216 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4217 decodeFunc = CRYPT_AsnDecodeAltName;
4218 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4219 decodeFunc = CRYPT_AsnDecodeAltName;
4220 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4221 decodeFunc = CRYPT_AsnDecodeAltName;
4222 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4223 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4224 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4225 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4226 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4227 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4231 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
4232 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4234 static HCRYPTOIDFUNCSET set = NULL;
4235 CryptDecodeObjectFunc decodeFunc = NULL;
4238 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
4239 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4240 (void **)&decodeFunc, hFunc);
4244 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
4245 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4247 static HCRYPTOIDFUNCSET set = NULL;
4248 CryptDecodeObjectExFunc decodeFunc = NULL;
4251 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
4252 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4253 (void **)&decodeFunc, hFunc);
4257 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4258 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
4259 DWORD *pcbStructInfo)
4262 CryptDecodeObjectFunc pCryptDecodeObject = NULL;
4263 CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
4264 HCRYPTOIDFUNCADDR hFunc = NULL;
4266 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
4267 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
4268 pvStructInfo, pcbStructInfo);
4270 if (!pvStructInfo && !pcbStructInfo)
4272 SetLastError(ERROR_INVALID_PARAMETER);
4277 SetLastError(CRYPT_E_ASN1_EOD);
4280 if (cbEncoded > MAX_ENCODED_LEN)
4282 SetLastError(CRYPT_E_ASN1_LARGE);
4286 if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
4289 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4290 debugstr_a(lpszStructType));
4291 pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
4292 lpszStructType, &hFunc);
4293 if (!pCryptDecodeObject)
4294 pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
4295 lpszStructType, &hFunc);
4297 if (pCryptDecodeObject)
4298 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4299 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4300 else if (pCryptDecodeObjectEx)
4301 ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
4302 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
4303 pvStructInfo, pcbStructInfo);
4305 CryptFreeOIDFunctionAddress(hFunc, 0);
4306 TRACE_(crypt)("returning %d\n", ret);
4310 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4311 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4312 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4315 CryptDecodeObjectExFunc decodeFunc;
4316 HCRYPTOIDFUNCADDR hFunc = NULL;
4318 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
4319 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
4320 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4322 if (!pvStructInfo && !pcbStructInfo)
4324 SetLastError(ERROR_INVALID_PARAMETER);
4329 SetLastError(CRYPT_E_ASN1_EOD);
4332 if (cbEncoded > MAX_ENCODED_LEN)
4334 SetLastError(CRYPT_E_ASN1_LARGE);
4338 SetLastError(NOERROR);
4339 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
4340 *(BYTE **)pvStructInfo = NULL;
4341 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
4344 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4345 debugstr_a(lpszStructType));
4346 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
4350 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
4351 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4354 CryptDecodeObjectFunc pCryptDecodeObject =
4355 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
4357 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
4358 * directly, as that could cause an infinite loop.
4360 if (pCryptDecodeObject)
4362 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4364 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4365 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
4366 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4367 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
4368 ret = pCryptDecodeObject(dwCertEncodingType,
4369 lpszStructType, pbEncoded, cbEncoded, dwFlags,
4370 *(BYTE **)pvStructInfo, pcbStructInfo);
4373 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4374 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4378 CryptFreeOIDFunctionAddress(hFunc, 0);
4379 TRACE_(crypt)("returning %d\n", ret);