push 88671f85dcf7a7cd89c63d6e9f34ad6b6ad2ae64
[wine/hacks.git] / dlls / crypt32 / decode.c
blob47b0ba6515e5a3d6509354f4ec40d4c35b2a082a
1 /*
2 * Copyright 2005-2007 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 * This file implements ASN.1 DER decoding of a limited set of types.
19 * It isn't a full ASN.1 implementation. Microsoft implements BER
20 * encoding of many of the basic types in msasn1.dll, but that interface isn't
21 * implemented, so I implement them here.
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 return ret;
237 static void CRYPT_FreeSpace(PCRYPT_DECODE_PARA pDecodePara, LPVOID pv)
239 if (pDecodePara && pDecodePara->pfnFree)
240 pDecodePara->pfnFree(pv);
241 else
242 LocalFree(pv);
245 /* Helper function to check *pcbStructInfo and set it to the required size.
246 * Assumes pvStructInfo is not NULL.
248 static BOOL CRYPT_DecodeCheckSpace(DWORD *pcbStructInfo, DWORD bytesNeeded)
250 BOOL ret;
252 if (*pcbStructInfo < bytesNeeded)
254 *pcbStructInfo = bytesNeeded;
255 SetLastError(ERROR_MORE_DATA);
256 ret = FALSE;
258 else
260 *pcbStructInfo = bytesNeeded;
261 ret = TRUE;
263 return ret;
266 /* tag:
267 * The expected tag of the item. If tag is 0, decodeFunc is called
268 * regardless of the tag value seen.
269 * offset:
270 * A sequence is decoded into a struct. The offset member is the
271 * offset of this item within that struct.
272 * decodeFunc:
273 * The decoder function to use. If this is NULL, then the member isn't
274 * decoded, but minSize space is reserved for it.
275 * minSize:
276 * The minimum amount of space occupied after decoding. You must set this.
277 * optional:
278 * If true, and the tag doesn't match the expected tag for this item,
279 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
280 * filled with 0 for this member.
281 * hasPointer, pointerOffset:
282 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
283 * the offset within the struct of the data pointer (or to the
284 * first data pointer, if more than one exist).
285 * size:
286 * Used by CRYPT_AsnDecodeSequence, not for your use.
288 struct AsnDecodeSequenceItem
290 BYTE tag;
291 DWORD offset;
292 InternalDecodeFunc decodeFunc;
293 DWORD minSize;
294 BOOL optional;
295 BOOL hasPointer;
296 DWORD pointerOffset;
297 DWORD size;
300 /* Decodes the items in a sequence, where the items are described in items,
301 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
302 * pvStructInfo. nextData is a pointer to the memory location at which the
303 * first decoded item with a dynamic pointer should point.
304 * Upon decoding, *cbDecoded is the total number of bytes decoded.
305 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
307 static BOOL CRYPT_AsnDecodeSequenceItems(struct AsnDecodeSequenceItem items[],
308 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
309 void *pvStructInfo, BYTE *nextData, DWORD *cbDecoded)
311 BOOL ret;
312 DWORD i, decoded = 0;
313 const BYTE *ptr = pbEncoded;
315 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
316 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
318 for (i = 0, ret = TRUE; ret && i < cItem; i++)
320 if (cbEncoded - (ptr - pbEncoded) != 0)
322 DWORD itemLen;
324 if ((ret = CRYPT_GetLengthIndefinite(ptr,
325 cbEncoded - (ptr - pbEncoded), &itemLen)))
327 BYTE itemLenBytes = GET_LEN_BYTES(ptr[1]);
329 if (ptr[0] == items[i].tag || !items[i].tag)
331 DWORD itemEncodedLen;
333 if (itemLen == CMSG_INDEFINITE_LENGTH)
334 itemEncodedLen = cbEncoded - (ptr - pbEncoded);
335 else
336 itemEncodedLen = 1 + itemLenBytes + itemLen;
337 if (nextData && pvStructInfo && items[i].hasPointer)
339 TRACE("Setting next pointer to %p\n",
340 nextData);
341 *(BYTE **)((BYTE *)pvStructInfo +
342 items[i].pointerOffset) = nextData;
344 if (items[i].decodeFunc)
346 DWORD itemDecoded;
348 if (pvStructInfo)
349 TRACE("decoding item %d\n", i);
350 else
351 TRACE("sizing item %d\n", i);
352 ret = items[i].decodeFunc(ptr, itemEncodedLen,
353 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
354 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
355 : NULL, &items[i].size, &itemDecoded);
356 if (ret)
358 /* Account for alignment padding */
359 if (items[i].size % sizeof(DWORD_PTR))
360 items[i].size += sizeof(DWORD_PTR) -
361 items[i].size % sizeof(DWORD_PTR);
362 TRACE("item %d size: %d\n", i, items[i].size);
363 if (nextData && items[i].hasPointer &&
364 items[i].size > items[i].minSize)
365 nextData += items[i].size - items[i].minSize;
366 if (itemDecoded > itemEncodedLen)
368 WARN("decoded length %d exceeds encoded %d\n",
369 itemDecoded, itemEncodedLen);
370 SetLastError(CRYPT_E_ASN1_CORRUPT);
371 ret = FALSE;
373 else
375 if (itemLen == CMSG_INDEFINITE_LENGTH)
377 if (itemDecoded > itemEncodedLen - 2 ||
378 *(ptr + itemDecoded) != 0 ||
379 *(ptr + itemDecoded + 1) != 0)
381 TRACE("expected 0 TLV\n");
382 SetLastError(CRYPT_E_ASN1_CORRUPT);
383 ret = FALSE;
385 else
386 itemDecoded += 2;
388 if (ret)
390 ptr += itemDecoded;
391 decoded += itemDecoded;
392 TRACE("item %d: decoded %d bytes\n", i,
393 itemDecoded);
397 else if (items[i].optional &&
398 GetLastError() == CRYPT_E_ASN1_BADTAG)
400 TRACE("skipping optional item %d\n", i);
401 items[i].size = items[i].minSize;
402 SetLastError(NOERROR);
403 ret = TRUE;
405 else
406 TRACE("item %d failed: %08x\n", i,
407 GetLastError());
409 else if (itemLen == CMSG_INDEFINITE_LENGTH)
411 ERR("can't use indefinite length encoding without a decoder\n");
412 SetLastError(CRYPT_E_ASN1_CORRUPT);
413 ret = FALSE;
415 else
417 TRACE("item %d: decoded %d bytes\n", i, itemEncodedLen);
418 ptr += itemEncodedLen;
419 decoded += itemEncodedLen;
420 items[i].size = items[i].minSize;
423 else if (items[i].optional)
425 TRACE("skipping optional item %d\n", i);
426 items[i].size = items[i].minSize;
428 else
430 TRACE("item %d: tag %02x doesn't match expected %02x\n",
431 i, ptr[0], items[i].tag);
432 SetLastError(CRYPT_E_ASN1_BADTAG);
433 ret = FALSE;
437 else if (items[i].optional)
439 TRACE("missing optional item %d, skipping\n", i);
440 items[i].size = items[i].minSize;
442 else
444 TRACE("not enough bytes for item %d, failing\n", i);
445 SetLastError(CRYPT_E_ASN1_CORRUPT);
446 ret = FALSE;
449 if (cbDecoded)
450 *cbDecoded = decoded;
451 TRACE("returning %d\n", ret);
452 return ret;
455 /* This decodes an arbitrary sequence into a contiguous block of memory
456 * (basically, a struct.) Each element being decoded is described by a struct
457 * AsnDecodeSequenceItem, see above.
458 * startingPointer is an optional pointer to the first place where dynamic
459 * data will be stored. If you know the starting offset, you may pass it
460 * here. Otherwise, pass NULL, and one will be inferred from the items.
462 static BOOL CRYPT_AsnDecodeSequence(struct AsnDecodeSequenceItem items[],
463 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
464 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
465 DWORD *pcbDecoded, void *startingPointer)
467 BOOL ret;
469 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
470 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
471 startingPointer);
473 if (pbEncoded[0] == ASN_SEQUENCE)
475 DWORD dataLen;
477 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
479 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
480 const BYTE *ptr = pbEncoded + 1 + lenBytes;
481 BOOL indefinite = FALSE;
483 cbEncoded -= 1 + lenBytes;
484 if (dataLen == CMSG_INDEFINITE_LENGTH)
486 dataLen = cbEncoded;
487 indefinite = TRUE;
489 else if (cbEncoded < dataLen)
491 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
492 cbEncoded);
493 SetLastError(CRYPT_E_ASN1_CORRUPT);
494 ret = FALSE;
496 if (ret)
498 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
499 ptr, dataLen, dwFlags, NULL, NULL, &cbDecoded);
500 if (ret && dataLen == CMSG_INDEFINITE_LENGTH)
502 if (cbDecoded > cbEncoded - 2)
504 /* Not enough space for 0 TLV */
505 SetLastError(CRYPT_E_ASN1_CORRUPT);
506 ret = FALSE;
508 else if (*(ptr + cbDecoded) != 0 ||
509 *(ptr + cbDecoded + 1) != 0)
511 TRACE("expected 0 TLV\n");
512 SetLastError(CRYPT_E_ASN1_CORRUPT);
513 ret = FALSE;
515 else
516 cbDecoded += 2;
519 if (ret && !indefinite && cbDecoded != dataLen)
521 TRACE("expected %d decoded, got %d, failing\n", dataLen,
522 cbDecoded);
523 SetLastError(CRYPT_E_ASN1_CORRUPT);
524 ret = FALSE;
526 if (ret)
528 DWORD i, bytesNeeded = 0, structSize = 0;
530 for (i = 0; i < cItem; i++)
532 bytesNeeded += items[i].size;
533 structSize += items[i].minSize;
535 if (pcbDecoded)
536 *pcbDecoded = 1 + lenBytes + cbDecoded;
537 if (!pvStructInfo)
538 *pcbStructInfo = bytesNeeded;
539 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
540 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
542 BYTE *nextData;
544 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
545 pvStructInfo = *(BYTE **)pvStructInfo;
546 if (startingPointer)
547 nextData = (BYTE *)startingPointer;
548 else
549 nextData = (BYTE *)pvStructInfo + structSize;
550 memset(pvStructInfo, 0, structSize);
551 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
552 ptr, dataLen, dwFlags, pvStructInfo, nextData,
553 &cbDecoded);
554 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
555 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
560 else
562 SetLastError(CRYPT_E_ASN1_BADTAG);
563 ret = FALSE;
565 TRACE("returning %d (%08x)\n", ret, GetLastError());
566 return ret;
569 /* tag:
570 * The expected tag of the entire encoded array (usually a variant
571 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
572 * regardless of the tag seen.
573 * decodeFunc:
574 * used to decode each item in the array
575 * itemSize:
576 * is the minimum size of each decoded item
577 * hasPointer:
578 * indicates whether each item has a dynamic pointer
579 * pointerOffset:
580 * indicates the offset within itemSize at which the pointer exists
582 struct AsnArrayDescriptor
584 BYTE tag;
585 InternalDecodeFunc decodeFunc;
586 DWORD itemSize;
587 BOOL hasPointer;
588 DWORD pointerOffset;
591 struct AsnArrayItemSize
593 DWORD encodedLen;
594 DWORD size;
597 /* Decodes an array of like types into a struct GenericArray.
598 * The layout and decoding of the array are described by a struct
599 * AsnArrayDescriptor.
601 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
602 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
603 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
604 DWORD *pcbDecoded, void *startingPointer)
606 BOOL ret = TRUE;
608 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
609 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
610 startingPointer);
612 if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
614 DWORD dataLen;
616 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
618 DWORD bytesNeeded, cItems = 0, decoded;
619 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
620 /* There can be arbitrarily many items, but there is often only one.
622 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
624 decoded = 1 + lenBytes;
625 bytesNeeded = sizeof(struct GenericArray);
626 if (dataLen)
628 const BYTE *ptr;
629 BOOL doneDecoding = FALSE;
631 for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
633 if (dataLen == CMSG_INDEFINITE_LENGTH)
635 if (ptr[0] == 0)
637 doneDecoding = TRUE;
638 if (ptr[1] != 0)
640 SetLastError(CRYPT_E_ASN1_CORRUPT);
641 ret = FALSE;
643 else
644 decoded += 2;
647 else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
648 doneDecoding = TRUE;
649 if (!doneDecoding)
651 DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
653 /* Each item decoded may not tolerate extraneous bytes,
654 * so get the length of the next element if known.
656 if ((ret = CRYPT_GetLengthIndefinite(ptr,
657 cbEncoded - (ptr - pbEncoded), &itemDataLen)))
659 if (itemDataLen == CMSG_INDEFINITE_LENGTH)
660 itemEncoded = cbEncoded - (ptr - pbEncoded);
661 else
662 itemEncoded = 1 + GET_LEN_BYTES(ptr[1]) +
663 itemDataLen;
665 if (ret)
666 ret = arrayDesc->decodeFunc(ptr, itemEncoded,
667 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size,
668 &itemDecoded);
669 if (ret)
671 cItems++;
672 if (itemSizes != &itemSize)
673 itemSizes = CryptMemRealloc(itemSizes,
674 cItems * sizeof(struct AsnArrayItemSize));
675 else if (cItems > 1)
677 itemSizes =
678 CryptMemAlloc(
679 cItems * sizeof(struct AsnArrayItemSize));
680 if (itemSizes)
681 memcpy(itemSizes, &itemSize,
682 sizeof(itemSize));
684 if (itemSizes)
686 decoded += itemDecoded;
687 itemSizes[cItems - 1].encodedLen = itemEncoded;
688 itemSizes[cItems - 1].size = size;
689 bytesNeeded += size;
690 ptr += itemEncoded;
692 else
693 ret = FALSE;
698 if (ret)
700 if (pcbDecoded)
701 *pcbDecoded = decoded;
702 if (!pvStructInfo)
703 *pcbStructInfo = bytesNeeded;
704 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
705 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
707 DWORD i;
708 BYTE *nextData;
709 const BYTE *ptr;
710 struct GenericArray *array;
712 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
713 pvStructInfo = *(BYTE **)pvStructInfo;
714 array = (struct GenericArray *)pvStructInfo;
715 array->cItems = cItems;
716 if (startingPointer)
717 array->rgItems = startingPointer;
718 else
719 array->rgItems = (BYTE *)array +
720 sizeof(struct GenericArray);
721 nextData = array->rgItems +
722 array->cItems * arrayDesc->itemSize;
723 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
724 i < cItems && ptr - pbEncoded - 1 - lenBytes <
725 dataLen; i++)
727 DWORD itemDecoded;
729 if (arrayDesc->hasPointer)
730 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
731 + arrayDesc->pointerOffset) = nextData;
732 ret = arrayDesc->decodeFunc(ptr,
733 itemSizes[i].encodedLen,
734 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
735 array->rgItems + i * arrayDesc->itemSize,
736 &itemSizes[i].size, &itemDecoded);
737 if (ret)
739 nextData += itemSizes[i].size - arrayDesc->itemSize;
740 ptr += itemDecoded;
743 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
744 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
747 if (itemSizes != &itemSize)
748 CryptMemFree(itemSizes);
751 else
753 SetLastError(CRYPT_E_ASN1_BADTAG);
754 ret = FALSE;
756 return ret;
759 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
760 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
761 * to CRYPT_E_ASN1_CORRUPT.
762 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
763 * set!
765 static BOOL CRYPT_AsnDecodeDerBlob(const BYTE *pbEncoded, DWORD cbEncoded,
766 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
768 BOOL ret;
769 DWORD dataLen;
771 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
773 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
774 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
776 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
777 bytesNeeded += 1 + lenBytes + dataLen;
779 if (pcbDecoded)
780 *pcbDecoded = 1 + lenBytes + dataLen;
781 if (!pvStructInfo)
782 *pcbStructInfo = bytesNeeded;
783 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded)))
785 CRYPT_DER_BLOB *blob;
787 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
788 pvStructInfo = *(BYTE **)pvStructInfo;
789 blob = (CRYPT_DER_BLOB *)pvStructInfo;
790 blob->cbData = 1 + lenBytes + dataLen;
791 if (blob->cbData)
793 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
794 blob->pbData = (BYTE *)pbEncoded;
795 else
797 assert(blob->pbData);
798 memcpy(blob->pbData, pbEncoded, blob->cbData);
801 else
803 SetLastError(CRYPT_E_ASN1_CORRUPT);
804 ret = FALSE;
808 return ret;
811 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
812 static BOOL CRYPT_AsnDecodeBitsSwapBytes(const BYTE *pbEncoded,
813 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
814 DWORD *pcbDecoded)
816 BOOL ret;
818 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
819 pvStructInfo, *pcbStructInfo, pcbDecoded);
821 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
822 * place.
824 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
825 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
826 pcbDecoded);
827 if (ret && pvStructInfo)
829 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
831 if (blob->cbData)
833 DWORD i;
834 BYTE temp;
836 for (i = 0; i < blob->cbData / 2; i++)
838 temp = blob->pbData[i];
839 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
840 blob->pbData[blob->cbData - i - 1] = temp;
844 TRACE("returning %d (%08x)\n", ret, GetLastError());
845 return ret;
848 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
849 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
850 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
852 BOOL ret = TRUE;
854 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
855 pDecodePara, pvStructInfo, *pcbStructInfo);
857 __TRY
859 struct AsnDecodeSequenceItem items[] = {
860 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
861 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
862 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
863 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
864 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
865 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
866 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
867 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
868 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
869 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
872 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
873 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
874 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
875 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
876 pcbStructInfo, NULL, NULL);
878 __EXCEPT_PAGE_FAULT
880 SetLastError(STATUS_ACCESS_VIOLATION);
881 ret = FALSE;
883 __ENDTRY
885 TRACE("Returning %d (%08x)\n", ret, GetLastError());
886 return ret;
889 static BOOL CRYPT_AsnDecodeCertVersion(const BYTE *pbEncoded, DWORD cbEncoded,
890 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
892 BOOL ret;
893 DWORD dataLen;
895 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
897 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
899 ret = CRYPT_AsnDecodeIntInternal(pbEncoded + 1 + lenBytes, dataLen,
900 dwFlags, pvStructInfo, pcbStructInfo, NULL);
901 if (pcbDecoded)
902 *pcbDecoded = 1 + lenBytes + dataLen;
904 return ret;
907 static BOOL CRYPT_AsnDecodeValidity(const BYTE *pbEncoded, DWORD cbEncoded,
908 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
910 BOOL ret;
912 struct AsnDecodeSequenceItem items[] = {
913 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
914 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
915 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
916 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
919 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
920 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
921 pcbDecoded, NULL);
922 return ret;
925 static BOOL CRYPT_AsnDecodeCertExtensions(const BYTE *pbEncoded,
926 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
927 DWORD *pcbDecoded)
929 BOOL ret;
930 DWORD dataLen;
932 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
934 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
936 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded + 1 + lenBytes,
937 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
938 if (ret && pcbDecoded)
939 *pcbDecoded = 1 + lenBytes + dataLen;
941 return ret;
944 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
945 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
946 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
948 BOOL ret = TRUE;
949 struct AsnDecodeSequenceItem items[] = {
950 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
951 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
952 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
953 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
954 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
955 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
956 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
957 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
958 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
959 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
960 Issuer.pbData) },
961 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
962 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
963 FALSE, 0 },
964 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
965 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
966 Subject.pbData) },
967 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
968 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
969 FALSE, TRUE, offsetof(CERT_INFO,
970 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
971 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
972 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
973 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
974 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
975 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
976 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
977 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
978 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
979 offsetof(CERT_INFO, rgExtension), 0 },
982 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
983 pDecodePara, pvStructInfo, *pcbStructInfo);
985 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
986 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
987 NULL, NULL);
988 if (ret && pvStructInfo)
990 CERT_INFO *info;
992 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
993 info = *(CERT_INFO **)pvStructInfo;
994 else
995 info = (CERT_INFO *)pvStructInfo;
996 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
997 !info->Subject.cbData)
999 SetLastError(CRYPT_E_ASN1_CORRUPT);
1000 /* Don't need to deallocate, because it should have failed on the
1001 * first pass (and no memory was allocated.)
1003 ret = FALSE;
1007 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1008 return ret;
1011 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
1012 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1013 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1015 BOOL ret = FALSE;
1017 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1018 pDecodePara, pvStructInfo, *pcbStructInfo);
1020 __TRY
1022 DWORD size = 0;
1024 /* Unless told not to, first try to decode it as a signed cert. */
1025 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1027 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
1029 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1030 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1031 (BYTE *)&signedCert, &size);
1032 if (ret)
1034 size = 0;
1035 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1036 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
1037 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
1038 pvStructInfo, pcbStructInfo);
1039 LocalFree(signedCert);
1042 /* Failing that, try it as an unsigned cert */
1043 if (!ret)
1045 size = 0;
1046 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1047 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
1048 pDecodePara, pvStructInfo, pcbStructInfo);
1051 __EXCEPT_PAGE_FAULT
1053 SetLastError(STATUS_ACCESS_VIOLATION);
1055 __ENDTRY
1057 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1058 return ret;
1061 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
1062 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1064 BOOL ret;
1065 struct AsnDecodeSequenceItem items[] = {
1066 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
1067 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
1068 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
1069 { 0, offsetof(CRL_ENTRY, RevocationDate),
1070 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
1071 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
1072 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1073 offsetof(CRL_ENTRY, rgExtension), 0 },
1075 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
1077 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
1078 *pcbStructInfo);
1080 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1081 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, pcbDecoded,
1082 entry ? entry->SerialNumber.pbData : NULL);
1083 if (ret && entry && !entry->SerialNumber.cbData)
1085 WARN("empty CRL entry serial number\n");
1086 SetLastError(CRYPT_E_ASN1_CORRUPT);
1087 ret = FALSE;
1089 return ret;
1092 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
1093 * been set prior to calling.
1095 static BOOL CRYPT_AsnDecodeCRLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
1096 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1098 BOOL ret;
1099 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1100 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
1101 offsetof(CRL_ENTRY, SerialNumber.pbData) };
1102 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
1104 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1105 pvStructInfo, *pcbStructInfo, pcbDecoded);
1107 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1108 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1109 entries ? entries->rgItems : NULL);
1110 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1111 return ret;
1114 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1115 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1116 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1118 struct AsnDecodeSequenceItem items[] = {
1119 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1120 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1121 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1122 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1123 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1124 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1125 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1126 Issuer.pbData) },
1127 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1128 sizeof(FILETIME), FALSE, FALSE, 0 },
1129 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1130 sizeof(FILETIME), TRUE, FALSE, 0 },
1131 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1132 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
1133 offsetof(CRL_INFO, rgCRLEntry), 0 },
1134 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1135 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1136 offsetof(CRL_INFO, rgExtension), 0 },
1138 BOOL ret = TRUE;
1140 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1141 pDecodePara, pvStructInfo, *pcbStructInfo);
1143 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1144 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
1145 NULL, NULL);
1147 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1148 return ret;
1151 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1152 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1153 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1155 BOOL ret = FALSE;
1157 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1158 pDecodePara, pvStructInfo, *pcbStructInfo);
1160 __TRY
1162 DWORD size = 0;
1164 /* Unless told not to, first try to decode it as a signed crl. */
1165 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1167 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1169 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1170 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1171 (BYTE *)&signedCrl, &size);
1172 if (ret)
1174 size = 0;
1175 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1176 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1177 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1178 pvStructInfo, pcbStructInfo);
1179 LocalFree(signedCrl);
1182 /* Failing that, try it as an unsigned crl */
1183 if (!ret)
1185 size = 0;
1186 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1187 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1188 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1191 __EXCEPT_PAGE_FAULT
1193 SetLastError(STATUS_ACCESS_VIOLATION);
1195 __ENDTRY
1197 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1198 return ret;
1201 static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded,
1202 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1204 BOOL ret = TRUE;
1205 DWORD dataLen;
1207 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1208 pvStructInfo, *pcbStructInfo);
1210 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1212 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1213 DWORD bytesNeeded = sizeof(LPSTR);
1215 if (dataLen)
1217 /* The largest possible string for the first two components
1218 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1220 char firstTwo[6];
1221 const BYTE *ptr;
1223 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1224 pbEncoded[1 + lenBytes] / 40,
1225 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1226 * 40);
1227 bytesNeeded += strlen(firstTwo) + 1;
1228 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1229 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1231 /* large enough for ".4000000" */
1232 char str[9];
1233 int val = 0;
1235 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1236 (*ptr & 0x80))
1238 val <<= 7;
1239 val |= *ptr & 0x7f;
1240 ptr++;
1242 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1243 (*ptr & 0x80))
1245 SetLastError(CRYPT_E_ASN1_CORRUPT);
1246 ret = FALSE;
1248 else
1250 val <<= 7;
1251 val |= *ptr++;
1252 snprintf(str, sizeof(str), ".%d", val);
1253 bytesNeeded += strlen(str);
1257 if (pcbDecoded)
1258 *pcbDecoded = 1 + lenBytes + dataLen;
1259 if (!pvStructInfo)
1260 *pcbStructInfo = bytesNeeded;
1261 else if (*pcbStructInfo < bytesNeeded)
1263 *pcbStructInfo = bytesNeeded;
1264 SetLastError(ERROR_MORE_DATA);
1265 ret = FALSE;
1267 else
1269 if (dataLen)
1271 const BYTE *ptr;
1272 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1274 *pszObjId = 0;
1275 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1276 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1277 40) * 40);
1278 pszObjId += strlen(pszObjId);
1279 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1280 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1282 int val = 0;
1284 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1285 (*ptr & 0x80))
1287 val <<= 7;
1288 val |= *ptr & 0x7f;
1289 ptr++;
1291 val <<= 7;
1292 val |= *ptr++;
1293 sprintf(pszObjId, ".%d", val);
1294 pszObjId += strlen(pszObjId);
1297 else
1298 *(LPSTR *)pvStructInfo = NULL;
1299 *pcbStructInfo = bytesNeeded;
1302 return ret;
1305 static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded,
1306 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1308 BOOL ret;
1310 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1311 pvStructInfo, *pcbStructInfo);
1313 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1314 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1315 pvStructInfo, pcbStructInfo, pcbDecoded);
1316 else
1318 SetLastError(CRYPT_E_ASN1_BADTAG);
1319 ret = FALSE;
1321 return ret;
1324 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1325 * ahead of time!
1327 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
1328 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1330 struct AsnDecodeSequenceItem items[] = {
1331 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1332 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1333 offsetof(CERT_EXTENSION, pszObjId), 0 },
1334 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1335 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1336 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1337 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1338 offsetof(CERT_EXTENSION, Value.pbData) },
1340 BOOL ret = TRUE;
1341 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1343 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1344 *pcbStructInfo);
1346 if (ext)
1347 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1348 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1349 pbEncoded, cbEncoded, dwFlags, NULL, ext, pcbStructInfo,
1350 pcbDecoded, ext ? ext->pszObjId : NULL);
1351 if (ext)
1352 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1353 debugstr_a(ext->pszObjId));
1354 TRACE("returning %d (%08x)\n", ret, GetLastError());
1355 return ret;
1358 static BOOL CRYPT_AsnDecodeExtensionsInternal(const BYTE *pbEncoded,
1359 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1360 DWORD *pcbDecoded)
1362 BOOL ret = TRUE;
1363 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1364 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1365 offsetof(CERT_EXTENSION, pszObjId) };
1366 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1368 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1369 pvStructInfo, *pcbStructInfo, pcbDecoded);
1371 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1372 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1373 exts ? exts->rgExtension : NULL);
1374 return ret;
1377 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1378 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1379 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1381 BOOL ret = TRUE;
1383 __TRY
1385 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
1386 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1387 if (ret && pvStructInfo)
1389 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1390 pcbStructInfo, *pcbStructInfo);
1391 if (ret)
1393 CERT_EXTENSIONS *exts;
1395 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1396 pvStructInfo = *(BYTE **)pvStructInfo;
1397 exts = (CERT_EXTENSIONS *)pvStructInfo;
1398 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1399 sizeof(CERT_EXTENSIONS));
1400 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
1401 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1402 pcbStructInfo, NULL);
1406 __EXCEPT_PAGE_FAULT
1408 SetLastError(STATUS_ACCESS_VIOLATION);
1409 ret = FALSE;
1411 __ENDTRY
1412 return ret;
1415 /* Warning: this assumes the address of value->Value.pbData is already set, in
1416 * order to avoid overwriting memory. (In some cases, it may change it, if it
1417 * doesn't copy anything to memory.) Be sure to set it correctly!
1419 static BOOL CRYPT_AsnDecodeNameValueInternal(const BYTE *pbEncoded,
1420 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1421 DWORD *pcbDecoded)
1423 BOOL ret = TRUE;
1424 DWORD dataLen;
1425 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1427 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1429 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1430 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1432 switch (pbEncoded[0])
1434 case ASN_OCTETSTRING:
1435 valueType = CERT_RDN_OCTET_STRING;
1436 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1437 bytesNeeded += dataLen;
1438 break;
1439 case ASN_NUMERICSTRING:
1440 valueType = CERT_RDN_NUMERIC_STRING;
1441 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1442 bytesNeeded += dataLen;
1443 break;
1444 case ASN_PRINTABLESTRING:
1445 valueType = CERT_RDN_PRINTABLE_STRING;
1446 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1447 bytesNeeded += dataLen;
1448 break;
1449 case ASN_IA5STRING:
1450 valueType = CERT_RDN_IA5_STRING;
1451 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1452 bytesNeeded += dataLen;
1453 break;
1454 case ASN_T61STRING:
1455 valueType = CERT_RDN_T61_STRING;
1456 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1457 bytesNeeded += dataLen;
1458 break;
1459 case ASN_VIDEOTEXSTRING:
1460 valueType = CERT_RDN_VIDEOTEX_STRING;
1461 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1462 bytesNeeded += dataLen;
1463 break;
1464 case ASN_GRAPHICSTRING:
1465 valueType = CERT_RDN_GRAPHIC_STRING;
1466 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1467 bytesNeeded += dataLen;
1468 break;
1469 case ASN_VISIBLESTRING:
1470 valueType = CERT_RDN_VISIBLE_STRING;
1471 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1472 bytesNeeded += dataLen;
1473 break;
1474 case ASN_GENERALSTRING:
1475 valueType = CERT_RDN_GENERAL_STRING;
1476 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1477 bytesNeeded += dataLen;
1478 break;
1479 case ASN_UNIVERSALSTRING:
1480 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1481 SetLastError(CRYPT_E_ASN1_BADTAG);
1482 return FALSE;
1483 case ASN_BMPSTRING:
1484 valueType = CERT_RDN_BMP_STRING;
1485 bytesNeeded += dataLen;
1486 break;
1487 case ASN_UTF8STRING:
1488 valueType = CERT_RDN_UTF8_STRING;
1489 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1490 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1491 break;
1492 default:
1493 SetLastError(CRYPT_E_ASN1_BADTAG);
1494 return FALSE;
1497 if (pcbDecoded)
1498 *pcbDecoded = 1 + lenBytes + dataLen;
1499 if (!value)
1500 *pcbStructInfo = bytesNeeded;
1501 else if (*pcbStructInfo < bytesNeeded)
1503 *pcbStructInfo = bytesNeeded;
1504 SetLastError(ERROR_MORE_DATA);
1505 ret = FALSE;
1507 else
1509 *pcbStructInfo = bytesNeeded;
1510 value->dwValueType = valueType;
1511 if (dataLen)
1513 DWORD i;
1515 assert(value->Value.pbData);
1516 switch (pbEncoded[0])
1518 case ASN_OCTETSTRING:
1519 case ASN_NUMERICSTRING:
1520 case ASN_PRINTABLESTRING:
1521 case ASN_IA5STRING:
1522 case ASN_T61STRING:
1523 case ASN_VIDEOTEXSTRING:
1524 case ASN_GRAPHICSTRING:
1525 case ASN_VISIBLESTRING:
1526 case ASN_GENERALSTRING:
1527 value->Value.cbData = dataLen;
1528 if (dataLen)
1530 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1531 memcpy(value->Value.pbData,
1532 pbEncoded + 1 + lenBytes, dataLen);
1533 else
1534 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1535 lenBytes;
1537 break;
1538 case ASN_BMPSTRING:
1540 LPWSTR str = (LPWSTR)value->Value.pbData;
1542 value->Value.cbData = dataLen;
1543 for (i = 0; i < dataLen / 2; i++)
1544 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1545 pbEncoded[1 + lenBytes + 2 * i + 1];
1546 break;
1548 case ASN_UTF8STRING:
1550 LPWSTR str = (LPWSTR)value->Value.pbData;
1552 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1553 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1554 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1555 break;
1559 else
1561 value->Value.cbData = 0;
1562 value->Value.pbData = NULL;
1566 return ret;
1569 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1570 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1571 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1573 BOOL ret = TRUE;
1575 __TRY
1577 ret = CRYPT_AsnDecodeNameValueInternal(pbEncoded, cbEncoded,
1578 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1579 if (ret && pvStructInfo)
1581 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1582 pcbStructInfo, *pcbStructInfo);
1583 if (ret)
1585 CERT_NAME_VALUE *value;
1587 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1588 pvStructInfo = *(BYTE **)pvStructInfo;
1589 value = (CERT_NAME_VALUE *)pvStructInfo;
1590 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1591 ret = CRYPT_AsnDecodeNameValueInternal( pbEncoded, cbEncoded,
1592 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1593 pcbStructInfo, NULL);
1597 __EXCEPT_PAGE_FAULT
1599 SetLastError(STATUS_ACCESS_VIOLATION);
1600 ret = FALSE;
1602 __ENDTRY
1603 return ret;
1606 static BOOL CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE *pbEncoded,
1607 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1608 DWORD *pcbDecoded)
1610 BOOL ret = TRUE;
1611 DWORD dataLen;
1612 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1614 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1616 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1617 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1619 switch (pbEncoded[0])
1621 case ASN_NUMERICSTRING:
1622 valueType = CERT_RDN_NUMERIC_STRING;
1623 bytesNeeded += dataLen * 2;
1624 break;
1625 case ASN_PRINTABLESTRING:
1626 valueType = CERT_RDN_PRINTABLE_STRING;
1627 bytesNeeded += dataLen * 2;
1628 break;
1629 case ASN_IA5STRING:
1630 valueType = CERT_RDN_IA5_STRING;
1631 bytesNeeded += dataLen * 2;
1632 break;
1633 case ASN_T61STRING:
1634 valueType = CERT_RDN_T61_STRING;
1635 bytesNeeded += dataLen * 2;
1636 break;
1637 case ASN_VIDEOTEXSTRING:
1638 valueType = CERT_RDN_VIDEOTEX_STRING;
1639 bytesNeeded += dataLen * 2;
1640 break;
1641 case ASN_GRAPHICSTRING:
1642 valueType = CERT_RDN_GRAPHIC_STRING;
1643 bytesNeeded += dataLen * 2;
1644 break;
1645 case ASN_VISIBLESTRING:
1646 valueType = CERT_RDN_VISIBLE_STRING;
1647 bytesNeeded += dataLen * 2;
1648 break;
1649 case ASN_GENERALSTRING:
1650 valueType = CERT_RDN_GENERAL_STRING;
1651 bytesNeeded += dataLen * 2;
1652 break;
1653 case ASN_UNIVERSALSTRING:
1654 valueType = CERT_RDN_UNIVERSAL_STRING;
1655 bytesNeeded += dataLen / 2;
1656 break;
1657 case ASN_BMPSTRING:
1658 valueType = CERT_RDN_BMP_STRING;
1659 bytesNeeded += dataLen;
1660 break;
1661 case ASN_UTF8STRING:
1662 valueType = CERT_RDN_UTF8_STRING;
1663 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1664 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1665 break;
1666 default:
1667 SetLastError(CRYPT_E_ASN1_BADTAG);
1668 return FALSE;
1671 if (pcbDecoded)
1672 *pcbDecoded = 1 + lenBytes + dataLen;
1673 if (!value)
1674 *pcbStructInfo = bytesNeeded;
1675 else if (*pcbStructInfo < bytesNeeded)
1677 *pcbStructInfo = bytesNeeded;
1678 SetLastError(ERROR_MORE_DATA);
1679 ret = FALSE;
1681 else
1683 *pcbStructInfo = bytesNeeded;
1684 value->dwValueType = valueType;
1685 if (dataLen)
1687 DWORD i;
1688 LPWSTR str = (LPWSTR)value->Value.pbData;
1690 assert(value->Value.pbData);
1691 switch (pbEncoded[0])
1693 case ASN_NUMERICSTRING:
1694 case ASN_PRINTABLESTRING:
1695 case ASN_IA5STRING:
1696 case ASN_T61STRING:
1697 case ASN_VIDEOTEXSTRING:
1698 case ASN_GRAPHICSTRING:
1699 case ASN_VISIBLESTRING:
1700 case ASN_GENERALSTRING:
1701 value->Value.cbData = dataLen * 2;
1702 for (i = 0; i < dataLen; i++)
1703 str[i] = pbEncoded[1 + lenBytes + i];
1704 break;
1705 case ASN_UNIVERSALSTRING:
1706 value->Value.cbData = dataLen / 2;
1707 for (i = 0; i < dataLen / 4; i++)
1708 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1709 | pbEncoded[1 + lenBytes + 2 * i + 3];
1710 break;
1711 case ASN_BMPSTRING:
1712 value->Value.cbData = dataLen;
1713 for (i = 0; i < dataLen / 2; i++)
1714 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1715 pbEncoded[1 + lenBytes + 2 * i + 1];
1716 break;
1717 case ASN_UTF8STRING:
1718 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1719 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1720 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1721 break;
1724 else
1726 value->Value.cbData = 0;
1727 value->Value.pbData = NULL;
1731 return ret;
1734 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1735 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1736 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1738 BOOL ret = TRUE;
1740 __TRY
1742 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded, cbEncoded,
1743 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1744 if (ret && pvStructInfo)
1746 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1747 pcbStructInfo, *pcbStructInfo);
1748 if (ret)
1750 CERT_NAME_VALUE *value;
1752 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1753 pvStructInfo = *(BYTE **)pvStructInfo;
1754 value = (CERT_NAME_VALUE *)pvStructInfo;
1755 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1756 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded,
1757 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1758 pcbStructInfo, NULL);
1762 __EXCEPT_PAGE_FAULT
1764 SetLastError(STATUS_ACCESS_VIOLATION);
1765 ret = FALSE;
1767 __ENDTRY
1768 return ret;
1771 static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
1772 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1774 BOOL ret;
1775 struct AsnDecodeSequenceItem items[] = {
1776 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1777 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1778 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1779 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1780 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1781 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1783 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1785 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1786 pvStructInfo, *pcbStructInfo);
1788 if (attr)
1789 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1790 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1791 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1792 attr ? attr->pszObjId : NULL);
1793 if (attr)
1795 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1796 debugstr_a(attr->pszObjId));
1797 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1799 TRACE("returning %d (%08x)\n", ret, GetLastError());
1800 return ret;
1803 static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1804 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1806 BOOL ret = TRUE;
1807 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1808 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1809 offsetof(CERT_RDN_ATTR, pszObjId) };
1810 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1812 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1813 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1814 rdn ? rdn->rgRDNAttr : NULL);
1815 return ret;
1818 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1819 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1820 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1822 BOOL ret = TRUE;
1824 __TRY
1826 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1827 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1828 offsetof(CERT_RDN, rgRDNAttr) };
1830 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1831 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1833 __EXCEPT_PAGE_FAULT
1835 SetLastError(STATUS_ACCESS_VIOLATION);
1836 ret = FALSE;
1838 __ENDTRY
1839 return ret;
1842 static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
1843 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1844 DWORD *pcbDecoded)
1846 BOOL ret;
1847 struct AsnDecodeSequenceItem items[] = {
1848 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1849 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1850 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1851 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1852 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1853 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1855 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1857 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1858 pvStructInfo, *pcbStructInfo);
1860 if (attr)
1861 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1862 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1863 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1864 attr ? attr->pszObjId : NULL);
1865 if (attr)
1867 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1868 debugstr_a(attr->pszObjId));
1869 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1871 TRACE("returning %d (%08x)\n", ret, GetLastError());
1872 return ret;
1875 static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1876 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1878 BOOL ret = TRUE;
1879 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1880 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1881 offsetof(CERT_RDN_ATTR, pszObjId) };
1882 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1884 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1885 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1886 rdn ? rdn->rgRDNAttr : NULL);
1887 return ret;
1890 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1891 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1892 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1894 BOOL ret = TRUE;
1896 __TRY
1898 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1899 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1900 offsetof(CERT_RDN, rgRDNAttr) };
1902 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1903 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1905 __EXCEPT_PAGE_FAULT
1907 SetLastError(STATUS_ACCESS_VIOLATION);
1908 ret = FALSE;
1910 __ENDTRY
1911 return ret;
1914 static BOOL CRYPT_FindEncodedLen(const BYTE *pbEncoded, DWORD cbEncoded,
1915 DWORD *pcbDecoded)
1917 BOOL ret = TRUE, done = FALSE;
1918 DWORD indefiniteNestingLevels = 0, decoded = 0;
1920 TRACE("(%p, %d)\n", pbEncoded, cbEncoded);
1922 do {
1923 DWORD dataLen;
1925 if (!cbEncoded)
1926 done = TRUE;
1927 else if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded,
1928 &dataLen)))
1930 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1932 if (dataLen == CMSG_INDEFINITE_LENGTH)
1934 indefiniteNestingLevels++;
1935 pbEncoded += 1 + lenBytes;
1936 cbEncoded -= 1 + lenBytes;
1937 decoded += 1 + lenBytes;
1938 TRACE("indefiniteNestingLevels = %d\n",
1939 indefiniteNestingLevels);
1941 else
1943 if (pbEncoded[0] == 0 && pbEncoded[1] == 0 &&
1944 indefiniteNestingLevels)
1946 indefiniteNestingLevels--;
1947 TRACE("indefiniteNestingLevels = %d\n",
1948 indefiniteNestingLevels);
1950 pbEncoded += 1 + lenBytes + dataLen;
1951 cbEncoded -= 1 + lenBytes + dataLen;
1952 decoded += 1 + lenBytes + dataLen;
1953 if (!indefiniteNestingLevels)
1954 done = TRUE;
1957 } while (ret && !done);
1958 /* If we haven't found all 0 TLVs, we haven't found the end */
1959 if (ret && indefiniteNestingLevels)
1961 SetLastError(CRYPT_E_ASN1_EOD);
1962 ret = FALSE;
1964 if (ret)
1965 *pcbDecoded = decoded;
1966 TRACE("returning %d (%d)\n", ret, ret ? *pcbDecoded : 0);
1967 return ret;
1970 static BOOL CRYPT_AsnDecodeCopyBytes(const BYTE *pbEncoded,
1971 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1972 DWORD *pcbDecoded)
1974 BOOL ret = TRUE;
1975 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB), encodedLen = 0;
1977 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1978 pvStructInfo, *pcbStructInfo);
1980 if ((ret = CRYPT_FindEncodedLen(pbEncoded, cbEncoded, &encodedLen)))
1982 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1983 bytesNeeded += encodedLen;
1984 if (!pvStructInfo)
1985 *pcbStructInfo = bytesNeeded;
1986 else if (*pcbStructInfo < bytesNeeded)
1988 SetLastError(ERROR_MORE_DATA);
1989 *pcbStructInfo = bytesNeeded;
1990 ret = FALSE;
1992 else
1994 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1996 *pcbStructInfo = bytesNeeded;
1997 blob->cbData = encodedLen;
1998 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1999 blob->pbData = (LPBYTE)pbEncoded;
2000 else
2002 assert(blob->pbData);
2003 memcpy(blob->pbData, pbEncoded, blob->cbData);
2006 if (pcbDecoded)
2007 *pcbDecoded = encodedLen;
2009 return ret;
2012 static BOOL CRYPT_DecodeDERArray(const BYTE *pbEncoded, DWORD cbEncoded,
2013 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2015 BOOL ret;
2016 struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytes,
2017 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
2018 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
2020 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2021 pvStructInfo, *pcbStructInfo, pcbDecoded);
2023 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2024 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2025 array ? array->rgItems : NULL);
2026 return ret;
2029 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
2030 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2031 DWORD *pcbDecoded)
2033 BOOL ret;
2034 struct AsnDecodeSequenceItem items[] = {
2035 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
2036 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2037 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
2038 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
2039 CRYPT_DecodeDERArray, sizeof(struct GenericArray), FALSE, TRUE,
2040 offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
2042 PCRYPT_ATTRIBUTE attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
2044 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2045 pvStructInfo, *pcbStructInfo);
2047 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2048 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2049 pcbDecoded, attr ? attr->pszObjId : NULL);
2050 TRACE("returning %d\n", ret);
2051 return ret;
2054 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
2055 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2056 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2058 BOOL ret = FALSE;
2060 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2061 pDecodePara, pvStructInfo, *pcbStructInfo);
2063 __TRY
2065 DWORD bytesNeeded;
2067 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2068 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
2069 if (ret)
2071 if (!pvStructInfo)
2072 *pcbStructInfo = bytesNeeded;
2073 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2074 pvStructInfo, pcbStructInfo, bytesNeeded)))
2076 PCRYPT_ATTRIBUTE attr;
2078 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2079 pvStructInfo = *(BYTE **)pvStructInfo;
2080 attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
2081 attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
2082 sizeof(CRYPT_ATTRIBUTE));
2083 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2084 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
2085 NULL);
2089 __EXCEPT_PAGE_FAULT
2091 SetLastError(STATUS_ACCESS_VIOLATION);
2093 __ENDTRY
2094 TRACE("returning %d\n", ret);
2095 return ret;
2098 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
2099 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2100 DWORD *pcbDecoded)
2102 struct AsnArrayDescriptor arrayDesc = { 0,
2103 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2104 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2105 PCRYPT_ATTRIBUTES attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
2106 BOOL ret;
2108 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2109 NULL, pvStructInfo, pcbStructInfo, pcbDecoded, attrs ? attrs->rgAttr :
2110 NULL);
2111 return ret;
2114 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
2115 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2116 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2118 BOOL ret = FALSE;
2120 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2121 pDecodePara, pvStructInfo, *pcbStructInfo);
2123 __TRY
2125 DWORD bytesNeeded;
2127 if (!cbEncoded)
2128 SetLastError(CRYPT_E_ASN1_EOD);
2129 else if (pbEncoded[0] != (ASN_CONSTRUCTOR | ASN_SETOF))
2130 SetLastError(CRYPT_E_ASN1_CORRUPT);
2131 else if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
2132 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2133 NULL)))
2135 if (!pvStructInfo)
2136 *pcbStructInfo = bytesNeeded;
2137 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2138 pvStructInfo, pcbStructInfo, bytesNeeded)))
2140 PCRYPT_ATTRIBUTES attrs;
2142 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2143 pvStructInfo = *(BYTE **)pvStructInfo;
2144 attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
2145 attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
2146 sizeof(CRYPT_ATTRIBUTES));
2147 ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
2148 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2149 &bytesNeeded, NULL);
2153 __EXCEPT_PAGE_FAULT
2155 SetLastError(STATUS_ACCESS_VIOLATION);
2157 __ENDTRY
2158 TRACE("returning %d\n", ret);
2159 return ret;
2162 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
2163 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2165 CRYPT_ALGORITHM_IDENTIFIER *algo =
2166 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
2167 BOOL ret = TRUE;
2168 struct AsnDecodeSequenceItem items[] = {
2169 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
2170 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2171 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
2172 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
2173 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2174 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
2177 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2178 pvStructInfo, *pcbStructInfo, pcbDecoded);
2180 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2181 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2182 pcbDecoded, algo ? algo->pszObjId : NULL);
2183 if (ret && pvStructInfo)
2185 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
2186 debugstr_a(algo->pszObjId));
2188 return ret;
2191 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
2192 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2193 DWORD *pcbDecoded)
2195 BOOL ret = TRUE;
2196 struct AsnDecodeSequenceItem items[] = {
2197 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
2198 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2199 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
2200 Algorithm.pszObjId) },
2201 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
2202 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2203 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
2205 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2207 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2208 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2209 pcbDecoded, info ? info->Algorithm.Parameters.pbData : NULL);
2210 return ret;
2213 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2214 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2215 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2217 BOOL ret = TRUE;
2219 __TRY
2221 DWORD bytesNeeded;
2223 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2224 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2226 if (!pvStructInfo)
2227 *pcbStructInfo = bytesNeeded;
2228 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2229 pvStructInfo, pcbStructInfo, bytesNeeded)))
2231 PCERT_PUBLIC_KEY_INFO info;
2233 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2234 pvStructInfo = *(BYTE **)pvStructInfo;
2235 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2236 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2237 sizeof(CERT_PUBLIC_KEY_INFO);
2238 ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2239 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2240 &bytesNeeded, NULL);
2244 __EXCEPT_PAGE_FAULT
2246 SetLastError(STATUS_ACCESS_VIOLATION);
2247 ret = FALSE;
2249 __ENDTRY
2250 return ret;
2253 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
2254 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2256 BOOL ret;
2258 if (cbEncoded < 3)
2260 SetLastError(CRYPT_E_ASN1_CORRUPT);
2261 return FALSE;
2263 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2265 SetLastError(CRYPT_E_ASN1_CORRUPT);
2266 return FALSE;
2268 if (pbEncoded[1] > 1)
2270 SetLastError(CRYPT_E_ASN1_CORRUPT);
2271 return FALSE;
2273 if (pcbDecoded)
2274 *pcbDecoded = 3;
2275 if (!pvStructInfo)
2277 *pcbStructInfo = sizeof(BOOL);
2278 ret = TRUE;
2280 else if (*pcbStructInfo < sizeof(BOOL))
2282 *pcbStructInfo = sizeof(BOOL);
2283 SetLastError(ERROR_MORE_DATA);
2284 ret = FALSE;
2286 else
2288 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2289 ret = TRUE;
2291 TRACE("returning %d (%08x)\n", ret, GetLastError());
2292 return ret;
2295 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2296 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2298 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
2299 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2300 BOOL ret;
2302 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2303 pvStructInfo, *pcbStructInfo);
2305 if (cbEncoded < 2)
2307 SetLastError(CRYPT_E_ASN1_CORRUPT);
2308 return FALSE;
2310 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2311 if (1 + lenBytes > cbEncoded)
2313 SetLastError(CRYPT_E_ASN1_CORRUPT);
2314 return FALSE;
2316 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2318 switch (pbEncoded[0] & ASN_TYPE_MASK)
2320 case 1: /* rfc822Name */
2321 case 2: /* dNSName */
2322 case 6: /* uniformResourceIdentifier */
2323 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
2324 break;
2325 case 4: /* directoryName */
2326 case 7: /* iPAddress */
2327 bytesNeeded += dataLen;
2328 break;
2329 case 8: /* registeredID */
2330 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
2331 &dataLen, NULL);
2332 if (ret)
2334 /* FIXME: ugly, shouldn't need to know internals of OID decode
2335 * function to use it.
2337 bytesNeeded += dataLen - sizeof(LPSTR);
2339 break;
2340 case 0: /* otherName */
2341 FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
2342 SetLastError(CRYPT_E_ASN1_BADTAG);
2343 ret = FALSE;
2344 break;
2345 case 3: /* x400Address, unimplemented */
2346 case 5: /* ediPartyName, unimplemented */
2347 TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
2348 SetLastError(CRYPT_E_ASN1_BADTAG);
2349 ret = FALSE;
2350 break;
2351 default:
2352 TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
2353 SetLastError(CRYPT_E_ASN1_CORRUPT);
2354 ret = FALSE;
2356 if (ret)
2358 if (pcbDecoded)
2359 *pcbDecoded = 1 + lenBytes + dataLen;
2360 if (!entry)
2361 *pcbStructInfo = bytesNeeded;
2362 else if (*pcbStructInfo < bytesNeeded)
2364 *pcbStructInfo = bytesNeeded;
2365 SetLastError(ERROR_MORE_DATA);
2366 ret = FALSE;
2368 else
2370 *pcbStructInfo = bytesNeeded;
2371 /* MS used values one greater than the asn1 ones.. sigh */
2372 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
2373 switch (pbEncoded[0] & ASN_TYPE_MASK)
2375 case 1: /* rfc822Name */
2376 case 2: /* dNSName */
2377 case 6: /* uniformResourceIdentifier */
2379 DWORD i;
2381 for (i = 0; i < dataLen; i++)
2382 entry->u.pwszURL[i] =
2383 (WCHAR)pbEncoded[1 + lenBytes + i];
2384 entry->u.pwszURL[i] = 0;
2385 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2386 debugstr_w(entry->u.pwszURL));
2387 break;
2389 case 4: /* directoryName */
2390 entry->dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
2391 /* The data are memory-equivalent with the IPAddress case,
2392 * fall-through
2394 case 7: /* iPAddress */
2395 /* The next data pointer is in the pwszURL spot, that is,
2396 * the first 4 bytes. Need to move it to the next spot.
2398 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2399 entry->u.IPAddress.cbData = dataLen;
2400 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2401 dataLen);
2402 break;
2403 case 8: /* registeredID */
2404 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
2405 &entry->u.pszRegisteredID, &dataLen, NULL);
2406 break;
2411 return ret;
2414 static BOOL CRYPT_AsnDecodeAltNameInternal(const BYTE *pbEncoded,
2415 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2416 DWORD *pcbDecoded)
2418 BOOL ret = TRUE;
2419 struct AsnArrayDescriptor arrayDesc = { 0,
2420 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2421 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2422 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
2424 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2425 pvStructInfo, *pcbStructInfo, pcbDecoded);
2427 if (info)
2428 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2429 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2430 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2431 info ? info->rgAltEntry : NULL);
2432 return ret;
2435 /* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */
2436 static BOOL CRYPT_AsnDecodeIntegerSwapBytes(const BYTE *pbEncoded,
2437 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2438 DWORD *pcbDecoded)
2440 BOOL ret;
2442 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
2443 pvStructInfo, *pcbStructInfo, pcbDecoded);
2445 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2446 * place.
2448 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
2449 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
2450 pcbDecoded);
2451 if (ret && pvStructInfo)
2453 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2455 if (blob->cbData)
2457 DWORD i;
2458 BYTE temp;
2460 for (i = 0; i < blob->cbData / 2; i++)
2462 temp = blob->pbData[i];
2463 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
2464 blob->pbData[blob->cbData - i - 1] = temp;
2468 TRACE("returning %d (%08x)\n", ret, GetLastError());
2469 return ret;
2472 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
2473 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2474 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2476 BOOL ret;
2478 __TRY
2480 struct AsnDecodeSequenceItem items[] = {
2481 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
2482 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2483 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
2484 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2485 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
2486 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
2487 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
2488 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
2489 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2490 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2491 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
2494 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2495 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2496 pcbStructInfo, NULL, NULL);
2498 __EXCEPT_PAGE_FAULT
2500 SetLastError(STATUS_ACCESS_VIOLATION);
2501 ret = FALSE;
2503 __ENDTRY
2504 return ret;
2507 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
2508 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2509 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2511 BOOL ret;
2513 __TRY
2515 struct AsnDecodeSequenceItem items[] = {
2516 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
2517 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2518 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
2519 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2520 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
2521 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
2522 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2523 AuthorityCertIssuer.rgAltEntry), 0 },
2524 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2525 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2526 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2527 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2528 AuthorityCertSerialNumber.pbData), 0 },
2531 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2532 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2533 pcbStructInfo, NULL, NULL);
2535 __EXCEPT_PAGE_FAULT
2537 SetLastError(STATUS_ACCESS_VIOLATION);
2538 ret = FALSE;
2540 __ENDTRY
2541 return ret;
2544 static BOOL CRYPT_AsnDecodePKCSContent(const BYTE *pbEncoded, DWORD cbEncoded,
2545 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2547 BOOL ret;
2548 DWORD dataLen;
2550 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2551 pvStructInfo, *pcbStructInfo, pcbDecoded);
2553 /* The caller has already checked the tag, no need to check it again.
2554 * Check the outer length is valid:
2556 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
2558 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2559 DWORD innerLen;
2561 pbEncoded += 1 + lenBytes;
2562 cbEncoded -= 1 + lenBytes;
2563 if (dataLen == CMSG_INDEFINITE_LENGTH)
2564 cbEncoded -= 2; /* space for 0 TLV */
2565 /* Check the inner length is valid: */
2566 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &innerLen)))
2568 DWORD decodedLen;
2570 ret = CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags,
2571 pvStructInfo, pcbStructInfo, &decodedLen);
2572 if (dataLen == CMSG_INDEFINITE_LENGTH)
2574 if (*(pbEncoded + decodedLen) != 0 ||
2575 *(pbEncoded + decodedLen + 1) != 0)
2577 TRACE("expected 0 TLV, got {%02x,%02x}\n",
2578 *(pbEncoded + decodedLen),
2579 *(pbEncoded + decodedLen + 1));
2580 SetLastError(CRYPT_E_ASN1_CORRUPT);
2581 ret = FALSE;
2583 else
2584 decodedLen += 2;
2586 if (ret && pcbDecoded)
2588 *pcbDecoded = 1 + lenBytes + decodedLen;
2589 TRACE("decoded %d bytes\n", *pcbDecoded);
2593 return ret;
2596 static BOOL CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE *pbEncoded,
2597 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2598 DWORD *pcbDecoded)
2600 CRYPT_CONTENT_INFO *info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2601 struct AsnDecodeSequenceItem items[] = {
2602 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
2603 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2604 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
2605 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
2606 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
2607 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
2608 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
2610 BOOL ret;
2612 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2613 pvStructInfo, *pcbStructInfo, pcbDecoded);
2615 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2616 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2617 pcbDecoded, info ? info->pszObjId : NULL);
2618 return ret;
2621 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
2622 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2623 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2625 BOOL ret = FALSE;
2627 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2628 pDecodePara, pvStructInfo, *pcbStructInfo);
2630 __TRY
2632 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, cbEncoded,
2633 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
2634 if (ret && pvStructInfo)
2636 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
2637 pcbStructInfo, *pcbStructInfo);
2638 if (ret)
2640 CRYPT_CONTENT_INFO *info;
2642 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2643 pvStructInfo = *(BYTE **)pvStructInfo;
2644 info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2645 info->pszObjId = (LPSTR)((BYTE *)info +
2646 sizeof(CRYPT_CONTENT_INFO));
2647 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded,
2648 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2649 pcbStructInfo, NULL);
2653 __EXCEPT_PAGE_FAULT
2655 SetLastError(STATUS_ACCESS_VIOLATION);
2657 __ENDTRY
2658 return ret;
2661 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
2662 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2663 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
2665 BOOL ret;
2666 struct AsnDecodeSequenceItem items[] = {
2667 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version),
2668 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2669 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
2670 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2671 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
2672 0 },
2673 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
2674 CRYPT_AsnDecodePKCSContentInfoInternal,
2675 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
2676 ContentInfo.pszObjId), 0 },
2677 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
2678 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
2679 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
2682 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2683 pbEncoded, cbEncoded, dwFlags, pDecodePara, digestedData, pcbDigestedData,
2684 NULL, NULL);
2685 return ret;
2688 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
2689 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2690 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2692 BOOL ret = TRUE;
2694 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2695 pDecodePara, pvStructInfo, *pcbStructInfo);
2697 __TRY
2699 DWORD bytesNeeded;
2701 if ((ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
2702 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2704 if (!pvStructInfo)
2705 *pcbStructInfo = bytesNeeded;
2706 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2707 pvStructInfo, pcbStructInfo, bytesNeeded)))
2709 CERT_ALT_NAME_INFO *name;
2711 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2712 pvStructInfo = *(BYTE **)pvStructInfo;
2713 name = (CERT_ALT_NAME_INFO *)pvStructInfo;
2714 name->rgAltEntry = (PCERT_ALT_NAME_ENTRY)
2715 ((BYTE *)pvStructInfo + sizeof(CERT_ALT_NAME_INFO));
2716 ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
2717 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2718 &bytesNeeded, NULL);
2722 __EXCEPT_PAGE_FAULT
2724 SetLastError(STATUS_ACCESS_VIOLATION);
2725 ret = FALSE;
2727 __ENDTRY
2728 return ret;
2731 struct PATH_LEN_CONSTRAINT
2733 BOOL fPathLenConstraint;
2734 DWORD dwPathLenConstraint;
2737 static BOOL CRYPT_AsnDecodePathLenConstraint(const BYTE *pbEncoded,
2738 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2739 DWORD *pcbDecoded)
2741 BOOL ret = TRUE;
2742 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT), size;
2744 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2745 pvStructInfo, *pcbStructInfo, pcbDecoded);
2747 if (!pvStructInfo)
2749 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, NULL,
2750 &size, pcbDecoded);
2751 *pcbStructInfo = bytesNeeded;
2753 else if (*pcbStructInfo < bytesNeeded)
2755 SetLastError(ERROR_MORE_DATA);
2756 *pcbStructInfo = bytesNeeded;
2757 ret = FALSE;
2759 else
2761 struct PATH_LEN_CONSTRAINT *constraint =
2762 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
2764 size = sizeof(constraint->dwPathLenConstraint);
2765 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
2766 &constraint->dwPathLenConstraint, &size, pcbDecoded);
2767 if (ret)
2768 constraint->fPathLenConstraint = TRUE;
2769 TRACE("got an int, dwPathLenConstraint is %d\n",
2770 constraint->dwPathLenConstraint);
2772 TRACE("returning %d (%08x)\n", ret, GetLastError());
2773 return ret;
2776 static BOOL CRYPT_AsnDecodeSubtreeConstraints(const BYTE *pbEncoded,
2777 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2778 DWORD *pcbDecoded)
2780 BOOL ret;
2781 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2782 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
2783 offsetof(CERT_NAME_BLOB, pbData) };
2784 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2786 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2787 pvStructInfo, *pcbStructInfo, pcbDecoded);
2789 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2790 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2791 entries ? entries->rgItems : NULL);
2792 TRACE("Returning %d (%08x)\n", ret, GetLastError());
2793 return ret;
2796 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
2797 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2798 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2800 BOOL ret;
2802 __TRY
2804 struct AsnDecodeSequenceItem items[] = {
2805 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
2806 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2807 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
2808 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2809 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2810 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2811 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2812 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
2813 sizeof(struct GenericArray), TRUE, TRUE,
2814 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
2817 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2818 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2819 pcbStructInfo, NULL, NULL);
2821 __EXCEPT_PAGE_FAULT
2823 SetLastError(STATUS_ACCESS_VIOLATION);
2824 ret = FALSE;
2826 __ENDTRY
2827 return ret;
2830 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
2831 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2832 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2834 BOOL ret;
2836 __TRY
2838 struct AsnDecodeSequenceItem items[] = {
2839 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
2840 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
2841 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
2842 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2843 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2846 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2847 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2848 pcbStructInfo, NULL, NULL);
2850 __EXCEPT_PAGE_FAULT
2852 SetLastError(STATUS_ACCESS_VIOLATION);
2853 ret = FALSE;
2855 __ENDTRY
2856 return ret;
2859 #define RSA1_MAGIC 0x31415352
2861 struct DECODED_RSA_PUB_KEY
2863 DWORD pubexp;
2864 CRYPT_INTEGER_BLOB modulus;
2867 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
2868 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2869 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2871 BOOL ret;
2873 __TRY
2875 struct AsnDecodeSequenceItem items[] = {
2876 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
2877 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2878 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
2879 0 },
2880 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
2881 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2883 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
2884 DWORD size = 0;
2886 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2887 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
2888 &size, NULL, NULL);
2889 if (ret)
2891 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2892 decodedKey->modulus.cbData;
2894 if (!pvStructInfo)
2896 *pcbStructInfo = bytesNeeded;
2897 ret = TRUE;
2899 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2900 pvStructInfo, pcbStructInfo, bytesNeeded)))
2902 BLOBHEADER *hdr;
2903 RSAPUBKEY *rsaPubKey;
2905 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2906 pvStructInfo = *(BYTE **)pvStructInfo;
2907 hdr = (BLOBHEADER *)pvStructInfo;
2908 hdr->bType = PUBLICKEYBLOB;
2909 hdr->bVersion = CUR_BLOB_VERSION;
2910 hdr->reserved = 0;
2911 hdr->aiKeyAlg = CALG_RSA_KEYX;
2912 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
2913 sizeof(BLOBHEADER));
2914 rsaPubKey->magic = RSA1_MAGIC;
2915 rsaPubKey->pubexp = decodedKey->pubexp;
2916 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
2917 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
2918 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
2919 decodedKey->modulus.cbData);
2921 LocalFree(decodedKey);
2924 __EXCEPT_PAGE_FAULT
2926 SetLastError(STATUS_ACCESS_VIOLATION);
2927 ret = FALSE;
2929 __ENDTRY
2930 return ret;
2933 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
2934 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2935 DWORD *pcbDecoded)
2937 BOOL ret;
2938 DWORD bytesNeeded, dataLen;
2940 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2941 pvStructInfo, *pcbStructInfo, pcbDecoded);
2943 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2945 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2947 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2948 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
2949 else
2950 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
2951 if (pcbDecoded)
2952 *pcbDecoded = 1 + lenBytes + dataLen;
2953 if (!pvStructInfo)
2954 *pcbStructInfo = bytesNeeded;
2955 else if (*pcbStructInfo < bytesNeeded)
2957 SetLastError(ERROR_MORE_DATA);
2958 *pcbStructInfo = bytesNeeded;
2959 ret = FALSE;
2961 else
2963 CRYPT_DATA_BLOB *blob;
2965 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2966 blob->cbData = dataLen;
2967 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2968 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
2969 else
2971 assert(blob->pbData);
2972 if (blob->cbData)
2973 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
2974 blob->cbData);
2978 return ret;
2981 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
2982 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2983 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2985 BOOL ret;
2987 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2988 pDecodePara, pvStructInfo, *pcbStructInfo);
2990 __TRY
2992 DWORD bytesNeeded;
2994 if (!cbEncoded)
2996 SetLastError(CRYPT_E_ASN1_CORRUPT);
2997 ret = FALSE;
2999 else if (pbEncoded[0] != ASN_OCTETSTRING)
3001 SetLastError(CRYPT_E_ASN1_BADTAG);
3002 ret = FALSE;
3004 else if ((ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
3005 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3007 if (!pvStructInfo)
3008 *pcbStructInfo = bytesNeeded;
3009 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3010 pvStructInfo, pcbStructInfo, bytesNeeded)))
3012 CRYPT_DATA_BLOB *blob;
3014 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3015 pvStructInfo = *(BYTE **)pvStructInfo;
3016 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
3017 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
3018 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
3019 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3020 &bytesNeeded, NULL);
3024 __EXCEPT_PAGE_FAULT
3026 SetLastError(STATUS_ACCESS_VIOLATION);
3027 ret = FALSE;
3029 __ENDTRY
3030 return ret;
3033 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3034 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3036 BOOL ret;
3038 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
3039 pvStructInfo, *pcbStructInfo, pcbDecoded);
3041 if (pbEncoded[0] == ASN_BITSTRING)
3043 DWORD bytesNeeded, dataLen;
3044 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3046 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3048 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3049 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
3050 else
3051 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
3052 if (pcbDecoded)
3053 *pcbDecoded = 1 + lenBytes + dataLen;
3054 if (!pvStructInfo)
3055 *pcbStructInfo = bytesNeeded;
3056 else if (*pcbStructInfo < bytesNeeded)
3058 *pcbStructInfo = bytesNeeded;
3059 SetLastError(ERROR_MORE_DATA);
3060 ret = FALSE;
3062 else
3064 CRYPT_BIT_BLOB *blob;
3066 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
3067 blob->cbData = dataLen - 1;
3068 blob->cUnusedBits = *(pbEncoded + 1 + lenBytes);
3069 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3071 blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes;
3073 else
3075 assert(blob->pbData);
3076 if (blob->cbData)
3078 BYTE mask = 0xff << blob->cUnusedBits;
3080 memcpy(blob->pbData, pbEncoded + 2 + lenBytes,
3081 blob->cbData);
3082 blob->pbData[blob->cbData - 1] &= mask;
3088 else
3090 SetLastError(CRYPT_E_ASN1_BADTAG);
3091 ret = FALSE;
3093 TRACE("returning %d (%08x)\n", ret, GetLastError());
3094 return ret;
3097 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
3098 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3099 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3101 BOOL ret;
3103 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
3104 pDecodePara, pvStructInfo, pcbStructInfo);
3106 __TRY
3108 DWORD bytesNeeded;
3110 if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3111 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3113 if (!pvStructInfo)
3114 *pcbStructInfo = bytesNeeded;
3115 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3116 pvStructInfo, pcbStructInfo, bytesNeeded)))
3118 CRYPT_BIT_BLOB *blob;
3120 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3121 pvStructInfo = *(BYTE **)pvStructInfo;
3122 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
3123 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
3124 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3125 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3126 &bytesNeeded, NULL);
3130 __EXCEPT_PAGE_FAULT
3132 SetLastError(STATUS_ACCESS_VIOLATION);
3133 ret = FALSE;
3135 __ENDTRY
3136 TRACE("returning %d (%08x)\n", ret, GetLastError());
3137 return ret;
3140 /* Ignores tag. Only allows integers 4 bytes or smaller in size. */
3141 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3142 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3144 BOOL ret;
3145 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
3146 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
3147 DWORD size = sizeof(buf);
3149 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
3150 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded, 0, &buf,
3151 &size, pcbDecoded);
3152 if (ret)
3154 if (!pvStructInfo)
3155 *pcbStructInfo = sizeof(int);
3156 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int))))
3158 int val, i;
3160 if (blob->pbData[blob->cbData - 1] & 0x80)
3162 /* initialize to a negative value to sign-extend */
3163 val = -1;
3165 else
3166 val = 0;
3167 for (i = 0; i < blob->cbData; i++)
3169 val <<= 8;
3170 val |= blob->pbData[blob->cbData - i - 1];
3172 memcpy(pvStructInfo, &val, sizeof(int));
3175 else if (GetLastError() == ERROR_MORE_DATA)
3176 SetLastError(CRYPT_E_ASN1_LARGE);
3177 return ret;
3180 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
3181 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3182 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3184 BOOL ret;
3186 __TRY
3188 DWORD bytesNeeded;
3190 if (!cbEncoded)
3192 SetLastError(CRYPT_E_ASN1_CORRUPT);
3193 ret = FALSE;
3195 else if (pbEncoded[0] != ASN_INTEGER)
3197 SetLastError(CRYPT_E_ASN1_BADTAG);
3198 ret = FALSE;
3200 else
3201 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3202 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3203 if (ret)
3205 if (!pvStructInfo)
3206 *pcbStructInfo = bytesNeeded;
3207 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3208 pvStructInfo, pcbStructInfo, bytesNeeded)))
3210 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3211 pvStructInfo = *(BYTE **)pvStructInfo;
3212 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3213 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3214 &bytesNeeded, NULL);
3218 __EXCEPT_PAGE_FAULT
3220 SetLastError(STATUS_ACCESS_VIOLATION);
3221 ret = FALSE;
3223 __ENDTRY
3224 return ret;
3227 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
3228 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3229 DWORD *pcbDecoded)
3231 BOOL ret;
3232 DWORD bytesNeeded, dataLen;
3234 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3236 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3238 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3239 if (pcbDecoded)
3240 *pcbDecoded = 1 + lenBytes + dataLen;
3241 if (!pvStructInfo)
3242 *pcbStructInfo = bytesNeeded;
3243 else if (*pcbStructInfo < bytesNeeded)
3245 *pcbStructInfo = bytesNeeded;
3246 SetLastError(ERROR_MORE_DATA);
3247 ret = FALSE;
3249 else
3251 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3253 blob->cbData = dataLen;
3254 assert(blob->pbData);
3255 if (blob->cbData)
3257 DWORD i;
3259 for (i = 0; i < blob->cbData; i++)
3261 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3262 dataLen - i - 1);
3267 return ret;
3270 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
3271 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3272 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3274 BOOL ret;
3276 __TRY
3278 DWORD bytesNeeded;
3280 if (pbEncoded[0] != ASN_INTEGER)
3282 SetLastError(CRYPT_E_ASN1_BADTAG);
3283 ret = FALSE;
3285 else
3286 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3287 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3288 if (ret)
3290 if (!pvStructInfo)
3291 *pcbStructInfo = bytesNeeded;
3292 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3293 pvStructInfo, pcbStructInfo, bytesNeeded)))
3295 CRYPT_INTEGER_BLOB *blob;
3297 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3298 pvStructInfo = *(BYTE **)pvStructInfo;
3299 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3300 blob->pbData = (BYTE *)pvStructInfo +
3301 sizeof(CRYPT_INTEGER_BLOB);
3302 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3303 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
3304 &bytesNeeded, NULL);
3308 __EXCEPT_PAGE_FAULT
3310 SetLastError(STATUS_ACCESS_VIOLATION);
3311 ret = FALSE;
3313 __ENDTRY
3314 return ret;
3317 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
3318 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3319 DWORD *pcbDecoded)
3321 BOOL ret;
3323 if (pbEncoded[0] == ASN_INTEGER)
3325 DWORD bytesNeeded, dataLen;
3327 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3329 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3331 if (pcbDecoded)
3332 *pcbDecoded = 1 + lenBytes + dataLen;
3333 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3334 if (!pvStructInfo)
3335 *pcbStructInfo = bytesNeeded;
3336 else if (*pcbStructInfo < bytesNeeded)
3338 *pcbStructInfo = bytesNeeded;
3339 SetLastError(ERROR_MORE_DATA);
3340 ret = FALSE;
3342 else
3344 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3346 blob->cbData = dataLen;
3347 assert(blob->pbData);
3348 /* remove leading zero byte if it exists */
3349 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
3351 blob->cbData--;
3352 blob->pbData++;
3354 if (blob->cbData)
3356 DWORD i;
3358 for (i = 0; i < blob->cbData; i++)
3360 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3361 dataLen - i - 1);
3367 else
3369 SetLastError(CRYPT_E_ASN1_BADTAG);
3370 ret = FALSE;
3372 return ret;
3375 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
3376 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3377 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3379 BOOL ret;
3381 __TRY
3383 DWORD bytesNeeded;
3385 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded,
3386 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3388 if (!pvStructInfo)
3389 *pcbStructInfo = bytesNeeded;
3390 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3391 pvStructInfo, pcbStructInfo, bytesNeeded)))
3393 CRYPT_INTEGER_BLOB *blob;
3395 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3396 pvStructInfo = *(BYTE **)pvStructInfo;
3397 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3398 blob->pbData = (BYTE *)pvStructInfo +
3399 sizeof(CRYPT_INTEGER_BLOB);
3400 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded,
3401 cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
3402 &bytesNeeded, NULL);
3406 __EXCEPT_PAGE_FAULT
3408 SetLastError(STATUS_ACCESS_VIOLATION);
3409 ret = FALSE;
3411 __ENDTRY
3412 return ret;
3415 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
3416 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3417 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3419 BOOL ret;
3421 if (!pvStructInfo)
3423 *pcbStructInfo = sizeof(int);
3424 return TRUE;
3426 __TRY
3428 if (pbEncoded[0] == ASN_ENUMERATED)
3430 unsigned int val = 0, i;
3432 if (cbEncoded <= 1)
3434 SetLastError(CRYPT_E_ASN1_EOD);
3435 ret = FALSE;
3437 else if (pbEncoded[1] == 0)
3439 SetLastError(CRYPT_E_ASN1_CORRUPT);
3440 ret = FALSE;
3442 else
3444 /* A little strange looking, but we have to accept a sign byte:
3445 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
3446 * assuming a small length is okay here, it has to be in short
3447 * form.
3449 if (pbEncoded[1] > sizeof(unsigned int) + 1)
3451 SetLastError(CRYPT_E_ASN1_LARGE);
3452 return FALSE;
3454 for (i = 0; i < pbEncoded[1]; i++)
3456 val <<= 8;
3457 val |= pbEncoded[2 + i];
3459 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3460 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
3462 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3463 pvStructInfo = *(BYTE **)pvStructInfo;
3464 memcpy(pvStructInfo, &val, sizeof(unsigned int));
3468 else
3470 SetLastError(CRYPT_E_ASN1_BADTAG);
3471 ret = FALSE;
3474 __EXCEPT_PAGE_FAULT
3476 SetLastError(STATUS_ACCESS_VIOLATION);
3477 ret = FALSE;
3479 __ENDTRY
3480 return ret;
3483 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
3484 * if it fails.
3486 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
3487 do { \
3488 BYTE i; \
3490 (word) = 0; \
3491 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
3493 if (!isdigit(*(pbEncoded))) \
3495 SetLastError(CRYPT_E_ASN1_CORRUPT); \
3496 ret = FALSE; \
3498 else \
3500 (word) *= 10; \
3501 (word) += *(pbEncoded)++ - '0'; \
3504 } while (0)
3506 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
3507 SYSTEMTIME *sysTime)
3509 BOOL ret = TRUE;
3511 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
3513 WORD hours, minutes = 0;
3514 BYTE sign = *pbEncoded++;
3516 len--;
3517 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
3518 if (ret && hours >= 24)
3520 SetLastError(CRYPT_E_ASN1_CORRUPT);
3521 ret = FALSE;
3523 else if (len >= 2)
3525 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
3526 if (ret && minutes >= 60)
3528 SetLastError(CRYPT_E_ASN1_CORRUPT);
3529 ret = FALSE;
3532 if (ret)
3534 if (sign == '+')
3536 sysTime->wHour += hours;
3537 sysTime->wMinute += minutes;
3539 else
3541 if (hours > sysTime->wHour)
3543 sysTime->wDay--;
3544 sysTime->wHour = 24 - (hours - sysTime->wHour);
3546 else
3547 sysTime->wHour -= hours;
3548 if (minutes > sysTime->wMinute)
3550 sysTime->wHour--;
3551 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
3553 else
3554 sysTime->wMinute -= minutes;
3558 return ret;
3561 #define MIN_ENCODED_TIME_LENGTH 10
3563 static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
3564 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3565 DWORD *pcbDecoded)
3567 BOOL ret = FALSE;
3569 if (pbEncoded[0] == ASN_UTCTIME)
3571 if (cbEncoded <= 1)
3572 SetLastError(CRYPT_E_ASN1_EOD);
3573 else if (pbEncoded[1] > 0x7f)
3575 /* long-form date strings really can't be valid */
3576 SetLastError(CRYPT_E_ASN1_CORRUPT);
3578 else
3580 SYSTEMTIME sysTime = { 0 };
3581 BYTE len = pbEncoded[1];
3583 if (len < MIN_ENCODED_TIME_LENGTH)
3584 SetLastError(CRYPT_E_ASN1_CORRUPT);
3585 else
3587 ret = TRUE;
3588 if (pcbDecoded)
3589 *pcbDecoded = 2 + len;
3590 pbEncoded += 2;
3591 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
3592 if (sysTime.wYear >= 50)
3593 sysTime.wYear += 1900;
3594 else
3595 sysTime.wYear += 2000;
3596 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3597 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3598 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3599 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
3600 if (ret && len > 0)
3602 if (len >= 2 && isdigit(*pbEncoded) &&
3603 isdigit(*(pbEncoded + 1)))
3604 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3605 sysTime.wSecond);
3606 else if (isdigit(*pbEncoded))
3607 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
3608 sysTime.wSecond);
3609 if (ret)
3610 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3611 &sysTime);
3613 if (ret)
3615 if (!pvStructInfo)
3616 *pcbStructInfo = sizeof(FILETIME);
3617 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
3618 sizeof(FILETIME))))
3619 ret = SystemTimeToFileTime(&sysTime,
3620 (FILETIME *)pvStructInfo);
3625 else
3626 SetLastError(CRYPT_E_ASN1_BADTAG);
3627 return ret;
3630 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
3631 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3632 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3634 BOOL ret = FALSE;
3636 __TRY
3638 DWORD bytesNeeded;
3640 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
3641 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3642 if (ret)
3644 if (!pvStructInfo)
3645 *pcbStructInfo = bytesNeeded;
3646 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
3647 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
3649 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3650 pvStructInfo = *(BYTE **)pvStructInfo;
3651 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
3652 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3653 &bytesNeeded, NULL);
3657 __EXCEPT_PAGE_FAULT
3659 SetLastError(STATUS_ACCESS_VIOLATION);
3661 __ENDTRY
3662 return ret;
3665 static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
3666 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3667 DWORD *pcbDecoded)
3669 BOOL ret = FALSE;
3671 if (pbEncoded[0] == ASN_GENERALTIME)
3673 if (cbEncoded <= 1)
3674 SetLastError(CRYPT_E_ASN1_EOD);
3675 else if (pbEncoded[1] > 0x7f)
3677 /* long-form date strings really can't be valid */
3678 SetLastError(CRYPT_E_ASN1_CORRUPT);
3680 else
3682 BYTE len = pbEncoded[1];
3684 if (len < MIN_ENCODED_TIME_LENGTH)
3685 SetLastError(CRYPT_E_ASN1_CORRUPT);
3686 else
3688 SYSTEMTIME sysTime = { 0 };
3690 ret = TRUE;
3691 if (pcbDecoded)
3692 *pcbDecoded = 2 + len;
3693 pbEncoded += 2;
3694 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
3695 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3696 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3697 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3698 if (ret && len > 0)
3700 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3701 sysTime.wMinute);
3702 if (ret && len > 0)
3703 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3704 sysTime.wSecond);
3705 if (ret && len > 0 && (*pbEncoded == '.' ||
3706 *pbEncoded == ','))
3708 BYTE digits;
3710 pbEncoded++;
3711 len--;
3712 /* workaround macro weirdness */
3713 digits = min(len, 3);
3714 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
3715 sysTime.wMilliseconds);
3717 if (ret)
3718 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3719 &sysTime);
3721 if (ret)
3723 if (!pvStructInfo)
3724 *pcbStructInfo = sizeof(FILETIME);
3725 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
3726 sizeof(FILETIME))))
3727 ret = SystemTimeToFileTime(&sysTime,
3728 (FILETIME *)pvStructInfo);
3733 else
3734 SetLastError(CRYPT_E_ASN1_BADTAG);
3735 return ret;
3738 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
3739 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3740 DWORD *pcbDecoded)
3742 BOOL ret;
3743 InternalDecodeFunc decode = NULL;
3745 if (pbEncoded[0] == ASN_UTCTIME)
3746 decode = CRYPT_AsnDecodeUtcTimeInternal;
3747 else if (pbEncoded[0] == ASN_GENERALTIME)
3748 decode = CRYPT_AsnDecodeGeneralizedTime;
3749 if (decode)
3750 ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
3751 pcbStructInfo, pcbDecoded);
3752 else
3754 SetLastError(CRYPT_E_ASN1_BADTAG);
3755 ret = FALSE;
3757 return ret;
3760 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
3761 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3762 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3764 BOOL ret;
3766 __TRY
3768 DWORD bytesNeeded;
3770 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
3771 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3772 if (ret)
3774 if (!pvStructInfo)
3775 *pcbStructInfo = bytesNeeded;
3776 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3777 pvStructInfo, pcbStructInfo, bytesNeeded)))
3779 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3780 pvStructInfo = *(BYTE **)pvStructInfo;
3781 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
3782 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3783 &bytesNeeded, NULL);
3787 __EXCEPT_PAGE_FAULT
3789 SetLastError(STATUS_ACCESS_VIOLATION);
3790 ret = FALSE;
3792 __ENDTRY
3793 return ret;
3796 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
3797 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3798 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3800 BOOL ret = TRUE;
3802 __TRY
3804 if (pbEncoded[0] == ASN_SEQUENCEOF)
3806 DWORD bytesNeeded, dataLen, remainingLen, cValue;
3808 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3810 BYTE lenBytes;
3811 const BYTE *ptr;
3813 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3814 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
3815 cValue = 0;
3816 ptr = pbEncoded + 1 + lenBytes;
3817 remainingLen = dataLen;
3818 while (ret && remainingLen)
3820 DWORD nextLen;
3822 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3823 if (ret)
3825 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3827 remainingLen -= 1 + nextLenBytes + nextLen;
3828 ptr += 1 + nextLenBytes + nextLen;
3829 bytesNeeded += sizeof(CRYPT_DER_BLOB);
3830 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3831 bytesNeeded += 1 + nextLenBytes + nextLen;
3832 cValue++;
3835 if (ret)
3837 CRYPT_SEQUENCE_OF_ANY *seq;
3838 BYTE *nextPtr;
3839 DWORD i;
3841 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3842 pvStructInfo, pcbStructInfo, bytesNeeded)))
3844 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3845 pvStructInfo = *(BYTE **)pvStructInfo;
3846 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
3847 seq->cValue = cValue;
3848 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
3849 sizeof(*seq));
3850 nextPtr = (BYTE *)seq->rgValue +
3851 cValue * sizeof(CRYPT_DER_BLOB);
3852 ptr = pbEncoded + 1 + lenBytes;
3853 remainingLen = dataLen;
3854 i = 0;
3855 while (ret && remainingLen)
3857 DWORD nextLen;
3859 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3860 if (ret)
3862 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3864 seq->rgValue[i].cbData = 1 + nextLenBytes +
3865 nextLen;
3866 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3867 seq->rgValue[i].pbData = (BYTE *)ptr;
3868 else
3870 seq->rgValue[i].pbData = nextPtr;
3871 memcpy(nextPtr, ptr, 1 + nextLenBytes +
3872 nextLen);
3873 nextPtr += 1 + nextLenBytes + nextLen;
3875 remainingLen -= 1 + nextLenBytes + nextLen;
3876 ptr += 1 + nextLenBytes + nextLen;
3877 i++;
3884 else
3886 SetLastError(CRYPT_E_ASN1_BADTAG);
3887 ret = FALSE;
3890 __EXCEPT_PAGE_FAULT
3892 SetLastError(STATUS_ACCESS_VIOLATION);
3893 ret = FALSE;
3895 __ENDTRY
3896 return ret;
3899 static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded,
3900 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3901 DWORD *pcbDecoded)
3903 BOOL ret;
3905 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
3907 DWORD bytesNeeded, dataLen;
3909 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3911 struct AsnArrayDescriptor arrayDesc = {
3912 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
3913 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3914 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3915 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3917 if (dataLen)
3919 DWORD nameLen;
3921 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3922 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3923 0, NULL, NULL, &nameLen, NULL, NULL);
3924 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen;
3926 else
3927 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
3928 if (pcbDecoded)
3929 *pcbDecoded = 1 + lenBytes + dataLen;
3930 if (!pvStructInfo)
3931 *pcbStructInfo = bytesNeeded;
3932 else if (*pcbStructInfo < bytesNeeded)
3934 *pcbStructInfo = bytesNeeded;
3935 SetLastError(ERROR_MORE_DATA);
3936 ret = FALSE;
3938 else
3940 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
3942 if (dataLen)
3944 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3945 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3946 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3947 0, NULL, &name->u.FullName, pcbStructInfo, NULL,
3948 name->u.FullName.rgAltEntry);
3950 else
3951 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3955 else
3957 SetLastError(CRYPT_E_ASN1_BADTAG);
3958 ret = FALSE;
3960 return ret;
3963 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
3964 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3966 struct AsnDecodeSequenceItem items[] = {
3967 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
3968 DistPointName), CRYPT_AsnDecodeDistPointName,
3969 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
3970 DistPointName.u.FullName.rgAltEntry), 0 },
3971 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
3972 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
3973 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
3974 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
3975 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
3976 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
3978 BOOL ret;
3980 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3981 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3982 pcbDecoded, NULL);
3983 return ret;
3986 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
3987 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3988 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3990 BOOL ret;
3992 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3993 pDecodePara, pvStructInfo, *pcbStructInfo);
3995 __TRY
3997 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3998 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
3999 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
4001 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4002 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
4004 __EXCEPT_PAGE_FAULT
4006 SetLastError(STATUS_ACCESS_VIOLATION);
4007 ret = FALSE;
4009 __ENDTRY
4010 return ret;
4013 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
4014 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4015 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4017 BOOL ret;
4019 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4020 pDecodePara, pvStructInfo, *pcbStructInfo);
4022 __TRY
4024 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
4025 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
4027 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4028 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
4030 __EXCEPT_PAGE_FAULT
4032 SetLastError(STATUS_ACCESS_VIOLATION);
4033 ret = FALSE;
4035 __ENDTRY
4036 return ret;
4039 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
4040 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4041 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4043 BOOL ret;
4045 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4046 pDecodePara, pvStructInfo, *pcbStructInfo);
4048 __TRY
4050 struct AsnDecodeSequenceItem items[] = {
4051 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
4052 DistPointName), CRYPT_AsnDecodeDistPointName,
4053 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
4054 offsetof(CRL_ISSUING_DIST_POINT,
4055 DistPointName.u.FullName.rgAltEntry), 0 },
4056 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
4057 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4058 FALSE, 0 },
4059 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
4060 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4061 FALSE, 0 },
4062 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
4063 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
4064 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
4065 OnlySomeReasonFlags.pbData), 0 },
4066 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
4067 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
4070 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4071 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
4072 pcbStructInfo, NULL, NULL);
4074 __EXCEPT_PAGE_FAULT
4076 SetLastError(STATUS_ACCESS_VIOLATION);
4077 ret = FALSE;
4079 __ENDTRY
4080 return ret;
4083 static BOOL CRYPT_AsnDecodeMaximum(const BYTE *pbEncoded,
4084 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4085 DWORD *pcbDecoded)
4087 BOOL ret = FALSE;
4089 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4090 pvStructInfo, *pcbStructInfo, pcbDecoded);
4092 if (!cbEncoded)
4094 SetLastError(CRYPT_E_ASN1_EOD);
4095 return FALSE;
4097 if (pbEncoded[0] != (ASN_CONTEXT | 1))
4099 SetLastError(CRYPT_E_ASN1_BADTAG);
4100 return FALSE;
4102 /* The BOOL is implicit: if the integer is present, then it's TRUE */
4103 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
4104 pvStructInfo ? (BYTE *)pvStructInfo + sizeof(BOOL) : NULL, pcbStructInfo,
4105 pcbDecoded);
4106 if (ret && pvStructInfo)
4107 *(BOOL *)pvStructInfo = TRUE;
4108 TRACE("returning %d\n", ret);
4109 return ret;
4112 static BOOL CRYPT_AsnDecodeSubtree(const BYTE *pbEncoded,
4113 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4114 DWORD *pcbDecoded)
4116 BOOL ret;
4117 struct AsnDecodeSequenceItem items[] = {
4118 { 0, offsetof(CERT_GENERAL_SUBTREE, Base),
4119 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE, TRUE,
4120 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL), 0 },
4121 { ASN_CONTEXT | 0, offsetof(CERT_GENERAL_SUBTREE, dwMinimum),
4122 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
4123 { ASN_CONTEXT | 1, offsetof(CERT_GENERAL_SUBTREE, fMaximum),
4124 CRYPT_AsnDecodeMaximum, sizeof(BOOL) + sizeof(DWORD), TRUE, FALSE, 0,
4125 0 },
4127 CERT_GENERAL_SUBTREE *subtree = (CERT_GENERAL_SUBTREE *)pvStructInfo;
4129 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4130 pvStructInfo, *pcbStructInfo, pcbDecoded);
4132 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4133 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4134 pcbDecoded, subtree ? (BYTE *)subtree->Base.u.pwszURL : NULL);
4135 if (pcbDecoded)
4137 TRACE("%d\n", *pcbDecoded);
4138 if (*pcbDecoded < cbEncoded)
4139 TRACE("%02x %02x\n", *(pbEncoded + *pcbDecoded),
4140 *(pbEncoded + *pcbDecoded + 1));
4142 TRACE("returning %d\n", ret);
4143 return ret;
4146 static BOOL CRYPT_AsnDecodeSubtreeArray(const BYTE *pbEncoded,
4147 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4148 DWORD *pcbDecoded)
4150 BOOL ret = TRUE;
4151 struct AsnArrayDescriptor arrayDesc = { 0,
4152 CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
4153 offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
4154 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
4156 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4157 pvStructInfo, *pcbStructInfo, pcbDecoded);
4159 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4160 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
4161 array ? array->rgItems : NULL);
4162 return ret;
4166 static BOOL WINAPI CRYPT_AsnDecodeNameConstraints(DWORD dwCertEncodingType,
4167 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4168 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4170 BOOL ret = FALSE;
4172 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4173 pDecodePara, pvStructInfo, *pcbStructInfo);
4175 __TRY
4177 struct AsnDecodeSequenceItem items[] = {
4178 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
4179 offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
4180 CRYPT_AsnDecodeSubtreeArray, sizeof(struct GenericArray), TRUE, TRUE,
4181 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree), 0 },
4182 { ASN_CONTEXT | ASN_CONSTRUCTOR | 1,
4183 offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
4184 CRYPT_AsnDecodeSubtreeArray, sizeof(struct GenericArray), TRUE, TRUE,
4185 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree), 0 },
4188 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4189 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
4190 pcbStructInfo, NULL, NULL);
4192 __EXCEPT_PAGE_FAULT
4194 SetLastError(STATUS_ACCESS_VIOLATION);
4196 __ENDTRY
4197 return ret;
4200 static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded,
4201 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4202 DWORD *pcbDecoded)
4204 BOOL ret;
4205 struct AsnDecodeSequenceItem items[] = {
4206 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
4207 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
4208 Issuer.pbData) },
4209 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
4210 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
4211 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
4213 CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
4214 (CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
4216 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4217 pvStructInfo, *pcbStructInfo, pcbDecoded);
4219 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4220 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4221 pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL);
4222 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
4224 SetLastError(CRYPT_E_ASN1_CORRUPT);
4225 ret = FALSE;
4227 TRACE("returning %d\n", ret);
4228 return ret;
4231 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
4232 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4233 DWORD *pcbDecoded)
4235 CMSG_SIGNER_INFO *info = (CMSG_SIGNER_INFO *)pvStructInfo;
4236 struct AsnDecodeSequenceItem items[] = {
4237 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
4238 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4239 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
4240 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
4241 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
4242 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
4243 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4244 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
4245 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4246 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
4247 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4248 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
4249 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
4250 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4251 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
4252 HashEncryptionAlgorithm.pszObjId), 0 },
4253 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
4254 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
4255 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
4256 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4257 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
4258 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4259 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
4261 BOOL ret;
4263 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4264 pvStructInfo, *pcbStructInfo);
4266 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4267 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4268 pcbDecoded, info ? info->Issuer.pbData : NULL);
4269 return ret;
4272 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
4273 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4274 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4276 BOOL ret = FALSE;
4278 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4279 pDecodePara, pvStructInfo, *pcbStructInfo);
4281 __TRY
4283 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
4284 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
4285 if (ret && pvStructInfo)
4287 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
4288 pcbStructInfo, *pcbStructInfo);
4289 if (ret)
4291 CMSG_SIGNER_INFO *info;
4293 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4294 pvStructInfo = *(BYTE **)pvStructInfo;
4295 info = (CMSG_SIGNER_INFO *)pvStructInfo;
4296 info->Issuer.pbData = ((BYTE *)info +
4297 sizeof(CMSG_SIGNER_INFO));
4298 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
4299 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4300 pcbStructInfo, NULL);
4304 __EXCEPT_PAGE_FAULT
4306 SetLastError(STATUS_ACCESS_VIOLATION);
4308 __ENDTRY
4309 TRACE("returning %d\n", ret);
4310 return ret;
4313 static BOOL CRYPT_DecodeSignerArray(const BYTE *pbEncoded, DWORD cbEncoded,
4314 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4316 BOOL ret;
4317 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
4318 CRYPT_AsnDecodePKCSSignerInfoInternal, sizeof(CMSG_SIGNER_INFO), TRUE,
4319 offsetof(CMSG_SIGNER_INFO, Issuer.pbData) };
4320 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
4322 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4323 pvStructInfo, *pcbStructInfo, pcbDecoded);
4325 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4326 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
4327 array ? array->rgItems : NULL);
4328 return ret;
4331 BOOL CRYPT_AsnDecodePKCSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
4332 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
4333 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
4335 BOOL ret = FALSE;
4336 struct AsnDecodeSequenceItem items[] = {
4337 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version),
4338 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4339 /* Placeholder for the hash algorithms - redundant with those in the
4340 * signers, so just ignore them.
4342 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
4343 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
4344 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
4345 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
4346 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4347 offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
4348 CRYPT_DecodeDERArray, sizeof(struct GenericArray), TRUE, TRUE,
4349 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
4350 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4351 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_DecodeDERArray,
4352 sizeof(struct GenericArray), TRUE, TRUE,
4353 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
4354 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
4355 CRYPT_DecodeSignerArray, sizeof(struct GenericArray), TRUE, TRUE,
4356 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
4359 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4360 pDecodePara, signedInfo, *pcbSignedInfo);
4362 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4363 pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo,
4364 NULL, NULL);
4365 TRACE("returning %d\n", ret);
4366 return ret;
4369 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
4370 LPCSTR lpszStructType)
4372 CryptDecodeObjectExFunc decodeFunc = NULL;
4374 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
4375 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
4377 SetLastError(ERROR_FILE_NOT_FOUND);
4378 return NULL;
4380 if (!HIWORD(lpszStructType))
4382 switch (LOWORD(lpszStructType))
4384 case LOWORD(X509_CERT):
4385 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
4386 break;
4387 case LOWORD(X509_CERT_TO_BE_SIGNED):
4388 decodeFunc = CRYPT_AsnDecodeCert;
4389 break;
4390 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
4391 decodeFunc = CRYPT_AsnDecodeCRL;
4392 break;
4393 case LOWORD(X509_EXTENSIONS):
4394 decodeFunc = CRYPT_AsnDecodeExtensions;
4395 break;
4396 case LOWORD(X509_NAME_VALUE):
4397 decodeFunc = CRYPT_AsnDecodeNameValue;
4398 break;
4399 case LOWORD(X509_NAME):
4400 decodeFunc = CRYPT_AsnDecodeName;
4401 break;
4402 case LOWORD(X509_PUBLIC_KEY_INFO):
4403 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
4404 break;
4405 case LOWORD(X509_AUTHORITY_KEY_ID):
4406 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4407 break;
4408 case LOWORD(X509_ALTERNATE_NAME):
4409 decodeFunc = CRYPT_AsnDecodeAltName;
4410 break;
4411 case LOWORD(X509_BASIC_CONSTRAINTS):
4412 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4413 break;
4414 case LOWORD(X509_BASIC_CONSTRAINTS2):
4415 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4416 break;
4417 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
4418 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
4419 break;
4420 case LOWORD(X509_UNICODE_NAME):
4421 decodeFunc = CRYPT_AsnDecodeUnicodeName;
4422 break;
4423 case LOWORD(PKCS_ATTRIBUTE):
4424 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
4425 break;
4426 case LOWORD(X509_UNICODE_NAME_VALUE):
4427 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
4428 break;
4429 case LOWORD(X509_OCTET_STRING):
4430 decodeFunc = CRYPT_AsnDecodeOctets;
4431 break;
4432 case LOWORD(X509_BITS):
4433 case LOWORD(X509_KEY_USAGE):
4434 decodeFunc = CRYPT_AsnDecodeBits;
4435 break;
4436 case LOWORD(X509_INTEGER):
4437 decodeFunc = CRYPT_AsnDecodeInt;
4438 break;
4439 case LOWORD(X509_MULTI_BYTE_INTEGER):
4440 decodeFunc = CRYPT_AsnDecodeInteger;
4441 break;
4442 case LOWORD(X509_MULTI_BYTE_UINT):
4443 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
4444 break;
4445 case LOWORD(X509_ENUMERATED):
4446 decodeFunc = CRYPT_AsnDecodeEnumerated;
4447 break;
4448 case LOWORD(X509_CHOICE_OF_TIME):
4449 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
4450 break;
4451 case LOWORD(X509_AUTHORITY_KEY_ID2):
4452 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4453 break;
4454 case LOWORD(PKCS_CONTENT_INFO):
4455 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
4456 break;
4457 case LOWORD(X509_SEQUENCE_OF_ANY):
4458 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
4459 break;
4460 case LOWORD(PKCS_UTC_TIME):
4461 decodeFunc = CRYPT_AsnDecodeUtcTime;
4462 break;
4463 case LOWORD(X509_CRL_DIST_POINTS):
4464 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4465 break;
4466 case LOWORD(X509_ENHANCED_KEY_USAGE):
4467 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4468 break;
4469 case LOWORD(PKCS_ATTRIBUTES):
4470 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
4471 break;
4472 case LOWORD(X509_ISSUING_DIST_POINT):
4473 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4474 break;
4475 case LOWORD(X509_NAME_CONSTRAINTS):
4476 decodeFunc = CRYPT_AsnDecodeNameConstraints;
4477 break;
4478 case LOWORD(PKCS7_SIGNER_INFO):
4479 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
4480 break;
4483 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4484 decodeFunc = CRYPT_AsnDecodeExtensions;
4485 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4486 decodeFunc = CRYPT_AsnDecodeUtcTime;
4487 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4488 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4489 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4490 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4491 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4492 decodeFunc = CRYPT_AsnDecodeEnumerated;
4493 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4494 decodeFunc = CRYPT_AsnDecodeBits;
4495 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4496 decodeFunc = CRYPT_AsnDecodeOctets;
4497 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4498 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4499 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4500 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4501 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4502 decodeFunc = CRYPT_AsnDecodeAltName;
4503 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4504 decodeFunc = CRYPT_AsnDecodeAltName;
4505 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4506 decodeFunc = CRYPT_AsnDecodeAltName;
4507 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4508 decodeFunc = CRYPT_AsnDecodeAltName;
4509 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4510 decodeFunc = CRYPT_AsnDecodeAltName;
4511 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4512 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4513 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4514 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4515 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4516 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4517 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
4518 decodeFunc = CRYPT_AsnDecodeNameConstraints;
4519 return decodeFunc;
4522 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
4523 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4525 static HCRYPTOIDFUNCSET set = NULL;
4526 CryptDecodeObjectFunc decodeFunc = NULL;
4528 if (!set)
4529 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
4530 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4531 (void **)&decodeFunc, hFunc);
4532 return decodeFunc;
4535 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
4536 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4538 static HCRYPTOIDFUNCSET set = NULL;
4539 CryptDecodeObjectExFunc decodeFunc = NULL;
4541 if (!set)
4542 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
4543 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4544 (void **)&decodeFunc, hFunc);
4545 return decodeFunc;
4548 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4549 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
4550 DWORD *pcbStructInfo)
4552 BOOL ret = FALSE;
4553 CryptDecodeObjectFunc pCryptDecodeObject = NULL;
4554 CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
4555 HCRYPTOIDFUNCADDR hFunc = NULL;
4557 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
4558 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
4559 pvStructInfo, pcbStructInfo);
4561 if (!pvStructInfo && !pcbStructInfo)
4563 SetLastError(ERROR_INVALID_PARAMETER);
4564 return FALSE;
4566 if (!cbEncoded)
4568 SetLastError(CRYPT_E_ASN1_EOD);
4569 return FALSE;
4571 if (cbEncoded > MAX_ENCODED_LEN)
4573 SetLastError(CRYPT_E_ASN1_LARGE);
4574 return FALSE;
4577 if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
4578 lpszStructType)))
4580 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4581 debugstr_a(lpszStructType));
4582 pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
4583 lpszStructType, &hFunc);
4584 if (!pCryptDecodeObject)
4585 pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
4586 lpszStructType, &hFunc);
4588 if (pCryptDecodeObject)
4589 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4590 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4591 else if (pCryptDecodeObjectEx)
4592 ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
4593 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
4594 pvStructInfo, pcbStructInfo);
4595 if (hFunc)
4596 CryptFreeOIDFunctionAddress(hFunc, 0);
4597 TRACE_(crypt)("returning %d\n", ret);
4598 return ret;
4601 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4602 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4603 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4605 BOOL ret = FALSE;
4606 CryptDecodeObjectExFunc decodeFunc;
4607 HCRYPTOIDFUNCADDR hFunc = NULL;
4609 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
4610 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
4611 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4613 if (!pvStructInfo && !pcbStructInfo)
4615 SetLastError(ERROR_INVALID_PARAMETER);
4616 return FALSE;
4618 if (!cbEncoded)
4620 SetLastError(CRYPT_E_ASN1_EOD);
4621 return FALSE;
4623 if (cbEncoded > MAX_ENCODED_LEN)
4625 SetLastError(CRYPT_E_ASN1_LARGE);
4626 return FALSE;
4629 SetLastError(NOERROR);
4630 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
4631 *(BYTE **)pvStructInfo = NULL;
4632 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
4633 if (!decodeFunc)
4635 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4636 debugstr_a(lpszStructType));
4637 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
4638 &hFunc);
4640 if (decodeFunc)
4641 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
4642 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4643 else
4645 CryptDecodeObjectFunc pCryptDecodeObject =
4646 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
4648 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
4649 * directly, as that could cause an infinite loop.
4651 if (pCryptDecodeObject)
4653 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4655 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4656 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
4657 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4658 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
4659 ret = pCryptDecodeObject(dwCertEncodingType,
4660 lpszStructType, pbEncoded, cbEncoded, dwFlags,
4661 *(BYTE **)pvStructInfo, pcbStructInfo);
4663 else
4664 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4665 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4668 if (hFunc)
4669 CryptFreeOIDFunctionAddress(hFunc, 0);
4670 TRACE_(crypt)("returning %d\n", ret);
4671 return ret;