push 514b285b0c98f6a7a84c63e51c3091a87ae6d177
[wine/hacks.git] / dlls / crypt32 / decode.c
bloba62482325f85a01a06d6078c21cd775f1e03bf85
1 /*
2 * Copyright 2005-2008 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.
23 * References:
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"
33 #include "config.h"
34 #include "wine/port.h"
36 #include <assert.h>
37 #include <stdarg.h>
38 #include <stdio.h>
39 #include <stdlib.h>
41 #define NONAMELESSUNION
43 #include "windef.h"
44 #include "winbase.h"
45 #include "wincrypt.h"
46 #include "winnls.h"
47 #include "snmp.h"
48 #include "wine/debug.h"
49 #include "wine/exception.h"
50 #include "crypt32_private.h"
52 /* This is a bit arbitrary, but to set some limit: */
53 #define MAX_ENCODED_LEN 0x02000000
55 #define ASN_FLAGS_MASK 0xe0
56 #define ASN_TYPE_MASK 0x1f
58 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
59 WINE_DECLARE_DEBUG_CHANNEL(crypt);
61 struct GenericArray
63 DWORD cItems;
64 BYTE *rgItems;
67 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
68 DWORD, DWORD, void *, DWORD *);
69 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
70 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
72 /* Internal decoders don't do memory allocation or exception handling, and
73 * they report how many bytes they decoded.
75 typedef BOOL (*InternalDecodeFunc)(const BYTE *pbEncoded, DWORD cbEncoded,
76 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
78 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
79 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
80 DWORD *pcbDecoded);
81 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
82 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
83 DWORD *pcbDecoded);
84 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
85 * time, doesn't do memory allocation, and doesn't do exception handling.
87 static BOOL CRYPT_AsnDecodeExtensionsInternal(const BYTE *pbEncoded,
88 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
89 DWORD *pcbDecoded);
90 /* Assumes algo->Parameters.pbData is set ahead of time. */
91 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
92 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
93 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
94 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
95 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
96 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
97 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
98 DWORD *pcbDecoded);
99 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
100 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
101 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
102 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
103 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
104 * member has been initialized, doesn't do exception handling, and doesn't do
105 * memory allocation. Also doesn't check tag, assumes the caller has checked
106 * it.
108 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
109 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
110 DWORD *pcbDecoded);
111 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
112 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
113 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
114 DWORD *pcbDecoded);
116 /* Gets the number of length bytes from the given (leading) length byte */
117 #define GET_LEN_BYTES(b) ((b) <= 0x80 ? 1 : 1 + ((b) & 0x7f))
119 /* Helper function to get the encoded length of the data starting at pbEncoded,
120 * where pbEncoded[0] is the tag. If the data are too short to contain a
121 * length or if the length is too large for cbEncoded, sets an appropriate
122 * error code and returns FALSE. If the encoded length is unknown due to
123 * indefinite length encoding, *len is set to CMSG_INDEFINITE_LENGTH.
125 static BOOL CRYPT_GetLengthIndefinite(const BYTE *pbEncoded, DWORD cbEncoded,
126 DWORD *len)
128 BOOL ret;
130 if (cbEncoded <= 1)
132 SetLastError(CRYPT_E_ASN1_CORRUPT);
133 ret = FALSE;
135 else if (pbEncoded[1] <= 0x7f)
137 if (pbEncoded[1] + 1 > cbEncoded)
139 SetLastError(CRYPT_E_ASN1_EOD);
140 ret = FALSE;
142 else
144 *len = pbEncoded[1];
145 ret = TRUE;
148 else if (pbEncoded[1] == 0x80)
150 *len = CMSG_INDEFINITE_LENGTH;
151 ret = TRUE;
153 else
155 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
157 if (lenLen > sizeof(DWORD) + 1)
159 SetLastError(CRYPT_E_ASN1_LARGE);
160 ret = FALSE;
162 else if (lenLen + 2 > cbEncoded)
164 SetLastError(CRYPT_E_ASN1_CORRUPT);
165 ret = FALSE;
167 else
169 DWORD out = 0;
171 pbEncoded += 2;
172 while (--lenLen)
174 out <<= 8;
175 out |= *pbEncoded++;
177 if (out + lenLen + 1 > cbEncoded)
179 SetLastError(CRYPT_E_ASN1_EOD);
180 ret = FALSE;
182 else
184 *len = out;
185 ret = TRUE;
189 return ret;
192 /* Like CRYPT_GetLengthIndefinite, but disallows indefinite-length encoding. */
193 static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
195 BOOL ret;
197 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, len)) &&
198 *len == CMSG_INDEFINITE_LENGTH)
200 SetLastError(CRYPT_E_ASN1_CORRUPT);
201 ret = FALSE;
203 return ret;
206 /* Helper function to check *pcbStructInfo, set it to the required size, and
207 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
208 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
209 * pointer to the newly allocated memory.
211 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
212 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
213 DWORD bytesNeeded)
215 BOOL ret = TRUE;
217 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
219 if (pDecodePara && pDecodePara->pfnAlloc)
220 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
221 else
222 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
223 if (!*(BYTE **)pvStructInfo)
224 ret = FALSE;
225 else
226 *pcbStructInfo = bytesNeeded;
228 else if (*pcbStructInfo < bytesNeeded)
230 *pcbStructInfo = bytesNeeded;
231 SetLastError(ERROR_MORE_DATA);
232 ret = FALSE;
234 else
235 *pcbStructInfo = bytesNeeded;
236 return ret;
239 static void CRYPT_FreeSpace(PCRYPT_DECODE_PARA pDecodePara, LPVOID pv)
241 if (pDecodePara && pDecodePara->pfnFree)
242 pDecodePara->pfnFree(pv);
243 else
244 LocalFree(pv);
247 /* Helper function to check *pcbStructInfo and set it to the required size.
248 * Assumes pvStructInfo is not NULL.
250 static BOOL CRYPT_DecodeCheckSpace(DWORD *pcbStructInfo, DWORD bytesNeeded)
252 BOOL ret;
254 if (*pcbStructInfo < bytesNeeded)
256 *pcbStructInfo = bytesNeeded;
257 SetLastError(ERROR_MORE_DATA);
258 ret = FALSE;
260 else
262 *pcbStructInfo = bytesNeeded;
263 ret = TRUE;
265 return ret;
268 /* tag:
269 * The expected tag of the item. If tag is 0, decodeFunc is called
270 * regardless of the tag value seen.
271 * offset:
272 * A sequence is decoded into a struct. The offset member is the
273 * offset of this item within that struct.
274 * decodeFunc:
275 * The decoder function to use. If this is NULL, then the member isn't
276 * decoded, but minSize space is reserved for it.
277 * minSize:
278 * The minimum amount of space occupied after decoding. You must set this.
279 * optional:
280 * If true, and the tag doesn't match the expected tag for this item,
281 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
282 * filled with 0 for this member.
283 * hasPointer, pointerOffset:
284 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
285 * the offset within the struct of the data pointer (or to the
286 * first data pointer, if more than one exist).
287 * size:
288 * Used by CRYPT_AsnDecodeSequence, not for your use.
290 struct AsnDecodeSequenceItem
292 BYTE tag;
293 DWORD offset;
294 InternalDecodeFunc decodeFunc;
295 DWORD minSize;
296 BOOL optional;
297 BOOL hasPointer;
298 DWORD pointerOffset;
299 DWORD size;
302 /* Decodes the items in a sequence, where the items are described in items,
303 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
304 * pvStructInfo. nextData is a pointer to the memory location at which the
305 * first decoded item with a dynamic pointer should point.
306 * Upon decoding, *cbDecoded is the total number of bytes decoded.
307 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
309 static BOOL CRYPT_AsnDecodeSequenceItems(struct AsnDecodeSequenceItem items[],
310 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
311 void *pvStructInfo, BYTE *nextData, DWORD *cbDecoded)
313 BOOL ret;
314 DWORD i, decoded = 0;
315 const BYTE *ptr = pbEncoded;
317 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
318 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
320 for (i = 0, ret = TRUE; ret && i < cItem; i++)
322 if (cbEncoded - (ptr - pbEncoded) != 0)
324 DWORD itemLen;
326 if ((ret = CRYPT_GetLengthIndefinite(ptr,
327 cbEncoded - (ptr - pbEncoded), &itemLen)))
329 BYTE itemLenBytes = GET_LEN_BYTES(ptr[1]);
331 if (ptr[0] == items[i].tag || !items[i].tag)
333 DWORD itemEncodedLen;
335 if (itemLen == CMSG_INDEFINITE_LENGTH)
336 itemEncodedLen = cbEncoded - (ptr - pbEncoded);
337 else
338 itemEncodedLen = 1 + itemLenBytes + itemLen;
339 if (nextData && pvStructInfo && items[i].hasPointer)
341 TRACE("Setting next pointer to %p\n",
342 nextData);
343 *(BYTE **)((BYTE *)pvStructInfo +
344 items[i].pointerOffset) = nextData;
346 if (items[i].decodeFunc)
348 DWORD itemDecoded;
350 if (pvStructInfo)
351 TRACE("decoding item %d\n", i);
352 else
353 TRACE("sizing item %d\n", i);
354 ret = items[i].decodeFunc(ptr, itemEncodedLen,
355 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
356 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
357 : NULL, &items[i].size, &itemDecoded);
358 if (ret)
360 /* Account for alignment padding */
361 if (items[i].size % sizeof(DWORD_PTR))
362 items[i].size += sizeof(DWORD_PTR) -
363 items[i].size % sizeof(DWORD_PTR);
364 TRACE("item %d size: %d\n", i, items[i].size);
365 if (nextData && items[i].hasPointer &&
366 items[i].size > items[i].minSize)
367 nextData += items[i].size - items[i].minSize;
368 if (itemDecoded > itemEncodedLen)
370 WARN("decoded length %d exceeds encoded %d\n",
371 itemDecoded, itemEncodedLen);
372 SetLastError(CRYPT_E_ASN1_CORRUPT);
373 ret = FALSE;
375 else
377 if (itemLen == CMSG_INDEFINITE_LENGTH)
379 if (itemDecoded > itemEncodedLen - 2 ||
380 *(ptr + itemDecoded) != 0 ||
381 *(ptr + itemDecoded + 1) != 0)
383 TRACE("expected 0 TLV\n");
384 SetLastError(CRYPT_E_ASN1_CORRUPT);
385 ret = FALSE;
387 else
388 itemDecoded += 2;
390 if (ret)
392 ptr += itemDecoded;
393 decoded += itemDecoded;
394 TRACE("item %d: decoded %d bytes\n", i,
395 itemDecoded);
399 else if (items[i].optional &&
400 GetLastError() == CRYPT_E_ASN1_BADTAG)
402 TRACE("skipping optional item %d\n", i);
403 items[i].size = items[i].minSize;
404 SetLastError(NOERROR);
405 ret = TRUE;
407 else
408 TRACE("item %d failed: %08x\n", i,
409 GetLastError());
411 else if (itemLen == CMSG_INDEFINITE_LENGTH)
413 ERR("can't use indefinite length encoding without a decoder\n");
414 SetLastError(CRYPT_E_ASN1_CORRUPT);
415 ret = FALSE;
417 else
419 TRACE("item %d: decoded %d bytes\n", i, itemEncodedLen);
420 ptr += itemEncodedLen;
421 decoded += itemEncodedLen;
422 items[i].size = items[i].minSize;
425 else if (items[i].optional)
427 TRACE("skipping optional item %d\n", i);
428 items[i].size = items[i].minSize;
430 else
432 TRACE("item %d: tag %02x doesn't match expected %02x\n",
433 i, ptr[0], items[i].tag);
434 SetLastError(CRYPT_E_ASN1_BADTAG);
435 ret = FALSE;
439 else if (items[i].optional)
441 TRACE("missing optional item %d, skipping\n", i);
442 items[i].size = items[i].minSize;
444 else
446 TRACE("not enough bytes for item %d, failing\n", i);
447 SetLastError(CRYPT_E_ASN1_CORRUPT);
448 ret = FALSE;
451 if (cbDecoded)
452 *cbDecoded = decoded;
453 TRACE("returning %d\n", ret);
454 return ret;
457 /* This decodes an arbitrary sequence into a contiguous block of memory
458 * (basically, a struct.) Each element being decoded is described by a struct
459 * AsnDecodeSequenceItem, see above.
460 * startingPointer is an optional pointer to the first place where dynamic
461 * data will be stored. If you know the starting offset, you may pass it
462 * here. Otherwise, pass NULL, and one will be inferred from the items.
464 static BOOL CRYPT_AsnDecodeSequence(struct AsnDecodeSequenceItem items[],
465 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
466 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
467 DWORD *pcbDecoded, void *startingPointer)
469 BOOL ret;
471 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
472 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
473 startingPointer);
475 if (pbEncoded[0] == ASN_SEQUENCE)
477 DWORD dataLen;
479 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
481 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
482 const BYTE *ptr = pbEncoded + 1 + lenBytes;
483 BOOL indefinite = FALSE;
485 cbEncoded -= 1 + lenBytes;
486 if (dataLen == CMSG_INDEFINITE_LENGTH)
488 dataLen = cbEncoded;
489 indefinite = TRUE;
491 else if (cbEncoded < dataLen)
493 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
494 cbEncoded);
495 SetLastError(CRYPT_E_ASN1_CORRUPT);
496 ret = FALSE;
498 if (ret)
500 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
501 ptr, dataLen, dwFlags, NULL, NULL, &cbDecoded);
502 if (ret && dataLen == CMSG_INDEFINITE_LENGTH)
504 if (cbDecoded > cbEncoded - 2)
506 /* Not enough space for 0 TLV */
507 SetLastError(CRYPT_E_ASN1_CORRUPT);
508 ret = FALSE;
510 else if (*(ptr + cbDecoded) != 0 ||
511 *(ptr + cbDecoded + 1) != 0)
513 TRACE("expected 0 TLV\n");
514 SetLastError(CRYPT_E_ASN1_CORRUPT);
515 ret = FALSE;
517 else
518 cbDecoded += 2;
521 if (ret && !indefinite && cbDecoded != dataLen)
523 TRACE("expected %d decoded, got %d, failing\n", dataLen,
524 cbDecoded);
525 SetLastError(CRYPT_E_ASN1_CORRUPT);
526 ret = FALSE;
528 if (ret)
530 DWORD i, bytesNeeded = 0, structSize = 0;
532 for (i = 0; i < cItem; i++)
534 bytesNeeded += items[i].size;
535 structSize += items[i].minSize;
537 if (pcbDecoded)
538 *pcbDecoded = 1 + lenBytes + cbDecoded;
539 if (!pvStructInfo)
540 *pcbStructInfo = bytesNeeded;
541 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
542 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
544 BYTE *nextData;
546 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
547 pvStructInfo = *(BYTE **)pvStructInfo;
548 if (startingPointer)
549 nextData = (BYTE *)startingPointer;
550 else
551 nextData = (BYTE *)pvStructInfo + structSize;
552 memset(pvStructInfo, 0, structSize);
553 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
554 ptr, dataLen, dwFlags, pvStructInfo, nextData,
555 &cbDecoded);
556 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
557 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
562 else
564 SetLastError(CRYPT_E_ASN1_BADTAG);
565 ret = FALSE;
567 TRACE("returning %d (%08x)\n", ret, GetLastError());
568 return ret;
571 /* tag:
572 * The expected tag of the entire encoded array (usually a variant
573 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
574 * regardless of the tag seen.
575 * decodeFunc:
576 * used to decode each item in the array
577 * itemSize:
578 * is the minimum size of each decoded item
579 * hasPointer:
580 * indicates whether each item has a dynamic pointer
581 * pointerOffset:
582 * indicates the offset within itemSize at which the pointer exists
584 struct AsnArrayDescriptor
586 BYTE tag;
587 InternalDecodeFunc decodeFunc;
588 DWORD itemSize;
589 BOOL hasPointer;
590 DWORD pointerOffset;
593 struct AsnArrayItemSize
595 DWORD encodedLen;
596 DWORD size;
599 /* Decodes an array of like types into a struct GenericArray.
600 * The layout and decoding of the array are described by a struct
601 * AsnArrayDescriptor.
603 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
604 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
605 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
606 DWORD *pcbDecoded, void *startingPointer)
608 BOOL ret = TRUE;
610 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
611 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
612 startingPointer);
614 if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
616 DWORD dataLen;
618 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
620 DWORD bytesNeeded, cItems = 0, decoded;
621 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
622 /* There can be arbitrarily many items, but there is often only one.
624 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
626 decoded = 1 + lenBytes;
627 bytesNeeded = sizeof(struct GenericArray);
628 if (dataLen)
630 const BYTE *ptr;
631 BOOL doneDecoding = FALSE;
633 for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
635 if (dataLen == CMSG_INDEFINITE_LENGTH)
637 if (ptr[0] == 0)
639 doneDecoding = TRUE;
640 if (ptr[1] != 0)
642 SetLastError(CRYPT_E_ASN1_CORRUPT);
643 ret = FALSE;
645 else
646 decoded += 2;
649 else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
650 doneDecoding = TRUE;
651 if (!doneDecoding)
653 DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
655 /* Each item decoded may not tolerate extraneous bytes,
656 * so get the length of the next element if known.
658 if ((ret = CRYPT_GetLengthIndefinite(ptr,
659 cbEncoded - (ptr - pbEncoded), &itemDataLen)))
661 if (itemDataLen == CMSG_INDEFINITE_LENGTH)
662 itemEncoded = cbEncoded - (ptr - pbEncoded);
663 else
664 itemEncoded = 1 + GET_LEN_BYTES(ptr[1]) +
665 itemDataLen;
667 if (ret)
668 ret = arrayDesc->decodeFunc(ptr, itemEncoded,
669 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size,
670 &itemDecoded);
671 if (ret)
673 cItems++;
674 if (itemSizes != &itemSize)
675 itemSizes = CryptMemRealloc(itemSizes,
676 cItems * sizeof(struct AsnArrayItemSize));
677 else if (cItems > 1)
679 itemSizes =
680 CryptMemAlloc(
681 cItems * sizeof(struct AsnArrayItemSize));
682 if (itemSizes)
683 memcpy(itemSizes, &itemSize,
684 sizeof(itemSize));
686 if (itemSizes)
688 decoded += itemDecoded;
689 itemSizes[cItems - 1].encodedLen = itemEncoded;
690 itemSizes[cItems - 1].size = size;
691 bytesNeeded += size;
692 ptr += itemEncoded;
694 else
695 ret = FALSE;
700 if (ret)
702 if (pcbDecoded)
703 *pcbDecoded = decoded;
704 if (!pvStructInfo)
705 *pcbStructInfo = bytesNeeded;
706 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
707 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
709 DWORD i;
710 BYTE *nextData;
711 const BYTE *ptr;
712 struct GenericArray *array;
714 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
715 pvStructInfo = *(BYTE **)pvStructInfo;
716 array = (struct GenericArray *)pvStructInfo;
717 array->cItems = cItems;
718 if (startingPointer)
719 array->rgItems = startingPointer;
720 else
721 array->rgItems = (BYTE *)array +
722 sizeof(struct GenericArray);
723 nextData = array->rgItems +
724 array->cItems * arrayDesc->itemSize;
725 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
726 i < cItems && ptr - pbEncoded - 1 - lenBytes <
727 dataLen; i++)
729 DWORD itemDecoded;
731 if (arrayDesc->hasPointer)
732 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
733 + arrayDesc->pointerOffset) = nextData;
734 ret = arrayDesc->decodeFunc(ptr,
735 itemSizes[i].encodedLen,
736 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
737 array->rgItems + i * arrayDesc->itemSize,
738 &itemSizes[i].size, &itemDecoded);
739 if (ret)
741 nextData += itemSizes[i].size - arrayDesc->itemSize;
742 ptr += itemDecoded;
745 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
746 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
749 if (itemSizes != &itemSize)
750 CryptMemFree(itemSizes);
753 else
755 SetLastError(CRYPT_E_ASN1_BADTAG);
756 ret = FALSE;
758 return ret;
761 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
762 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
763 * to CRYPT_E_ASN1_CORRUPT.
764 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
765 * set!
767 static BOOL CRYPT_AsnDecodeDerBlob(const BYTE *pbEncoded, DWORD cbEncoded,
768 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
770 BOOL ret;
771 DWORD dataLen;
773 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
775 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
776 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
778 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
779 bytesNeeded += 1 + lenBytes + dataLen;
781 if (pcbDecoded)
782 *pcbDecoded = 1 + lenBytes + dataLen;
783 if (!pvStructInfo)
784 *pcbStructInfo = bytesNeeded;
785 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded)))
787 CRYPT_DER_BLOB *blob;
789 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
790 pvStructInfo = *(BYTE **)pvStructInfo;
791 blob = (CRYPT_DER_BLOB *)pvStructInfo;
792 blob->cbData = 1 + lenBytes + dataLen;
793 if (blob->cbData)
795 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
796 blob->pbData = (BYTE *)pbEncoded;
797 else
799 assert(blob->pbData);
800 memcpy(blob->pbData, pbEncoded, blob->cbData);
803 else
805 SetLastError(CRYPT_E_ASN1_CORRUPT);
806 ret = FALSE;
810 return ret;
813 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
814 static BOOL CRYPT_AsnDecodeBitsSwapBytes(const BYTE *pbEncoded,
815 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
816 DWORD *pcbDecoded)
818 BOOL ret;
820 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
821 pvStructInfo, *pcbStructInfo, pcbDecoded);
823 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
824 * place.
826 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
827 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
828 pcbDecoded);
829 if (ret && pvStructInfo)
831 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
833 if (blob->cbData)
835 DWORD i;
836 BYTE temp;
838 for (i = 0; i < blob->cbData / 2; i++)
840 temp = blob->pbData[i];
841 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
842 blob->pbData[blob->cbData - i - 1] = temp;
846 TRACE("returning %d (%08x)\n", ret, GetLastError());
847 return ret;
850 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
851 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
852 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
854 BOOL ret = TRUE;
856 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
857 pDecodePara, pvStructInfo, *pcbStructInfo);
859 __TRY
861 struct AsnDecodeSequenceItem items[] = {
862 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
863 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
864 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
865 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
866 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
867 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
868 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
869 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
870 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
871 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
874 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
875 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
876 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
877 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
878 pcbStructInfo, NULL, NULL);
880 __EXCEPT_PAGE_FAULT
882 SetLastError(STATUS_ACCESS_VIOLATION);
883 ret = FALSE;
885 __ENDTRY
887 TRACE("Returning %d (%08x)\n", ret, GetLastError());
888 return ret;
891 static BOOL CRYPT_AsnDecodeCertVersion(const BYTE *pbEncoded, DWORD cbEncoded,
892 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
894 BOOL ret;
895 DWORD dataLen;
897 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
899 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
901 ret = CRYPT_AsnDecodeIntInternal(pbEncoded + 1 + lenBytes, dataLen,
902 dwFlags, pvStructInfo, pcbStructInfo, NULL);
903 if (pcbDecoded)
904 *pcbDecoded = 1 + lenBytes + dataLen;
906 return ret;
909 static BOOL CRYPT_AsnDecodeValidity(const BYTE *pbEncoded, DWORD cbEncoded,
910 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
912 BOOL ret;
914 struct AsnDecodeSequenceItem items[] = {
915 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
916 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
917 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
918 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
921 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
922 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
923 pcbDecoded, NULL);
924 return ret;
927 static BOOL CRYPT_AsnDecodeCertExtensions(const BYTE *pbEncoded,
928 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
929 DWORD *pcbDecoded)
931 BOOL ret;
932 DWORD dataLen;
934 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
936 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
938 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded + 1 + lenBytes,
939 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
940 if (ret && pcbDecoded)
941 *pcbDecoded = 1 + lenBytes + dataLen;
943 return ret;
946 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
947 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
948 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
950 BOOL ret = TRUE;
951 struct AsnDecodeSequenceItem items[] = {
952 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
953 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
954 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
955 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
956 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
957 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
958 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
959 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
960 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
961 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
962 Issuer.pbData) },
963 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
964 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
965 FALSE, 0 },
966 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
967 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
968 Subject.pbData) },
969 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
970 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
971 FALSE, TRUE, offsetof(CERT_INFO,
972 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
973 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
974 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
975 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
976 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
977 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
978 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
979 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
980 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
981 offsetof(CERT_INFO, rgExtension), 0 },
984 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
985 pDecodePara, pvStructInfo, *pcbStructInfo);
987 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
988 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
989 NULL, NULL);
990 if (ret && pvStructInfo)
992 CERT_INFO *info;
994 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
995 info = *(CERT_INFO **)pvStructInfo;
996 else
997 info = (CERT_INFO *)pvStructInfo;
998 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
999 !info->Subject.cbData)
1001 SetLastError(CRYPT_E_ASN1_CORRUPT);
1002 /* Don't need to deallocate, because it should have failed on the
1003 * first pass (and no memory was allocated.)
1005 ret = FALSE;
1009 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1010 return ret;
1013 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
1014 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1015 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1017 BOOL ret = FALSE;
1019 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1020 pDecodePara, pvStructInfo, *pcbStructInfo);
1022 __TRY
1024 DWORD size = 0;
1026 /* Unless told not to, first try to decode it as a signed cert. */
1027 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1029 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
1031 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1032 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1033 (BYTE *)&signedCert, &size);
1034 if (ret)
1036 size = 0;
1037 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1038 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
1039 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
1040 pvStructInfo, pcbStructInfo);
1041 LocalFree(signedCert);
1044 /* Failing that, try it as an unsigned cert */
1045 if (!ret)
1047 size = 0;
1048 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1049 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
1050 pDecodePara, pvStructInfo, pcbStructInfo);
1053 __EXCEPT_PAGE_FAULT
1055 SetLastError(STATUS_ACCESS_VIOLATION);
1057 __ENDTRY
1059 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1060 return ret;
1063 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
1064 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1066 BOOL ret;
1067 struct AsnDecodeSequenceItem items[] = {
1068 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
1069 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
1070 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
1071 { 0, offsetof(CRL_ENTRY, RevocationDate),
1072 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
1073 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
1074 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1075 offsetof(CRL_ENTRY, rgExtension), 0 },
1077 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
1079 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
1080 *pcbStructInfo);
1082 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1083 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, pcbDecoded,
1084 entry ? entry->SerialNumber.pbData : NULL);
1085 if (ret && entry && !entry->SerialNumber.cbData)
1087 WARN("empty CRL entry serial number\n");
1088 SetLastError(CRYPT_E_ASN1_CORRUPT);
1089 ret = FALSE;
1091 return ret;
1094 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
1095 * been set prior to calling.
1097 static BOOL CRYPT_AsnDecodeCRLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
1098 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1100 BOOL ret;
1101 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1102 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
1103 offsetof(CRL_ENTRY, SerialNumber.pbData) };
1104 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
1106 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1107 pvStructInfo, *pcbStructInfo, pcbDecoded);
1109 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1110 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1111 entries ? entries->rgItems : NULL);
1112 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1113 return ret;
1116 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1117 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1118 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1120 struct AsnDecodeSequenceItem items[] = {
1121 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1122 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1123 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1124 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1125 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1126 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1127 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1128 Issuer.pbData) },
1129 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1130 sizeof(FILETIME), FALSE, FALSE, 0 },
1131 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1132 sizeof(FILETIME), TRUE, FALSE, 0 },
1133 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1134 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
1135 offsetof(CRL_INFO, rgCRLEntry), 0 },
1136 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1137 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1138 offsetof(CRL_INFO, rgExtension), 0 },
1140 BOOL ret = TRUE;
1142 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1143 pDecodePara, pvStructInfo, *pcbStructInfo);
1145 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1146 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
1147 NULL, NULL);
1149 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1150 return ret;
1153 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1154 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1155 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1157 BOOL ret = FALSE;
1159 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1160 pDecodePara, pvStructInfo, *pcbStructInfo);
1162 __TRY
1164 DWORD size = 0;
1166 /* Unless told not to, first try to decode it as a signed crl. */
1167 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1169 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1171 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1172 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1173 (BYTE *)&signedCrl, &size);
1174 if (ret)
1176 size = 0;
1177 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1178 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1179 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1180 pvStructInfo, pcbStructInfo);
1181 LocalFree(signedCrl);
1184 /* Failing that, try it as an unsigned crl */
1185 if (!ret)
1187 size = 0;
1188 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1189 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1190 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1193 __EXCEPT_PAGE_FAULT
1195 SetLastError(STATUS_ACCESS_VIOLATION);
1197 __ENDTRY
1199 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1200 return ret;
1203 static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded,
1204 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1206 BOOL ret = TRUE;
1207 DWORD dataLen;
1209 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1210 pvStructInfo, *pcbStructInfo);
1212 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1214 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1215 DWORD bytesNeeded = sizeof(LPSTR);
1217 if (dataLen)
1219 /* The largest possible string for the first two components
1220 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1222 char firstTwo[6];
1223 const BYTE *ptr;
1225 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1226 pbEncoded[1 + lenBytes] / 40,
1227 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1228 * 40);
1229 bytesNeeded += strlen(firstTwo) + 1;
1230 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1231 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1233 /* large enough for ".4000000" */
1234 char str[9];
1235 int val = 0;
1237 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1238 (*ptr & 0x80))
1240 val <<= 7;
1241 val |= *ptr & 0x7f;
1242 ptr++;
1244 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1245 (*ptr & 0x80))
1247 SetLastError(CRYPT_E_ASN1_CORRUPT);
1248 ret = FALSE;
1250 else
1252 val <<= 7;
1253 val |= *ptr++;
1254 snprintf(str, sizeof(str), ".%d", val);
1255 bytesNeeded += strlen(str);
1259 if (pcbDecoded)
1260 *pcbDecoded = 1 + lenBytes + dataLen;
1261 if (!pvStructInfo)
1262 *pcbStructInfo = bytesNeeded;
1263 else if (*pcbStructInfo < bytesNeeded)
1265 *pcbStructInfo = bytesNeeded;
1266 SetLastError(ERROR_MORE_DATA);
1267 ret = FALSE;
1269 else
1271 if (dataLen)
1273 const BYTE *ptr;
1274 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1276 *pszObjId = 0;
1277 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1278 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1279 40) * 40);
1280 pszObjId += strlen(pszObjId);
1281 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1282 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1284 int val = 0;
1286 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1287 (*ptr & 0x80))
1289 val <<= 7;
1290 val |= *ptr & 0x7f;
1291 ptr++;
1293 val <<= 7;
1294 val |= *ptr++;
1295 sprintf(pszObjId, ".%d", val);
1296 pszObjId += strlen(pszObjId);
1299 else
1300 *(LPSTR *)pvStructInfo = NULL;
1301 *pcbStructInfo = bytesNeeded;
1304 return ret;
1307 static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded,
1308 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1310 BOOL ret;
1312 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1313 pvStructInfo, *pcbStructInfo);
1315 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1316 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1317 pvStructInfo, pcbStructInfo, pcbDecoded);
1318 else
1320 SetLastError(CRYPT_E_ASN1_BADTAG);
1321 ret = FALSE;
1323 return ret;
1326 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1327 * ahead of time!
1329 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
1330 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1332 struct AsnDecodeSequenceItem items[] = {
1333 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1334 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1335 offsetof(CERT_EXTENSION, pszObjId), 0 },
1336 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1337 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1338 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1339 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1340 offsetof(CERT_EXTENSION, Value.pbData) },
1342 BOOL ret = TRUE;
1343 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1345 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1346 *pcbStructInfo);
1348 if (ext)
1349 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1350 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1351 pbEncoded, cbEncoded, dwFlags, NULL, ext, pcbStructInfo,
1352 pcbDecoded, ext ? ext->pszObjId : NULL);
1353 if (ext)
1354 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1355 debugstr_a(ext->pszObjId));
1356 TRACE("returning %d (%08x)\n", ret, GetLastError());
1357 return ret;
1360 static BOOL CRYPT_AsnDecodeExtensionsInternal(const BYTE *pbEncoded,
1361 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1362 DWORD *pcbDecoded)
1364 BOOL ret = TRUE;
1365 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1366 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1367 offsetof(CERT_EXTENSION, pszObjId) };
1368 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1370 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1371 pvStructInfo, *pcbStructInfo, pcbDecoded);
1373 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1374 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1375 exts ? exts->rgExtension : NULL);
1376 return ret;
1379 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1380 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1381 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1383 BOOL ret = TRUE;
1385 __TRY
1387 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
1388 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1389 if (ret && pvStructInfo)
1391 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1392 pcbStructInfo, *pcbStructInfo);
1393 if (ret)
1395 CERT_EXTENSIONS *exts;
1397 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1398 pvStructInfo = *(BYTE **)pvStructInfo;
1399 exts = (CERT_EXTENSIONS *)pvStructInfo;
1400 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1401 sizeof(CERT_EXTENSIONS));
1402 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
1403 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1404 pcbStructInfo, NULL);
1408 __EXCEPT_PAGE_FAULT
1410 SetLastError(STATUS_ACCESS_VIOLATION);
1411 ret = FALSE;
1413 __ENDTRY
1414 return ret;
1417 /* Warning: this assumes the address of value->Value.pbData is already set, in
1418 * order to avoid overwriting memory. (In some cases, it may change it, if it
1419 * doesn't copy anything to memory.) Be sure to set it correctly!
1421 static BOOL CRYPT_AsnDecodeNameValueInternal(const BYTE *pbEncoded,
1422 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1423 DWORD *pcbDecoded)
1425 BOOL ret = TRUE;
1426 DWORD dataLen;
1427 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1429 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1431 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1432 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1434 switch (pbEncoded[0])
1436 case ASN_OCTETSTRING:
1437 valueType = CERT_RDN_OCTET_STRING;
1438 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1439 bytesNeeded += dataLen;
1440 break;
1441 case ASN_NUMERICSTRING:
1442 valueType = CERT_RDN_NUMERIC_STRING;
1443 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1444 bytesNeeded += dataLen;
1445 break;
1446 case ASN_PRINTABLESTRING:
1447 valueType = CERT_RDN_PRINTABLE_STRING;
1448 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1449 bytesNeeded += dataLen;
1450 break;
1451 case ASN_IA5STRING:
1452 valueType = CERT_RDN_IA5_STRING;
1453 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1454 bytesNeeded += dataLen;
1455 break;
1456 case ASN_T61STRING:
1457 valueType = CERT_RDN_T61_STRING;
1458 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1459 bytesNeeded += dataLen;
1460 break;
1461 case ASN_VIDEOTEXSTRING:
1462 valueType = CERT_RDN_VIDEOTEX_STRING;
1463 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1464 bytesNeeded += dataLen;
1465 break;
1466 case ASN_GRAPHICSTRING:
1467 valueType = CERT_RDN_GRAPHIC_STRING;
1468 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1469 bytesNeeded += dataLen;
1470 break;
1471 case ASN_VISIBLESTRING:
1472 valueType = CERT_RDN_VISIBLE_STRING;
1473 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1474 bytesNeeded += dataLen;
1475 break;
1476 case ASN_GENERALSTRING:
1477 valueType = CERT_RDN_GENERAL_STRING;
1478 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1479 bytesNeeded += dataLen;
1480 break;
1481 case ASN_UNIVERSALSTRING:
1482 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1483 SetLastError(CRYPT_E_ASN1_BADTAG);
1484 return FALSE;
1485 case ASN_BMPSTRING:
1486 valueType = CERT_RDN_BMP_STRING;
1487 bytesNeeded += dataLen;
1488 break;
1489 case ASN_UTF8STRING:
1490 valueType = CERT_RDN_UTF8_STRING;
1491 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1492 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1493 break;
1494 default:
1495 SetLastError(CRYPT_E_ASN1_BADTAG);
1496 return FALSE;
1499 if (pcbDecoded)
1500 *pcbDecoded = 1 + lenBytes + dataLen;
1501 if (!value)
1502 *pcbStructInfo = bytesNeeded;
1503 else if (*pcbStructInfo < bytesNeeded)
1505 *pcbStructInfo = bytesNeeded;
1506 SetLastError(ERROR_MORE_DATA);
1507 ret = FALSE;
1509 else
1511 *pcbStructInfo = bytesNeeded;
1512 value->dwValueType = valueType;
1513 if (dataLen)
1515 DWORD i;
1517 assert(value->Value.pbData);
1518 switch (pbEncoded[0])
1520 case ASN_OCTETSTRING:
1521 case ASN_NUMERICSTRING:
1522 case ASN_PRINTABLESTRING:
1523 case ASN_IA5STRING:
1524 case ASN_T61STRING:
1525 case ASN_VIDEOTEXSTRING:
1526 case ASN_GRAPHICSTRING:
1527 case ASN_VISIBLESTRING:
1528 case ASN_GENERALSTRING:
1529 value->Value.cbData = dataLen;
1530 if (dataLen)
1532 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1533 memcpy(value->Value.pbData,
1534 pbEncoded + 1 + lenBytes, dataLen);
1535 else
1536 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1537 lenBytes;
1539 break;
1540 case ASN_BMPSTRING:
1542 LPWSTR str = (LPWSTR)value->Value.pbData;
1544 value->Value.cbData = dataLen;
1545 for (i = 0; i < dataLen / 2; i++)
1546 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1547 pbEncoded[1 + lenBytes + 2 * i + 1];
1548 break;
1550 case ASN_UTF8STRING:
1552 LPWSTR str = (LPWSTR)value->Value.pbData;
1554 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1555 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1556 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1557 break;
1561 else
1563 value->Value.cbData = 0;
1564 value->Value.pbData = NULL;
1568 return ret;
1571 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1572 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1573 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1575 BOOL ret = TRUE;
1577 __TRY
1579 ret = CRYPT_AsnDecodeNameValueInternal(pbEncoded, cbEncoded,
1580 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1581 if (ret && pvStructInfo)
1583 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1584 pcbStructInfo, *pcbStructInfo);
1585 if (ret)
1587 CERT_NAME_VALUE *value;
1589 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1590 pvStructInfo = *(BYTE **)pvStructInfo;
1591 value = (CERT_NAME_VALUE *)pvStructInfo;
1592 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1593 ret = CRYPT_AsnDecodeNameValueInternal( pbEncoded, cbEncoded,
1594 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1595 pcbStructInfo, NULL);
1599 __EXCEPT_PAGE_FAULT
1601 SetLastError(STATUS_ACCESS_VIOLATION);
1602 ret = FALSE;
1604 __ENDTRY
1605 return ret;
1608 static BOOL CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE *pbEncoded,
1609 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1610 DWORD *pcbDecoded)
1612 BOOL ret = TRUE;
1613 DWORD dataLen;
1614 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1616 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1618 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1619 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1621 switch (pbEncoded[0])
1623 case ASN_NUMERICSTRING:
1624 valueType = CERT_RDN_NUMERIC_STRING;
1625 bytesNeeded += dataLen * 2;
1626 break;
1627 case ASN_PRINTABLESTRING:
1628 valueType = CERT_RDN_PRINTABLE_STRING;
1629 bytesNeeded += dataLen * 2;
1630 break;
1631 case ASN_IA5STRING:
1632 valueType = CERT_RDN_IA5_STRING;
1633 bytesNeeded += dataLen * 2;
1634 break;
1635 case ASN_T61STRING:
1636 valueType = CERT_RDN_T61_STRING;
1637 bytesNeeded += dataLen * 2;
1638 break;
1639 case ASN_VIDEOTEXSTRING:
1640 valueType = CERT_RDN_VIDEOTEX_STRING;
1641 bytesNeeded += dataLen * 2;
1642 break;
1643 case ASN_GRAPHICSTRING:
1644 valueType = CERT_RDN_GRAPHIC_STRING;
1645 bytesNeeded += dataLen * 2;
1646 break;
1647 case ASN_VISIBLESTRING:
1648 valueType = CERT_RDN_VISIBLE_STRING;
1649 bytesNeeded += dataLen * 2;
1650 break;
1651 case ASN_GENERALSTRING:
1652 valueType = CERT_RDN_GENERAL_STRING;
1653 bytesNeeded += dataLen * 2;
1654 break;
1655 case ASN_UNIVERSALSTRING:
1656 valueType = CERT_RDN_UNIVERSAL_STRING;
1657 bytesNeeded += dataLen / 2;
1658 break;
1659 case ASN_BMPSTRING:
1660 valueType = CERT_RDN_BMP_STRING;
1661 bytesNeeded += dataLen;
1662 break;
1663 case ASN_UTF8STRING:
1664 valueType = CERT_RDN_UTF8_STRING;
1665 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1666 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1667 break;
1668 default:
1669 SetLastError(CRYPT_E_ASN1_BADTAG);
1670 return FALSE;
1673 if (pcbDecoded)
1674 *pcbDecoded = 1 + lenBytes + dataLen;
1675 if (!value)
1676 *pcbStructInfo = bytesNeeded;
1677 else if (*pcbStructInfo < bytesNeeded)
1679 *pcbStructInfo = bytesNeeded;
1680 SetLastError(ERROR_MORE_DATA);
1681 ret = FALSE;
1683 else
1685 *pcbStructInfo = bytesNeeded;
1686 value->dwValueType = valueType;
1687 if (dataLen)
1689 DWORD i;
1690 LPWSTR str = (LPWSTR)value->Value.pbData;
1692 assert(value->Value.pbData);
1693 switch (pbEncoded[0])
1695 case ASN_NUMERICSTRING:
1696 case ASN_PRINTABLESTRING:
1697 case ASN_IA5STRING:
1698 case ASN_T61STRING:
1699 case ASN_VIDEOTEXSTRING:
1700 case ASN_GRAPHICSTRING:
1701 case ASN_VISIBLESTRING:
1702 case ASN_GENERALSTRING:
1703 value->Value.cbData = dataLen * 2;
1704 for (i = 0; i < dataLen; i++)
1705 str[i] = pbEncoded[1 + lenBytes + i];
1706 break;
1707 case ASN_UNIVERSALSTRING:
1708 value->Value.cbData = dataLen / 2;
1709 for (i = 0; i < dataLen / 4; i++)
1710 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1711 | pbEncoded[1 + lenBytes + 2 * i + 3];
1712 break;
1713 case ASN_BMPSTRING:
1714 value->Value.cbData = dataLen;
1715 for (i = 0; i < dataLen / 2; i++)
1716 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1717 pbEncoded[1 + lenBytes + 2 * i + 1];
1718 break;
1719 case ASN_UTF8STRING:
1720 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1721 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1722 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1723 break;
1726 else
1728 value->Value.cbData = 0;
1729 value->Value.pbData = NULL;
1733 return ret;
1736 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1737 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1738 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1740 BOOL ret = TRUE;
1742 __TRY
1744 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded, cbEncoded,
1745 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1746 if (ret && pvStructInfo)
1748 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1749 pcbStructInfo, *pcbStructInfo);
1750 if (ret)
1752 CERT_NAME_VALUE *value;
1754 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1755 pvStructInfo = *(BYTE **)pvStructInfo;
1756 value = (CERT_NAME_VALUE *)pvStructInfo;
1757 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1758 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded,
1759 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1760 pcbStructInfo, NULL);
1764 __EXCEPT_PAGE_FAULT
1766 SetLastError(STATUS_ACCESS_VIOLATION);
1767 ret = FALSE;
1769 __ENDTRY
1770 return ret;
1773 static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
1774 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1776 BOOL ret;
1777 struct AsnDecodeSequenceItem items[] = {
1778 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1779 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1780 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1781 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1782 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1783 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1785 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1787 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1788 pvStructInfo, *pcbStructInfo);
1790 if (attr)
1791 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1792 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1793 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1794 attr ? attr->pszObjId : NULL);
1795 if (attr)
1797 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1798 debugstr_a(attr->pszObjId));
1799 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1801 TRACE("returning %d (%08x)\n", ret, GetLastError());
1802 return ret;
1805 static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1806 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1808 BOOL ret = TRUE;
1809 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1810 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1811 offsetof(CERT_RDN_ATTR, pszObjId) };
1812 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1814 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1815 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1816 rdn ? rdn->rgRDNAttr : NULL);
1817 return ret;
1820 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1821 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1822 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1824 BOOL ret = TRUE;
1826 __TRY
1828 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1829 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1830 offsetof(CERT_RDN, rgRDNAttr) };
1832 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1833 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1835 __EXCEPT_PAGE_FAULT
1837 SetLastError(STATUS_ACCESS_VIOLATION);
1838 ret = FALSE;
1840 __ENDTRY
1841 return ret;
1844 static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
1845 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1846 DWORD *pcbDecoded)
1848 BOOL ret;
1849 struct AsnDecodeSequenceItem items[] = {
1850 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1851 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1852 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1853 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1854 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1855 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1857 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1859 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1860 pvStructInfo, *pcbStructInfo);
1862 if (attr)
1863 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1864 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1865 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1866 attr ? attr->pszObjId : NULL);
1867 if (attr)
1869 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1870 debugstr_a(attr->pszObjId));
1871 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1873 TRACE("returning %d (%08x)\n", ret, GetLastError());
1874 return ret;
1877 static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1878 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1880 BOOL ret = TRUE;
1881 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1882 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1883 offsetof(CERT_RDN_ATTR, pszObjId) };
1884 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1886 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1887 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1888 rdn ? rdn->rgRDNAttr : NULL);
1889 return ret;
1892 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1893 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1894 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1896 BOOL ret = TRUE;
1898 __TRY
1900 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1901 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1902 offsetof(CERT_RDN, rgRDNAttr) };
1904 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1905 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1907 __EXCEPT_PAGE_FAULT
1909 SetLastError(STATUS_ACCESS_VIOLATION);
1910 ret = FALSE;
1912 __ENDTRY
1913 return ret;
1916 static BOOL CRYPT_FindEncodedLen(const BYTE *pbEncoded, DWORD cbEncoded,
1917 DWORD *pcbDecoded)
1919 BOOL ret = TRUE, done = FALSE;
1920 DWORD indefiniteNestingLevels = 0, decoded = 0;
1922 TRACE("(%p, %d)\n", pbEncoded, cbEncoded);
1924 do {
1925 DWORD dataLen;
1927 if (!cbEncoded)
1928 done = TRUE;
1929 else if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded,
1930 &dataLen)))
1932 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1934 if (dataLen == CMSG_INDEFINITE_LENGTH)
1936 indefiniteNestingLevels++;
1937 pbEncoded += 1 + lenBytes;
1938 cbEncoded -= 1 + lenBytes;
1939 decoded += 1 + lenBytes;
1940 TRACE("indefiniteNestingLevels = %d\n",
1941 indefiniteNestingLevels);
1943 else
1945 if (pbEncoded[0] == 0 && pbEncoded[1] == 0 &&
1946 indefiniteNestingLevels)
1948 indefiniteNestingLevels--;
1949 TRACE("indefiniteNestingLevels = %d\n",
1950 indefiniteNestingLevels);
1952 pbEncoded += 1 + lenBytes + dataLen;
1953 cbEncoded -= 1 + lenBytes + dataLen;
1954 decoded += 1 + lenBytes + dataLen;
1955 if (!indefiniteNestingLevels)
1956 done = TRUE;
1959 } while (ret && !done);
1960 /* If we haven't found all 0 TLVs, we haven't found the end */
1961 if (ret && indefiniteNestingLevels)
1963 SetLastError(CRYPT_E_ASN1_EOD);
1964 ret = FALSE;
1966 if (ret)
1967 *pcbDecoded = decoded;
1968 TRACE("returning %d (%d)\n", ret, ret ? *pcbDecoded : 0);
1969 return ret;
1972 static BOOL CRYPT_AsnDecodeCopyBytes(const BYTE *pbEncoded,
1973 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1974 DWORD *pcbDecoded)
1976 BOOL ret = TRUE;
1977 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB), encodedLen = 0;
1979 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1980 pvStructInfo, *pcbStructInfo);
1982 if ((ret = CRYPT_FindEncodedLen(pbEncoded, cbEncoded, &encodedLen)))
1984 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1985 bytesNeeded += encodedLen;
1986 if (!pvStructInfo)
1987 *pcbStructInfo = bytesNeeded;
1988 else if (*pcbStructInfo < bytesNeeded)
1990 SetLastError(ERROR_MORE_DATA);
1991 *pcbStructInfo = bytesNeeded;
1992 ret = FALSE;
1994 else
1996 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1998 *pcbStructInfo = bytesNeeded;
1999 blob->cbData = encodedLen;
2000 if (encodedLen)
2002 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2003 blob->pbData = (LPBYTE)pbEncoded;
2004 else
2006 assert(blob->pbData);
2007 memcpy(blob->pbData, pbEncoded, blob->cbData);
2010 else
2011 blob->pbData = NULL;
2013 if (pcbDecoded)
2014 *pcbDecoded = encodedLen;
2016 return ret;
2019 static BOOL CRYPT_DecodeDERArray(const BYTE *pbEncoded, DWORD cbEncoded,
2020 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2022 BOOL ret;
2023 struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytes,
2024 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
2025 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
2027 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2028 pvStructInfo, *pcbStructInfo, pcbDecoded);
2030 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2031 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2032 array ? array->rgItems : NULL);
2033 return ret;
2036 static BOOL CRYPT_AsnDecodeSMIMECapability(const BYTE *pbEncoded,
2037 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2038 DWORD *pcbDecoded)
2040 BOOL ret;
2041 struct AsnDecodeSequenceItem items[] = {
2042 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_SMIME_CAPABILITY, pszObjId),
2043 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2044 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId), 0 },
2045 { 0, offsetof(CRYPT_SMIME_CAPABILITY, Parameters),
2046 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2047 offsetof(CRYPT_SMIME_CAPABILITY, Parameters.pbData), 0 },
2049 PCRYPT_SMIME_CAPABILITY capability = (PCRYPT_SMIME_CAPABILITY)pvStructInfo;
2051 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2052 pvStructInfo, *pcbStructInfo);
2054 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2055 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2056 pcbDecoded, capability ? capability->pszObjId : NULL);
2057 TRACE("returning %d\n", ret);
2058 return ret;
2061 static BOOL CRYPT_AsnDecodeSMIMECapabilitiesInternal(const BYTE *pbEncoded,
2062 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2063 DWORD *pcbDecoded)
2065 struct AsnArrayDescriptor arrayDesc = { 0,
2066 CRYPT_AsnDecodeSMIMECapability, sizeof(CRYPT_SMIME_CAPABILITY), TRUE,
2067 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId) };
2068 PCRYPT_SMIME_CAPABILITIES capabilities =
2069 (PCRYPT_SMIME_CAPABILITIES)pvStructInfo;
2070 BOOL ret;
2072 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2073 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2074 capabilities ? capabilities->rgCapability : NULL);
2075 return ret;
2078 static BOOL WINAPI CRYPT_AsnDecodeSMIMECapabilities(DWORD dwCertEncodingType,
2079 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2080 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2082 BOOL ret = FALSE;
2084 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2085 pDecodePara, pvStructInfo, *pcbStructInfo);
2087 __TRY
2089 DWORD bytesNeeded;
2091 if (!cbEncoded)
2092 SetLastError(CRYPT_E_ASN1_EOD);
2093 else if (pbEncoded[0] != ASN_SEQUENCEOF)
2094 SetLastError(CRYPT_E_ASN1_CORRUPT);
2095 else if ((ret = CRYPT_AsnDecodeSMIMECapabilitiesInternal(pbEncoded,
2096 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2097 NULL)))
2099 if (!pvStructInfo)
2100 *pcbStructInfo = bytesNeeded;
2101 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2102 pvStructInfo, pcbStructInfo, bytesNeeded)))
2104 PCRYPT_SMIME_CAPABILITIES capabilities;
2106 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2107 pvStructInfo = *(BYTE **)pvStructInfo;
2108 capabilities = (PCRYPT_SMIME_CAPABILITIES)pvStructInfo;
2109 capabilities->rgCapability =
2110 (PCRYPT_SMIME_CAPABILITY)((BYTE *)pvStructInfo +
2111 sizeof(CRYPT_SMIME_CAPABILITIES));
2112 ret = CRYPT_AsnDecodeSMIMECapabilitiesInternal(pbEncoded,
2113 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2114 &bytesNeeded, NULL);
2118 __EXCEPT_PAGE_FAULT
2120 SetLastError(STATUS_ACCESS_VIOLATION);
2122 __ENDTRY
2123 TRACE("returning %d\n", ret);
2124 return ret;
2127 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
2128 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2129 DWORD *pcbDecoded)
2131 BOOL ret;
2132 struct AsnDecodeSequenceItem items[] = {
2133 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
2134 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2135 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
2136 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
2137 CRYPT_DecodeDERArray, sizeof(struct GenericArray), FALSE, TRUE,
2138 offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
2140 PCRYPT_ATTRIBUTE attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
2142 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2143 pvStructInfo, *pcbStructInfo);
2145 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2146 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2147 pcbDecoded, attr ? attr->pszObjId : NULL);
2148 TRACE("returning %d\n", ret);
2149 return ret;
2152 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
2153 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2154 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2156 BOOL ret = FALSE;
2158 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2159 pDecodePara, pvStructInfo, *pcbStructInfo);
2161 __TRY
2163 DWORD bytesNeeded;
2165 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2166 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
2167 if (ret)
2169 if (!pvStructInfo)
2170 *pcbStructInfo = bytesNeeded;
2171 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2172 pvStructInfo, pcbStructInfo, bytesNeeded)))
2174 PCRYPT_ATTRIBUTE attr;
2176 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2177 pvStructInfo = *(BYTE **)pvStructInfo;
2178 attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
2179 attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
2180 sizeof(CRYPT_ATTRIBUTE));
2181 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2182 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
2183 NULL);
2187 __EXCEPT_PAGE_FAULT
2189 SetLastError(STATUS_ACCESS_VIOLATION);
2191 __ENDTRY
2192 TRACE("returning %d\n", ret);
2193 return ret;
2196 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
2197 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2198 DWORD *pcbDecoded)
2200 struct AsnArrayDescriptor arrayDesc = { 0,
2201 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2202 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2203 PCRYPT_ATTRIBUTES attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
2204 BOOL ret;
2206 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2207 NULL, pvStructInfo, pcbStructInfo, pcbDecoded, attrs ? attrs->rgAttr :
2208 NULL);
2209 return ret;
2212 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
2213 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2214 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2216 BOOL ret = FALSE;
2218 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2219 pDecodePara, pvStructInfo, *pcbStructInfo);
2221 __TRY
2223 DWORD bytesNeeded;
2225 if (!cbEncoded)
2226 SetLastError(CRYPT_E_ASN1_EOD);
2227 else if (pbEncoded[0] != (ASN_CONSTRUCTOR | ASN_SETOF))
2228 SetLastError(CRYPT_E_ASN1_CORRUPT);
2229 else if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
2230 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2231 NULL)))
2233 if (!pvStructInfo)
2234 *pcbStructInfo = bytesNeeded;
2235 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2236 pvStructInfo, pcbStructInfo, bytesNeeded)))
2238 PCRYPT_ATTRIBUTES attrs;
2240 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2241 pvStructInfo = *(BYTE **)pvStructInfo;
2242 attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
2243 attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
2244 sizeof(CRYPT_ATTRIBUTES));
2245 ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
2246 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2247 &bytesNeeded, NULL);
2251 __EXCEPT_PAGE_FAULT
2253 SetLastError(STATUS_ACCESS_VIOLATION);
2255 __ENDTRY
2256 TRACE("returning %d\n", ret);
2257 return ret;
2260 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
2261 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2263 CRYPT_ALGORITHM_IDENTIFIER *algo =
2264 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
2265 BOOL ret = TRUE;
2266 struct AsnDecodeSequenceItem items[] = {
2267 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
2268 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2269 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
2270 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
2271 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2272 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
2275 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2276 pvStructInfo, *pcbStructInfo, pcbDecoded);
2278 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2279 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2280 pcbDecoded, algo ? algo->pszObjId : NULL);
2281 if (ret && pvStructInfo)
2283 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
2284 debugstr_a(algo->pszObjId));
2286 return ret;
2289 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
2290 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2291 DWORD *pcbDecoded)
2293 BOOL ret = TRUE;
2294 struct AsnDecodeSequenceItem items[] = {
2295 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
2296 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2297 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
2298 Algorithm.pszObjId) },
2299 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
2300 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2301 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
2303 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2305 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2306 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2307 pcbDecoded, info ? info->Algorithm.Parameters.pbData : NULL);
2308 return ret;
2311 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2312 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2313 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2315 BOOL ret = TRUE;
2317 __TRY
2319 DWORD bytesNeeded;
2321 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2322 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2324 if (!pvStructInfo)
2325 *pcbStructInfo = bytesNeeded;
2326 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2327 pvStructInfo, pcbStructInfo, bytesNeeded)))
2329 PCERT_PUBLIC_KEY_INFO info;
2331 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2332 pvStructInfo = *(BYTE **)pvStructInfo;
2333 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2334 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2335 sizeof(CERT_PUBLIC_KEY_INFO);
2336 ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2337 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2338 &bytesNeeded, NULL);
2342 __EXCEPT_PAGE_FAULT
2344 SetLastError(STATUS_ACCESS_VIOLATION);
2345 ret = FALSE;
2347 __ENDTRY
2348 return ret;
2351 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
2352 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2354 BOOL ret;
2356 if (cbEncoded < 3)
2358 SetLastError(CRYPT_E_ASN1_CORRUPT);
2359 return FALSE;
2361 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2363 SetLastError(CRYPT_E_ASN1_CORRUPT);
2364 return FALSE;
2366 if (pbEncoded[1] > 1)
2368 SetLastError(CRYPT_E_ASN1_CORRUPT);
2369 return FALSE;
2371 if (pcbDecoded)
2372 *pcbDecoded = 3;
2373 if (!pvStructInfo)
2375 *pcbStructInfo = sizeof(BOOL);
2376 ret = TRUE;
2378 else if (*pcbStructInfo < sizeof(BOOL))
2380 *pcbStructInfo = sizeof(BOOL);
2381 SetLastError(ERROR_MORE_DATA);
2382 ret = FALSE;
2384 else
2386 *pcbStructInfo = sizeof(BOOL);
2387 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2388 ret = TRUE;
2390 TRACE("returning %d (%08x)\n", ret, GetLastError());
2391 return ret;
2394 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2395 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2397 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
2398 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2399 BOOL ret;
2401 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2402 pvStructInfo, *pcbStructInfo);
2404 if (cbEncoded < 2)
2406 SetLastError(CRYPT_E_ASN1_CORRUPT);
2407 return FALSE;
2409 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2410 if (1 + lenBytes > cbEncoded)
2412 SetLastError(CRYPT_E_ASN1_CORRUPT);
2413 return FALSE;
2415 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2417 switch (pbEncoded[0] & ASN_TYPE_MASK)
2419 case 1: /* rfc822Name */
2420 case 2: /* dNSName */
2421 case 6: /* uniformResourceIdentifier */
2422 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
2423 break;
2424 case 4: /* directoryName */
2425 case 7: /* iPAddress */
2426 bytesNeeded += dataLen;
2427 break;
2428 case 8: /* registeredID */
2429 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
2430 &dataLen, NULL);
2431 if (ret)
2433 /* FIXME: ugly, shouldn't need to know internals of OID decode
2434 * function to use it.
2436 bytesNeeded += dataLen - sizeof(LPSTR);
2438 break;
2439 case 0: /* otherName */
2440 FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
2441 SetLastError(CRYPT_E_ASN1_BADTAG);
2442 ret = FALSE;
2443 break;
2444 case 3: /* x400Address, unimplemented */
2445 case 5: /* ediPartyName, unimplemented */
2446 TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
2447 SetLastError(CRYPT_E_ASN1_BADTAG);
2448 ret = FALSE;
2449 break;
2450 default:
2451 TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
2452 SetLastError(CRYPT_E_ASN1_CORRUPT);
2453 ret = FALSE;
2455 if (ret)
2457 if (pcbDecoded)
2458 *pcbDecoded = 1 + lenBytes + dataLen;
2459 if (!entry)
2460 *pcbStructInfo = bytesNeeded;
2461 else if (*pcbStructInfo < bytesNeeded)
2463 *pcbStructInfo = bytesNeeded;
2464 SetLastError(ERROR_MORE_DATA);
2465 ret = FALSE;
2467 else
2469 *pcbStructInfo = bytesNeeded;
2470 /* MS used values one greater than the asn1 ones.. sigh */
2471 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
2472 switch (pbEncoded[0] & ASN_TYPE_MASK)
2474 case 1: /* rfc822Name */
2475 case 2: /* dNSName */
2476 case 6: /* uniformResourceIdentifier */
2478 DWORD i;
2480 for (i = 0; i < dataLen; i++)
2481 entry->u.pwszURL[i] =
2482 (WCHAR)pbEncoded[1 + lenBytes + i];
2483 entry->u.pwszURL[i] = 0;
2484 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2485 debugstr_w(entry->u.pwszURL));
2486 break;
2488 case 4: /* directoryName */
2489 entry->dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
2490 /* The data are memory-equivalent with the IPAddress case,
2491 * fall-through
2493 case 7: /* iPAddress */
2494 /* The next data pointer is in the pwszURL spot, that is,
2495 * the first 4 bytes. Need to move it to the next spot.
2497 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2498 entry->u.IPAddress.cbData = dataLen;
2499 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2500 dataLen);
2501 break;
2502 case 8: /* registeredID */
2503 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
2504 &entry->u.pszRegisteredID, &dataLen, NULL);
2505 break;
2510 return ret;
2513 static BOOL CRYPT_AsnDecodeAltNameInternal(const BYTE *pbEncoded,
2514 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2515 DWORD *pcbDecoded)
2517 BOOL ret = TRUE;
2518 struct AsnArrayDescriptor arrayDesc = { 0,
2519 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2520 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2521 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
2523 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2524 pvStructInfo, *pcbStructInfo, pcbDecoded);
2526 if (info)
2527 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2528 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2529 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2530 info ? info->rgAltEntry : NULL);
2531 return ret;
2534 /* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */
2535 static BOOL CRYPT_AsnDecodeIntegerSwapBytes(const BYTE *pbEncoded,
2536 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2537 DWORD *pcbDecoded)
2539 BOOL ret;
2541 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
2542 pvStructInfo, *pcbStructInfo, pcbDecoded);
2544 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2545 * place.
2547 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
2548 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
2549 pcbDecoded);
2550 if (ret && pvStructInfo)
2552 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2554 if (blob->cbData)
2556 DWORD i;
2557 BYTE temp;
2559 for (i = 0; i < blob->cbData / 2; i++)
2561 temp = blob->pbData[i];
2562 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
2563 blob->pbData[blob->cbData - i - 1] = temp;
2567 TRACE("returning %d (%08x)\n", ret, GetLastError());
2568 return ret;
2571 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
2572 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2573 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2575 BOOL ret;
2577 __TRY
2579 struct AsnDecodeSequenceItem items[] = {
2580 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
2581 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2582 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
2583 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2584 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
2585 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
2586 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
2587 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
2588 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2589 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2590 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
2593 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2594 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2595 pcbStructInfo, NULL, NULL);
2597 __EXCEPT_PAGE_FAULT
2599 SetLastError(STATUS_ACCESS_VIOLATION);
2600 ret = FALSE;
2602 __ENDTRY
2603 return ret;
2606 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
2607 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2608 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2610 BOOL ret;
2612 __TRY
2614 struct AsnDecodeSequenceItem items[] = {
2615 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
2616 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2617 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
2618 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2619 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
2620 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
2621 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2622 AuthorityCertIssuer.rgAltEntry), 0 },
2623 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2624 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2625 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2626 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2627 AuthorityCertSerialNumber.pbData), 0 },
2630 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2631 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2632 pcbStructInfo, NULL, NULL);
2634 __EXCEPT_PAGE_FAULT
2636 SetLastError(STATUS_ACCESS_VIOLATION);
2637 ret = FALSE;
2639 __ENDTRY
2640 return ret;
2643 static BOOL CRYPT_AsnDecodePKCSContent(const BYTE *pbEncoded, DWORD cbEncoded,
2644 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2646 BOOL ret;
2647 DWORD dataLen;
2649 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2650 pvStructInfo, *pcbStructInfo, pcbDecoded);
2652 /* The caller has already checked the tag, no need to check it again.
2653 * Check the outer length is valid:
2655 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
2657 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2658 DWORD innerLen;
2660 pbEncoded += 1 + lenBytes;
2661 cbEncoded -= 1 + lenBytes;
2662 if (dataLen == CMSG_INDEFINITE_LENGTH)
2663 cbEncoded -= 2; /* space for 0 TLV */
2664 /* Check the inner length is valid: */
2665 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &innerLen)))
2667 DWORD decodedLen;
2669 ret = CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags,
2670 pvStructInfo, pcbStructInfo, &decodedLen);
2671 if (dataLen == CMSG_INDEFINITE_LENGTH)
2673 if (*(pbEncoded + decodedLen) != 0 ||
2674 *(pbEncoded + decodedLen + 1) != 0)
2676 TRACE("expected 0 TLV, got {%02x,%02x}\n",
2677 *(pbEncoded + decodedLen),
2678 *(pbEncoded + decodedLen + 1));
2679 SetLastError(CRYPT_E_ASN1_CORRUPT);
2680 ret = FALSE;
2682 else
2683 decodedLen += 2;
2685 if (ret && pcbDecoded)
2687 *pcbDecoded = 1 + lenBytes + decodedLen;
2688 TRACE("decoded %d bytes\n", *pcbDecoded);
2692 return ret;
2695 static BOOL CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE *pbEncoded,
2696 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2697 DWORD *pcbDecoded)
2699 CRYPT_CONTENT_INFO *info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2700 struct AsnDecodeSequenceItem items[] = {
2701 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
2702 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2703 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
2704 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
2705 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
2706 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
2707 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
2709 BOOL ret;
2711 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2712 pvStructInfo, *pcbStructInfo, pcbDecoded);
2714 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2715 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2716 pcbDecoded, info ? info->pszObjId : NULL);
2717 return ret;
2720 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
2721 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2722 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2724 BOOL ret = FALSE;
2726 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2727 pDecodePara, pvStructInfo, *pcbStructInfo);
2729 __TRY
2731 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, cbEncoded,
2732 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
2733 if (ret && pvStructInfo)
2735 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
2736 pcbStructInfo, *pcbStructInfo);
2737 if (ret)
2739 CRYPT_CONTENT_INFO *info;
2741 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2742 pvStructInfo = *(BYTE **)pvStructInfo;
2743 info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2744 info->pszObjId = (LPSTR)((BYTE *)info +
2745 sizeof(CRYPT_CONTENT_INFO));
2746 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded,
2747 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2748 pcbStructInfo, NULL);
2752 __EXCEPT_PAGE_FAULT
2754 SetLastError(STATUS_ACCESS_VIOLATION);
2756 __ENDTRY
2757 return ret;
2760 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
2761 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2762 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
2764 BOOL ret;
2765 struct AsnDecodeSequenceItem items[] = {
2766 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version),
2767 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2768 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
2769 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2770 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
2771 0 },
2772 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
2773 CRYPT_AsnDecodePKCSContentInfoInternal,
2774 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
2775 ContentInfo.pszObjId), 0 },
2776 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
2777 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
2778 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
2781 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2782 pbEncoded, cbEncoded, dwFlags, pDecodePara, digestedData, pcbDigestedData,
2783 NULL, NULL);
2784 return ret;
2787 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
2788 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2789 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2791 BOOL ret = TRUE;
2793 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2794 pDecodePara, pvStructInfo, *pcbStructInfo);
2796 __TRY
2798 DWORD bytesNeeded;
2800 if ((ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
2801 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2803 if (!pvStructInfo)
2804 *pcbStructInfo = bytesNeeded;
2805 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2806 pvStructInfo, pcbStructInfo, bytesNeeded)))
2808 CERT_ALT_NAME_INFO *name;
2810 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2811 pvStructInfo = *(BYTE **)pvStructInfo;
2812 name = (CERT_ALT_NAME_INFO *)pvStructInfo;
2813 name->rgAltEntry = (PCERT_ALT_NAME_ENTRY)
2814 ((BYTE *)pvStructInfo + sizeof(CERT_ALT_NAME_INFO));
2815 ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
2816 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2817 &bytesNeeded, NULL);
2821 __EXCEPT_PAGE_FAULT
2823 SetLastError(STATUS_ACCESS_VIOLATION);
2824 ret = FALSE;
2826 __ENDTRY
2827 return ret;
2830 struct PATH_LEN_CONSTRAINT
2832 BOOL fPathLenConstraint;
2833 DWORD dwPathLenConstraint;
2836 static BOOL CRYPT_AsnDecodePathLenConstraint(const BYTE *pbEncoded,
2837 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2838 DWORD *pcbDecoded)
2840 BOOL ret = TRUE;
2841 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT), size;
2843 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2844 pvStructInfo, *pcbStructInfo, pcbDecoded);
2846 if (!pvStructInfo)
2848 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, NULL,
2849 &size, pcbDecoded);
2850 *pcbStructInfo = bytesNeeded;
2852 else if (*pcbStructInfo < bytesNeeded)
2854 SetLastError(ERROR_MORE_DATA);
2855 *pcbStructInfo = bytesNeeded;
2856 ret = FALSE;
2858 else
2860 struct PATH_LEN_CONSTRAINT *constraint =
2861 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
2863 *pcbStructInfo = bytesNeeded;
2864 size = sizeof(constraint->dwPathLenConstraint);
2865 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
2866 &constraint->dwPathLenConstraint, &size, pcbDecoded);
2867 if (ret)
2868 constraint->fPathLenConstraint = TRUE;
2869 TRACE("got an int, dwPathLenConstraint is %d\n",
2870 constraint->dwPathLenConstraint);
2872 TRACE("returning %d (%08x)\n", ret, GetLastError());
2873 return ret;
2876 static BOOL CRYPT_AsnDecodeSubtreeConstraints(const BYTE *pbEncoded,
2877 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2878 DWORD *pcbDecoded)
2880 BOOL ret;
2881 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2882 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
2883 offsetof(CERT_NAME_BLOB, pbData) };
2884 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2886 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2887 pvStructInfo, *pcbStructInfo, pcbDecoded);
2889 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2890 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2891 entries ? entries->rgItems : NULL);
2892 TRACE("Returning %d (%08x)\n", ret, GetLastError());
2893 return ret;
2896 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
2897 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2898 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2900 BOOL ret;
2902 __TRY
2904 struct AsnDecodeSequenceItem items[] = {
2905 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
2906 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2907 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
2908 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2909 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2910 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2911 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2912 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
2913 sizeof(struct GenericArray), TRUE, TRUE,
2914 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
2917 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2918 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2919 pcbStructInfo, NULL, NULL);
2921 __EXCEPT_PAGE_FAULT
2923 SetLastError(STATUS_ACCESS_VIOLATION);
2924 ret = FALSE;
2926 __ENDTRY
2927 return ret;
2930 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
2931 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2932 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2934 BOOL ret;
2936 __TRY
2938 struct AsnDecodeSequenceItem items[] = {
2939 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
2940 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
2941 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
2942 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2943 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2946 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2947 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2948 pcbStructInfo, NULL, NULL);
2950 __EXCEPT_PAGE_FAULT
2952 SetLastError(STATUS_ACCESS_VIOLATION);
2953 ret = FALSE;
2955 __ENDTRY
2956 return ret;
2959 #define RSA1_MAGIC 0x31415352
2961 struct DECODED_RSA_PUB_KEY
2963 DWORD pubexp;
2964 CRYPT_INTEGER_BLOB modulus;
2967 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
2968 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2969 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2971 BOOL ret;
2973 __TRY
2975 struct AsnDecodeSequenceItem items[] = {
2976 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
2977 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2978 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
2979 0 },
2980 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
2981 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2983 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
2984 DWORD size = 0;
2986 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2987 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
2988 &size, NULL, NULL);
2989 if (ret)
2991 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2992 decodedKey->modulus.cbData;
2994 if (!pvStructInfo)
2996 *pcbStructInfo = bytesNeeded;
2997 ret = TRUE;
2999 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3000 pvStructInfo, pcbStructInfo, bytesNeeded)))
3002 BLOBHEADER *hdr;
3003 RSAPUBKEY *rsaPubKey;
3005 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3006 pvStructInfo = *(BYTE **)pvStructInfo;
3007 hdr = (BLOBHEADER *)pvStructInfo;
3008 hdr->bType = PUBLICKEYBLOB;
3009 hdr->bVersion = CUR_BLOB_VERSION;
3010 hdr->reserved = 0;
3011 hdr->aiKeyAlg = CALG_RSA_KEYX;
3012 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
3013 sizeof(BLOBHEADER));
3014 rsaPubKey->magic = RSA1_MAGIC;
3015 rsaPubKey->pubexp = decodedKey->pubexp;
3016 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
3017 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
3018 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
3019 decodedKey->modulus.cbData);
3021 LocalFree(decodedKey);
3024 __EXCEPT_PAGE_FAULT
3026 SetLastError(STATUS_ACCESS_VIOLATION);
3027 ret = FALSE;
3029 __ENDTRY
3030 return ret;
3033 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
3034 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3035 DWORD *pcbDecoded)
3037 BOOL ret;
3038 DWORD bytesNeeded, dataLen;
3040 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3041 pvStructInfo, *pcbStructInfo, pcbDecoded);
3043 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3045 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3047 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3048 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
3049 else
3050 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
3051 if (pcbDecoded)
3052 *pcbDecoded = 1 + lenBytes + dataLen;
3053 if (!pvStructInfo)
3054 *pcbStructInfo = bytesNeeded;
3055 else if (*pcbStructInfo < bytesNeeded)
3057 SetLastError(ERROR_MORE_DATA);
3058 *pcbStructInfo = bytesNeeded;
3059 ret = FALSE;
3061 else
3063 CRYPT_DATA_BLOB *blob;
3065 *pcbStructInfo = bytesNeeded;
3066 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
3067 blob->cbData = dataLen;
3068 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3069 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
3070 else
3072 assert(blob->pbData);
3073 if (blob->cbData)
3074 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
3075 blob->cbData);
3079 return ret;
3082 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
3083 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3084 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3086 BOOL ret;
3088 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3089 pDecodePara, pvStructInfo, *pcbStructInfo);
3091 __TRY
3093 DWORD bytesNeeded;
3095 if (!cbEncoded)
3097 SetLastError(CRYPT_E_ASN1_CORRUPT);
3098 ret = FALSE;
3100 else if (pbEncoded[0] != ASN_OCTETSTRING)
3102 SetLastError(CRYPT_E_ASN1_BADTAG);
3103 ret = FALSE;
3105 else if ((ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
3106 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3108 if (!pvStructInfo)
3109 *pcbStructInfo = bytesNeeded;
3110 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3111 pvStructInfo, pcbStructInfo, bytesNeeded)))
3113 CRYPT_DATA_BLOB *blob;
3115 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3116 pvStructInfo = *(BYTE **)pvStructInfo;
3117 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
3118 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
3119 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
3120 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3121 &bytesNeeded, NULL);
3125 __EXCEPT_PAGE_FAULT
3127 SetLastError(STATUS_ACCESS_VIOLATION);
3128 ret = FALSE;
3130 __ENDTRY
3131 return ret;
3134 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3135 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3137 BOOL ret;
3139 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
3140 pvStructInfo, *pcbStructInfo, pcbDecoded);
3142 if (pbEncoded[0] == ASN_BITSTRING)
3144 DWORD bytesNeeded, dataLen;
3145 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3147 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3149 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3150 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
3151 else
3152 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
3153 if (pcbDecoded)
3154 *pcbDecoded = 1 + lenBytes + dataLen;
3155 if (!pvStructInfo)
3156 *pcbStructInfo = bytesNeeded;
3157 else if (*pcbStructInfo < bytesNeeded)
3159 *pcbStructInfo = bytesNeeded;
3160 SetLastError(ERROR_MORE_DATA);
3161 ret = FALSE;
3163 else
3165 CRYPT_BIT_BLOB *blob;
3167 *pcbStructInfo = bytesNeeded;
3168 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
3169 blob->cbData = dataLen - 1;
3170 blob->cUnusedBits = *(pbEncoded + 1 + lenBytes);
3171 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3173 blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes;
3175 else
3177 assert(blob->pbData);
3178 if (blob->cbData)
3180 BYTE mask = 0xff << blob->cUnusedBits;
3182 memcpy(blob->pbData, pbEncoded + 2 + lenBytes,
3183 blob->cbData);
3184 blob->pbData[blob->cbData - 1] &= mask;
3190 else
3192 SetLastError(CRYPT_E_ASN1_BADTAG);
3193 ret = FALSE;
3195 TRACE("returning %d (%08x)\n", ret, GetLastError());
3196 return ret;
3199 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
3200 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3201 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3203 BOOL ret;
3205 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
3206 pDecodePara, pvStructInfo, pcbStructInfo);
3208 __TRY
3210 DWORD bytesNeeded;
3212 if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3213 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3215 if (!pvStructInfo)
3216 *pcbStructInfo = bytesNeeded;
3217 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3218 pvStructInfo, pcbStructInfo, bytesNeeded)))
3220 CRYPT_BIT_BLOB *blob;
3222 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3223 pvStructInfo = *(BYTE **)pvStructInfo;
3224 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
3225 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
3226 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3227 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3228 &bytesNeeded, NULL);
3232 __EXCEPT_PAGE_FAULT
3234 SetLastError(STATUS_ACCESS_VIOLATION);
3235 ret = FALSE;
3237 __ENDTRY
3238 TRACE("returning %d (%08x)\n", ret, GetLastError());
3239 return ret;
3242 /* Ignores tag. Only allows integers 4 bytes or smaller in size. */
3243 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3244 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3246 BOOL ret;
3247 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
3248 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
3249 DWORD size = sizeof(buf);
3251 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
3252 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded, 0, buf,
3253 &size, pcbDecoded);
3254 if (ret)
3256 if (!pvStructInfo)
3257 *pcbStructInfo = sizeof(int);
3258 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int))))
3260 int val, i;
3262 if (blob->pbData[blob->cbData - 1] & 0x80)
3264 /* initialize to a negative value to sign-extend */
3265 val = -1;
3267 else
3268 val = 0;
3269 for (i = 0; i < blob->cbData; i++)
3271 val <<= 8;
3272 val |= blob->pbData[blob->cbData - i - 1];
3274 memcpy(pvStructInfo, &val, sizeof(int));
3277 else if (GetLastError() == ERROR_MORE_DATA)
3278 SetLastError(CRYPT_E_ASN1_LARGE);
3279 return ret;
3282 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
3283 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3284 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3286 BOOL ret;
3288 __TRY
3290 DWORD bytesNeeded;
3292 if (!cbEncoded)
3294 SetLastError(CRYPT_E_ASN1_CORRUPT);
3295 ret = FALSE;
3297 else if (pbEncoded[0] != ASN_INTEGER)
3299 SetLastError(CRYPT_E_ASN1_BADTAG);
3300 ret = FALSE;
3302 else
3303 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3304 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3305 if (ret)
3307 if (!pvStructInfo)
3308 *pcbStructInfo = bytesNeeded;
3309 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3310 pvStructInfo, pcbStructInfo, bytesNeeded)))
3312 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3313 pvStructInfo = *(BYTE **)pvStructInfo;
3314 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3315 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3316 &bytesNeeded, NULL);
3320 __EXCEPT_PAGE_FAULT
3322 SetLastError(STATUS_ACCESS_VIOLATION);
3323 ret = FALSE;
3325 __ENDTRY
3326 return ret;
3329 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
3330 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3331 DWORD *pcbDecoded)
3333 BOOL ret;
3334 DWORD bytesNeeded, dataLen;
3336 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3338 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3340 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3341 if (pcbDecoded)
3342 *pcbDecoded = 1 + lenBytes + dataLen;
3343 if (!pvStructInfo)
3344 *pcbStructInfo = bytesNeeded;
3345 else if (*pcbStructInfo < bytesNeeded)
3347 *pcbStructInfo = bytesNeeded;
3348 SetLastError(ERROR_MORE_DATA);
3349 ret = FALSE;
3351 else
3353 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3355 *pcbStructInfo = bytesNeeded;
3356 blob->cbData = dataLen;
3357 assert(blob->pbData);
3358 if (blob->cbData)
3360 DWORD i;
3362 for (i = 0; i < blob->cbData; i++)
3364 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3365 dataLen - i - 1);
3370 return ret;
3373 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
3374 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3375 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3377 BOOL ret;
3379 __TRY
3381 DWORD bytesNeeded;
3383 if (pbEncoded[0] != ASN_INTEGER)
3385 SetLastError(CRYPT_E_ASN1_BADTAG);
3386 ret = FALSE;
3388 else
3389 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3390 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3391 if (ret)
3393 if (!pvStructInfo)
3394 *pcbStructInfo = bytesNeeded;
3395 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3396 pvStructInfo, pcbStructInfo, bytesNeeded)))
3398 CRYPT_INTEGER_BLOB *blob;
3400 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3401 pvStructInfo = *(BYTE **)pvStructInfo;
3402 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3403 blob->pbData = (BYTE *)pvStructInfo +
3404 sizeof(CRYPT_INTEGER_BLOB);
3405 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3406 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
3407 &bytesNeeded, NULL);
3411 __EXCEPT_PAGE_FAULT
3413 SetLastError(STATUS_ACCESS_VIOLATION);
3414 ret = FALSE;
3416 __ENDTRY
3417 return ret;
3420 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
3421 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3422 DWORD *pcbDecoded)
3424 BOOL ret;
3426 if (pbEncoded[0] == ASN_INTEGER)
3428 DWORD bytesNeeded, dataLen;
3430 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3432 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3434 if (pcbDecoded)
3435 *pcbDecoded = 1 + lenBytes + dataLen;
3436 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3437 if (!pvStructInfo)
3438 *pcbStructInfo = bytesNeeded;
3439 else if (*pcbStructInfo < bytesNeeded)
3441 *pcbStructInfo = bytesNeeded;
3442 SetLastError(ERROR_MORE_DATA);
3443 ret = FALSE;
3445 else
3447 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3449 *pcbStructInfo = bytesNeeded;
3450 blob->cbData = dataLen;
3451 assert(blob->pbData);
3452 /* remove leading zero byte if it exists */
3453 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
3455 blob->cbData--;
3456 blob->pbData++;
3458 if (blob->cbData)
3460 DWORD i;
3462 for (i = 0; i < blob->cbData; i++)
3464 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3465 dataLen - i - 1);
3471 else
3473 SetLastError(CRYPT_E_ASN1_BADTAG);
3474 ret = FALSE;
3476 return ret;
3479 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
3480 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3481 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3483 BOOL ret;
3485 __TRY
3487 DWORD bytesNeeded;
3489 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded,
3490 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3492 if (!pvStructInfo)
3493 *pcbStructInfo = bytesNeeded;
3494 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3495 pvStructInfo, pcbStructInfo, bytesNeeded)))
3497 CRYPT_INTEGER_BLOB *blob;
3499 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3500 pvStructInfo = *(BYTE **)pvStructInfo;
3501 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3502 blob->pbData = (BYTE *)pvStructInfo +
3503 sizeof(CRYPT_INTEGER_BLOB);
3504 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded,
3505 cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
3506 &bytesNeeded, NULL);
3510 __EXCEPT_PAGE_FAULT
3512 SetLastError(STATUS_ACCESS_VIOLATION);
3513 ret = FALSE;
3515 __ENDTRY
3516 return ret;
3519 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
3520 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3521 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3523 BOOL ret;
3525 if (!pvStructInfo)
3527 *pcbStructInfo = sizeof(int);
3528 return TRUE;
3530 __TRY
3532 if (pbEncoded[0] == ASN_ENUMERATED)
3534 unsigned int val = 0, i;
3536 if (cbEncoded <= 1)
3538 SetLastError(CRYPT_E_ASN1_EOD);
3539 ret = FALSE;
3541 else if (pbEncoded[1] == 0)
3543 SetLastError(CRYPT_E_ASN1_CORRUPT);
3544 ret = FALSE;
3546 else
3548 /* A little strange looking, but we have to accept a sign byte:
3549 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
3550 * assuming a small length is okay here, it has to be in short
3551 * form.
3553 if (pbEncoded[1] > sizeof(unsigned int) + 1)
3555 SetLastError(CRYPT_E_ASN1_LARGE);
3556 return FALSE;
3558 for (i = 0; i < pbEncoded[1]; i++)
3560 val <<= 8;
3561 val |= pbEncoded[2 + i];
3563 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3564 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
3566 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3567 pvStructInfo = *(BYTE **)pvStructInfo;
3568 memcpy(pvStructInfo, &val, sizeof(unsigned int));
3572 else
3574 SetLastError(CRYPT_E_ASN1_BADTAG);
3575 ret = FALSE;
3578 __EXCEPT_PAGE_FAULT
3580 SetLastError(STATUS_ACCESS_VIOLATION);
3581 ret = FALSE;
3583 __ENDTRY
3584 return ret;
3587 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
3588 * if it fails.
3590 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
3591 do { \
3592 BYTE i; \
3594 (word) = 0; \
3595 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
3597 if (!isdigit(*(pbEncoded))) \
3599 SetLastError(CRYPT_E_ASN1_CORRUPT); \
3600 ret = FALSE; \
3602 else \
3604 (word) *= 10; \
3605 (word) += *(pbEncoded)++ - '0'; \
3608 } while (0)
3610 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
3611 SYSTEMTIME *sysTime)
3613 BOOL ret = TRUE;
3615 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
3617 WORD hours, minutes = 0;
3618 BYTE sign = *pbEncoded++;
3620 len--;
3621 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
3622 if (ret && hours >= 24)
3624 SetLastError(CRYPT_E_ASN1_CORRUPT);
3625 ret = FALSE;
3627 else if (len >= 2)
3629 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
3630 if (ret && minutes >= 60)
3632 SetLastError(CRYPT_E_ASN1_CORRUPT);
3633 ret = FALSE;
3636 if (ret)
3638 if (sign == '+')
3640 sysTime->wHour += hours;
3641 sysTime->wMinute += minutes;
3643 else
3645 if (hours > sysTime->wHour)
3647 sysTime->wDay--;
3648 sysTime->wHour = 24 - (hours - sysTime->wHour);
3650 else
3651 sysTime->wHour -= hours;
3652 if (minutes > sysTime->wMinute)
3654 sysTime->wHour--;
3655 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
3657 else
3658 sysTime->wMinute -= minutes;
3662 return ret;
3665 #define MIN_ENCODED_TIME_LENGTH 10
3667 static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
3668 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3669 DWORD *pcbDecoded)
3671 BOOL ret = FALSE;
3673 if (pbEncoded[0] == ASN_UTCTIME)
3675 if (cbEncoded <= 1)
3676 SetLastError(CRYPT_E_ASN1_EOD);
3677 else if (pbEncoded[1] > 0x7f)
3679 /* long-form date strings really can't be valid */
3680 SetLastError(CRYPT_E_ASN1_CORRUPT);
3682 else
3684 SYSTEMTIME sysTime = { 0 };
3685 BYTE len = pbEncoded[1];
3687 if (len < MIN_ENCODED_TIME_LENGTH)
3688 SetLastError(CRYPT_E_ASN1_CORRUPT);
3689 else
3691 ret = TRUE;
3692 if (pcbDecoded)
3693 *pcbDecoded = 2 + len;
3694 pbEncoded += 2;
3695 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
3696 if (sysTime.wYear >= 50)
3697 sysTime.wYear += 1900;
3698 else
3699 sysTime.wYear += 2000;
3700 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3701 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3702 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3703 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
3704 if (ret && len > 0)
3706 if (len >= 2 && isdigit(*pbEncoded) &&
3707 isdigit(*(pbEncoded + 1)))
3708 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3709 sysTime.wSecond);
3710 else if (isdigit(*pbEncoded))
3711 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
3712 sysTime.wSecond);
3713 if (ret)
3714 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3715 &sysTime);
3717 if (ret)
3719 if (!pvStructInfo)
3720 *pcbStructInfo = sizeof(FILETIME);
3721 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
3722 sizeof(FILETIME))))
3723 ret = SystemTimeToFileTime(&sysTime,
3724 (FILETIME *)pvStructInfo);
3729 else
3730 SetLastError(CRYPT_E_ASN1_BADTAG);
3731 return ret;
3734 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
3735 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3736 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3738 BOOL ret = FALSE;
3740 __TRY
3742 DWORD bytesNeeded;
3744 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
3745 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3746 if (ret)
3748 if (!pvStructInfo)
3749 *pcbStructInfo = bytesNeeded;
3750 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
3751 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
3753 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3754 pvStructInfo = *(BYTE **)pvStructInfo;
3755 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
3756 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3757 &bytesNeeded, NULL);
3761 __EXCEPT_PAGE_FAULT
3763 SetLastError(STATUS_ACCESS_VIOLATION);
3765 __ENDTRY
3766 return ret;
3769 static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
3770 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3771 DWORD *pcbDecoded)
3773 BOOL ret = FALSE;
3775 if (pbEncoded[0] == ASN_GENERALTIME)
3777 if (cbEncoded <= 1)
3778 SetLastError(CRYPT_E_ASN1_EOD);
3779 else if (pbEncoded[1] > 0x7f)
3781 /* long-form date strings really can't be valid */
3782 SetLastError(CRYPT_E_ASN1_CORRUPT);
3784 else
3786 BYTE len = pbEncoded[1];
3788 if (len < MIN_ENCODED_TIME_LENGTH)
3789 SetLastError(CRYPT_E_ASN1_CORRUPT);
3790 else
3792 SYSTEMTIME sysTime = { 0 };
3794 ret = TRUE;
3795 if (pcbDecoded)
3796 *pcbDecoded = 2 + len;
3797 pbEncoded += 2;
3798 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
3799 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3800 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3801 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3802 if (ret && len > 0)
3804 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3805 sysTime.wMinute);
3806 if (ret && len > 0)
3807 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3808 sysTime.wSecond);
3809 if (ret && len > 0 && (*pbEncoded == '.' ||
3810 *pbEncoded == ','))
3812 BYTE digits;
3814 pbEncoded++;
3815 len--;
3816 /* workaround macro weirdness */
3817 digits = min(len, 3);
3818 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
3819 sysTime.wMilliseconds);
3821 if (ret)
3822 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3823 &sysTime);
3825 if (ret)
3827 if (!pvStructInfo)
3828 *pcbStructInfo = sizeof(FILETIME);
3829 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
3830 sizeof(FILETIME))))
3831 ret = SystemTimeToFileTime(&sysTime,
3832 (FILETIME *)pvStructInfo);
3837 else
3838 SetLastError(CRYPT_E_ASN1_BADTAG);
3839 return ret;
3842 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
3843 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3844 DWORD *pcbDecoded)
3846 BOOL ret;
3847 InternalDecodeFunc decode = NULL;
3849 if (pbEncoded[0] == ASN_UTCTIME)
3850 decode = CRYPT_AsnDecodeUtcTimeInternal;
3851 else if (pbEncoded[0] == ASN_GENERALTIME)
3852 decode = CRYPT_AsnDecodeGeneralizedTime;
3853 if (decode)
3854 ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
3855 pcbStructInfo, pcbDecoded);
3856 else
3858 SetLastError(CRYPT_E_ASN1_BADTAG);
3859 ret = FALSE;
3861 return ret;
3864 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
3865 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3866 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3868 BOOL ret;
3870 __TRY
3872 DWORD bytesNeeded;
3874 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
3875 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3876 if (ret)
3878 if (!pvStructInfo)
3879 *pcbStructInfo = bytesNeeded;
3880 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3881 pvStructInfo, pcbStructInfo, bytesNeeded)))
3883 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3884 pvStructInfo = *(BYTE **)pvStructInfo;
3885 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
3886 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3887 &bytesNeeded, NULL);
3891 __EXCEPT_PAGE_FAULT
3893 SetLastError(STATUS_ACCESS_VIOLATION);
3894 ret = FALSE;
3896 __ENDTRY
3897 return ret;
3900 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
3901 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3902 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3904 BOOL ret = TRUE;
3906 __TRY
3908 if (pbEncoded[0] == ASN_SEQUENCEOF)
3910 DWORD bytesNeeded, dataLen, remainingLen, cValue;
3912 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3914 BYTE lenBytes;
3915 const BYTE *ptr;
3917 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3918 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
3919 cValue = 0;
3920 ptr = pbEncoded + 1 + lenBytes;
3921 remainingLen = dataLen;
3922 while (ret && remainingLen)
3924 DWORD nextLen;
3926 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3927 if (ret)
3929 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3931 remainingLen -= 1 + nextLenBytes + nextLen;
3932 ptr += 1 + nextLenBytes + nextLen;
3933 bytesNeeded += sizeof(CRYPT_DER_BLOB);
3934 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3935 bytesNeeded += 1 + nextLenBytes + nextLen;
3936 cValue++;
3939 if (ret)
3941 CRYPT_SEQUENCE_OF_ANY *seq;
3942 BYTE *nextPtr;
3943 DWORD i;
3945 if (!pvStructInfo)
3946 *pcbStructInfo = bytesNeeded;
3947 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3948 pvStructInfo, pcbStructInfo, bytesNeeded)))
3950 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3951 pvStructInfo = *(BYTE **)pvStructInfo;
3952 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
3953 seq->cValue = cValue;
3954 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
3955 sizeof(*seq));
3956 nextPtr = (BYTE *)seq->rgValue +
3957 cValue * sizeof(CRYPT_DER_BLOB);
3958 ptr = pbEncoded + 1 + lenBytes;
3959 remainingLen = dataLen;
3960 i = 0;
3961 while (ret && remainingLen)
3963 DWORD nextLen;
3965 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3966 if (ret)
3968 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3970 seq->rgValue[i].cbData = 1 + nextLenBytes +
3971 nextLen;
3972 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3973 seq->rgValue[i].pbData = (BYTE *)ptr;
3974 else
3976 seq->rgValue[i].pbData = nextPtr;
3977 memcpy(nextPtr, ptr, 1 + nextLenBytes +
3978 nextLen);
3979 nextPtr += 1 + nextLenBytes + nextLen;
3981 remainingLen -= 1 + nextLenBytes + nextLen;
3982 ptr += 1 + nextLenBytes + nextLen;
3983 i++;
3990 else
3992 SetLastError(CRYPT_E_ASN1_BADTAG);
3993 ret = FALSE;
3996 __EXCEPT_PAGE_FAULT
3998 SetLastError(STATUS_ACCESS_VIOLATION);
3999 ret = FALSE;
4001 __ENDTRY
4002 return ret;
4005 static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded,
4006 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4007 DWORD *pcbDecoded)
4009 BOOL ret;
4011 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
4013 DWORD bytesNeeded, dataLen;
4015 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4017 struct AsnArrayDescriptor arrayDesc = {
4018 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
4019 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
4020 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
4021 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4022 DWORD nameLen;
4024 if (dataLen)
4026 ret = CRYPT_AsnDecodeArray(&arrayDesc,
4027 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
4028 0, NULL, NULL, &nameLen, NULL, NULL);
4029 /* The CERT_ALT_NAME_INFO's size is included by CRYPT_AsnDecodeArray
4030 * as the sizeof(struct GenericArray), so don't include it in the
4031 * total bytes needed.
4033 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen -
4034 sizeof(CERT_ALT_NAME_INFO);
4036 else
4037 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
4038 if (pcbDecoded)
4039 *pcbDecoded = 1 + lenBytes + dataLen;
4040 if (!pvStructInfo)
4041 *pcbStructInfo = bytesNeeded;
4042 else if (*pcbStructInfo < bytesNeeded)
4044 *pcbStructInfo = bytesNeeded;
4045 SetLastError(ERROR_MORE_DATA);
4046 ret = FALSE;
4048 else
4050 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
4052 *pcbStructInfo = bytesNeeded;
4053 if (dataLen)
4055 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
4056 ret = CRYPT_AsnDecodeArray(&arrayDesc,
4057 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
4058 0, NULL, &name->u.FullName, &nameLen, NULL,
4059 name->u.FullName.rgAltEntry);
4061 else
4062 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
4066 else
4068 SetLastError(CRYPT_E_ASN1_BADTAG);
4069 ret = FALSE;
4071 return ret;
4074 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
4075 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4077 struct AsnDecodeSequenceItem items[] = {
4078 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
4079 DistPointName), CRYPT_AsnDecodeDistPointName,
4080 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
4081 DistPointName.u.FullName.rgAltEntry), 0 },
4082 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
4083 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
4084 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
4085 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
4086 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
4087 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
4089 BOOL ret;
4091 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4092 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4093 pcbDecoded, NULL);
4094 return ret;
4097 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
4098 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4099 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4101 BOOL ret;
4103 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4104 pDecodePara, pvStructInfo, *pcbStructInfo);
4106 __TRY
4108 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
4109 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
4110 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
4112 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4113 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
4115 __EXCEPT_PAGE_FAULT
4117 SetLastError(STATUS_ACCESS_VIOLATION);
4118 ret = FALSE;
4120 __ENDTRY
4121 return ret;
4124 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
4125 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4126 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4128 BOOL ret;
4130 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4131 pDecodePara, pvStructInfo, *pcbStructInfo);
4133 __TRY
4135 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
4136 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
4138 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4139 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
4141 __EXCEPT_PAGE_FAULT
4143 SetLastError(STATUS_ACCESS_VIOLATION);
4144 ret = FALSE;
4146 __ENDTRY
4147 return ret;
4150 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
4151 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4152 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4154 BOOL ret;
4156 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4157 pDecodePara, pvStructInfo, *pcbStructInfo);
4159 __TRY
4161 struct AsnDecodeSequenceItem items[] = {
4162 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
4163 DistPointName), CRYPT_AsnDecodeDistPointName,
4164 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
4165 offsetof(CRL_ISSUING_DIST_POINT,
4166 DistPointName.u.FullName.rgAltEntry), 0 },
4167 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
4168 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4169 FALSE, 0 },
4170 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
4171 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4172 FALSE, 0 },
4173 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
4174 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
4175 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
4176 OnlySomeReasonFlags.pbData), 0 },
4177 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
4178 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
4181 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4182 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
4183 pcbStructInfo, NULL, NULL);
4185 __EXCEPT_PAGE_FAULT
4187 SetLastError(STATUS_ACCESS_VIOLATION);
4188 ret = FALSE;
4190 __ENDTRY
4191 return ret;
4194 static BOOL CRYPT_AsnDecodeMaximum(const BYTE *pbEncoded,
4195 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4196 DWORD *pcbDecoded)
4198 BOOL ret = FALSE;
4200 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4201 pvStructInfo, *pcbStructInfo, pcbDecoded);
4203 if (!cbEncoded)
4205 SetLastError(CRYPT_E_ASN1_EOD);
4206 return FALSE;
4208 if (pbEncoded[0] != (ASN_CONTEXT | 1))
4210 SetLastError(CRYPT_E_ASN1_BADTAG);
4211 return FALSE;
4213 /* The BOOL is implicit: if the integer is present, then it's TRUE */
4214 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
4215 pvStructInfo ? (BYTE *)pvStructInfo + sizeof(BOOL) : NULL, pcbStructInfo,
4216 pcbDecoded);
4217 if (ret && pvStructInfo)
4218 *(BOOL *)pvStructInfo = TRUE;
4219 TRACE("returning %d\n", ret);
4220 return ret;
4223 static BOOL CRYPT_AsnDecodeSubtree(const BYTE *pbEncoded,
4224 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4225 DWORD *pcbDecoded)
4227 BOOL ret;
4228 struct AsnDecodeSequenceItem items[] = {
4229 { 0, offsetof(CERT_GENERAL_SUBTREE, Base),
4230 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE, TRUE,
4231 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL), 0 },
4232 { ASN_CONTEXT | 0, offsetof(CERT_GENERAL_SUBTREE, dwMinimum),
4233 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
4234 { ASN_CONTEXT | 1, offsetof(CERT_GENERAL_SUBTREE, fMaximum),
4235 CRYPT_AsnDecodeMaximum, sizeof(BOOL) + sizeof(DWORD), TRUE, FALSE, 0,
4236 0 },
4238 CERT_GENERAL_SUBTREE *subtree = (CERT_GENERAL_SUBTREE *)pvStructInfo;
4240 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4241 pvStructInfo, *pcbStructInfo, pcbDecoded);
4243 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4244 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4245 pcbDecoded, subtree ? (BYTE *)subtree->Base.u.pwszURL : NULL);
4246 if (pcbDecoded)
4248 TRACE("%d\n", *pcbDecoded);
4249 if (*pcbDecoded < cbEncoded)
4250 TRACE("%02x %02x\n", *(pbEncoded + *pcbDecoded),
4251 *(pbEncoded + *pcbDecoded + 1));
4253 TRACE("returning %d\n", ret);
4254 return ret;
4257 static BOOL CRYPT_AsnDecodeSubtreeArray(const BYTE *pbEncoded,
4258 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4259 DWORD *pcbDecoded)
4261 BOOL ret = TRUE;
4262 struct AsnArrayDescriptor arrayDesc = { 0,
4263 CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
4264 offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
4265 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
4267 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4268 pvStructInfo, *pcbStructInfo, pcbDecoded);
4270 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4271 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
4272 array ? array->rgItems : NULL);
4273 return ret;
4277 static BOOL WINAPI CRYPT_AsnDecodeNameConstraints(DWORD dwCertEncodingType,
4278 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4279 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4281 BOOL ret = FALSE;
4283 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4284 pDecodePara, pvStructInfo, *pcbStructInfo);
4286 __TRY
4288 struct AsnDecodeSequenceItem items[] = {
4289 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
4290 offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
4291 CRYPT_AsnDecodeSubtreeArray, sizeof(struct GenericArray), TRUE, TRUE,
4292 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree), 0 },
4293 { ASN_CONTEXT | ASN_CONSTRUCTOR | 1,
4294 offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
4295 CRYPT_AsnDecodeSubtreeArray, sizeof(struct GenericArray), TRUE, TRUE,
4296 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree), 0 },
4299 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4300 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
4301 pcbStructInfo, NULL, NULL);
4303 __EXCEPT_PAGE_FAULT
4305 SetLastError(STATUS_ACCESS_VIOLATION);
4307 __ENDTRY
4308 return ret;
4311 static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded,
4312 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4313 DWORD *pcbDecoded)
4315 BOOL ret;
4316 struct AsnDecodeSequenceItem items[] = {
4317 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
4318 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
4319 Issuer.pbData) },
4320 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
4321 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
4322 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
4324 CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
4325 (CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
4327 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4328 pvStructInfo, *pcbStructInfo, pcbDecoded);
4330 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4331 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4332 pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL);
4333 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
4335 SetLastError(CRYPT_E_ASN1_CORRUPT);
4336 ret = FALSE;
4338 TRACE("returning %d\n", ret);
4339 return ret;
4342 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
4343 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4344 DWORD *pcbDecoded)
4346 CMSG_SIGNER_INFO *info = (CMSG_SIGNER_INFO *)pvStructInfo;
4347 struct AsnDecodeSequenceItem items[] = {
4348 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
4349 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4350 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
4351 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
4352 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
4353 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
4354 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4355 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
4356 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4357 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
4358 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4359 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
4360 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
4361 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4362 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
4363 HashEncryptionAlgorithm.pszObjId), 0 },
4364 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
4365 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
4366 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
4367 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4368 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
4369 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4370 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
4372 BOOL ret;
4374 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4375 pvStructInfo, *pcbStructInfo);
4377 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4378 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4379 pcbDecoded, info ? info->Issuer.pbData : NULL);
4380 return ret;
4383 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
4384 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4385 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4387 BOOL ret = FALSE;
4389 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4390 pDecodePara, pvStructInfo, *pcbStructInfo);
4392 __TRY
4394 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
4395 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
4396 if (ret && pvStructInfo)
4398 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
4399 pcbStructInfo, *pcbStructInfo);
4400 if (ret)
4402 CMSG_SIGNER_INFO *info;
4404 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4405 pvStructInfo = *(BYTE **)pvStructInfo;
4406 info = (CMSG_SIGNER_INFO *)pvStructInfo;
4407 info->Issuer.pbData = ((BYTE *)info +
4408 sizeof(CMSG_SIGNER_INFO));
4409 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
4410 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4411 pcbStructInfo, NULL);
4415 __EXCEPT_PAGE_FAULT
4417 SetLastError(STATUS_ACCESS_VIOLATION);
4419 __ENDTRY
4420 TRACE("returning %d\n", ret);
4421 return ret;
4424 static BOOL CRYPT_AsnDecodeCMSSignerId(const BYTE *pbEncoded,
4425 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4426 DWORD *pcbDecoded)
4428 CERT_ID *id = (CERT_ID *)pvStructInfo;
4429 BOOL ret = FALSE;
4431 if (*pbEncoded == ASN_SEQUENCEOF)
4433 ret = CRYPT_AsnDecodeIssuerSerialNumber(pbEncoded, cbEncoded, dwFlags,
4434 id ? &id->u.IssuerSerialNumber : NULL, pcbStructInfo, pcbDecoded);
4435 if (ret)
4437 if (id)
4438 id->dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
4439 if (*pcbStructInfo > sizeof(CERT_ISSUER_SERIAL_NUMBER))
4440 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
4441 sizeof(CERT_ISSUER_SERIAL_NUMBER);
4442 else
4443 *pcbStructInfo = sizeof(CERT_ID);
4446 else if (*pbEncoded == (ASN_CONTEXT | 0))
4448 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded, dwFlags,
4449 id ? &id->u.KeyId : NULL, pcbStructInfo, pcbDecoded);
4450 if (ret)
4452 if (id)
4453 id->dwIdChoice = CERT_ID_KEY_IDENTIFIER;
4454 if (*pcbStructInfo > sizeof(CRYPT_DATA_BLOB))
4455 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
4456 sizeof(CRYPT_DATA_BLOB);
4457 else
4458 *pcbStructInfo = sizeof(CERT_ID);
4461 else
4462 SetLastError(CRYPT_E_ASN1_BADTAG);
4463 return ret;
4466 static BOOL CRYPT_AsnDecodeCMSSignerInfoInternal(const BYTE *pbEncoded,
4467 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4468 DWORD *pcbDecoded)
4470 CMSG_CMS_SIGNER_INFO *info = (CMSG_CMS_SIGNER_INFO *)pvStructInfo;
4471 struct AsnDecodeSequenceItem items[] = {
4472 { ASN_INTEGER, offsetof(CMSG_CMS_SIGNER_INFO, dwVersion),
4473 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4474 { 0, offsetof(CMSG_CMS_SIGNER_INFO, SignerId),
4475 CRYPT_AsnDecodeCMSSignerId, sizeof(CERT_ID), FALSE, TRUE,
4476 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData), 0 },
4477 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm),
4478 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4479 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
4480 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4481 offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs),
4482 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4483 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
4484 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashEncryptionAlgorithm),
4485 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4486 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO,
4487 HashEncryptionAlgorithm.pszObjId), 0 },
4488 { ASN_OCTETSTRING, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash),
4489 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
4490 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash.pbData), 0 },
4491 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4492 offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs),
4493 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4494 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
4496 BOOL ret;
4498 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4499 pvStructInfo, *pcbStructInfo);
4501 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4502 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4503 pcbDecoded, info ? info->SignerId.u.KeyId.pbData : NULL);
4504 return ret;
4507 static BOOL WINAPI CRYPT_AsnDecodeCMSSignerInfo(DWORD dwCertEncodingType,
4508 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4509 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4511 BOOL ret = FALSE;
4513 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4514 pDecodePara, pvStructInfo, *pcbStructInfo);
4516 __TRY
4518 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded, cbEncoded,
4519 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
4520 if (ret && pvStructInfo)
4522 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
4523 pcbStructInfo, *pcbStructInfo);
4524 if (ret)
4526 CMSG_CMS_SIGNER_INFO *info;
4528 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4529 pvStructInfo = *(BYTE **)pvStructInfo;
4530 info = (CMSG_CMS_SIGNER_INFO *)pvStructInfo;
4531 info->SignerId.u.KeyId.pbData = ((BYTE *)info +
4532 sizeof(CMSG_CMS_SIGNER_INFO));
4533 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded,
4534 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4535 pcbStructInfo, NULL);
4539 __EXCEPT_PAGE_FAULT
4541 SetLastError(STATUS_ACCESS_VIOLATION);
4543 __ENDTRY
4544 TRACE("returning %d\n", ret);
4545 return ret;
4548 static BOOL CRYPT_DecodeSignerArray(const BYTE *pbEncoded, DWORD cbEncoded,
4549 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4551 BOOL ret;
4552 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
4553 CRYPT_AsnDecodeCMSSignerInfoInternal, sizeof(CMSG_CMS_SIGNER_INFO), TRUE,
4554 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData) };
4555 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
4557 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4558 pvStructInfo, *pcbStructInfo, pcbDecoded);
4560 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4561 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
4562 array ? array->rgItems : NULL);
4563 return ret;
4566 BOOL CRYPT_AsnDecodeCMSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
4567 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
4568 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
4570 BOOL ret = FALSE;
4571 struct AsnDecodeSequenceItem items[] = {
4572 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version),
4573 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4574 /* Placeholder for the hash algorithms - redundant with those in the
4575 * signers, so just ignore them.
4577 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
4578 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
4579 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
4580 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
4581 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4582 offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
4583 CRYPT_DecodeDERArray, sizeof(struct GenericArray), TRUE, TRUE,
4584 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
4585 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4586 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_DecodeDERArray,
4587 sizeof(struct GenericArray), TRUE, TRUE,
4588 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
4589 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
4590 CRYPT_DecodeSignerArray, sizeof(struct GenericArray), TRUE, TRUE,
4591 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
4594 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4595 pDecodePara, signedInfo, *pcbSignedInfo);
4597 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4598 pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo,
4599 NULL, NULL);
4600 TRACE("returning %d\n", ret);
4601 return ret;
4604 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
4605 LPCSTR lpszStructType)
4607 CryptDecodeObjectExFunc decodeFunc = NULL;
4609 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
4610 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
4612 SetLastError(ERROR_FILE_NOT_FOUND);
4613 return NULL;
4615 if (!HIWORD(lpszStructType))
4617 switch (LOWORD(lpszStructType))
4619 case LOWORD(X509_CERT):
4620 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
4621 break;
4622 case LOWORD(X509_CERT_TO_BE_SIGNED):
4623 decodeFunc = CRYPT_AsnDecodeCert;
4624 break;
4625 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
4626 decodeFunc = CRYPT_AsnDecodeCRL;
4627 break;
4628 case LOWORD(X509_EXTENSIONS):
4629 decodeFunc = CRYPT_AsnDecodeExtensions;
4630 break;
4631 case LOWORD(X509_NAME_VALUE):
4632 decodeFunc = CRYPT_AsnDecodeNameValue;
4633 break;
4634 case LOWORD(X509_NAME):
4635 decodeFunc = CRYPT_AsnDecodeName;
4636 break;
4637 case LOWORD(X509_PUBLIC_KEY_INFO):
4638 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
4639 break;
4640 case LOWORD(X509_AUTHORITY_KEY_ID):
4641 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4642 break;
4643 case LOWORD(X509_ALTERNATE_NAME):
4644 decodeFunc = CRYPT_AsnDecodeAltName;
4645 break;
4646 case LOWORD(X509_BASIC_CONSTRAINTS):
4647 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4648 break;
4649 case LOWORD(X509_BASIC_CONSTRAINTS2):
4650 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4651 break;
4652 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
4653 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
4654 break;
4655 case LOWORD(X509_UNICODE_NAME):
4656 decodeFunc = CRYPT_AsnDecodeUnicodeName;
4657 break;
4658 case LOWORD(PKCS_ATTRIBUTE):
4659 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
4660 break;
4661 case LOWORD(X509_UNICODE_NAME_VALUE):
4662 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
4663 break;
4664 case LOWORD(X509_OCTET_STRING):
4665 decodeFunc = CRYPT_AsnDecodeOctets;
4666 break;
4667 case LOWORD(X509_BITS):
4668 case LOWORD(X509_KEY_USAGE):
4669 decodeFunc = CRYPT_AsnDecodeBits;
4670 break;
4671 case LOWORD(X509_INTEGER):
4672 decodeFunc = CRYPT_AsnDecodeInt;
4673 break;
4674 case LOWORD(X509_MULTI_BYTE_INTEGER):
4675 decodeFunc = CRYPT_AsnDecodeInteger;
4676 break;
4677 case LOWORD(X509_MULTI_BYTE_UINT):
4678 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
4679 break;
4680 case LOWORD(X509_ENUMERATED):
4681 decodeFunc = CRYPT_AsnDecodeEnumerated;
4682 break;
4683 case LOWORD(X509_CHOICE_OF_TIME):
4684 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
4685 break;
4686 case LOWORD(X509_AUTHORITY_KEY_ID2):
4687 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4688 break;
4689 case LOWORD(PKCS_CONTENT_INFO):
4690 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
4691 break;
4692 case LOWORD(X509_SEQUENCE_OF_ANY):
4693 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
4694 break;
4695 case LOWORD(PKCS_UTC_TIME):
4696 decodeFunc = CRYPT_AsnDecodeUtcTime;
4697 break;
4698 case LOWORD(X509_CRL_DIST_POINTS):
4699 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4700 break;
4701 case LOWORD(X509_ENHANCED_KEY_USAGE):
4702 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4703 break;
4704 case LOWORD(PKCS_SMIME_CAPABILITIES):
4705 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
4706 break;
4707 case LOWORD(PKCS_ATTRIBUTES):
4708 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
4709 break;
4710 case LOWORD(X509_ISSUING_DIST_POINT):
4711 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4712 break;
4713 case LOWORD(X509_NAME_CONSTRAINTS):
4714 decodeFunc = CRYPT_AsnDecodeNameConstraints;
4715 break;
4716 case LOWORD(PKCS7_SIGNER_INFO):
4717 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
4718 break;
4719 case LOWORD(CMS_SIGNER_INFO):
4720 decodeFunc = CRYPT_AsnDecodeCMSSignerInfo;
4721 break;
4724 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4725 decodeFunc = CRYPT_AsnDecodeExtensions;
4726 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4727 decodeFunc = CRYPT_AsnDecodeUtcTime;
4728 else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
4729 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
4730 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4731 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4732 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4733 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4734 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4735 decodeFunc = CRYPT_AsnDecodeEnumerated;
4736 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4737 decodeFunc = CRYPT_AsnDecodeBits;
4738 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4739 decodeFunc = CRYPT_AsnDecodeOctets;
4740 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4741 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4742 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4743 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4744 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4745 decodeFunc = CRYPT_AsnDecodeAltName;
4746 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4747 decodeFunc = CRYPT_AsnDecodeAltName;
4748 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4749 decodeFunc = CRYPT_AsnDecodeAltName;
4750 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4751 decodeFunc = CRYPT_AsnDecodeAltName;
4752 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4753 decodeFunc = CRYPT_AsnDecodeAltName;
4754 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4755 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4756 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4757 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4758 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4759 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4760 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
4761 decodeFunc = CRYPT_AsnDecodeNameConstraints;
4762 return decodeFunc;
4765 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
4766 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4768 static HCRYPTOIDFUNCSET set = NULL;
4769 CryptDecodeObjectFunc decodeFunc = NULL;
4771 if (!set)
4772 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
4773 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4774 (void **)&decodeFunc, hFunc);
4775 return decodeFunc;
4778 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
4779 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4781 static HCRYPTOIDFUNCSET set = NULL;
4782 CryptDecodeObjectExFunc decodeFunc = NULL;
4784 if (!set)
4785 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
4786 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4787 (void **)&decodeFunc, hFunc);
4788 return decodeFunc;
4791 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4792 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
4793 DWORD *pcbStructInfo)
4795 BOOL ret = FALSE;
4796 CryptDecodeObjectFunc pCryptDecodeObject = NULL;
4797 CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
4798 HCRYPTOIDFUNCADDR hFunc = NULL;
4800 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
4801 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
4802 pvStructInfo, pcbStructInfo);
4804 if (!pvStructInfo && !pcbStructInfo)
4806 SetLastError(ERROR_INVALID_PARAMETER);
4807 return FALSE;
4809 if (!cbEncoded)
4811 SetLastError(CRYPT_E_ASN1_EOD);
4812 return FALSE;
4814 if (cbEncoded > MAX_ENCODED_LEN)
4816 SetLastError(CRYPT_E_ASN1_LARGE);
4817 return FALSE;
4820 if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
4821 lpszStructType)))
4823 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4824 debugstr_a(lpszStructType));
4825 pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
4826 lpszStructType, &hFunc);
4827 if (!pCryptDecodeObject)
4828 pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
4829 lpszStructType, &hFunc);
4831 if (pCryptDecodeObject)
4832 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4833 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4834 else if (pCryptDecodeObjectEx)
4835 ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
4836 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
4837 pvStructInfo, pcbStructInfo);
4838 if (hFunc)
4839 CryptFreeOIDFunctionAddress(hFunc, 0);
4840 TRACE_(crypt)("returning %d\n", ret);
4841 return ret;
4844 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4845 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4846 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4848 BOOL ret = FALSE;
4849 CryptDecodeObjectExFunc decodeFunc;
4850 HCRYPTOIDFUNCADDR hFunc = NULL;
4852 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
4853 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
4854 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4856 if (!pvStructInfo && !pcbStructInfo)
4858 SetLastError(ERROR_INVALID_PARAMETER);
4859 return FALSE;
4861 if (!cbEncoded)
4863 SetLastError(CRYPT_E_ASN1_EOD);
4864 return FALSE;
4866 if (cbEncoded > MAX_ENCODED_LEN)
4868 SetLastError(CRYPT_E_ASN1_LARGE);
4869 return FALSE;
4872 SetLastError(NOERROR);
4873 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
4874 *(BYTE **)pvStructInfo = NULL;
4875 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
4876 if (!decodeFunc)
4878 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4879 debugstr_a(lpszStructType));
4880 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
4881 &hFunc);
4883 if (decodeFunc)
4884 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
4885 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4886 else
4888 CryptDecodeObjectFunc pCryptDecodeObject =
4889 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
4891 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
4892 * directly, as that could cause an infinite loop.
4894 if (pCryptDecodeObject)
4896 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4898 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4899 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
4900 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4901 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
4902 ret = pCryptDecodeObject(dwCertEncodingType,
4903 lpszStructType, pbEncoded, cbEncoded, dwFlags,
4904 *(BYTE **)pvStructInfo, pcbStructInfo);
4906 else
4907 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4908 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4911 if (hFunc)
4912 CryptFreeOIDFunctionAddress(hFunc, 0);
4913 TRACE_(crypt)("returning %d\n", ret);
4914 return ret;