crypt32: Simplify DecodePathLenConstraint.
[wine/hacks.git] / dlls / crypt32 / decode.c
blob7b231ea85c9856a6dcbb3964a1f1438de0b7a7be
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 <assert.h>
34 #include <stdarg.h>
35 #include <stdio.h>
36 #include <stdlib.h>
38 #define NONAMELESSUNION
40 #include "windef.h"
41 #include "winbase.h"
42 #include "wincrypt.h"
43 #include "winnls.h"
44 #include "snmp.h"
45 #include "wine/debug.h"
46 #include "wine/exception.h"
47 #include "crypt32_private.h"
49 /* This is a bit arbitrary, but to set some limit: */
50 #define MAX_ENCODED_LEN 0x02000000
52 #define ASN_FLAGS_MASK 0xe0
53 #define ASN_TYPE_MASK 0x1f
55 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
56 WINE_DECLARE_DEBUG_CHANNEL(crypt);
58 struct GenericArray
60 DWORD cItems;
61 BYTE *rgItems;
64 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
65 DWORD, DWORD, void *, DWORD *);
66 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
67 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
69 /* Internal decoders don't do memory allocation or exception handling, and
70 * they report how many bytes they decoded.
72 typedef BOOL (*InternalDecodeFunc)(const BYTE *pbEncoded, DWORD cbEncoded,
73 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
75 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
76 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
77 DWORD *pcbDecoded);
78 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
79 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
80 DWORD *pcbDecoded);
81 /* Like CRYPT_AsnDecodeExtensions, except assumes rgExtension is set ahead of
82 * time, doesn't do memory allocation, and doesn't do exception handling.
84 static BOOL CRYPT_AsnDecodeExtensionsInternal(const BYTE *pbEncoded,
85 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
86 DWORD *pcbDecoded);
87 /* Assumes algo->Parameters.pbData is set ahead of time. */
88 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
89 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
90 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
91 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
92 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
93 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
94 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
95 DWORD *pcbDecoded);
96 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
97 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
98 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
99 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
100 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
101 * member has been initialized, doesn't do exception handling, and doesn't do
102 * memory allocation. Also doesn't check tag, assumes the caller has checked
103 * it.
105 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
106 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
107 DWORD *pcbDecoded);
108 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
109 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
110 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
111 DWORD *pcbDecoded);
113 /* Gets the number of length bytes from the given (leading) length byte */
114 #define GET_LEN_BYTES(b) ((b) <= 0x80 ? 1 : 1 + ((b) & 0x7f))
116 /* Helper function to get the encoded length of the data starting at pbEncoded,
117 * where pbEncoded[0] is the tag. If the data are too short to contain a
118 * length or if the length is too large for cbEncoded, sets an appropriate
119 * error code and returns FALSE. If the encoded length is unknown due to
120 * indefinite length encoding, *len is set to CMSG_INDEFINITE_LENGTH.
122 static BOOL CRYPT_GetLengthIndefinite(const BYTE *pbEncoded, DWORD cbEncoded,
123 DWORD *len)
125 BOOL ret;
127 if (cbEncoded <= 1)
129 SetLastError(CRYPT_E_ASN1_CORRUPT);
130 ret = FALSE;
132 else if (pbEncoded[1] <= 0x7f)
134 if (pbEncoded[1] + 1 > cbEncoded)
136 SetLastError(CRYPT_E_ASN1_EOD);
137 ret = FALSE;
139 else
141 *len = pbEncoded[1];
142 ret = TRUE;
145 else if (pbEncoded[1] == 0x80)
147 *len = CMSG_INDEFINITE_LENGTH;
148 ret = TRUE;
150 else
152 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
154 if (lenLen > sizeof(DWORD) + 1)
156 SetLastError(CRYPT_E_ASN1_LARGE);
157 ret = FALSE;
159 else if (lenLen + 2 > cbEncoded)
161 SetLastError(CRYPT_E_ASN1_CORRUPT);
162 ret = FALSE;
164 else
166 DWORD out = 0;
168 pbEncoded += 2;
169 while (--lenLen)
171 out <<= 8;
172 out |= *pbEncoded++;
174 if (out + lenLen + 1 > cbEncoded)
176 SetLastError(CRYPT_E_ASN1_EOD);
177 ret = FALSE;
179 else
181 *len = out;
182 ret = TRUE;
186 return ret;
189 /* Like CRYPT_GetLengthIndefinite, but disallows indefinite-length encoding. */
190 static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
192 BOOL ret;
194 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, len)) &&
195 *len == CMSG_INDEFINITE_LENGTH)
197 SetLastError(CRYPT_E_ASN1_CORRUPT);
198 ret = FALSE;
200 return ret;
203 /* Helper function to check *pcbStructInfo, set it to the required size, and
204 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
205 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
206 * pointer to the newly allocated memory.
208 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
209 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
210 DWORD bytesNeeded)
212 BOOL ret = TRUE;
214 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
216 if (pDecodePara && pDecodePara->pfnAlloc)
217 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
218 else
219 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
220 if (!*(BYTE **)pvStructInfo)
221 ret = FALSE;
222 else
223 *pcbStructInfo = bytesNeeded;
225 else if (*pcbStructInfo < bytesNeeded)
227 *pcbStructInfo = bytesNeeded;
228 SetLastError(ERROR_MORE_DATA);
229 ret = FALSE;
231 return ret;
234 /* Helper function to check *pcbStructInfo and set it to the required size.
235 * Assumes pvStructInfo is not NULL.
237 static BOOL CRYPT_DecodeCheckSpace(DWORD *pcbStructInfo, DWORD bytesNeeded)
239 BOOL ret;
241 if (*pcbStructInfo < bytesNeeded)
243 *pcbStructInfo = bytesNeeded;
244 SetLastError(ERROR_MORE_DATA);
245 ret = FALSE;
247 else
249 *pcbStructInfo = bytesNeeded;
250 ret = TRUE;
252 return ret;
255 /* tag:
256 * The expected tag of the item. If tag is 0, decodeFunc is called
257 * regardless of the tag value seen.
258 * offset:
259 * A sequence is decoded into a struct. The offset member is the
260 * offset of this item within that struct.
261 * decodeFunc:
262 * The decoder function to use. If this is NULL, then the member isn't
263 * decoded, but minSize space is reserved for it.
264 * minSize:
265 * The minimum amount of space occupied after decoding. You must set this.
266 * optional:
267 * If true, and the tag doesn't match the expected tag for this item,
268 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
269 * filled with 0 for this member.
270 * hasPointer, pointerOffset:
271 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
272 * the offset within the struct of the data pointer (or to the
273 * first data pointer, if more than one exist).
274 * size:
275 * Used by CRYPT_AsnDecodeSequence, not for your use.
277 struct AsnDecodeSequenceItem
279 BYTE tag;
280 DWORD offset;
281 InternalDecodeFunc decodeFunc;
282 DWORD minSize;
283 BOOL optional;
284 BOOL hasPointer;
285 DWORD pointerOffset;
286 DWORD size;
289 /* Decodes the items in a sequence, where the items are described in items,
290 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
291 * pvStructInfo. nextData is a pointer to the memory location at which the
292 * first decoded item with a dynamic pointer should point.
293 * Upon decoding, *cbDecoded is the total number of bytes decoded.
294 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
296 static BOOL CRYPT_AsnDecodeSequenceItems(struct AsnDecodeSequenceItem items[],
297 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
298 void *pvStructInfo, BYTE *nextData, DWORD *cbDecoded)
300 BOOL ret;
301 DWORD i, decoded = 0;
302 const BYTE *ptr = pbEncoded;
304 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
305 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
307 for (i = 0, ret = TRUE; ret && i < cItem; i++)
309 if (cbEncoded - (ptr - pbEncoded) != 0)
311 DWORD nextItemLen;
313 if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
314 &nextItemLen)))
316 BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
318 if (ptr[0] == items[i].tag || !items[i].tag)
320 if (nextData && pvStructInfo && items[i].hasPointer)
322 TRACE("Setting next pointer to %p\n",
323 nextData);
324 *(BYTE **)((BYTE *)pvStructInfo +
325 items[i].pointerOffset) = nextData;
327 if (items[i].decodeFunc)
329 if (pvStructInfo)
330 TRACE("decoding item %d\n", i);
331 else
332 TRACE("sizing item %d\n", i);
333 ret = items[i].decodeFunc(ptr,
334 1 + nextItemLenBytes + nextItemLen,
335 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
336 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
337 : NULL, &items[i].size, NULL);
338 if (ret)
340 /* Account for alignment padding */
341 if (items[i].size % sizeof(DWORD_PTR))
342 items[i].size += sizeof(DWORD_PTR) -
343 items[i].size % sizeof(DWORD_PTR);
344 TRACE("item %d size: %d\n", i, items[i].size);
345 if (nextData && items[i].hasPointer &&
346 items[i].size > items[i].minSize)
347 nextData += items[i].size - items[i].minSize;
348 ptr += 1 + nextItemLenBytes + nextItemLen;
349 decoded += 1 + nextItemLenBytes + nextItemLen;
350 TRACE("item %d: decoded %d bytes\n", i,
351 1 + nextItemLenBytes + nextItemLen);
353 else if (items[i].optional &&
354 GetLastError() == CRYPT_E_ASN1_BADTAG)
356 TRACE("skipping optional item %d\n", i);
357 items[i].size = items[i].minSize;
358 SetLastError(NOERROR);
359 ret = TRUE;
361 else
362 TRACE("item %d failed: %08x\n", i,
363 GetLastError());
365 else
367 TRACE("item %d: decoded %d bytes\n", i,
368 1 + nextItemLenBytes + nextItemLen);
369 ptr += 1 + nextItemLenBytes + nextItemLen;
370 decoded += 1 + nextItemLenBytes + nextItemLen;
371 items[i].size = items[i].minSize;
374 else if (items[i].optional)
376 TRACE("skipping optional item %d\n", i);
377 items[i].size = items[i].minSize;
379 else
381 TRACE("item %d: tag %02x doesn't match expected %02x\n",
382 i, ptr[0], items[i].tag);
383 SetLastError(CRYPT_E_ASN1_BADTAG);
384 ret = FALSE;
388 else if (items[i].optional)
390 TRACE("missing optional item %d, skipping\n", i);
391 items[i].size = items[i].minSize;
393 else
395 TRACE("not enough bytes for item %d, failing\n", i);
396 SetLastError(CRYPT_E_ASN1_CORRUPT);
397 ret = FALSE;
400 if (cbDecoded)
401 *cbDecoded = decoded;
402 TRACE("returning %d\n", ret);
403 return ret;
406 /* This decodes an arbitrary sequence into a contiguous block of memory
407 * (basically, a struct.) Each element being decoded is described by a struct
408 * AsnDecodeSequenceItem, see above.
409 * startingPointer is an optional pointer to the first place where dynamic
410 * data will be stored. If you know the starting offset, you may pass it
411 * here. Otherwise, pass NULL, and one will be inferred from the items.
413 static BOOL CRYPT_AsnDecodeSequence(struct AsnDecodeSequenceItem items[],
414 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
415 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
416 DWORD *pcbDecoded, void *startingPointer)
418 BOOL ret;
420 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
421 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
422 startingPointer);
424 if (pbEncoded[0] == ASN_SEQUENCE)
426 DWORD dataLen;
428 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
430 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
431 const BYTE *ptr = pbEncoded + 1 + lenBytes;
433 cbEncoded -= 1 + lenBytes;
434 if (dataLen == CMSG_INDEFINITE_LENGTH)
435 cbEncoded = dataLen;
436 else if (cbEncoded < dataLen)
438 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
439 cbEncoded);
440 SetLastError(CRYPT_E_ASN1_CORRUPT);
441 ret = FALSE;
443 else
444 cbEncoded = dataLen;
445 if (ret)
447 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
448 ptr, cbEncoded, dwFlags, NULL, NULL, &cbDecoded);
449 if (ret && dataLen == CMSG_INDEFINITE_LENGTH)
451 if (cbDecoded > cbEncoded - 2)
453 /* Not enough space for 0 TLV */
454 SetLastError(CRYPT_E_ASN1_CORRUPT);
455 ret = FALSE;
457 else if (*(ptr + cbDecoded) != 0 ||
458 *(ptr + cbDecoded + 1) != 0)
460 TRACE("expected 0 TLV\n");
461 SetLastError(CRYPT_E_ASN1_CORRUPT);
462 ret = FALSE;
464 else
465 cbDecoded += 2;
468 if (ret && cbDecoded != cbEncoded)
470 TRACE("expected %d decoded, got %d, failing\n", cbEncoded,
471 cbDecoded);
472 SetLastError(CRYPT_E_ASN1_CORRUPT);
473 ret = FALSE;
475 if (ret)
477 DWORD i, bytesNeeded = 0, structSize = 0;
479 for (i = 0; i < cItem; i++)
481 bytesNeeded += items[i].size;
482 structSize += items[i].minSize;
484 if (ret && pcbDecoded)
485 *pcbDecoded = 1 + lenBytes + cbDecoded;
486 if (!pvStructInfo)
487 *pcbStructInfo = bytesNeeded;
488 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
489 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
491 BYTE *nextData;
493 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
494 pvStructInfo = *(BYTE **)pvStructInfo;
495 if (startingPointer)
496 nextData = (BYTE *)startingPointer;
497 else
498 nextData = (BYTE *)pvStructInfo + structSize;
499 memset(pvStructInfo, 0, structSize);
500 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
501 ptr, cbEncoded, dwFlags, pvStructInfo, nextData,
502 &cbDecoded);
507 else
509 SetLastError(CRYPT_E_ASN1_BADTAG);
510 ret = FALSE;
512 TRACE("returning %d (%08x)\n", ret, GetLastError());
513 return ret;
516 /* tag:
517 * The expected tag of the entire encoded array (usually a variant
518 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
519 * regardless of the tag seen.
520 * decodeFunc:
521 * used to decode each item in the array
522 * itemSize:
523 * is the minimum size of each decoded item
524 * hasPointer:
525 * indicates whether each item has a dynamic pointer
526 * pointerOffset:
527 * indicates the offset within itemSize at which the pointer exists
529 struct AsnArrayDescriptor
531 BYTE tag;
532 InternalDecodeFunc decodeFunc;
533 DWORD itemSize;
534 BOOL hasPointer;
535 DWORD pointerOffset;
538 struct AsnArrayItemSize
540 DWORD encodedLen;
541 DWORD size;
544 /* Decodes an array of like types into a struct GenericArray.
545 * The layout and decoding of the array are described by a struct
546 * AsnArrayDescriptor.
548 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
549 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
550 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
551 DWORD *pcbDecoded, void *startingPointer)
553 BOOL ret = TRUE;
555 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
556 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
557 startingPointer);
559 if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
561 DWORD dataLen;
563 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
565 DWORD bytesNeeded, cItems = 0, decoded;
566 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
567 /* There can be arbitrarily many items, but there is often only one.
569 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
571 decoded = 1 + lenBytes;
572 bytesNeeded = sizeof(struct GenericArray);
573 if (dataLen)
575 const BYTE *ptr;
576 BOOL doneDecoding = FALSE;
578 for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
580 DWORD itemLenBytes;
582 itemLenBytes = GET_LEN_BYTES(ptr[1]);
583 if (dataLen == CMSG_INDEFINITE_LENGTH)
585 if (ptr[0] == 0)
587 doneDecoding = TRUE;
588 if (itemLenBytes != 1 || ptr[1] != 0)
590 SetLastError(CRYPT_E_ASN1_CORRUPT);
591 ret = FALSE;
593 else
594 decoded += 2;
597 else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
598 doneDecoding = TRUE;
599 if (!doneDecoding)
601 DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
603 /* Each item decoded may not tolerate extraneous bytes,
604 * so get the length of the next element if known.
606 if ((ret = CRYPT_GetLengthIndefinite(ptr,
607 cbEncoded - (ptr - pbEncoded), &itemDataLen)))
609 if (itemDataLen == CMSG_INDEFINITE_LENGTH)
610 itemEncoded = cbEncoded - (ptr - pbEncoded);
611 else
612 itemEncoded = 1 + itemLenBytes + itemDataLen;
614 if (ret)
615 ret = arrayDesc->decodeFunc(ptr, itemEncoded,
616 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size,
617 &itemDecoded);
618 if (ret)
620 cItems++;
621 if (itemSizes != &itemSize)
622 itemSizes = CryptMemRealloc(itemSizes,
623 cItems * sizeof(struct AsnArrayItemSize));
624 else if (cItems > 1)
626 itemSizes =
627 CryptMemAlloc(
628 cItems * sizeof(struct AsnArrayItemSize));
629 if (itemSizes)
630 memcpy(itemSizes, &itemSize,
631 sizeof(itemSize));
633 if (itemSizes)
635 decoded += itemDecoded;
636 itemSizes[cItems - 1].encodedLen = itemEncoded;
637 itemSizes[cItems - 1].size = size;
638 bytesNeeded += size;
639 ptr += itemEncoded;
641 else
642 ret = FALSE;
647 if (ret)
649 if (pcbDecoded)
650 *pcbDecoded = decoded;
651 if (!pvStructInfo)
652 *pcbStructInfo = bytesNeeded;
653 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
654 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
656 DWORD i;
657 BYTE *nextData;
658 const BYTE *ptr;
659 struct GenericArray *array;
661 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
662 pvStructInfo = *(BYTE **)pvStructInfo;
663 array = (struct GenericArray *)pvStructInfo;
664 array->cItems = cItems;
665 if (startingPointer)
666 array->rgItems = startingPointer;
667 else
668 array->rgItems = (BYTE *)array +
669 sizeof(struct GenericArray);
670 nextData = (BYTE *)array->rgItems +
671 array->cItems * arrayDesc->itemSize;
672 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
673 i < cItems && ptr - pbEncoded - 1 - lenBytes <
674 dataLen; i++)
676 if (arrayDesc->hasPointer)
677 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
678 + arrayDesc->pointerOffset) = nextData;
679 ret = arrayDesc->decodeFunc(ptr,
680 itemSizes[i].encodedLen,
681 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
682 array->rgItems + i * arrayDesc->itemSize,
683 &itemSizes[i].size, NULL);
684 if (ret)
686 DWORD nextLen;
688 nextData += itemSizes[i].size - arrayDesc->itemSize;
689 ret = CRYPT_GetLen(ptr,
690 cbEncoded - (ptr - pbEncoded), &nextLen);
691 if (ret)
692 ptr += nextLen + 1 + GET_LEN_BYTES(ptr[1]);
697 if (itemSizes != &itemSize)
698 CryptMemFree(itemSizes);
701 else
703 SetLastError(CRYPT_E_ASN1_BADTAG);
704 ret = FALSE;
706 return ret;
709 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
710 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
711 * to CRYPT_E_ASN1_CORRUPT.
712 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
713 * set!
715 static BOOL CRYPT_AsnDecodeDerBlob(const BYTE *pbEncoded, DWORD cbEncoded,
716 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
718 BOOL ret;
719 DWORD dataLen;
721 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
723 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
724 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
726 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
727 bytesNeeded += 1 + lenBytes + dataLen;
729 if (pcbDecoded)
730 *pcbDecoded = 1 + lenBytes + dataLen;
731 if (!pvStructInfo)
732 *pcbStructInfo = bytesNeeded;
733 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded)))
735 CRYPT_DER_BLOB *blob;
737 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
738 pvStructInfo = *(BYTE **)pvStructInfo;
739 blob = (CRYPT_DER_BLOB *)pvStructInfo;
740 blob->cbData = 1 + lenBytes + dataLen;
741 if (blob->cbData)
743 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
744 blob->pbData = (BYTE *)pbEncoded;
745 else
747 assert(blob->pbData);
748 memcpy(blob->pbData, pbEncoded, blob->cbData);
751 else
753 SetLastError(CRYPT_E_ASN1_CORRUPT);
754 ret = FALSE;
758 return ret;
761 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
762 static BOOL CRYPT_AsnDecodeBitsSwapBytes(const BYTE *pbEncoded,
763 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
764 DWORD *pcbDecoded)
766 BOOL ret;
768 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
769 pvStructInfo, *pcbStructInfo, pcbDecoded);
771 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
772 * place.
774 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
775 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
776 pcbDecoded);
777 if (ret && pvStructInfo)
779 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
781 if (blob->cbData)
783 DWORD i;
784 BYTE temp;
786 for (i = 0; i < blob->cbData / 2; i++)
788 temp = blob->pbData[i];
789 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
790 blob->pbData[blob->cbData - i - 1] = temp;
794 TRACE("returning %d (%08x)\n", ret, GetLastError());
795 return ret;
798 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
799 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
800 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
802 BOOL ret = TRUE;
804 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
805 pDecodePara, pvStructInfo, *pcbStructInfo);
807 __TRY
809 struct AsnDecodeSequenceItem items[] = {
810 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
811 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
812 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
813 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
814 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
815 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
816 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
817 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
818 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
819 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
822 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
823 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
824 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
825 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
826 pcbStructInfo, NULL, NULL);
828 __EXCEPT_PAGE_FAULT
830 SetLastError(STATUS_ACCESS_VIOLATION);
831 ret = FALSE;
833 __ENDTRY
835 TRACE("Returning %d (%08x)\n", ret, GetLastError());
836 return ret;
839 static BOOL CRYPT_AsnDecodeCertVersion(const BYTE *pbEncoded, DWORD cbEncoded,
840 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
842 BOOL ret;
843 DWORD dataLen;
845 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
847 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
849 ret = CRYPT_AsnDecodeIntInternal(pbEncoded + 1 + lenBytes, dataLen,
850 dwFlags, pvStructInfo, pcbStructInfo, NULL);
851 if (pcbDecoded)
852 *pcbDecoded = 1 + lenBytes + dataLen;
854 return ret;
857 static BOOL CRYPT_AsnDecodeValidity(const BYTE *pbEncoded, DWORD cbEncoded,
858 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
860 BOOL ret;
862 struct AsnDecodeSequenceItem items[] = {
863 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
864 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
865 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
866 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
869 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
870 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
871 pcbDecoded, NULL);
872 return ret;
875 static BOOL CRYPT_AsnDecodeCertExtensions(const BYTE *pbEncoded,
876 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
877 DWORD *pcbDecoded)
879 BOOL ret;
880 DWORD dataLen;
882 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
884 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
886 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded + 1 + lenBytes,
887 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
888 if (ret && pcbDecoded)
889 *pcbDecoded = 1 + lenBytes + dataLen;
891 return ret;
894 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
895 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
896 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
898 BOOL ret = TRUE;
899 struct AsnDecodeSequenceItem items[] = {
900 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
901 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
902 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
903 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
904 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
905 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
906 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
907 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
908 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
909 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
910 Issuer.pbData) },
911 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
912 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
913 FALSE, 0 },
914 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
915 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
916 Subject.pbData) },
917 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
918 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
919 FALSE, TRUE, offsetof(CERT_INFO,
920 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
921 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
922 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
923 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
924 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
925 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
926 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
927 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
928 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
929 offsetof(CERT_INFO, rgExtension), 0 },
932 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
933 pDecodePara, pvStructInfo, *pcbStructInfo);
935 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
936 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
937 NULL, NULL);
938 if (ret && pvStructInfo)
940 CERT_INFO *info;
942 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
943 info = *(CERT_INFO **)pvStructInfo;
944 else
945 info = (CERT_INFO *)pvStructInfo;
946 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
947 !info->Subject.cbData)
949 SetLastError(CRYPT_E_ASN1_CORRUPT);
950 /* Don't need to deallocate, because it should have failed on the
951 * first pass (and no memory was allocated.)
953 ret = FALSE;
957 TRACE("Returning %d (%08x)\n", ret, GetLastError());
958 return ret;
961 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
962 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
963 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
965 BOOL ret = FALSE;
967 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
968 pDecodePara, pvStructInfo, *pcbStructInfo);
970 __TRY
972 DWORD size = 0;
974 /* Unless told not to, first try to decode it as a signed cert. */
975 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
977 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
979 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
980 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
981 (BYTE *)&signedCert, &size);
982 if (ret)
984 size = 0;
985 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
986 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
987 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
988 pvStructInfo, pcbStructInfo);
989 LocalFree(signedCert);
992 /* Failing that, try it as an unsigned cert */
993 if (!ret)
995 size = 0;
996 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
997 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
998 pDecodePara, pvStructInfo, pcbStructInfo);
1001 __EXCEPT_PAGE_FAULT
1003 SetLastError(STATUS_ACCESS_VIOLATION);
1005 __ENDTRY
1007 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1008 return ret;
1011 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
1012 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1014 BOOL ret;
1015 struct AsnDecodeSequenceItem items[] = {
1016 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
1017 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
1018 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
1019 { 0, offsetof(CRL_ENTRY, RevocationDate),
1020 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
1021 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
1022 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1023 offsetof(CRL_ENTRY, rgExtension), 0 },
1025 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
1027 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
1028 *pcbStructInfo);
1030 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1031 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, pcbDecoded,
1032 entry ? entry->SerialNumber.pbData : NULL);
1033 return ret;
1036 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
1037 * been set prior to calling.
1039 static BOOL CRYPT_AsnDecodeCRLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
1040 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1042 BOOL ret;
1043 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1044 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
1045 offsetof(CRL_ENTRY, SerialNumber.pbData) };
1046 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
1048 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1049 pvStructInfo, *pcbStructInfo, pcbDecoded);
1051 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1052 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1053 entries ? entries->rgItems : NULL);
1054 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1055 return ret;
1058 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1059 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1060 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1062 struct AsnDecodeSequenceItem items[] = {
1063 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1064 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1065 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1066 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1067 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1068 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1069 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1070 Issuer.pbData) },
1071 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1072 sizeof(FILETIME), FALSE, FALSE, 0 },
1073 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1074 sizeof(FILETIME), TRUE, FALSE, 0 },
1075 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1076 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
1077 offsetof(CRL_INFO, rgCRLEntry), 0 },
1078 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1079 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1080 offsetof(CRL_INFO, rgExtension), 0 },
1082 BOOL ret = TRUE;
1084 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1085 pDecodePara, pvStructInfo, *pcbStructInfo);
1087 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1088 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
1089 NULL, NULL);
1091 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1092 return ret;
1095 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1096 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1097 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1099 BOOL ret = FALSE;
1101 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1102 pDecodePara, pvStructInfo, *pcbStructInfo);
1104 __TRY
1106 DWORD size = 0;
1108 /* Unless told not to, first try to decode it as a signed crl. */
1109 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1111 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1113 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1114 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1115 (BYTE *)&signedCrl, &size);
1116 if (ret)
1118 size = 0;
1119 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1120 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1121 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1122 pvStructInfo, pcbStructInfo);
1123 LocalFree(signedCrl);
1126 /* Failing that, try it as an unsigned crl */
1127 if (!ret)
1129 size = 0;
1130 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1131 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1132 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1135 __EXCEPT_PAGE_FAULT
1137 SetLastError(STATUS_ACCESS_VIOLATION);
1139 __ENDTRY
1141 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1142 return ret;
1145 static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded,
1146 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1148 BOOL ret = TRUE;
1149 DWORD dataLen;
1151 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1152 pvStructInfo, *pcbStructInfo);
1154 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1156 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1157 DWORD bytesNeeded = sizeof(LPSTR);
1159 if (dataLen)
1161 /* The largest possible string for the first two components
1162 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1164 char firstTwo[6];
1165 const BYTE *ptr;
1167 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1168 pbEncoded[1 + lenBytes] / 40,
1169 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1170 * 40);
1171 bytesNeeded += strlen(firstTwo) + 1;
1172 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1173 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1175 /* large enough for ".4000000" */
1176 char str[9];
1177 int val = 0;
1179 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1180 (*ptr & 0x80))
1182 val <<= 7;
1183 val |= *ptr & 0x7f;
1184 ptr++;
1186 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1187 (*ptr & 0x80))
1189 SetLastError(CRYPT_E_ASN1_CORRUPT);
1190 ret = FALSE;
1192 else
1194 val <<= 7;
1195 val |= *ptr++;
1196 snprintf(str, sizeof(str), ".%d", val);
1197 bytesNeeded += strlen(str);
1201 if (pcbDecoded)
1202 *pcbDecoded = 1 + lenBytes + dataLen;
1203 if (!pvStructInfo)
1204 *pcbStructInfo = bytesNeeded;
1205 else if (*pcbStructInfo < bytesNeeded)
1207 *pcbStructInfo = bytesNeeded;
1208 SetLastError(ERROR_MORE_DATA);
1209 ret = FALSE;
1211 else
1213 if (dataLen)
1215 const BYTE *ptr;
1216 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1218 *pszObjId = 0;
1219 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1220 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1221 40) * 40);
1222 pszObjId += strlen(pszObjId);
1223 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1224 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1226 int val = 0;
1228 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1229 (*ptr & 0x80))
1231 val <<= 7;
1232 val |= *ptr & 0x7f;
1233 ptr++;
1235 val <<= 7;
1236 val |= *ptr++;
1237 sprintf(pszObjId, ".%d", val);
1238 pszObjId += strlen(pszObjId);
1241 else
1242 *(LPSTR *)pvStructInfo = NULL;
1243 *pcbStructInfo = bytesNeeded;
1246 return ret;
1249 static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded,
1250 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1252 BOOL ret;
1254 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1255 pvStructInfo, *pcbStructInfo);
1257 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1258 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1259 pvStructInfo, pcbStructInfo, pcbDecoded);
1260 else
1262 SetLastError(CRYPT_E_ASN1_BADTAG);
1263 ret = FALSE;
1265 return ret;
1268 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1269 * ahead of time!
1271 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
1272 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1274 struct AsnDecodeSequenceItem items[] = {
1275 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1276 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1277 offsetof(CERT_EXTENSION, pszObjId), 0 },
1278 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1279 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1280 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1281 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1282 offsetof(CERT_EXTENSION, Value.pbData) },
1284 BOOL ret = TRUE;
1285 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1287 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1288 *pcbStructInfo);
1290 if (ext)
1291 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1292 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1293 pbEncoded, cbEncoded, dwFlags, NULL, ext, pcbStructInfo,
1294 pcbDecoded, ext ? ext->pszObjId : NULL);
1295 if (ext)
1296 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1297 debugstr_a(ext->pszObjId));
1298 TRACE("returning %d (%08x)\n", ret, GetLastError());
1299 return ret;
1302 static BOOL CRYPT_AsnDecodeExtensionsInternal(const BYTE *pbEncoded,
1303 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1304 DWORD *pcbDecoded)
1306 BOOL ret = TRUE;
1307 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1308 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1309 offsetof(CERT_EXTENSION, pszObjId) };
1310 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1312 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1313 pvStructInfo, *pcbStructInfo, pcbDecoded);
1315 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1316 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1317 exts ? exts->rgExtension : NULL);
1318 return ret;
1321 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1322 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1323 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1325 BOOL ret = TRUE;
1327 __TRY
1329 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
1330 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1331 if (ret && pvStructInfo)
1333 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1334 pcbStructInfo, *pcbStructInfo);
1335 if (ret)
1337 CERT_EXTENSIONS *exts;
1339 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1340 pvStructInfo = *(BYTE **)pvStructInfo;
1341 exts = (CERT_EXTENSIONS *)pvStructInfo;
1342 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1343 sizeof(CERT_EXTENSIONS));
1344 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
1345 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1346 pcbStructInfo, NULL);
1350 __EXCEPT_PAGE_FAULT
1352 SetLastError(STATUS_ACCESS_VIOLATION);
1353 ret = FALSE;
1355 __ENDTRY
1356 return ret;
1359 /* Warning: this assumes the address of value->Value.pbData is already set, in
1360 * order to avoid overwriting memory. (In some cases, it may change it, if it
1361 * doesn't copy anything to memory.) Be sure to set it correctly!
1363 static BOOL CRYPT_AsnDecodeNameValueInternal(const BYTE *pbEncoded,
1364 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1365 DWORD *pcbDecoded)
1367 BOOL ret = TRUE;
1368 DWORD dataLen;
1369 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1371 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1373 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1374 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1376 switch (pbEncoded[0])
1378 case ASN_OCTETSTRING:
1379 valueType = CERT_RDN_OCTET_STRING;
1380 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1381 bytesNeeded += dataLen;
1382 break;
1383 case ASN_NUMERICSTRING:
1384 valueType = CERT_RDN_NUMERIC_STRING;
1385 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1386 bytesNeeded += dataLen;
1387 break;
1388 case ASN_PRINTABLESTRING:
1389 valueType = CERT_RDN_PRINTABLE_STRING;
1390 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1391 bytesNeeded += dataLen;
1392 break;
1393 case ASN_IA5STRING:
1394 valueType = CERT_RDN_IA5_STRING;
1395 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1396 bytesNeeded += dataLen;
1397 break;
1398 case ASN_T61STRING:
1399 valueType = CERT_RDN_T61_STRING;
1400 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1401 bytesNeeded += dataLen;
1402 break;
1403 case ASN_VIDEOTEXSTRING:
1404 valueType = CERT_RDN_VIDEOTEX_STRING;
1405 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1406 bytesNeeded += dataLen;
1407 break;
1408 case ASN_GRAPHICSTRING:
1409 valueType = CERT_RDN_GRAPHIC_STRING;
1410 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1411 bytesNeeded += dataLen;
1412 break;
1413 case ASN_VISIBLESTRING:
1414 valueType = CERT_RDN_VISIBLE_STRING;
1415 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1416 bytesNeeded += dataLen;
1417 break;
1418 case ASN_GENERALSTRING:
1419 valueType = CERT_RDN_GENERAL_STRING;
1420 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1421 bytesNeeded += dataLen;
1422 break;
1423 case ASN_UNIVERSALSTRING:
1424 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1425 SetLastError(CRYPT_E_ASN1_BADTAG);
1426 return FALSE;
1427 case ASN_BMPSTRING:
1428 valueType = CERT_RDN_BMP_STRING;
1429 bytesNeeded += dataLen;
1430 break;
1431 case ASN_UTF8STRING:
1432 valueType = CERT_RDN_UTF8_STRING;
1433 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1434 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1435 break;
1436 default:
1437 SetLastError(CRYPT_E_ASN1_BADTAG);
1438 return FALSE;
1441 if (pcbDecoded)
1442 *pcbDecoded = 1 + lenBytes + dataLen;
1443 if (!value)
1444 *pcbStructInfo = bytesNeeded;
1445 else if (*pcbStructInfo < bytesNeeded)
1447 *pcbStructInfo = bytesNeeded;
1448 SetLastError(ERROR_MORE_DATA);
1449 ret = FALSE;
1451 else
1453 *pcbStructInfo = bytesNeeded;
1454 value->dwValueType = valueType;
1455 if (dataLen)
1457 DWORD i;
1459 assert(value->Value.pbData);
1460 switch (pbEncoded[0])
1462 case ASN_OCTETSTRING:
1463 case ASN_NUMERICSTRING:
1464 case ASN_PRINTABLESTRING:
1465 case ASN_IA5STRING:
1466 case ASN_T61STRING:
1467 case ASN_VIDEOTEXSTRING:
1468 case ASN_GRAPHICSTRING:
1469 case ASN_VISIBLESTRING:
1470 case ASN_GENERALSTRING:
1471 value->Value.cbData = dataLen;
1472 if (dataLen)
1474 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1475 memcpy(value->Value.pbData,
1476 pbEncoded + 1 + lenBytes, dataLen);
1477 else
1478 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1479 lenBytes;
1481 break;
1482 case ASN_BMPSTRING:
1484 LPWSTR str = (LPWSTR)value->Value.pbData;
1486 value->Value.cbData = dataLen;
1487 for (i = 0; i < dataLen / 2; i++)
1488 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1489 pbEncoded[1 + lenBytes + 2 * i + 1];
1490 break;
1492 case ASN_UTF8STRING:
1494 LPWSTR str = (LPWSTR)value->Value.pbData;
1496 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1497 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1498 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1499 break;
1503 else
1505 value->Value.cbData = 0;
1506 value->Value.pbData = NULL;
1510 return ret;
1513 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1514 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1515 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1517 BOOL ret = TRUE;
1519 __TRY
1521 ret = CRYPT_AsnDecodeNameValueInternal(pbEncoded, cbEncoded,
1522 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1523 if (ret && pvStructInfo)
1525 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1526 pcbStructInfo, *pcbStructInfo);
1527 if (ret)
1529 CERT_NAME_VALUE *value;
1531 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1532 pvStructInfo = *(BYTE **)pvStructInfo;
1533 value = (CERT_NAME_VALUE *)pvStructInfo;
1534 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1535 ret = CRYPT_AsnDecodeNameValueInternal( pbEncoded, cbEncoded,
1536 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1537 pcbStructInfo, NULL);
1541 __EXCEPT_PAGE_FAULT
1543 SetLastError(STATUS_ACCESS_VIOLATION);
1544 ret = FALSE;
1546 __ENDTRY
1547 return ret;
1550 static BOOL CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE *pbEncoded,
1551 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1552 DWORD *pcbDecoded)
1554 BOOL ret = TRUE;
1555 DWORD dataLen;
1556 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1558 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1560 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1561 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1563 switch (pbEncoded[0])
1565 case ASN_NUMERICSTRING:
1566 valueType = CERT_RDN_NUMERIC_STRING;
1567 bytesNeeded += dataLen * 2;
1568 break;
1569 case ASN_PRINTABLESTRING:
1570 valueType = CERT_RDN_PRINTABLE_STRING;
1571 bytesNeeded += dataLen * 2;
1572 break;
1573 case ASN_IA5STRING:
1574 valueType = CERT_RDN_IA5_STRING;
1575 bytesNeeded += dataLen * 2;
1576 break;
1577 case ASN_T61STRING:
1578 valueType = CERT_RDN_T61_STRING;
1579 bytesNeeded += dataLen * 2;
1580 break;
1581 case ASN_VIDEOTEXSTRING:
1582 valueType = CERT_RDN_VIDEOTEX_STRING;
1583 bytesNeeded += dataLen * 2;
1584 break;
1585 case ASN_GRAPHICSTRING:
1586 valueType = CERT_RDN_GRAPHIC_STRING;
1587 bytesNeeded += dataLen * 2;
1588 break;
1589 case ASN_VISIBLESTRING:
1590 valueType = CERT_RDN_VISIBLE_STRING;
1591 bytesNeeded += dataLen * 2;
1592 break;
1593 case ASN_GENERALSTRING:
1594 valueType = CERT_RDN_GENERAL_STRING;
1595 bytesNeeded += dataLen * 2;
1596 break;
1597 case ASN_UNIVERSALSTRING:
1598 valueType = CERT_RDN_UNIVERSAL_STRING;
1599 bytesNeeded += dataLen / 2;
1600 break;
1601 case ASN_BMPSTRING:
1602 valueType = CERT_RDN_BMP_STRING;
1603 bytesNeeded += dataLen;
1604 break;
1605 case ASN_UTF8STRING:
1606 valueType = CERT_RDN_UTF8_STRING;
1607 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1608 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1609 break;
1610 default:
1611 SetLastError(CRYPT_E_ASN1_BADTAG);
1612 return FALSE;
1615 if (pcbDecoded)
1616 *pcbDecoded = 1 + lenBytes + dataLen;
1617 if (!value)
1618 *pcbStructInfo = bytesNeeded;
1619 else if (*pcbStructInfo < bytesNeeded)
1621 *pcbStructInfo = bytesNeeded;
1622 SetLastError(ERROR_MORE_DATA);
1623 ret = FALSE;
1625 else
1627 *pcbStructInfo = bytesNeeded;
1628 value->dwValueType = valueType;
1629 if (dataLen)
1631 DWORD i;
1632 LPWSTR str = (LPWSTR)value->Value.pbData;
1634 assert(value->Value.pbData);
1635 switch (pbEncoded[0])
1637 case ASN_NUMERICSTRING:
1638 case ASN_PRINTABLESTRING:
1639 case ASN_IA5STRING:
1640 case ASN_T61STRING:
1641 case ASN_VIDEOTEXSTRING:
1642 case ASN_GRAPHICSTRING:
1643 case ASN_VISIBLESTRING:
1644 case ASN_GENERALSTRING:
1645 value->Value.cbData = dataLen * 2;
1646 for (i = 0; i < dataLen; i++)
1647 str[i] = pbEncoded[1 + lenBytes + i];
1648 break;
1649 case ASN_UNIVERSALSTRING:
1650 value->Value.cbData = dataLen / 2;
1651 for (i = 0; i < dataLen / 4; i++)
1652 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1653 | pbEncoded[1 + lenBytes + 2 * i + 3];
1654 break;
1655 case ASN_BMPSTRING:
1656 value->Value.cbData = dataLen;
1657 for (i = 0; i < dataLen / 2; i++)
1658 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1659 pbEncoded[1 + lenBytes + 2 * i + 1];
1660 break;
1661 case ASN_UTF8STRING:
1662 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1663 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1664 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1665 break;
1668 else
1670 value->Value.cbData = 0;
1671 value->Value.pbData = NULL;
1675 return ret;
1678 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1679 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1680 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1682 BOOL ret = TRUE;
1684 __TRY
1686 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded, cbEncoded,
1687 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1688 if (ret && pvStructInfo)
1690 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1691 pcbStructInfo, *pcbStructInfo);
1692 if (ret)
1694 CERT_NAME_VALUE *value;
1696 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1697 pvStructInfo = *(BYTE **)pvStructInfo;
1698 value = (CERT_NAME_VALUE *)pvStructInfo;
1699 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1700 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded,
1701 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1702 pcbStructInfo, NULL);
1706 __EXCEPT_PAGE_FAULT
1708 SetLastError(STATUS_ACCESS_VIOLATION);
1709 ret = FALSE;
1711 __ENDTRY
1712 return ret;
1715 static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
1716 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1718 BOOL ret;
1719 struct AsnDecodeSequenceItem items[] = {
1720 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1721 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1722 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1723 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1724 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1725 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1727 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1729 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1730 pvStructInfo, *pcbStructInfo);
1732 if (attr)
1733 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1734 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1735 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1736 attr ? attr->pszObjId : NULL);
1737 if (attr)
1739 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1740 debugstr_a(attr->pszObjId));
1741 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1743 TRACE("returning %d (%08x)\n", ret, GetLastError());
1744 return ret;
1747 static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1748 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1750 BOOL ret = TRUE;
1751 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1752 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1753 offsetof(CERT_RDN_ATTR, pszObjId) };
1754 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1756 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1757 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1758 rdn ? rdn->rgRDNAttr : NULL);
1759 return ret;
1762 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1763 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1764 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1766 BOOL ret = TRUE;
1768 __TRY
1770 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1771 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1772 offsetof(CERT_RDN, rgRDNAttr) };
1774 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1775 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1777 __EXCEPT_PAGE_FAULT
1779 SetLastError(STATUS_ACCESS_VIOLATION);
1780 ret = FALSE;
1782 __ENDTRY
1783 return ret;
1786 static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
1787 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1788 DWORD *pcbDecoded)
1790 BOOL ret;
1791 struct AsnDecodeSequenceItem items[] = {
1792 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1793 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1794 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1795 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1796 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1797 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1799 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1801 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1802 pvStructInfo, *pcbStructInfo);
1804 if (attr)
1805 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1806 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1807 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1808 attr ? attr->pszObjId : NULL);
1809 if (attr)
1811 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1812 debugstr_a(attr->pszObjId));
1813 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1815 TRACE("returning %d (%08x)\n", ret, GetLastError());
1816 return ret;
1819 static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1820 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1822 BOOL ret = TRUE;
1823 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1824 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1825 offsetof(CERT_RDN_ATTR, pszObjId) };
1826 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1828 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1829 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1830 rdn ? rdn->rgRDNAttr : NULL);
1831 return ret;
1834 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1835 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1836 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1838 BOOL ret = TRUE;
1840 __TRY
1842 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1843 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1844 offsetof(CERT_RDN, rgRDNAttr) };
1846 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1847 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1849 __EXCEPT_PAGE_FAULT
1851 SetLastError(STATUS_ACCESS_VIOLATION);
1852 ret = FALSE;
1854 __ENDTRY
1855 return ret;
1858 static BOOL CRYPT_AsnDecodeCopyBytes(const BYTE *pbEncoded,
1859 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1860 DWORD *pcbDecoded)
1862 BOOL ret = TRUE;
1863 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB);
1865 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1866 pvStructInfo, *pcbStructInfo);
1868 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1869 bytesNeeded += cbEncoded;
1870 if (pcbDecoded)
1871 *pcbDecoded = cbEncoded;
1872 if (!pvStructInfo)
1873 *pcbStructInfo = bytesNeeded;
1874 else if (*pcbStructInfo < bytesNeeded)
1876 SetLastError(ERROR_MORE_DATA);
1877 *pcbStructInfo = bytesNeeded;
1878 ret = FALSE;
1880 else
1882 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1884 *pcbStructInfo = bytesNeeded;
1885 blob->cbData = cbEncoded;
1886 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1887 blob->pbData = (LPBYTE)pbEncoded;
1888 else
1890 assert(blob->pbData);
1891 memcpy(blob->pbData, pbEncoded, blob->cbData);
1894 return ret;
1897 static BOOL CRYPT_DecodeDERArray(const BYTE *pbEncoded, DWORD cbEncoded,
1898 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1900 BOOL ret;
1901 struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytes,
1902 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
1903 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
1905 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1906 pvStructInfo, *pcbStructInfo, pcbDecoded);
1908 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1909 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1910 array ? array->rgItems : NULL);
1911 return ret;
1914 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
1915 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1916 DWORD *pcbDecoded)
1918 BOOL ret;
1919 struct AsnDecodeSequenceItem items[] = {
1920 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
1921 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1922 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
1923 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
1924 CRYPT_DecodeDERArray, sizeof(struct GenericArray), FALSE, TRUE,
1925 offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
1927 PCRYPT_ATTRIBUTE attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
1929 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1930 pvStructInfo, *pcbStructInfo);
1932 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1933 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
1934 pcbDecoded, attr ? attr->pszObjId : NULL);
1935 TRACE("returning %d\n", ret);
1936 return ret;
1939 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
1940 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1941 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1943 BOOL ret = FALSE;
1945 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1946 pDecodePara, pvStructInfo, *pcbStructInfo);
1948 __TRY
1950 DWORD bytesNeeded;
1952 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
1953 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
1954 if (ret)
1956 if (!pvStructInfo)
1957 *pcbStructInfo = bytesNeeded;
1958 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1959 pvStructInfo, pcbStructInfo, bytesNeeded)))
1961 PCRYPT_ATTRIBUTE attr;
1963 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1964 pvStructInfo = *(BYTE **)pvStructInfo;
1965 attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
1966 attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
1967 sizeof(CRYPT_ATTRIBUTE));
1968 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
1969 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
1970 NULL);
1974 __EXCEPT_PAGE_FAULT
1976 SetLastError(STATUS_ACCESS_VIOLATION);
1978 __ENDTRY
1979 TRACE("returning %d\n", ret);
1980 return ret;
1983 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
1984 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1985 DWORD *pcbDecoded)
1987 struct AsnArrayDescriptor arrayDesc = { 0,
1988 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
1989 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
1990 PCRYPT_ATTRIBUTES attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
1991 BOOL ret;
1993 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1994 NULL, pvStructInfo, pcbStructInfo, pcbDecoded, attrs ? attrs->rgAttr :
1995 NULL);
1996 return ret;
1999 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
2000 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2001 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2003 BOOL ret = FALSE;
2005 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2006 pDecodePara, pvStructInfo, *pcbStructInfo);
2008 __TRY
2010 DWORD bytesNeeded;
2012 if (!cbEncoded)
2013 SetLastError(CRYPT_E_ASN1_EOD);
2014 else if (pbEncoded[0] != (ASN_CONSTRUCTOR | ASN_SETOF))
2015 SetLastError(CRYPT_E_ASN1_CORRUPT);
2016 else if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
2017 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2018 NULL)))
2020 if (!pvStructInfo)
2021 *pcbStructInfo = bytesNeeded;
2022 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2023 pvStructInfo, pcbStructInfo, bytesNeeded)))
2025 PCRYPT_ATTRIBUTES attrs;
2027 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2028 pvStructInfo = *(BYTE **)pvStructInfo;
2029 attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
2030 attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
2031 sizeof(CRYPT_ATTRIBUTES));
2032 ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
2033 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2034 &bytesNeeded, NULL);
2038 __EXCEPT_PAGE_FAULT
2040 SetLastError(STATUS_ACCESS_VIOLATION);
2042 __ENDTRY
2043 TRACE("returning %d\n", ret);
2044 return ret;
2047 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
2048 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2050 CRYPT_ALGORITHM_IDENTIFIER *algo =
2051 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
2052 BOOL ret = TRUE;
2053 struct AsnDecodeSequenceItem items[] = {
2054 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
2055 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2056 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
2057 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
2058 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2059 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
2062 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2063 pvStructInfo, *pcbStructInfo, pcbDecoded);
2065 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2066 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2067 pcbDecoded, algo ? algo->pszObjId : NULL);
2068 if (ret && pvStructInfo)
2070 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
2071 debugstr_a(algo->pszObjId));
2073 return ret;
2076 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
2077 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2078 DWORD *pcbDecoded)
2080 BOOL ret = TRUE;
2081 struct AsnDecodeSequenceItem items[] = {
2082 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
2083 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2084 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
2085 Algorithm.pszObjId) },
2086 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
2087 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2088 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
2090 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2092 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2093 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2094 pcbDecoded, info ? info->Algorithm.Parameters.pbData : NULL);
2095 return ret;
2098 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2099 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2100 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2102 BOOL ret = TRUE;
2104 __TRY
2106 DWORD bytesNeeded;
2108 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2109 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2111 if (!pvStructInfo)
2112 *pcbStructInfo = bytesNeeded;
2113 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2114 pvStructInfo, pcbStructInfo, bytesNeeded)))
2116 PCERT_PUBLIC_KEY_INFO info;
2118 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2119 pvStructInfo = *(BYTE **)pvStructInfo;
2120 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2121 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2122 sizeof(CERT_PUBLIC_KEY_INFO);
2123 ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2124 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2125 &bytesNeeded, NULL);
2129 __EXCEPT_PAGE_FAULT
2131 SetLastError(STATUS_ACCESS_VIOLATION);
2132 ret = FALSE;
2134 __ENDTRY
2135 return ret;
2138 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
2139 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2141 BOOL ret;
2143 if (cbEncoded < 3)
2145 SetLastError(CRYPT_E_ASN1_CORRUPT);
2146 return FALSE;
2148 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2150 SetLastError(CRYPT_E_ASN1_CORRUPT);
2151 return FALSE;
2153 if (pbEncoded[1] > 1)
2155 SetLastError(CRYPT_E_ASN1_CORRUPT);
2156 return FALSE;
2158 if (pcbDecoded)
2159 *pcbDecoded = 3;
2160 if (!pvStructInfo)
2162 *pcbStructInfo = sizeof(BOOL);
2163 ret = TRUE;
2165 else if (*pcbStructInfo < sizeof(BOOL))
2167 *pcbStructInfo = sizeof(BOOL);
2168 SetLastError(ERROR_MORE_DATA);
2169 ret = FALSE;
2171 else
2173 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2174 ret = TRUE;
2176 TRACE("returning %d (%08x)\n", ret, GetLastError());
2177 return ret;
2180 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2181 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2183 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
2184 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2185 BOOL ret;
2187 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2188 pvStructInfo, *pcbStructInfo);
2190 if (cbEncoded < 2)
2192 SetLastError(CRYPT_E_ASN1_CORRUPT);
2193 return FALSE;
2195 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2196 if (1 + lenBytes > cbEncoded)
2198 SetLastError(CRYPT_E_ASN1_CORRUPT);
2199 return FALSE;
2201 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2203 switch (pbEncoded[0] & ASN_TYPE_MASK)
2205 case 1: /* rfc822Name */
2206 case 2: /* dNSName */
2207 case 6: /* uniformResourceIdentifier */
2208 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
2209 break;
2210 case 4: /* directoryName */
2211 case 7: /* iPAddress */
2212 bytesNeeded += dataLen;
2213 break;
2214 case 8: /* registeredID */
2215 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
2216 &dataLen, NULL);
2217 if (ret)
2219 /* FIXME: ugly, shouldn't need to know internals of OID decode
2220 * function to use it.
2222 bytesNeeded += dataLen - sizeof(LPSTR);
2224 break;
2225 case 0: /* otherName */
2226 FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
2227 SetLastError(CRYPT_E_ASN1_BADTAG);
2228 ret = FALSE;
2229 break;
2230 case 3: /* x400Address, unimplemented */
2231 case 5: /* ediPartyName, unimplemented */
2232 TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
2233 SetLastError(CRYPT_E_ASN1_BADTAG);
2234 ret = FALSE;
2235 break;
2236 default:
2237 TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
2238 SetLastError(CRYPT_E_ASN1_CORRUPT);
2239 ret = FALSE;
2241 if (ret)
2243 if (pcbDecoded)
2244 *pcbDecoded = 1 + lenBytes + dataLen;
2245 if (!entry)
2246 *pcbStructInfo = bytesNeeded;
2247 else if (*pcbStructInfo < bytesNeeded)
2249 *pcbStructInfo = bytesNeeded;
2250 SetLastError(ERROR_MORE_DATA);
2251 ret = FALSE;
2253 else
2255 *pcbStructInfo = bytesNeeded;
2256 /* MS used values one greater than the asn1 ones.. sigh */
2257 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
2258 switch (pbEncoded[0] & ASN_TYPE_MASK)
2260 case 1: /* rfc822Name */
2261 case 2: /* dNSName */
2262 case 6: /* uniformResourceIdentifier */
2264 DWORD i;
2266 for (i = 0; i < dataLen; i++)
2267 entry->u.pwszURL[i] =
2268 (WCHAR)pbEncoded[1 + lenBytes + i];
2269 entry->u.pwszURL[i] = 0;
2270 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2271 debugstr_w(entry->u.pwszURL));
2272 break;
2274 case 4: /* directoryName */
2275 entry->dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
2276 /* The data are memory-equivalent with the IPAddress case,
2277 * fall-through
2279 case 7: /* iPAddress */
2280 /* The next data pointer is in the pwszURL spot, that is,
2281 * the first 4 bytes. Need to move it to the next spot.
2283 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2284 entry->u.IPAddress.cbData = dataLen;
2285 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2286 dataLen);
2287 break;
2288 case 8: /* registeredID */
2289 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
2290 &entry->u.pszRegisteredID, &dataLen, NULL);
2291 break;
2296 return ret;
2299 static BOOL CRYPT_AsnDecodeAltNameInternal(const BYTE *pbEncoded,
2300 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2301 DWORD *pcbDecoded)
2303 BOOL ret = TRUE;
2304 struct AsnArrayDescriptor arrayDesc = { 0,
2305 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2306 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2307 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
2309 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2310 pvStructInfo, *pcbStructInfo, pcbDecoded);
2312 if (info)
2313 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2314 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2315 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2316 info ? info->rgAltEntry : NULL);
2317 return ret;
2320 /* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */
2321 static BOOL CRYPT_AsnDecodeIntegerSwapBytes(const BYTE *pbEncoded,
2322 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2323 DWORD *pcbDecoded)
2325 BOOL ret;
2327 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
2328 pvStructInfo, *pcbStructInfo, pcbDecoded);
2330 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2331 * place.
2333 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
2334 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
2335 pcbDecoded);
2336 if (ret && pvStructInfo)
2338 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2340 if (blob->cbData)
2342 DWORD i;
2343 BYTE temp;
2345 for (i = 0; i < blob->cbData / 2; i++)
2347 temp = blob->pbData[i];
2348 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
2349 blob->pbData[blob->cbData - i - 1] = temp;
2353 TRACE("returning %d (%08x)\n", ret, GetLastError());
2354 return ret;
2357 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
2358 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2359 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2361 BOOL ret;
2363 __TRY
2365 struct AsnDecodeSequenceItem items[] = {
2366 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
2367 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2368 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
2369 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2370 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
2371 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
2372 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
2373 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
2374 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2375 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2376 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
2379 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2380 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2381 pcbStructInfo, NULL, NULL);
2383 __EXCEPT_PAGE_FAULT
2385 SetLastError(STATUS_ACCESS_VIOLATION);
2386 ret = FALSE;
2388 __ENDTRY
2389 return ret;
2392 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
2393 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2394 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2396 BOOL ret;
2398 __TRY
2400 struct AsnDecodeSequenceItem items[] = {
2401 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
2402 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2403 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
2404 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2405 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
2406 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
2407 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2408 AuthorityCertIssuer.rgAltEntry), 0 },
2409 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2410 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2411 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2412 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2413 AuthorityCertSerialNumber.pbData), 0 },
2416 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2417 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2418 pcbStructInfo, NULL, NULL);
2420 __EXCEPT_PAGE_FAULT
2422 SetLastError(STATUS_ACCESS_VIOLATION);
2423 ret = FALSE;
2425 __ENDTRY
2426 return ret;
2429 static BOOL CRYPT_AsnDecodePKCSContent(const BYTE *pbEncoded, DWORD cbEncoded,
2430 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2432 BOOL ret;
2433 DWORD dataLen;
2435 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2436 pvStructInfo, *pcbStructInfo, pcbDecoded);
2438 /* The caller has already checked the tag, no need to check it again.
2439 * Check the outer length is valid by calling CRYPT_GetLen:
2441 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2443 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2444 DWORD innerLen;
2446 pbEncoded += 1 + lenBytes;
2447 /* Check the inner length is valid by calling CRYPT_GetLen again: */
2448 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &innerLen)))
2450 ret = CRYPT_AsnDecodeCopyBytes(pbEncoded, dataLen, dwFlags,
2451 pvStructInfo, pcbStructInfo, NULL);
2452 if (pcbDecoded)
2453 *pcbDecoded = 1 + lenBytes + dataLen;
2456 return ret;
2459 static BOOL CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE *pbEncoded,
2460 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2461 DWORD *pcbDecoded)
2463 CRYPT_CONTENT_INFO *info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2464 struct AsnDecodeSequenceItem items[] = {
2465 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
2466 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2467 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
2468 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
2469 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
2470 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
2471 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
2473 BOOL ret;
2475 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2476 pvStructInfo, *pcbStructInfo, pcbDecoded);
2478 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2479 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2480 pcbDecoded, info ? info->pszObjId : NULL);
2481 return ret;
2484 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
2485 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2486 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2488 BOOL ret = FALSE;
2490 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2491 pDecodePara, pvStructInfo, *pcbStructInfo);
2493 __TRY
2495 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, cbEncoded,
2496 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
2497 if (ret && pvStructInfo)
2499 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
2500 pcbStructInfo, *pcbStructInfo);
2501 if (ret)
2503 CRYPT_CONTENT_INFO *info;
2505 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2506 pvStructInfo = *(BYTE **)pvStructInfo;
2507 info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2508 info->pszObjId = (LPSTR)((BYTE *)info +
2509 sizeof(CRYPT_CONTENT_INFO));
2510 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded,
2511 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2512 pcbStructInfo, NULL);
2516 __EXCEPT_PAGE_FAULT
2518 SetLastError(STATUS_ACCESS_VIOLATION);
2520 __ENDTRY
2521 return ret;
2524 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
2525 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2526 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
2528 BOOL ret;
2529 struct AsnDecodeSequenceItem items[] = {
2530 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version),
2531 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2532 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
2533 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2534 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
2535 0 },
2536 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
2537 CRYPT_AsnDecodePKCSContentInfoInternal,
2538 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
2539 ContentInfo.pszObjId), 0 },
2540 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
2541 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
2542 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
2545 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2546 pbEncoded, cbEncoded, dwFlags, pDecodePara, digestedData, pcbDigestedData,
2547 NULL, NULL);
2548 return ret;
2551 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
2552 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2553 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2555 BOOL ret = TRUE;
2557 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2558 pDecodePara, pvStructInfo, *pcbStructInfo);
2560 __TRY
2562 DWORD bytesNeeded;
2564 if ((ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
2565 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2567 if (!pvStructInfo)
2568 *pcbStructInfo = bytesNeeded;
2569 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2570 pvStructInfo, pcbStructInfo, bytesNeeded)))
2572 CERT_ALT_NAME_INFO *name;
2574 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2575 pvStructInfo = *(BYTE **)pvStructInfo;
2576 name = (CERT_ALT_NAME_INFO *)pvStructInfo;
2577 name->rgAltEntry = (PCERT_ALT_NAME_ENTRY)
2578 ((BYTE *)pvStructInfo + sizeof(CERT_ALT_NAME_INFO));
2579 ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
2580 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2581 &bytesNeeded, NULL);
2585 __EXCEPT_PAGE_FAULT
2587 SetLastError(STATUS_ACCESS_VIOLATION);
2588 ret = FALSE;
2590 __ENDTRY
2591 return ret;
2594 struct PATH_LEN_CONSTRAINT
2596 BOOL fPathLenConstraint;
2597 DWORD dwPathLenConstraint;
2600 static BOOL CRYPT_AsnDecodePathLenConstraint(const BYTE *pbEncoded,
2601 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2602 DWORD *pcbDecoded)
2604 BOOL ret = TRUE;
2605 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT), size;
2607 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2608 pvStructInfo, *pcbStructInfo, pcbDecoded);
2610 if (!pvStructInfo)
2612 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, NULL,
2613 &size, pcbDecoded);
2614 *pcbStructInfo = bytesNeeded;
2616 else if (*pcbStructInfo < bytesNeeded)
2618 SetLastError(ERROR_MORE_DATA);
2619 *pcbStructInfo = bytesNeeded;
2620 ret = FALSE;
2622 else
2624 struct PATH_LEN_CONSTRAINT *constraint =
2625 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
2627 size = sizeof(constraint->dwPathLenConstraint);
2628 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
2629 &constraint->dwPathLenConstraint, &size, pcbDecoded);
2630 if (ret)
2631 constraint->fPathLenConstraint = TRUE;
2632 TRACE("got an int, dwPathLenConstraint is %d\n",
2633 constraint->dwPathLenConstraint);
2635 TRACE("returning %d (%08x)\n", ret, GetLastError());
2636 return ret;
2639 static BOOL CRYPT_AsnDecodeSubtreeConstraints(const BYTE *pbEncoded,
2640 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2641 DWORD *pcbDecoded)
2643 BOOL ret;
2644 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2645 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
2646 offsetof(CERT_NAME_BLOB, pbData) };
2647 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2649 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2650 pvStructInfo, *pcbStructInfo, pcbDecoded);
2652 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2653 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2654 entries ? entries->rgItems : NULL);
2655 TRACE("Returning %d (%08x)\n", ret, GetLastError());
2656 return ret;
2659 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
2660 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2661 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2663 BOOL ret;
2665 __TRY
2667 struct AsnDecodeSequenceItem items[] = {
2668 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
2669 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2670 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
2671 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2672 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2673 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2674 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2675 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
2676 sizeof(struct GenericArray), TRUE, TRUE,
2677 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
2680 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2681 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2682 pcbStructInfo, NULL, NULL);
2684 __EXCEPT_PAGE_FAULT
2686 SetLastError(STATUS_ACCESS_VIOLATION);
2687 ret = FALSE;
2689 __ENDTRY
2690 return ret;
2693 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
2694 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2695 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2697 BOOL ret;
2699 __TRY
2701 struct AsnDecodeSequenceItem items[] = {
2702 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
2703 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
2704 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
2705 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2706 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2709 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2710 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2711 pcbStructInfo, NULL, NULL);
2713 __EXCEPT_PAGE_FAULT
2715 SetLastError(STATUS_ACCESS_VIOLATION);
2716 ret = FALSE;
2718 __ENDTRY
2719 return ret;
2722 #define RSA1_MAGIC 0x31415352
2724 struct DECODED_RSA_PUB_KEY
2726 DWORD pubexp;
2727 CRYPT_INTEGER_BLOB modulus;
2730 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
2731 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2732 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2734 BOOL ret;
2736 __TRY
2738 struct AsnDecodeSequenceItem items[] = {
2739 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
2740 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2741 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
2742 0 },
2743 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
2744 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2746 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
2747 DWORD size = 0;
2749 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2750 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
2751 &size, NULL, NULL);
2752 if (ret)
2754 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2755 decodedKey->modulus.cbData;
2757 if (!pvStructInfo)
2759 *pcbStructInfo = bytesNeeded;
2760 ret = TRUE;
2762 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2763 pvStructInfo, pcbStructInfo, bytesNeeded)))
2765 BLOBHEADER *hdr;
2766 RSAPUBKEY *rsaPubKey;
2768 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2769 pvStructInfo = *(BYTE **)pvStructInfo;
2770 hdr = (BLOBHEADER *)pvStructInfo;
2771 hdr->bType = PUBLICKEYBLOB;
2772 hdr->bVersion = CUR_BLOB_VERSION;
2773 hdr->reserved = 0;
2774 hdr->aiKeyAlg = CALG_RSA_KEYX;
2775 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
2776 sizeof(BLOBHEADER));
2777 rsaPubKey->magic = RSA1_MAGIC;
2778 rsaPubKey->pubexp = decodedKey->pubexp;
2779 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
2780 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
2781 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
2782 decodedKey->modulus.cbData);
2784 LocalFree(decodedKey);
2787 __EXCEPT_PAGE_FAULT
2789 SetLastError(STATUS_ACCESS_VIOLATION);
2790 ret = FALSE;
2792 __ENDTRY
2793 return ret;
2796 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
2797 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2798 DWORD *pcbDecoded)
2800 BOOL ret;
2801 DWORD bytesNeeded, dataLen;
2803 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2804 pvStructInfo, *pcbStructInfo, pcbDecoded);
2806 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2808 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2810 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2811 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
2812 else
2813 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
2814 if (pcbDecoded)
2815 *pcbDecoded = 1 + lenBytes + dataLen;
2816 if (!pvStructInfo)
2817 *pcbStructInfo = bytesNeeded;
2818 else if (*pcbStructInfo < bytesNeeded)
2820 SetLastError(ERROR_MORE_DATA);
2821 *pcbStructInfo = bytesNeeded;
2822 ret = FALSE;
2824 else
2826 CRYPT_DATA_BLOB *blob;
2828 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2829 blob->cbData = dataLen;
2830 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2831 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
2832 else
2834 assert(blob->pbData);
2835 if (blob->cbData)
2836 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
2837 blob->cbData);
2841 return ret;
2844 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
2845 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2846 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2848 BOOL ret;
2850 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2851 pDecodePara, pvStructInfo, *pcbStructInfo);
2853 __TRY
2855 DWORD bytesNeeded;
2857 if (!cbEncoded)
2859 SetLastError(CRYPT_E_ASN1_CORRUPT);
2860 ret = FALSE;
2862 else if (pbEncoded[0] != ASN_OCTETSTRING)
2864 SetLastError(CRYPT_E_ASN1_BADTAG);
2865 ret = FALSE;
2867 else if ((ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
2868 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2870 if (!pvStructInfo)
2871 *pcbStructInfo = bytesNeeded;
2872 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2873 pvStructInfo, pcbStructInfo, bytesNeeded)))
2875 CRYPT_DATA_BLOB *blob;
2877 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2878 pvStructInfo = *(BYTE **)pvStructInfo;
2879 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2880 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
2881 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
2882 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2883 &bytesNeeded, NULL);
2887 __EXCEPT_PAGE_FAULT
2889 SetLastError(STATUS_ACCESS_VIOLATION);
2890 ret = FALSE;
2892 __ENDTRY
2893 return ret;
2896 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
2897 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2899 BOOL ret;
2901 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
2902 pvStructInfo, *pcbStructInfo, pcbDecoded);
2904 if (pbEncoded[0] == ASN_BITSTRING)
2906 DWORD bytesNeeded, dataLen;
2907 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2909 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2911 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2912 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
2913 else
2914 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
2915 if (pcbDecoded)
2916 *pcbDecoded = 1 + lenBytes + dataLen;
2917 if (!pvStructInfo)
2918 *pcbStructInfo = bytesNeeded;
2919 else if (*pcbStructInfo < bytesNeeded)
2921 *pcbStructInfo = bytesNeeded;
2922 SetLastError(ERROR_MORE_DATA);
2923 ret = FALSE;
2925 else
2927 CRYPT_BIT_BLOB *blob;
2929 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2930 blob->cbData = dataLen - 1;
2931 blob->cUnusedBits = *(pbEncoded + 1 + lenBytes);
2932 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2934 blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes;
2936 else
2938 assert(blob->pbData);
2939 if (blob->cbData)
2941 BYTE mask = 0xff << blob->cUnusedBits;
2943 memcpy(blob->pbData, pbEncoded + 2 + lenBytes,
2944 blob->cbData);
2945 blob->pbData[blob->cbData - 1] &= mask;
2951 else
2953 SetLastError(CRYPT_E_ASN1_BADTAG);
2954 ret = FALSE;
2956 TRACE("returning %d (%08x)\n", ret, GetLastError());
2957 return ret;
2960 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
2961 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2962 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2964 BOOL ret;
2966 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
2967 pDecodePara, pvStructInfo, pcbStructInfo);
2969 __TRY
2971 DWORD bytesNeeded;
2973 if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
2974 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2976 if (!pvStructInfo)
2977 *pcbStructInfo = bytesNeeded;
2978 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2979 pvStructInfo, pcbStructInfo, bytesNeeded)))
2981 CRYPT_BIT_BLOB *blob;
2983 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2984 pvStructInfo = *(BYTE **)pvStructInfo;
2985 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
2986 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
2987 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
2988 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2989 &bytesNeeded, NULL);
2993 __EXCEPT_PAGE_FAULT
2995 SetLastError(STATUS_ACCESS_VIOLATION);
2996 ret = FALSE;
2998 __ENDTRY
2999 TRACE("returning %d (%08x)\n", ret, GetLastError());
3000 return ret;
3003 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3004 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3006 BOOL ret;
3007 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
3008 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
3009 DWORD size = sizeof(buf);
3011 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
3012 if (pbEncoded[0] != ASN_INTEGER)
3014 SetLastError(CRYPT_E_ASN1_BADTAG);
3015 ret = FALSE;
3017 else
3018 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded, 0, &buf,
3019 &size, pcbDecoded);
3020 if (ret)
3022 if (!pvStructInfo)
3023 *pcbStructInfo = sizeof(int);
3024 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int))))
3026 int val, i;
3028 if (blob->pbData[blob->cbData - 1] & 0x80)
3030 /* initialize to a negative value to sign-extend */
3031 val = -1;
3033 else
3034 val = 0;
3035 for (i = 0; i < blob->cbData; i++)
3037 val <<= 8;
3038 val |= blob->pbData[blob->cbData - i - 1];
3040 memcpy(pvStructInfo, &val, sizeof(int));
3043 else if (GetLastError() == ERROR_MORE_DATA)
3044 SetLastError(CRYPT_E_ASN1_LARGE);
3045 return ret;
3048 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
3049 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3050 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3052 BOOL ret;
3054 __TRY
3056 DWORD bytesNeeded;
3058 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3059 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3060 if (ret)
3062 if (!pvStructInfo)
3063 *pcbStructInfo = bytesNeeded;
3064 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3065 pvStructInfo, pcbStructInfo, bytesNeeded)))
3067 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3068 pvStructInfo = *(BYTE **)pvStructInfo;
3069 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3070 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3071 &bytesNeeded, NULL);
3075 __EXCEPT_PAGE_FAULT
3077 SetLastError(STATUS_ACCESS_VIOLATION);
3078 ret = FALSE;
3080 __ENDTRY
3081 return ret;
3084 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
3085 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3086 DWORD *pcbDecoded)
3088 BOOL ret;
3089 DWORD bytesNeeded, dataLen;
3091 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3093 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3095 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3096 if (pcbDecoded)
3097 *pcbDecoded = 1 + lenBytes + dataLen;
3098 if (!pvStructInfo)
3099 *pcbStructInfo = bytesNeeded;
3100 else if (*pcbStructInfo < bytesNeeded)
3102 *pcbStructInfo = bytesNeeded;
3103 SetLastError(ERROR_MORE_DATA);
3104 ret = FALSE;
3106 else
3108 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3110 blob->cbData = dataLen;
3111 assert(blob->pbData);
3112 if (blob->cbData)
3114 DWORD i;
3116 for (i = 0; i < blob->cbData; i++)
3118 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3119 dataLen - i - 1);
3124 return ret;
3127 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
3128 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3129 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3131 BOOL ret;
3133 __TRY
3135 DWORD bytesNeeded;
3137 if (pbEncoded[0] != ASN_INTEGER)
3139 SetLastError(CRYPT_E_ASN1_BADTAG);
3140 ret = FALSE;
3142 else
3143 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3144 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3145 if (ret)
3147 if (!pvStructInfo)
3148 *pcbStructInfo = bytesNeeded;
3149 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3150 pvStructInfo, pcbStructInfo, bytesNeeded)))
3152 CRYPT_INTEGER_BLOB *blob;
3154 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3155 pvStructInfo = *(BYTE **)pvStructInfo;
3156 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3157 blob->pbData = (BYTE *)pvStructInfo +
3158 sizeof(CRYPT_INTEGER_BLOB);
3159 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3160 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
3161 &bytesNeeded, NULL);
3165 __EXCEPT_PAGE_FAULT
3167 SetLastError(STATUS_ACCESS_VIOLATION);
3168 ret = FALSE;
3170 __ENDTRY
3171 return ret;
3174 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
3175 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3176 DWORD *pcbDecoded)
3178 BOOL ret;
3180 if (pbEncoded[0] == ASN_INTEGER)
3182 DWORD bytesNeeded, dataLen;
3184 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3186 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3188 if (pcbDecoded)
3189 *pcbDecoded = 1 + lenBytes + dataLen;
3190 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3191 if (!pvStructInfo)
3192 *pcbStructInfo = bytesNeeded;
3193 else if (*pcbStructInfo < bytesNeeded)
3195 *pcbStructInfo = bytesNeeded;
3196 SetLastError(ERROR_MORE_DATA);
3197 ret = FALSE;
3199 else
3201 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3203 blob->cbData = dataLen;
3204 assert(blob->pbData);
3205 /* remove leading zero byte if it exists */
3206 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
3208 blob->cbData--;
3209 blob->pbData++;
3211 if (blob->cbData)
3213 DWORD i;
3215 for (i = 0; i < blob->cbData; i++)
3217 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3218 dataLen - i - 1);
3224 else
3226 SetLastError(CRYPT_E_ASN1_BADTAG);
3227 ret = FALSE;
3229 return ret;
3232 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
3233 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3234 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3236 BOOL ret;
3238 __TRY
3240 DWORD bytesNeeded;
3242 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded,
3243 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3245 if (!pvStructInfo)
3246 *pcbStructInfo = bytesNeeded;
3247 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3248 pvStructInfo, pcbStructInfo, bytesNeeded)))
3250 CRYPT_INTEGER_BLOB *blob;
3252 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3253 pvStructInfo = *(BYTE **)pvStructInfo;
3254 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3255 blob->pbData = (BYTE *)pvStructInfo +
3256 sizeof(CRYPT_INTEGER_BLOB);
3257 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded,
3258 cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
3259 &bytesNeeded, NULL);
3263 __EXCEPT_PAGE_FAULT
3265 SetLastError(STATUS_ACCESS_VIOLATION);
3266 ret = FALSE;
3268 __ENDTRY
3269 return ret;
3272 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
3273 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3274 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3276 BOOL ret;
3278 if (!pvStructInfo)
3280 *pcbStructInfo = sizeof(int);
3281 return TRUE;
3283 __TRY
3285 if (pbEncoded[0] == ASN_ENUMERATED)
3287 unsigned int val = 0, i;
3289 if (cbEncoded <= 1)
3291 SetLastError(CRYPT_E_ASN1_EOD);
3292 ret = FALSE;
3294 else if (pbEncoded[1] == 0)
3296 SetLastError(CRYPT_E_ASN1_CORRUPT);
3297 ret = FALSE;
3299 else
3301 /* A little strange looking, but we have to accept a sign byte:
3302 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
3303 * assuming a small length is okay here, it has to be in short
3304 * form.
3306 if (pbEncoded[1] > sizeof(unsigned int) + 1)
3308 SetLastError(CRYPT_E_ASN1_LARGE);
3309 return FALSE;
3311 for (i = 0; i < pbEncoded[1]; i++)
3313 val <<= 8;
3314 val |= pbEncoded[2 + i];
3316 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3317 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
3319 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3320 pvStructInfo = *(BYTE **)pvStructInfo;
3321 memcpy(pvStructInfo, &val, sizeof(unsigned int));
3325 else
3327 SetLastError(CRYPT_E_ASN1_BADTAG);
3328 ret = FALSE;
3331 __EXCEPT_PAGE_FAULT
3333 SetLastError(STATUS_ACCESS_VIOLATION);
3334 ret = FALSE;
3336 __ENDTRY
3337 return ret;
3340 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
3341 * if it fails.
3343 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
3344 do { \
3345 BYTE i; \
3347 (word) = 0; \
3348 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
3350 if (!isdigit(*(pbEncoded))) \
3352 SetLastError(CRYPT_E_ASN1_CORRUPT); \
3353 ret = FALSE; \
3355 else \
3357 (word) *= 10; \
3358 (word) += *(pbEncoded)++ - '0'; \
3361 } while (0)
3363 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
3364 SYSTEMTIME *sysTime)
3366 BOOL ret = TRUE;
3368 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
3370 WORD hours, minutes = 0;
3371 BYTE sign = *pbEncoded++;
3373 len--;
3374 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
3375 if (ret && hours >= 24)
3377 SetLastError(CRYPT_E_ASN1_CORRUPT);
3378 ret = FALSE;
3380 else if (len >= 2)
3382 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
3383 if (ret && minutes >= 60)
3385 SetLastError(CRYPT_E_ASN1_CORRUPT);
3386 ret = FALSE;
3389 if (ret)
3391 if (sign == '+')
3393 sysTime->wHour += hours;
3394 sysTime->wMinute += minutes;
3396 else
3398 if (hours > sysTime->wHour)
3400 sysTime->wDay--;
3401 sysTime->wHour = 24 - (hours - sysTime->wHour);
3403 else
3404 sysTime->wHour -= hours;
3405 if (minutes > sysTime->wMinute)
3407 sysTime->wHour--;
3408 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
3410 else
3411 sysTime->wMinute -= minutes;
3415 return ret;
3418 #define MIN_ENCODED_TIME_LENGTH 10
3420 static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
3421 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3422 DWORD *pcbDecoded)
3424 BOOL ret = FALSE;
3426 if (pbEncoded[0] == ASN_UTCTIME)
3428 if (cbEncoded <= 1)
3429 SetLastError(CRYPT_E_ASN1_EOD);
3430 else if (pbEncoded[1] > 0x7f)
3432 /* long-form date strings really can't be valid */
3433 SetLastError(CRYPT_E_ASN1_CORRUPT);
3435 else
3437 SYSTEMTIME sysTime = { 0 };
3438 BYTE len = pbEncoded[1];
3440 if (len < MIN_ENCODED_TIME_LENGTH)
3441 SetLastError(CRYPT_E_ASN1_CORRUPT);
3442 else
3444 ret = TRUE;
3445 if (pcbDecoded)
3446 *pcbDecoded = 2 + len;
3447 pbEncoded += 2;
3448 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
3449 if (sysTime.wYear >= 50)
3450 sysTime.wYear += 1900;
3451 else
3452 sysTime.wYear += 2000;
3453 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3454 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3455 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3456 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
3457 if (ret && len > 0)
3459 if (len >= 2 && isdigit(*pbEncoded) &&
3460 isdigit(*(pbEncoded + 1)))
3461 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3462 sysTime.wSecond);
3463 else if (isdigit(*pbEncoded))
3464 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
3465 sysTime.wSecond);
3466 if (ret)
3467 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3468 &sysTime);
3470 if (ret)
3472 if (!pvStructInfo)
3473 *pcbStructInfo = sizeof(FILETIME);
3474 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
3475 sizeof(FILETIME))))
3476 ret = SystemTimeToFileTime(&sysTime,
3477 (FILETIME *)pvStructInfo);
3482 else
3483 SetLastError(CRYPT_E_ASN1_BADTAG);
3484 return ret;
3487 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
3488 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3489 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3491 BOOL ret = FALSE;
3493 __TRY
3495 DWORD bytesNeeded;
3497 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
3498 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3499 if (ret)
3501 if (!pvStructInfo)
3502 *pcbStructInfo = bytesNeeded;
3503 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
3504 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
3506 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3507 pvStructInfo = *(BYTE **)pvStructInfo;
3508 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
3509 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3510 &bytesNeeded, NULL);
3514 __EXCEPT_PAGE_FAULT
3516 SetLastError(STATUS_ACCESS_VIOLATION);
3518 __ENDTRY
3519 return ret;
3522 static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
3523 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3524 DWORD *pcbDecoded)
3526 BOOL ret = FALSE;
3528 if (pbEncoded[0] == ASN_GENERALTIME)
3530 if (cbEncoded <= 1)
3531 SetLastError(CRYPT_E_ASN1_EOD);
3532 else if (pbEncoded[1] > 0x7f)
3534 /* long-form date strings really can't be valid */
3535 SetLastError(CRYPT_E_ASN1_CORRUPT);
3537 else
3539 BYTE len = pbEncoded[1];
3541 if (len < MIN_ENCODED_TIME_LENGTH)
3542 SetLastError(CRYPT_E_ASN1_CORRUPT);
3543 else
3545 SYSTEMTIME sysTime = { 0 };
3547 ret = TRUE;
3548 if (pcbDecoded)
3549 *pcbDecoded = 2 + len;
3550 pbEncoded += 2;
3551 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
3552 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3553 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3554 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3555 if (ret && len > 0)
3557 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3558 sysTime.wMinute);
3559 if (ret && len > 0)
3560 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3561 sysTime.wSecond);
3562 if (ret && len > 0 && (*pbEncoded == '.' ||
3563 *pbEncoded == ','))
3565 BYTE digits;
3567 pbEncoded++;
3568 len--;
3569 /* workaround macro weirdness */
3570 digits = min(len, 3);
3571 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
3572 sysTime.wMilliseconds);
3574 if (ret)
3575 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3576 &sysTime);
3578 if (ret)
3580 if (!pvStructInfo)
3581 *pcbStructInfo = sizeof(FILETIME);
3582 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
3583 sizeof(FILETIME))))
3584 ret = SystemTimeToFileTime(&sysTime,
3585 (FILETIME *)pvStructInfo);
3590 else
3591 SetLastError(CRYPT_E_ASN1_BADTAG);
3592 return ret;
3595 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
3596 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3597 DWORD *pcbDecoded)
3599 BOOL ret;
3600 InternalDecodeFunc decode = NULL;
3602 if (pbEncoded[0] == ASN_UTCTIME)
3603 decode = CRYPT_AsnDecodeUtcTimeInternal;
3604 else if (pbEncoded[0] == ASN_GENERALTIME)
3605 decode = CRYPT_AsnDecodeGeneralizedTime;
3606 if (decode)
3607 ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
3608 pcbStructInfo, pcbDecoded);
3609 else
3611 SetLastError(CRYPT_E_ASN1_BADTAG);
3612 ret = FALSE;
3614 return ret;
3617 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
3618 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3619 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3621 BOOL ret;
3623 __TRY
3625 DWORD bytesNeeded;
3627 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
3628 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3629 if (ret)
3631 if (!pvStructInfo)
3632 *pcbStructInfo = bytesNeeded;
3633 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3634 pvStructInfo, pcbStructInfo, bytesNeeded)))
3636 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3637 pvStructInfo = *(BYTE **)pvStructInfo;
3638 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
3639 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3640 &bytesNeeded, NULL);
3644 __EXCEPT_PAGE_FAULT
3646 SetLastError(STATUS_ACCESS_VIOLATION);
3647 ret = FALSE;
3649 __ENDTRY
3650 return ret;
3653 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
3654 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3655 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3657 BOOL ret = TRUE;
3659 __TRY
3661 if (pbEncoded[0] == ASN_SEQUENCEOF)
3663 DWORD bytesNeeded, dataLen, remainingLen, cValue;
3665 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3667 BYTE lenBytes;
3668 const BYTE *ptr;
3670 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3671 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
3672 cValue = 0;
3673 ptr = pbEncoded + 1 + lenBytes;
3674 remainingLen = dataLen;
3675 while (ret && remainingLen)
3677 DWORD nextLen;
3679 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3680 if (ret)
3682 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3684 remainingLen -= 1 + nextLenBytes + nextLen;
3685 ptr += 1 + nextLenBytes + nextLen;
3686 bytesNeeded += sizeof(CRYPT_DER_BLOB);
3687 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3688 bytesNeeded += 1 + nextLenBytes + nextLen;
3689 cValue++;
3692 if (ret)
3694 CRYPT_SEQUENCE_OF_ANY *seq;
3695 BYTE *nextPtr;
3696 DWORD i;
3698 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3699 pvStructInfo, pcbStructInfo, bytesNeeded)))
3701 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3702 pvStructInfo = *(BYTE **)pvStructInfo;
3703 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
3704 seq->cValue = cValue;
3705 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
3706 sizeof(*seq));
3707 nextPtr = (BYTE *)seq->rgValue +
3708 cValue * sizeof(CRYPT_DER_BLOB);
3709 ptr = pbEncoded + 1 + lenBytes;
3710 remainingLen = dataLen;
3711 i = 0;
3712 while (ret && remainingLen)
3714 DWORD nextLen;
3716 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3717 if (ret)
3719 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3721 seq->rgValue[i].cbData = 1 + nextLenBytes +
3722 nextLen;
3723 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3724 seq->rgValue[i].pbData = (BYTE *)ptr;
3725 else
3727 seq->rgValue[i].pbData = nextPtr;
3728 memcpy(nextPtr, ptr, 1 + nextLenBytes +
3729 nextLen);
3730 nextPtr += 1 + nextLenBytes + nextLen;
3732 remainingLen -= 1 + nextLenBytes + nextLen;
3733 ptr += 1 + nextLenBytes + nextLen;
3734 i++;
3741 else
3743 SetLastError(CRYPT_E_ASN1_BADTAG);
3744 ret = FALSE;
3747 __EXCEPT_PAGE_FAULT
3749 SetLastError(STATUS_ACCESS_VIOLATION);
3750 ret = FALSE;
3752 __ENDTRY
3753 return ret;
3756 static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded,
3757 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3758 DWORD *pcbDecoded)
3760 BOOL ret;
3762 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
3764 DWORD bytesNeeded, dataLen;
3766 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3768 struct AsnArrayDescriptor arrayDesc = {
3769 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
3770 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3771 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3772 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3774 if (dataLen)
3776 DWORD nameLen;
3778 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3779 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3780 0, NULL, NULL, &nameLen, NULL, NULL);
3781 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen;
3783 else
3784 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
3785 if (pcbDecoded)
3786 *pcbDecoded = 1 + lenBytes + dataLen;
3787 if (!pvStructInfo)
3788 *pcbStructInfo = bytesNeeded;
3789 else if (*pcbStructInfo < bytesNeeded)
3791 *pcbStructInfo = bytesNeeded;
3792 SetLastError(ERROR_MORE_DATA);
3793 ret = FALSE;
3795 else
3797 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
3799 if (dataLen)
3801 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3802 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3803 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3804 0, NULL, &name->u.FullName, pcbStructInfo, NULL,
3805 name->u.FullName.rgAltEntry);
3807 else
3808 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3812 else
3814 SetLastError(CRYPT_E_ASN1_BADTAG);
3815 ret = FALSE;
3817 return ret;
3820 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
3821 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3823 struct AsnDecodeSequenceItem items[] = {
3824 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
3825 DistPointName), CRYPT_AsnDecodeDistPointName,
3826 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
3827 DistPointName.u.FullName.rgAltEntry), 0 },
3828 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
3829 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
3830 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
3831 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
3832 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
3833 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
3835 BOOL ret;
3837 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3838 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3839 pcbDecoded, NULL);
3840 return ret;
3843 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
3844 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3845 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3847 BOOL ret;
3849 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3850 pDecodePara, pvStructInfo, *pcbStructInfo);
3852 __TRY
3854 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3855 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
3856 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
3858 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3859 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
3861 __EXCEPT_PAGE_FAULT
3863 SetLastError(STATUS_ACCESS_VIOLATION);
3864 ret = FALSE;
3866 __ENDTRY
3867 return ret;
3870 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3871 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3872 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3874 BOOL ret;
3876 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3877 pDecodePara, pvStructInfo, *pcbStructInfo);
3879 __TRY
3881 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3882 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
3884 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3885 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
3887 __EXCEPT_PAGE_FAULT
3889 SetLastError(STATUS_ACCESS_VIOLATION);
3890 ret = FALSE;
3892 __ENDTRY
3893 return ret;
3896 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
3897 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3898 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3900 BOOL ret;
3902 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3903 pDecodePara, pvStructInfo, *pcbStructInfo);
3905 __TRY
3907 struct AsnDecodeSequenceItem items[] = {
3908 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
3909 DistPointName), CRYPT_AsnDecodeDistPointName,
3910 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
3911 offsetof(CRL_ISSUING_DIST_POINT,
3912 DistPointName.u.FullName.rgAltEntry), 0 },
3913 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
3914 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3915 FALSE, 0 },
3916 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
3917 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
3918 FALSE, 0 },
3919 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
3920 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
3921 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
3922 OnlySomeReasonFlags.pbData), 0 },
3923 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
3924 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
3927 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3928 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3929 pcbStructInfo, NULL, NULL);
3931 __EXCEPT_PAGE_FAULT
3933 SetLastError(STATUS_ACCESS_VIOLATION);
3934 ret = FALSE;
3936 __ENDTRY
3937 return ret;
3940 static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded,
3941 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3942 DWORD *pcbDecoded)
3944 BOOL ret;
3945 struct AsnDecodeSequenceItem items[] = {
3946 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
3947 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
3948 Issuer.pbData) },
3949 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
3950 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
3951 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
3953 CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
3954 (CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
3956 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3957 pvStructInfo, *pcbStructInfo, pcbDecoded);
3959 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3960 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3961 pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL);
3962 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
3964 SetLastError(CRYPT_E_ASN1_CORRUPT);
3965 ret = FALSE;
3967 TRACE("returning %d\n", ret);
3968 return ret;
3971 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
3972 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3973 DWORD *pcbDecoded)
3975 CMSG_SIGNER_INFO *info = (CMSG_SIGNER_INFO *)pvStructInfo;
3976 struct AsnDecodeSequenceItem items[] = {
3977 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
3978 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3979 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
3980 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
3981 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
3982 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
3983 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3984 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
3985 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
3986 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
3987 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
3988 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
3989 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
3990 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3991 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
3992 HashEncryptionAlgorithm.pszObjId), 0 },
3993 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
3994 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
3995 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
3996 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
3997 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
3998 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
3999 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
4001 BOOL ret;
4003 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4004 pvStructInfo, *pcbStructInfo);
4006 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4007 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4008 pcbDecoded, info ? info->Issuer.pbData : NULL);
4009 return ret;
4012 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
4013 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4014 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4016 BOOL ret = FALSE;
4018 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4019 pDecodePara, pvStructInfo, *pcbStructInfo);
4021 __TRY
4023 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
4024 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
4025 if (ret && pvStructInfo)
4027 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
4028 pcbStructInfo, *pcbStructInfo);
4029 if (ret)
4031 CMSG_SIGNER_INFO *info;
4033 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4034 pvStructInfo = *(BYTE **)pvStructInfo;
4035 info = (CMSG_SIGNER_INFO *)pvStructInfo;
4036 info->Issuer.pbData = ((BYTE *)info +
4037 sizeof(CMSG_SIGNER_INFO));
4038 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
4039 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4040 pcbStructInfo, NULL);
4044 __EXCEPT_PAGE_FAULT
4046 SetLastError(STATUS_ACCESS_VIOLATION);
4048 __ENDTRY
4049 TRACE("returning %d\n", ret);
4050 return ret;
4053 static BOOL CRYPT_DecodeSignerArray(const BYTE *pbEncoded, DWORD cbEncoded,
4054 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4056 BOOL ret;
4057 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
4058 CRYPT_AsnDecodePKCSSignerInfoInternal, sizeof(CMSG_SIGNER_INFO), TRUE,
4059 offsetof(CMSG_SIGNER_INFO, Issuer.pbData) };
4060 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
4062 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4063 pvStructInfo, *pcbStructInfo, pcbDecoded);
4065 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4066 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
4067 array ? array->rgItems : NULL);
4068 return ret;
4071 BOOL CRYPT_AsnDecodePKCSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
4072 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
4073 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
4075 BOOL ret = FALSE;
4076 struct AsnDecodeSequenceItem items[] = {
4077 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version),
4078 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4079 /* Placeholder for the hash algorithms - redundant with those in the
4080 * signers, so just ignore them.
4082 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
4083 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
4084 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
4085 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
4086 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4087 offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
4088 CRYPT_DecodeDERArray, sizeof(struct GenericArray), TRUE, TRUE,
4089 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
4090 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4091 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_DecodeDERArray,
4092 sizeof(struct GenericArray), TRUE, TRUE,
4093 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
4094 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
4095 CRYPT_DecodeSignerArray, sizeof(struct GenericArray), TRUE, TRUE,
4096 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
4099 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4100 pDecodePara, signedInfo, *pcbSignedInfo);
4102 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4103 pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo,
4104 NULL, NULL);
4105 TRACE("returning %d\n", ret);
4106 return ret;
4109 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
4110 LPCSTR lpszStructType)
4112 CryptDecodeObjectExFunc decodeFunc = NULL;
4114 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
4115 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
4117 SetLastError(ERROR_FILE_NOT_FOUND);
4118 return NULL;
4120 if (!HIWORD(lpszStructType))
4122 switch (LOWORD(lpszStructType))
4124 case (WORD)X509_CERT:
4125 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
4126 break;
4127 case (WORD)X509_CERT_TO_BE_SIGNED:
4128 decodeFunc = CRYPT_AsnDecodeCert;
4129 break;
4130 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
4131 decodeFunc = CRYPT_AsnDecodeCRL;
4132 break;
4133 case (WORD)X509_EXTENSIONS:
4134 decodeFunc = CRYPT_AsnDecodeExtensions;
4135 break;
4136 case (WORD)X509_NAME_VALUE:
4137 decodeFunc = CRYPT_AsnDecodeNameValue;
4138 break;
4139 case (WORD)X509_NAME:
4140 decodeFunc = CRYPT_AsnDecodeName;
4141 break;
4142 case (WORD)X509_PUBLIC_KEY_INFO:
4143 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
4144 break;
4145 case (WORD)X509_AUTHORITY_KEY_ID:
4146 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4147 break;
4148 case (WORD)X509_ALTERNATE_NAME:
4149 decodeFunc = CRYPT_AsnDecodeAltName;
4150 break;
4151 case (WORD)X509_BASIC_CONSTRAINTS:
4152 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4153 break;
4154 case (WORD)X509_BASIC_CONSTRAINTS2:
4155 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4156 break;
4157 case (WORD)RSA_CSP_PUBLICKEYBLOB:
4158 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
4159 break;
4160 case (WORD)X509_UNICODE_NAME:
4161 decodeFunc = CRYPT_AsnDecodeUnicodeName;
4162 break;
4163 case (WORD)PKCS_ATTRIBUTE:
4164 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
4165 break;
4166 case (WORD)X509_UNICODE_NAME_VALUE:
4167 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
4168 break;
4169 case (WORD)X509_OCTET_STRING:
4170 decodeFunc = CRYPT_AsnDecodeOctets;
4171 break;
4172 case (WORD)X509_BITS:
4173 case (WORD)X509_KEY_USAGE:
4174 decodeFunc = CRYPT_AsnDecodeBits;
4175 break;
4176 case (WORD)X509_INTEGER:
4177 decodeFunc = CRYPT_AsnDecodeInt;
4178 break;
4179 case (WORD)X509_MULTI_BYTE_INTEGER:
4180 decodeFunc = CRYPT_AsnDecodeInteger;
4181 break;
4182 case (WORD)X509_MULTI_BYTE_UINT:
4183 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
4184 break;
4185 case (WORD)X509_ENUMERATED:
4186 decodeFunc = CRYPT_AsnDecodeEnumerated;
4187 break;
4188 case (WORD)X509_CHOICE_OF_TIME:
4189 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
4190 break;
4191 case (WORD)X509_AUTHORITY_KEY_ID2:
4192 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4193 break;
4194 case (WORD)PKCS_CONTENT_INFO:
4195 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
4196 break;
4197 case (WORD)X509_SEQUENCE_OF_ANY:
4198 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
4199 break;
4200 case (WORD)PKCS_UTC_TIME:
4201 decodeFunc = CRYPT_AsnDecodeUtcTime;
4202 break;
4203 case (WORD)X509_CRL_DIST_POINTS:
4204 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4205 break;
4206 case (WORD)X509_ENHANCED_KEY_USAGE:
4207 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4208 break;
4209 case (WORD)PKCS_ATTRIBUTES:
4210 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
4211 break;
4212 case (WORD)X509_ISSUING_DIST_POINT:
4213 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4214 break;
4215 case (WORD)PKCS7_SIGNER_INFO:
4216 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
4217 break;
4220 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4221 decodeFunc = CRYPT_AsnDecodeExtensions;
4222 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4223 decodeFunc = CRYPT_AsnDecodeUtcTime;
4224 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4225 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4226 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4227 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4228 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4229 decodeFunc = CRYPT_AsnDecodeEnumerated;
4230 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4231 decodeFunc = CRYPT_AsnDecodeBits;
4232 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4233 decodeFunc = CRYPT_AsnDecodeOctets;
4234 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4235 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4236 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4237 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4238 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4239 decodeFunc = CRYPT_AsnDecodeAltName;
4240 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4241 decodeFunc = CRYPT_AsnDecodeAltName;
4242 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4243 decodeFunc = CRYPT_AsnDecodeAltName;
4244 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4245 decodeFunc = CRYPT_AsnDecodeAltName;
4246 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4247 decodeFunc = CRYPT_AsnDecodeAltName;
4248 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4249 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4250 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4251 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4252 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4253 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4254 return decodeFunc;
4257 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
4258 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4260 static HCRYPTOIDFUNCSET set = NULL;
4261 CryptDecodeObjectFunc decodeFunc = NULL;
4263 if (!set)
4264 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
4265 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4266 (void **)&decodeFunc, hFunc);
4267 return decodeFunc;
4270 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
4271 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4273 static HCRYPTOIDFUNCSET set = NULL;
4274 CryptDecodeObjectExFunc decodeFunc = NULL;
4276 if (!set)
4277 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
4278 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4279 (void **)&decodeFunc, hFunc);
4280 return decodeFunc;
4283 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4284 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
4285 DWORD *pcbStructInfo)
4287 BOOL ret = FALSE;
4288 CryptDecodeObjectFunc pCryptDecodeObject = NULL;
4289 CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
4290 HCRYPTOIDFUNCADDR hFunc = NULL;
4292 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
4293 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
4294 pvStructInfo, pcbStructInfo);
4296 if (!pvStructInfo && !pcbStructInfo)
4298 SetLastError(ERROR_INVALID_PARAMETER);
4299 return FALSE;
4301 if (!cbEncoded)
4303 SetLastError(CRYPT_E_ASN1_EOD);
4304 return FALSE;
4306 if (cbEncoded > MAX_ENCODED_LEN)
4308 SetLastError(CRYPT_E_ASN1_LARGE);
4309 return FALSE;
4312 if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
4313 lpszStructType)))
4315 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4316 debugstr_a(lpszStructType));
4317 pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
4318 lpszStructType, &hFunc);
4319 if (!pCryptDecodeObject)
4320 pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
4321 lpszStructType, &hFunc);
4323 if (pCryptDecodeObject)
4324 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4325 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4326 else if (pCryptDecodeObjectEx)
4327 ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
4328 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
4329 pvStructInfo, pcbStructInfo);
4330 if (hFunc)
4331 CryptFreeOIDFunctionAddress(hFunc, 0);
4332 TRACE_(crypt)("returning %d\n", ret);
4333 return ret;
4336 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4337 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4338 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4340 BOOL ret = FALSE;
4341 CryptDecodeObjectExFunc decodeFunc;
4342 HCRYPTOIDFUNCADDR hFunc = NULL;
4344 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
4345 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
4346 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4348 if (!pvStructInfo && !pcbStructInfo)
4350 SetLastError(ERROR_INVALID_PARAMETER);
4351 return FALSE;
4353 if (!cbEncoded)
4355 SetLastError(CRYPT_E_ASN1_EOD);
4356 return FALSE;
4358 if (cbEncoded > MAX_ENCODED_LEN)
4360 SetLastError(CRYPT_E_ASN1_LARGE);
4361 return FALSE;
4364 SetLastError(NOERROR);
4365 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
4366 *(BYTE **)pvStructInfo = NULL;
4367 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
4368 if (!decodeFunc)
4370 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4371 debugstr_a(lpszStructType));
4372 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
4373 &hFunc);
4375 if (decodeFunc)
4376 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
4377 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4378 else
4380 CryptDecodeObjectFunc pCryptDecodeObject =
4381 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
4383 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
4384 * directly, as that could cause an infinite loop.
4386 if (pCryptDecodeObject)
4388 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4390 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4391 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
4392 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4393 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
4394 ret = pCryptDecodeObject(dwCertEncodingType,
4395 lpszStructType, pbEncoded, cbEncoded, dwFlags,
4396 *(BYTE **)pvStructInfo, pcbStructInfo);
4398 else
4399 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4400 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4403 if (hFunc)
4404 CryptFreeOIDFunctionAddress(hFunc, 0);
4405 TRACE_(crypt)("returning %d\n", ret);
4406 return ret;