msvcrt: New implementation of fcvt.
[wine/multimedia.git] / dlls / crypt32 / decode.c
blob082c28af9270e459c2b4f932e9c91f1bd7ecf9c1
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 itemLen;
313 if ((ret = CRYPT_GetLengthIndefinite(ptr,
314 cbEncoded - (ptr - pbEncoded), &itemLen)))
316 BYTE itemLenBytes = GET_LEN_BYTES(ptr[1]);
318 if (ptr[0] == items[i].tag || !items[i].tag)
320 DWORD itemEncodedLen;
322 if (itemLen == CMSG_INDEFINITE_LENGTH)
323 itemEncodedLen = cbEncoded - (ptr - pbEncoded);
324 else
325 itemEncodedLen = 1 + itemLenBytes + itemLen;
326 if (nextData && pvStructInfo && items[i].hasPointer)
328 TRACE("Setting next pointer to %p\n",
329 nextData);
330 *(BYTE **)((BYTE *)pvStructInfo +
331 items[i].pointerOffset) = nextData;
333 if (items[i].decodeFunc)
335 DWORD itemDecoded;
337 if (pvStructInfo)
338 TRACE("decoding item %d\n", i);
339 else
340 TRACE("sizing item %d\n", i);
341 ret = items[i].decodeFunc(ptr, itemEncodedLen,
342 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
343 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
344 : NULL, &items[i].size, &itemDecoded);
345 if (ret)
347 /* Account for alignment padding */
348 if (items[i].size % sizeof(DWORD_PTR))
349 items[i].size += sizeof(DWORD_PTR) -
350 items[i].size % sizeof(DWORD_PTR);
351 TRACE("item %d size: %d\n", i, items[i].size);
352 if (nextData && items[i].hasPointer &&
353 items[i].size > items[i].minSize)
354 nextData += items[i].size - items[i].minSize;
355 if (itemDecoded > itemEncodedLen)
357 WARN("decoded length %d exceeds encoded %d\n",
358 itemDecoded, itemEncodedLen);
359 SetLastError(CRYPT_E_ASN1_CORRUPT);
360 ret = FALSE;
362 else
364 if (itemLen == CMSG_INDEFINITE_LENGTH)
366 if (itemDecoded > itemEncodedLen - 2 ||
367 *(ptr + itemDecoded) != 0 ||
368 *(ptr + itemDecoded + 1) != 0)
370 TRACE("expected 0 TLV\n");
371 SetLastError(CRYPT_E_ASN1_CORRUPT);
372 ret = FALSE;
374 else
375 itemDecoded += 2;
377 if (ret)
379 ptr += itemDecoded;
380 decoded += itemDecoded;
381 TRACE("item %d: decoded %d bytes\n", i,
382 itemDecoded);
386 else if (items[i].optional &&
387 GetLastError() == CRYPT_E_ASN1_BADTAG)
389 TRACE("skipping optional item %d\n", i);
390 items[i].size = items[i].minSize;
391 SetLastError(NOERROR);
392 ret = TRUE;
394 else
395 TRACE("item %d failed: %08x\n", i,
396 GetLastError());
398 else if (itemLen == CMSG_INDEFINITE_LENGTH)
400 ERR("can't use indefinite length encoding without a decoder\n");
401 SetLastError(CRYPT_E_ASN1_CORRUPT);
402 ret = FALSE;
404 else
406 TRACE("item %d: decoded %d bytes\n", i, itemEncodedLen);
407 ptr += itemEncodedLen;
408 decoded += itemEncodedLen;
409 items[i].size = items[i].minSize;
412 else if (items[i].optional)
414 TRACE("skipping optional item %d\n", i);
415 items[i].size = items[i].minSize;
417 else
419 TRACE("item %d: tag %02x doesn't match expected %02x\n",
420 i, ptr[0], items[i].tag);
421 SetLastError(CRYPT_E_ASN1_BADTAG);
422 ret = FALSE;
426 else if (items[i].optional)
428 TRACE("missing optional item %d, skipping\n", i);
429 items[i].size = items[i].minSize;
431 else
433 TRACE("not enough bytes for item %d, failing\n", i);
434 SetLastError(CRYPT_E_ASN1_CORRUPT);
435 ret = FALSE;
438 if (cbDecoded)
439 *cbDecoded = decoded;
440 TRACE("returning %d\n", ret);
441 return ret;
444 /* This decodes an arbitrary sequence into a contiguous block of memory
445 * (basically, a struct.) Each element being decoded is described by a struct
446 * AsnDecodeSequenceItem, see above.
447 * startingPointer is an optional pointer to the first place where dynamic
448 * data will be stored. If you know the starting offset, you may pass it
449 * here. Otherwise, pass NULL, and one will be inferred from the items.
451 static BOOL CRYPT_AsnDecodeSequence(struct AsnDecodeSequenceItem items[],
452 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
453 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
454 DWORD *pcbDecoded, void *startingPointer)
456 BOOL ret;
458 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
459 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
460 startingPointer);
462 if (pbEncoded[0] == ASN_SEQUENCE)
464 DWORD dataLen;
466 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
468 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
469 const BYTE *ptr = pbEncoded + 1 + lenBytes;
471 cbEncoded -= 1 + lenBytes;
472 if (dataLen == CMSG_INDEFINITE_LENGTH)
473 dataLen = cbEncoded;
474 else if (cbEncoded < dataLen)
476 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
477 cbEncoded);
478 SetLastError(CRYPT_E_ASN1_CORRUPT);
479 ret = FALSE;
481 if (ret)
483 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
484 ptr, dataLen, dwFlags, NULL, NULL, &cbDecoded);
485 if (ret && dataLen == CMSG_INDEFINITE_LENGTH)
487 if (cbDecoded > cbEncoded - 2)
489 /* Not enough space for 0 TLV */
490 SetLastError(CRYPT_E_ASN1_CORRUPT);
491 ret = FALSE;
493 else if (*(ptr + cbDecoded) != 0 ||
494 *(ptr + cbDecoded + 1) != 0)
496 TRACE("expected 0 TLV\n");
497 SetLastError(CRYPT_E_ASN1_CORRUPT);
498 ret = FALSE;
500 else
501 cbDecoded += 2;
504 if (ret && cbDecoded != dataLen)
506 TRACE("expected %d decoded, got %d, failing\n", dataLen,
507 cbDecoded);
508 SetLastError(CRYPT_E_ASN1_CORRUPT);
509 ret = FALSE;
511 if (ret)
513 DWORD i, bytesNeeded = 0, structSize = 0;
515 for (i = 0; i < cItem; i++)
517 bytesNeeded += items[i].size;
518 structSize += items[i].minSize;
520 if (pcbDecoded)
521 *pcbDecoded = 1 + lenBytes + cbDecoded;
522 if (!pvStructInfo)
523 *pcbStructInfo = bytesNeeded;
524 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
525 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
527 BYTE *nextData;
529 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
530 pvStructInfo = *(BYTE **)pvStructInfo;
531 if (startingPointer)
532 nextData = (BYTE *)startingPointer;
533 else
534 nextData = (BYTE *)pvStructInfo + structSize;
535 memset(pvStructInfo, 0, structSize);
536 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
537 ptr, dataLen, dwFlags, pvStructInfo, nextData,
538 &cbDecoded);
543 else
545 SetLastError(CRYPT_E_ASN1_BADTAG);
546 ret = FALSE;
548 TRACE("returning %d (%08x)\n", ret, GetLastError());
549 return ret;
552 /* tag:
553 * The expected tag of the entire encoded array (usually a variant
554 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
555 * regardless of the tag seen.
556 * decodeFunc:
557 * used to decode each item in the array
558 * itemSize:
559 * is the minimum size of each decoded item
560 * hasPointer:
561 * indicates whether each item has a dynamic pointer
562 * pointerOffset:
563 * indicates the offset within itemSize at which the pointer exists
565 struct AsnArrayDescriptor
567 BYTE tag;
568 InternalDecodeFunc decodeFunc;
569 DWORD itemSize;
570 BOOL hasPointer;
571 DWORD pointerOffset;
574 struct AsnArrayItemSize
576 DWORD encodedLen;
577 DWORD size;
580 /* Decodes an array of like types into a struct GenericArray.
581 * The layout and decoding of the array are described by a struct
582 * AsnArrayDescriptor.
584 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
585 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
586 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
587 DWORD *pcbDecoded, void *startingPointer)
589 BOOL ret = TRUE;
591 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
592 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
593 startingPointer);
595 if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
597 DWORD dataLen;
599 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
601 DWORD bytesNeeded, cItems = 0, decoded;
602 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
603 /* There can be arbitrarily many items, but there is often only one.
605 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
607 decoded = 1 + lenBytes;
608 bytesNeeded = sizeof(struct GenericArray);
609 if (dataLen)
611 const BYTE *ptr;
612 BOOL doneDecoding = FALSE;
614 for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
616 DWORD itemLenBytes;
618 itemLenBytes = GET_LEN_BYTES(ptr[1]);
619 if (dataLen == CMSG_INDEFINITE_LENGTH)
621 if (ptr[0] == 0)
623 doneDecoding = TRUE;
624 if (itemLenBytes != 1 || ptr[1] != 0)
626 SetLastError(CRYPT_E_ASN1_CORRUPT);
627 ret = FALSE;
629 else
630 decoded += 2;
633 else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
634 doneDecoding = TRUE;
635 if (!doneDecoding)
637 DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
639 /* Each item decoded may not tolerate extraneous bytes,
640 * so get the length of the next element if known.
642 if ((ret = CRYPT_GetLengthIndefinite(ptr,
643 cbEncoded - (ptr - pbEncoded), &itemDataLen)))
645 if (itemDataLen == CMSG_INDEFINITE_LENGTH)
646 itemEncoded = cbEncoded - (ptr - pbEncoded);
647 else
648 itemEncoded = 1 + itemLenBytes + itemDataLen;
650 if (ret)
651 ret = arrayDesc->decodeFunc(ptr, itemEncoded,
652 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size,
653 &itemDecoded);
654 if (ret)
656 cItems++;
657 if (itemSizes != &itemSize)
658 itemSizes = CryptMemRealloc(itemSizes,
659 cItems * sizeof(struct AsnArrayItemSize));
660 else if (cItems > 1)
662 itemSizes =
663 CryptMemAlloc(
664 cItems * sizeof(struct AsnArrayItemSize));
665 if (itemSizes)
666 memcpy(itemSizes, &itemSize,
667 sizeof(itemSize));
669 if (itemSizes)
671 decoded += itemDecoded;
672 itemSizes[cItems - 1].encodedLen = itemEncoded;
673 itemSizes[cItems - 1].size = size;
674 bytesNeeded += size;
675 ptr += itemEncoded;
677 else
678 ret = FALSE;
683 if (ret)
685 if (pcbDecoded)
686 *pcbDecoded = decoded;
687 if (!pvStructInfo)
688 *pcbStructInfo = bytesNeeded;
689 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
690 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
692 DWORD i;
693 BYTE *nextData;
694 const BYTE *ptr;
695 struct GenericArray *array;
697 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
698 pvStructInfo = *(BYTE **)pvStructInfo;
699 array = (struct GenericArray *)pvStructInfo;
700 array->cItems = cItems;
701 if (startingPointer)
702 array->rgItems = startingPointer;
703 else
704 array->rgItems = (BYTE *)array +
705 sizeof(struct GenericArray);
706 nextData = (BYTE *)array->rgItems +
707 array->cItems * arrayDesc->itemSize;
708 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
709 i < cItems && ptr - pbEncoded - 1 - lenBytes <
710 dataLen; i++)
712 DWORD itemDecoded;
714 if (arrayDesc->hasPointer)
715 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
716 + arrayDesc->pointerOffset) = nextData;
717 ret = arrayDesc->decodeFunc(ptr,
718 itemSizes[i].encodedLen,
719 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
720 array->rgItems + i * arrayDesc->itemSize,
721 &itemSizes[i].size, &itemDecoded);
722 if (ret)
724 nextData += itemSizes[i].size - arrayDesc->itemSize;
725 ptr += itemDecoded;
730 if (itemSizes != &itemSize)
731 CryptMemFree(itemSizes);
734 else
736 SetLastError(CRYPT_E_ASN1_BADTAG);
737 ret = FALSE;
739 return ret;
742 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
743 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
744 * to CRYPT_E_ASN1_CORRUPT.
745 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
746 * set!
748 static BOOL CRYPT_AsnDecodeDerBlob(const BYTE *pbEncoded, DWORD cbEncoded,
749 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
751 BOOL ret;
752 DWORD dataLen;
754 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
756 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
757 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
759 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
760 bytesNeeded += 1 + lenBytes + dataLen;
762 if (pcbDecoded)
763 *pcbDecoded = 1 + lenBytes + dataLen;
764 if (!pvStructInfo)
765 *pcbStructInfo = bytesNeeded;
766 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded)))
768 CRYPT_DER_BLOB *blob;
770 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
771 pvStructInfo = *(BYTE **)pvStructInfo;
772 blob = (CRYPT_DER_BLOB *)pvStructInfo;
773 blob->cbData = 1 + lenBytes + dataLen;
774 if (blob->cbData)
776 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
777 blob->pbData = (BYTE *)pbEncoded;
778 else
780 assert(blob->pbData);
781 memcpy(blob->pbData, pbEncoded, blob->cbData);
784 else
786 SetLastError(CRYPT_E_ASN1_CORRUPT);
787 ret = FALSE;
791 return ret;
794 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
795 static BOOL CRYPT_AsnDecodeBitsSwapBytes(const BYTE *pbEncoded,
796 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
797 DWORD *pcbDecoded)
799 BOOL ret;
801 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
802 pvStructInfo, *pcbStructInfo, pcbDecoded);
804 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
805 * place.
807 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
808 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
809 pcbDecoded);
810 if (ret && pvStructInfo)
812 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
814 if (blob->cbData)
816 DWORD i;
817 BYTE temp;
819 for (i = 0; i < blob->cbData / 2; i++)
821 temp = blob->pbData[i];
822 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
823 blob->pbData[blob->cbData - i - 1] = temp;
827 TRACE("returning %d (%08x)\n", ret, GetLastError());
828 return ret;
831 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
832 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
833 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
835 BOOL ret = TRUE;
837 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
838 pDecodePara, pvStructInfo, *pcbStructInfo);
840 __TRY
842 struct AsnDecodeSequenceItem items[] = {
843 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
844 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
845 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
846 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
847 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
848 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
849 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
850 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
851 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
852 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
855 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
856 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
857 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
858 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
859 pcbStructInfo, NULL, NULL);
861 __EXCEPT_PAGE_FAULT
863 SetLastError(STATUS_ACCESS_VIOLATION);
864 ret = FALSE;
866 __ENDTRY
868 TRACE("Returning %d (%08x)\n", ret, GetLastError());
869 return ret;
872 static BOOL CRYPT_AsnDecodeCertVersion(const BYTE *pbEncoded, DWORD cbEncoded,
873 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
875 BOOL ret;
876 DWORD dataLen;
878 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
880 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
882 ret = CRYPT_AsnDecodeIntInternal(pbEncoded + 1 + lenBytes, dataLen,
883 dwFlags, pvStructInfo, pcbStructInfo, NULL);
884 if (pcbDecoded)
885 *pcbDecoded = 1 + lenBytes + dataLen;
887 return ret;
890 static BOOL CRYPT_AsnDecodeValidity(const BYTE *pbEncoded, DWORD cbEncoded,
891 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
893 BOOL ret;
895 struct AsnDecodeSequenceItem items[] = {
896 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
897 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
898 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
899 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
902 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
903 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
904 pcbDecoded, NULL);
905 return ret;
908 static BOOL CRYPT_AsnDecodeCertExtensions(const BYTE *pbEncoded,
909 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
910 DWORD *pcbDecoded)
912 BOOL ret;
913 DWORD dataLen;
915 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
917 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
919 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded + 1 + lenBytes,
920 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
921 if (ret && pcbDecoded)
922 *pcbDecoded = 1 + lenBytes + dataLen;
924 return ret;
927 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
928 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
929 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
931 BOOL ret = TRUE;
932 struct AsnDecodeSequenceItem items[] = {
933 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
934 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
935 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
936 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
937 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
938 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
939 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
940 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
941 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
942 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
943 Issuer.pbData) },
944 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
945 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
946 FALSE, 0 },
947 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
948 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
949 Subject.pbData) },
950 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
951 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
952 FALSE, TRUE, offsetof(CERT_INFO,
953 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
954 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
955 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
956 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
957 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
958 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
959 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
960 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
961 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
962 offsetof(CERT_INFO, rgExtension), 0 },
965 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
966 pDecodePara, pvStructInfo, *pcbStructInfo);
968 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
969 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
970 NULL, NULL);
971 if (ret && pvStructInfo)
973 CERT_INFO *info;
975 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
976 info = *(CERT_INFO **)pvStructInfo;
977 else
978 info = (CERT_INFO *)pvStructInfo;
979 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
980 !info->Subject.cbData)
982 SetLastError(CRYPT_E_ASN1_CORRUPT);
983 /* Don't need to deallocate, because it should have failed on the
984 * first pass (and no memory was allocated.)
986 ret = FALSE;
990 TRACE("Returning %d (%08x)\n", ret, GetLastError());
991 return ret;
994 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
995 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
996 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
998 BOOL ret = FALSE;
1000 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1001 pDecodePara, pvStructInfo, *pcbStructInfo);
1003 __TRY
1005 DWORD size = 0;
1007 /* Unless told not to, first try to decode it as a signed cert. */
1008 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1010 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
1012 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1013 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1014 (BYTE *)&signedCert, &size);
1015 if (ret)
1017 size = 0;
1018 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1019 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
1020 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
1021 pvStructInfo, pcbStructInfo);
1022 LocalFree(signedCert);
1025 /* Failing that, try it as an unsigned cert */
1026 if (!ret)
1028 size = 0;
1029 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1030 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
1031 pDecodePara, pvStructInfo, pcbStructInfo);
1034 __EXCEPT_PAGE_FAULT
1036 SetLastError(STATUS_ACCESS_VIOLATION);
1038 __ENDTRY
1040 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1041 return ret;
1044 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
1045 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1047 BOOL ret;
1048 struct AsnDecodeSequenceItem items[] = {
1049 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
1050 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
1051 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
1052 { 0, offsetof(CRL_ENTRY, RevocationDate),
1053 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
1054 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
1055 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1056 offsetof(CRL_ENTRY, rgExtension), 0 },
1058 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
1060 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
1061 *pcbStructInfo);
1063 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1064 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, pcbDecoded,
1065 entry ? entry->SerialNumber.pbData : NULL);
1066 return ret;
1069 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
1070 * been set prior to calling.
1072 static BOOL CRYPT_AsnDecodeCRLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
1073 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1075 BOOL ret;
1076 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1077 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
1078 offsetof(CRL_ENTRY, SerialNumber.pbData) };
1079 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
1081 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1082 pvStructInfo, *pcbStructInfo, pcbDecoded);
1084 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1085 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1086 entries ? entries->rgItems : NULL);
1087 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1088 return ret;
1091 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1092 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1093 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1095 struct AsnDecodeSequenceItem items[] = {
1096 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1097 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1098 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1099 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1100 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1101 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1102 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1103 Issuer.pbData) },
1104 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1105 sizeof(FILETIME), FALSE, FALSE, 0 },
1106 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1107 sizeof(FILETIME), TRUE, FALSE, 0 },
1108 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1109 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
1110 offsetof(CRL_INFO, rgCRLEntry), 0 },
1111 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1112 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1113 offsetof(CRL_INFO, rgExtension), 0 },
1115 BOOL ret = TRUE;
1117 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1118 pDecodePara, pvStructInfo, *pcbStructInfo);
1120 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1121 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
1122 NULL, NULL);
1124 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1125 return ret;
1128 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1129 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1130 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1132 BOOL ret = FALSE;
1134 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1135 pDecodePara, pvStructInfo, *pcbStructInfo);
1137 __TRY
1139 DWORD size = 0;
1141 /* Unless told not to, first try to decode it as a signed crl. */
1142 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1144 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1146 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1147 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1148 (BYTE *)&signedCrl, &size);
1149 if (ret)
1151 size = 0;
1152 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1153 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1154 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1155 pvStructInfo, pcbStructInfo);
1156 LocalFree(signedCrl);
1159 /* Failing that, try it as an unsigned crl */
1160 if (!ret)
1162 size = 0;
1163 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1164 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1165 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1168 __EXCEPT_PAGE_FAULT
1170 SetLastError(STATUS_ACCESS_VIOLATION);
1172 __ENDTRY
1174 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1175 return ret;
1178 static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded,
1179 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1181 BOOL ret = TRUE;
1182 DWORD dataLen;
1184 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1185 pvStructInfo, *pcbStructInfo);
1187 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1189 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1190 DWORD bytesNeeded = sizeof(LPSTR);
1192 if (dataLen)
1194 /* The largest possible string for the first two components
1195 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1197 char firstTwo[6];
1198 const BYTE *ptr;
1200 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1201 pbEncoded[1 + lenBytes] / 40,
1202 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1203 * 40);
1204 bytesNeeded += strlen(firstTwo) + 1;
1205 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1206 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1208 /* large enough for ".4000000" */
1209 char str[9];
1210 int val = 0;
1212 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1213 (*ptr & 0x80))
1215 val <<= 7;
1216 val |= *ptr & 0x7f;
1217 ptr++;
1219 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1220 (*ptr & 0x80))
1222 SetLastError(CRYPT_E_ASN1_CORRUPT);
1223 ret = FALSE;
1225 else
1227 val <<= 7;
1228 val |= *ptr++;
1229 snprintf(str, sizeof(str), ".%d", val);
1230 bytesNeeded += strlen(str);
1234 if (pcbDecoded)
1235 *pcbDecoded = 1 + lenBytes + dataLen;
1236 if (!pvStructInfo)
1237 *pcbStructInfo = bytesNeeded;
1238 else if (*pcbStructInfo < bytesNeeded)
1240 *pcbStructInfo = bytesNeeded;
1241 SetLastError(ERROR_MORE_DATA);
1242 ret = FALSE;
1244 else
1246 if (dataLen)
1248 const BYTE *ptr;
1249 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1251 *pszObjId = 0;
1252 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1253 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1254 40) * 40);
1255 pszObjId += strlen(pszObjId);
1256 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1257 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1259 int val = 0;
1261 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1262 (*ptr & 0x80))
1264 val <<= 7;
1265 val |= *ptr & 0x7f;
1266 ptr++;
1268 val <<= 7;
1269 val |= *ptr++;
1270 sprintf(pszObjId, ".%d", val);
1271 pszObjId += strlen(pszObjId);
1274 else
1275 *(LPSTR *)pvStructInfo = NULL;
1276 *pcbStructInfo = bytesNeeded;
1279 return ret;
1282 static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded,
1283 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1285 BOOL ret;
1287 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1288 pvStructInfo, *pcbStructInfo);
1290 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1291 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1292 pvStructInfo, pcbStructInfo, pcbDecoded);
1293 else
1295 SetLastError(CRYPT_E_ASN1_BADTAG);
1296 ret = FALSE;
1298 return ret;
1301 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1302 * ahead of time!
1304 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
1305 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1307 struct AsnDecodeSequenceItem items[] = {
1308 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1309 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1310 offsetof(CERT_EXTENSION, pszObjId), 0 },
1311 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1312 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1313 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1314 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1315 offsetof(CERT_EXTENSION, Value.pbData) },
1317 BOOL ret = TRUE;
1318 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1320 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1321 *pcbStructInfo);
1323 if (ext)
1324 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1325 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1326 pbEncoded, cbEncoded, dwFlags, NULL, ext, pcbStructInfo,
1327 pcbDecoded, ext ? ext->pszObjId : NULL);
1328 if (ext)
1329 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1330 debugstr_a(ext->pszObjId));
1331 TRACE("returning %d (%08x)\n", ret, GetLastError());
1332 return ret;
1335 static BOOL CRYPT_AsnDecodeExtensionsInternal(const BYTE *pbEncoded,
1336 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1337 DWORD *pcbDecoded)
1339 BOOL ret = TRUE;
1340 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1341 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1342 offsetof(CERT_EXTENSION, pszObjId) };
1343 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1345 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1346 pvStructInfo, *pcbStructInfo, pcbDecoded);
1348 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1349 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1350 exts ? exts->rgExtension : NULL);
1351 return ret;
1354 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1355 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1356 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1358 BOOL ret = TRUE;
1360 __TRY
1362 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
1363 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1364 if (ret && pvStructInfo)
1366 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1367 pcbStructInfo, *pcbStructInfo);
1368 if (ret)
1370 CERT_EXTENSIONS *exts;
1372 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1373 pvStructInfo = *(BYTE **)pvStructInfo;
1374 exts = (CERT_EXTENSIONS *)pvStructInfo;
1375 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1376 sizeof(CERT_EXTENSIONS));
1377 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
1378 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1379 pcbStructInfo, NULL);
1383 __EXCEPT_PAGE_FAULT
1385 SetLastError(STATUS_ACCESS_VIOLATION);
1386 ret = FALSE;
1388 __ENDTRY
1389 return ret;
1392 /* Warning: this assumes the address of value->Value.pbData is already set, in
1393 * order to avoid overwriting memory. (In some cases, it may change it, if it
1394 * doesn't copy anything to memory.) Be sure to set it correctly!
1396 static BOOL CRYPT_AsnDecodeNameValueInternal(const BYTE *pbEncoded,
1397 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1398 DWORD *pcbDecoded)
1400 BOOL ret = TRUE;
1401 DWORD dataLen;
1402 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1404 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1406 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1407 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1409 switch (pbEncoded[0])
1411 case ASN_OCTETSTRING:
1412 valueType = CERT_RDN_OCTET_STRING;
1413 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1414 bytesNeeded += dataLen;
1415 break;
1416 case ASN_NUMERICSTRING:
1417 valueType = CERT_RDN_NUMERIC_STRING;
1418 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1419 bytesNeeded += dataLen;
1420 break;
1421 case ASN_PRINTABLESTRING:
1422 valueType = CERT_RDN_PRINTABLE_STRING;
1423 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1424 bytesNeeded += dataLen;
1425 break;
1426 case ASN_IA5STRING:
1427 valueType = CERT_RDN_IA5_STRING;
1428 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1429 bytesNeeded += dataLen;
1430 break;
1431 case ASN_T61STRING:
1432 valueType = CERT_RDN_T61_STRING;
1433 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1434 bytesNeeded += dataLen;
1435 break;
1436 case ASN_VIDEOTEXSTRING:
1437 valueType = CERT_RDN_VIDEOTEX_STRING;
1438 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1439 bytesNeeded += dataLen;
1440 break;
1441 case ASN_GRAPHICSTRING:
1442 valueType = CERT_RDN_GRAPHIC_STRING;
1443 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1444 bytesNeeded += dataLen;
1445 break;
1446 case ASN_VISIBLESTRING:
1447 valueType = CERT_RDN_VISIBLE_STRING;
1448 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1449 bytesNeeded += dataLen;
1450 break;
1451 case ASN_GENERALSTRING:
1452 valueType = CERT_RDN_GENERAL_STRING;
1453 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1454 bytesNeeded += dataLen;
1455 break;
1456 case ASN_UNIVERSALSTRING:
1457 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1458 SetLastError(CRYPT_E_ASN1_BADTAG);
1459 return FALSE;
1460 case ASN_BMPSTRING:
1461 valueType = CERT_RDN_BMP_STRING;
1462 bytesNeeded += dataLen;
1463 break;
1464 case ASN_UTF8STRING:
1465 valueType = CERT_RDN_UTF8_STRING;
1466 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1467 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1468 break;
1469 default:
1470 SetLastError(CRYPT_E_ASN1_BADTAG);
1471 return FALSE;
1474 if (pcbDecoded)
1475 *pcbDecoded = 1 + lenBytes + dataLen;
1476 if (!value)
1477 *pcbStructInfo = bytesNeeded;
1478 else if (*pcbStructInfo < bytesNeeded)
1480 *pcbStructInfo = bytesNeeded;
1481 SetLastError(ERROR_MORE_DATA);
1482 ret = FALSE;
1484 else
1486 *pcbStructInfo = bytesNeeded;
1487 value->dwValueType = valueType;
1488 if (dataLen)
1490 DWORD i;
1492 assert(value->Value.pbData);
1493 switch (pbEncoded[0])
1495 case ASN_OCTETSTRING:
1496 case ASN_NUMERICSTRING:
1497 case ASN_PRINTABLESTRING:
1498 case ASN_IA5STRING:
1499 case ASN_T61STRING:
1500 case ASN_VIDEOTEXSTRING:
1501 case ASN_GRAPHICSTRING:
1502 case ASN_VISIBLESTRING:
1503 case ASN_GENERALSTRING:
1504 value->Value.cbData = dataLen;
1505 if (dataLen)
1507 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1508 memcpy(value->Value.pbData,
1509 pbEncoded + 1 + lenBytes, dataLen);
1510 else
1511 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1512 lenBytes;
1514 break;
1515 case ASN_BMPSTRING:
1517 LPWSTR str = (LPWSTR)value->Value.pbData;
1519 value->Value.cbData = dataLen;
1520 for (i = 0; i < dataLen / 2; i++)
1521 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1522 pbEncoded[1 + lenBytes + 2 * i + 1];
1523 break;
1525 case ASN_UTF8STRING:
1527 LPWSTR str = (LPWSTR)value->Value.pbData;
1529 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1530 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1531 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1532 break;
1536 else
1538 value->Value.cbData = 0;
1539 value->Value.pbData = NULL;
1543 return ret;
1546 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1547 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1548 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1550 BOOL ret = TRUE;
1552 __TRY
1554 ret = CRYPT_AsnDecodeNameValueInternal(pbEncoded, cbEncoded,
1555 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1556 if (ret && pvStructInfo)
1558 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1559 pcbStructInfo, *pcbStructInfo);
1560 if (ret)
1562 CERT_NAME_VALUE *value;
1564 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1565 pvStructInfo = *(BYTE **)pvStructInfo;
1566 value = (CERT_NAME_VALUE *)pvStructInfo;
1567 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1568 ret = CRYPT_AsnDecodeNameValueInternal( pbEncoded, cbEncoded,
1569 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1570 pcbStructInfo, NULL);
1574 __EXCEPT_PAGE_FAULT
1576 SetLastError(STATUS_ACCESS_VIOLATION);
1577 ret = FALSE;
1579 __ENDTRY
1580 return ret;
1583 static BOOL CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE *pbEncoded,
1584 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1585 DWORD *pcbDecoded)
1587 BOOL ret = TRUE;
1588 DWORD dataLen;
1589 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1591 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1593 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1594 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1596 switch (pbEncoded[0])
1598 case ASN_NUMERICSTRING:
1599 valueType = CERT_RDN_NUMERIC_STRING;
1600 bytesNeeded += dataLen * 2;
1601 break;
1602 case ASN_PRINTABLESTRING:
1603 valueType = CERT_RDN_PRINTABLE_STRING;
1604 bytesNeeded += dataLen * 2;
1605 break;
1606 case ASN_IA5STRING:
1607 valueType = CERT_RDN_IA5_STRING;
1608 bytesNeeded += dataLen * 2;
1609 break;
1610 case ASN_T61STRING:
1611 valueType = CERT_RDN_T61_STRING;
1612 bytesNeeded += dataLen * 2;
1613 break;
1614 case ASN_VIDEOTEXSTRING:
1615 valueType = CERT_RDN_VIDEOTEX_STRING;
1616 bytesNeeded += dataLen * 2;
1617 break;
1618 case ASN_GRAPHICSTRING:
1619 valueType = CERT_RDN_GRAPHIC_STRING;
1620 bytesNeeded += dataLen * 2;
1621 break;
1622 case ASN_VISIBLESTRING:
1623 valueType = CERT_RDN_VISIBLE_STRING;
1624 bytesNeeded += dataLen * 2;
1625 break;
1626 case ASN_GENERALSTRING:
1627 valueType = CERT_RDN_GENERAL_STRING;
1628 bytesNeeded += dataLen * 2;
1629 break;
1630 case ASN_UNIVERSALSTRING:
1631 valueType = CERT_RDN_UNIVERSAL_STRING;
1632 bytesNeeded += dataLen / 2;
1633 break;
1634 case ASN_BMPSTRING:
1635 valueType = CERT_RDN_BMP_STRING;
1636 bytesNeeded += dataLen;
1637 break;
1638 case ASN_UTF8STRING:
1639 valueType = CERT_RDN_UTF8_STRING;
1640 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1641 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1642 break;
1643 default:
1644 SetLastError(CRYPT_E_ASN1_BADTAG);
1645 return FALSE;
1648 if (pcbDecoded)
1649 *pcbDecoded = 1 + lenBytes + dataLen;
1650 if (!value)
1651 *pcbStructInfo = bytesNeeded;
1652 else if (*pcbStructInfo < bytesNeeded)
1654 *pcbStructInfo = bytesNeeded;
1655 SetLastError(ERROR_MORE_DATA);
1656 ret = FALSE;
1658 else
1660 *pcbStructInfo = bytesNeeded;
1661 value->dwValueType = valueType;
1662 if (dataLen)
1664 DWORD i;
1665 LPWSTR str = (LPWSTR)value->Value.pbData;
1667 assert(value->Value.pbData);
1668 switch (pbEncoded[0])
1670 case ASN_NUMERICSTRING:
1671 case ASN_PRINTABLESTRING:
1672 case ASN_IA5STRING:
1673 case ASN_T61STRING:
1674 case ASN_VIDEOTEXSTRING:
1675 case ASN_GRAPHICSTRING:
1676 case ASN_VISIBLESTRING:
1677 case ASN_GENERALSTRING:
1678 value->Value.cbData = dataLen * 2;
1679 for (i = 0; i < dataLen; i++)
1680 str[i] = pbEncoded[1 + lenBytes + i];
1681 break;
1682 case ASN_UNIVERSALSTRING:
1683 value->Value.cbData = dataLen / 2;
1684 for (i = 0; i < dataLen / 4; i++)
1685 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1686 | pbEncoded[1 + lenBytes + 2 * i + 3];
1687 break;
1688 case ASN_BMPSTRING:
1689 value->Value.cbData = dataLen;
1690 for (i = 0; i < dataLen / 2; i++)
1691 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1692 pbEncoded[1 + lenBytes + 2 * i + 1];
1693 break;
1694 case ASN_UTF8STRING:
1695 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1696 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1697 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1698 break;
1701 else
1703 value->Value.cbData = 0;
1704 value->Value.pbData = NULL;
1708 return ret;
1711 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1712 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1713 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1715 BOOL ret = TRUE;
1717 __TRY
1719 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded, cbEncoded,
1720 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1721 if (ret && pvStructInfo)
1723 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1724 pcbStructInfo, *pcbStructInfo);
1725 if (ret)
1727 CERT_NAME_VALUE *value;
1729 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1730 pvStructInfo = *(BYTE **)pvStructInfo;
1731 value = (CERT_NAME_VALUE *)pvStructInfo;
1732 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1733 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded,
1734 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1735 pcbStructInfo, NULL);
1739 __EXCEPT_PAGE_FAULT
1741 SetLastError(STATUS_ACCESS_VIOLATION);
1742 ret = FALSE;
1744 __ENDTRY
1745 return ret;
1748 static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
1749 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1751 BOOL ret;
1752 struct AsnDecodeSequenceItem items[] = {
1753 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1754 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1755 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1756 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1757 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1758 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1760 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1762 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1763 pvStructInfo, *pcbStructInfo);
1765 if (attr)
1766 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1767 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1768 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1769 attr ? attr->pszObjId : NULL);
1770 if (attr)
1772 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1773 debugstr_a(attr->pszObjId));
1774 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1776 TRACE("returning %d (%08x)\n", ret, GetLastError());
1777 return ret;
1780 static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1781 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1783 BOOL ret = TRUE;
1784 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1785 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1786 offsetof(CERT_RDN_ATTR, pszObjId) };
1787 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1789 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1790 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1791 rdn ? rdn->rgRDNAttr : NULL);
1792 return ret;
1795 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1796 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1797 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1799 BOOL ret = TRUE;
1801 __TRY
1803 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1804 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1805 offsetof(CERT_RDN, rgRDNAttr) };
1807 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1808 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1810 __EXCEPT_PAGE_FAULT
1812 SetLastError(STATUS_ACCESS_VIOLATION);
1813 ret = FALSE;
1815 __ENDTRY
1816 return ret;
1819 static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
1820 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1821 DWORD *pcbDecoded)
1823 BOOL ret;
1824 struct AsnDecodeSequenceItem items[] = {
1825 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1826 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1827 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1828 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1829 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1830 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1832 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1834 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1835 pvStructInfo, *pcbStructInfo);
1837 if (attr)
1838 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1839 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1840 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1841 attr ? attr->pszObjId : NULL);
1842 if (attr)
1844 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1845 debugstr_a(attr->pszObjId));
1846 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1848 TRACE("returning %d (%08x)\n", ret, GetLastError());
1849 return ret;
1852 static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1853 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1855 BOOL ret = TRUE;
1856 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1857 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1858 offsetof(CERT_RDN_ATTR, pszObjId) };
1859 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1861 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1862 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1863 rdn ? rdn->rgRDNAttr : NULL);
1864 return ret;
1867 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1868 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1869 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1871 BOOL ret = TRUE;
1873 __TRY
1875 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1876 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1877 offsetof(CERT_RDN, rgRDNAttr) };
1879 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1880 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1882 __EXCEPT_PAGE_FAULT
1884 SetLastError(STATUS_ACCESS_VIOLATION);
1885 ret = FALSE;
1887 __ENDTRY
1888 return ret;
1891 static BOOL CRYPT_FindEncodedLen(const BYTE *pbEncoded, DWORD cbEncoded,
1892 DWORD *pcbDecoded)
1894 BOOL ret = TRUE, done = FALSE;
1895 DWORD indefiniteNestingLevels = 0, decoded = 0;
1897 TRACE("(%p, %d)\n", pbEncoded, cbEncoded);
1899 do {
1900 DWORD dataLen;
1902 if (!cbEncoded)
1903 done = TRUE;
1904 else if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded,
1905 &dataLen)))
1907 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1909 if (dataLen == CMSG_INDEFINITE_LENGTH)
1911 indefiniteNestingLevels++;
1912 pbEncoded += 1 + lenBytes;
1913 cbEncoded -= 1 + lenBytes;
1914 decoded += 1 + lenBytes;
1915 TRACE("indefiniteNestingLevels = %d\n",
1916 indefiniteNestingLevels);
1918 else
1920 if (pbEncoded[0] == 0 && pbEncoded[1] == 0 &&
1921 indefiniteNestingLevels)
1923 indefiniteNestingLevels--;
1924 TRACE("indefiniteNestingLevels = %d\n",
1925 indefiniteNestingLevels);
1927 pbEncoded += 1 + lenBytes + dataLen;
1928 cbEncoded -= 1 + lenBytes + dataLen;
1929 decoded += 1 + lenBytes + dataLen;
1930 if (!indefiniteNestingLevels)
1931 done = TRUE;
1934 } while (ret && !done);
1935 /* If we haven't found all 0 TLVs, we haven't found the end */
1936 if (ret && indefiniteNestingLevels)
1938 SetLastError(CRYPT_E_ASN1_EOD);
1939 ret = FALSE;
1941 if (ret)
1942 *pcbDecoded = decoded;
1943 TRACE("returning %d (%d)\n", ret, ret ? *pcbDecoded : 0);
1944 return ret;
1947 static BOOL CRYPT_AsnDecodeCopyBytes(const BYTE *pbEncoded,
1948 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1949 DWORD *pcbDecoded)
1951 BOOL ret = TRUE;
1952 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB), encodedLen = 0;
1954 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1955 pvStructInfo, *pcbStructInfo);
1957 if ((ret = CRYPT_FindEncodedLen(pbEncoded, cbEncoded, &encodedLen)))
1959 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1960 bytesNeeded += encodedLen;
1961 if (!pvStructInfo)
1962 *pcbStructInfo = bytesNeeded;
1963 else if (*pcbStructInfo < bytesNeeded)
1965 SetLastError(ERROR_MORE_DATA);
1966 *pcbStructInfo = bytesNeeded;
1967 ret = FALSE;
1969 else
1971 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1973 *pcbStructInfo = bytesNeeded;
1974 blob->cbData = encodedLen;
1975 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1976 blob->pbData = (LPBYTE)pbEncoded;
1977 else
1979 assert(blob->pbData);
1980 memcpy(blob->pbData, pbEncoded, blob->cbData);
1983 if (pcbDecoded)
1984 *pcbDecoded = encodedLen;
1986 return ret;
1989 static BOOL CRYPT_DecodeDERArray(const BYTE *pbEncoded, DWORD cbEncoded,
1990 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1992 BOOL ret;
1993 struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytes,
1994 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
1995 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
1997 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1998 pvStructInfo, *pcbStructInfo, pcbDecoded);
2000 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2001 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2002 array ? array->rgItems : NULL);
2003 return ret;
2006 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
2007 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2008 DWORD *pcbDecoded)
2010 BOOL ret;
2011 struct AsnDecodeSequenceItem items[] = {
2012 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
2013 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2014 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
2015 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
2016 CRYPT_DecodeDERArray, sizeof(struct GenericArray), FALSE, TRUE,
2017 offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
2019 PCRYPT_ATTRIBUTE attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
2021 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2022 pvStructInfo, *pcbStructInfo);
2024 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2025 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2026 pcbDecoded, attr ? attr->pszObjId : NULL);
2027 TRACE("returning %d\n", ret);
2028 return ret;
2031 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
2032 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2033 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2035 BOOL ret = FALSE;
2037 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2038 pDecodePara, pvStructInfo, *pcbStructInfo);
2040 __TRY
2042 DWORD bytesNeeded;
2044 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2045 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
2046 if (ret)
2048 if (!pvStructInfo)
2049 *pcbStructInfo = bytesNeeded;
2050 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2051 pvStructInfo, pcbStructInfo, bytesNeeded)))
2053 PCRYPT_ATTRIBUTE attr;
2055 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2056 pvStructInfo = *(BYTE **)pvStructInfo;
2057 attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
2058 attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
2059 sizeof(CRYPT_ATTRIBUTE));
2060 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2061 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
2062 NULL);
2066 __EXCEPT_PAGE_FAULT
2068 SetLastError(STATUS_ACCESS_VIOLATION);
2070 __ENDTRY
2071 TRACE("returning %d\n", ret);
2072 return ret;
2075 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
2076 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2077 DWORD *pcbDecoded)
2079 struct AsnArrayDescriptor arrayDesc = { 0,
2080 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2081 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2082 PCRYPT_ATTRIBUTES attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
2083 BOOL ret;
2085 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2086 NULL, pvStructInfo, pcbStructInfo, pcbDecoded, attrs ? attrs->rgAttr :
2087 NULL);
2088 return ret;
2091 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
2092 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2093 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2095 BOOL ret = FALSE;
2097 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2098 pDecodePara, pvStructInfo, *pcbStructInfo);
2100 __TRY
2102 DWORD bytesNeeded;
2104 if (!cbEncoded)
2105 SetLastError(CRYPT_E_ASN1_EOD);
2106 else if (pbEncoded[0] != (ASN_CONSTRUCTOR | ASN_SETOF))
2107 SetLastError(CRYPT_E_ASN1_CORRUPT);
2108 else if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
2109 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2110 NULL)))
2112 if (!pvStructInfo)
2113 *pcbStructInfo = bytesNeeded;
2114 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2115 pvStructInfo, pcbStructInfo, bytesNeeded)))
2117 PCRYPT_ATTRIBUTES attrs;
2119 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2120 pvStructInfo = *(BYTE **)pvStructInfo;
2121 attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
2122 attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
2123 sizeof(CRYPT_ATTRIBUTES));
2124 ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
2125 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2126 &bytesNeeded, NULL);
2130 __EXCEPT_PAGE_FAULT
2132 SetLastError(STATUS_ACCESS_VIOLATION);
2134 __ENDTRY
2135 TRACE("returning %d\n", ret);
2136 return ret;
2139 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
2140 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2142 CRYPT_ALGORITHM_IDENTIFIER *algo =
2143 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
2144 BOOL ret = TRUE;
2145 struct AsnDecodeSequenceItem items[] = {
2146 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
2147 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2148 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
2149 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
2150 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2151 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
2154 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2155 pvStructInfo, *pcbStructInfo, pcbDecoded);
2157 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2158 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2159 pcbDecoded, algo ? algo->pszObjId : NULL);
2160 if (ret && pvStructInfo)
2162 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
2163 debugstr_a(algo->pszObjId));
2165 return ret;
2168 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
2169 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2170 DWORD *pcbDecoded)
2172 BOOL ret = TRUE;
2173 struct AsnDecodeSequenceItem items[] = {
2174 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
2175 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2176 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
2177 Algorithm.pszObjId) },
2178 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
2179 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2180 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
2182 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2184 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2185 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2186 pcbDecoded, info ? info->Algorithm.Parameters.pbData : NULL);
2187 return ret;
2190 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2191 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2192 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2194 BOOL ret = TRUE;
2196 __TRY
2198 DWORD bytesNeeded;
2200 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2201 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2203 if (!pvStructInfo)
2204 *pcbStructInfo = bytesNeeded;
2205 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2206 pvStructInfo, pcbStructInfo, bytesNeeded)))
2208 PCERT_PUBLIC_KEY_INFO info;
2210 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2211 pvStructInfo = *(BYTE **)pvStructInfo;
2212 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2213 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2214 sizeof(CERT_PUBLIC_KEY_INFO);
2215 ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2216 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2217 &bytesNeeded, NULL);
2221 __EXCEPT_PAGE_FAULT
2223 SetLastError(STATUS_ACCESS_VIOLATION);
2224 ret = FALSE;
2226 __ENDTRY
2227 return ret;
2230 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
2231 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2233 BOOL ret;
2235 if (cbEncoded < 3)
2237 SetLastError(CRYPT_E_ASN1_CORRUPT);
2238 return FALSE;
2240 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2242 SetLastError(CRYPT_E_ASN1_CORRUPT);
2243 return FALSE;
2245 if (pbEncoded[1] > 1)
2247 SetLastError(CRYPT_E_ASN1_CORRUPT);
2248 return FALSE;
2250 if (pcbDecoded)
2251 *pcbDecoded = 3;
2252 if (!pvStructInfo)
2254 *pcbStructInfo = sizeof(BOOL);
2255 ret = TRUE;
2257 else if (*pcbStructInfo < sizeof(BOOL))
2259 *pcbStructInfo = sizeof(BOOL);
2260 SetLastError(ERROR_MORE_DATA);
2261 ret = FALSE;
2263 else
2265 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2266 ret = TRUE;
2268 TRACE("returning %d (%08x)\n", ret, GetLastError());
2269 return ret;
2272 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2273 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2275 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
2276 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2277 BOOL ret;
2279 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2280 pvStructInfo, *pcbStructInfo);
2282 if (cbEncoded < 2)
2284 SetLastError(CRYPT_E_ASN1_CORRUPT);
2285 return FALSE;
2287 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2288 if (1 + lenBytes > cbEncoded)
2290 SetLastError(CRYPT_E_ASN1_CORRUPT);
2291 return FALSE;
2293 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2295 switch (pbEncoded[0] & ASN_TYPE_MASK)
2297 case 1: /* rfc822Name */
2298 case 2: /* dNSName */
2299 case 6: /* uniformResourceIdentifier */
2300 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
2301 break;
2302 case 4: /* directoryName */
2303 case 7: /* iPAddress */
2304 bytesNeeded += dataLen;
2305 break;
2306 case 8: /* registeredID */
2307 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
2308 &dataLen, NULL);
2309 if (ret)
2311 /* FIXME: ugly, shouldn't need to know internals of OID decode
2312 * function to use it.
2314 bytesNeeded += dataLen - sizeof(LPSTR);
2316 break;
2317 case 0: /* otherName */
2318 FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
2319 SetLastError(CRYPT_E_ASN1_BADTAG);
2320 ret = FALSE;
2321 break;
2322 case 3: /* x400Address, unimplemented */
2323 case 5: /* ediPartyName, unimplemented */
2324 TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
2325 SetLastError(CRYPT_E_ASN1_BADTAG);
2326 ret = FALSE;
2327 break;
2328 default:
2329 TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
2330 SetLastError(CRYPT_E_ASN1_CORRUPT);
2331 ret = FALSE;
2333 if (ret)
2335 if (pcbDecoded)
2336 *pcbDecoded = 1 + lenBytes + dataLen;
2337 if (!entry)
2338 *pcbStructInfo = bytesNeeded;
2339 else if (*pcbStructInfo < bytesNeeded)
2341 *pcbStructInfo = bytesNeeded;
2342 SetLastError(ERROR_MORE_DATA);
2343 ret = FALSE;
2345 else
2347 *pcbStructInfo = bytesNeeded;
2348 /* MS used values one greater than the asn1 ones.. sigh */
2349 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
2350 switch (pbEncoded[0] & ASN_TYPE_MASK)
2352 case 1: /* rfc822Name */
2353 case 2: /* dNSName */
2354 case 6: /* uniformResourceIdentifier */
2356 DWORD i;
2358 for (i = 0; i < dataLen; i++)
2359 entry->u.pwszURL[i] =
2360 (WCHAR)pbEncoded[1 + lenBytes + i];
2361 entry->u.pwszURL[i] = 0;
2362 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2363 debugstr_w(entry->u.pwszURL));
2364 break;
2366 case 4: /* directoryName */
2367 entry->dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
2368 /* The data are memory-equivalent with the IPAddress case,
2369 * fall-through
2371 case 7: /* iPAddress */
2372 /* The next data pointer is in the pwszURL spot, that is,
2373 * the first 4 bytes. Need to move it to the next spot.
2375 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2376 entry->u.IPAddress.cbData = dataLen;
2377 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2378 dataLen);
2379 break;
2380 case 8: /* registeredID */
2381 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
2382 &entry->u.pszRegisteredID, &dataLen, NULL);
2383 break;
2388 return ret;
2391 static BOOL CRYPT_AsnDecodeAltNameInternal(const BYTE *pbEncoded,
2392 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2393 DWORD *pcbDecoded)
2395 BOOL ret = TRUE;
2396 struct AsnArrayDescriptor arrayDesc = { 0,
2397 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2398 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2399 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
2401 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2402 pvStructInfo, *pcbStructInfo, pcbDecoded);
2404 if (info)
2405 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2406 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2407 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2408 info ? info->rgAltEntry : NULL);
2409 return ret;
2412 /* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */
2413 static BOOL CRYPT_AsnDecodeIntegerSwapBytes(const BYTE *pbEncoded,
2414 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2415 DWORD *pcbDecoded)
2417 BOOL ret;
2419 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
2420 pvStructInfo, *pcbStructInfo, pcbDecoded);
2422 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2423 * place.
2425 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
2426 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
2427 pcbDecoded);
2428 if (ret && pvStructInfo)
2430 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2432 if (blob->cbData)
2434 DWORD i;
2435 BYTE temp;
2437 for (i = 0; i < blob->cbData / 2; i++)
2439 temp = blob->pbData[i];
2440 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
2441 blob->pbData[blob->cbData - i - 1] = temp;
2445 TRACE("returning %d (%08x)\n", ret, GetLastError());
2446 return ret;
2449 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
2450 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2451 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2453 BOOL ret;
2455 __TRY
2457 struct AsnDecodeSequenceItem items[] = {
2458 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
2459 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2460 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
2461 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2462 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
2463 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
2464 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
2465 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
2466 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2467 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2468 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
2471 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2472 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2473 pcbStructInfo, NULL, NULL);
2475 __EXCEPT_PAGE_FAULT
2477 SetLastError(STATUS_ACCESS_VIOLATION);
2478 ret = FALSE;
2480 __ENDTRY
2481 return ret;
2484 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
2485 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2486 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2488 BOOL ret;
2490 __TRY
2492 struct AsnDecodeSequenceItem items[] = {
2493 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
2494 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2495 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
2496 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2497 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
2498 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
2499 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2500 AuthorityCertIssuer.rgAltEntry), 0 },
2501 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2502 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2503 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2504 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2505 AuthorityCertSerialNumber.pbData), 0 },
2508 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2509 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2510 pcbStructInfo, NULL, NULL);
2512 __EXCEPT_PAGE_FAULT
2514 SetLastError(STATUS_ACCESS_VIOLATION);
2515 ret = FALSE;
2517 __ENDTRY
2518 return ret;
2521 static BOOL CRYPT_AsnDecodePKCSContent(const BYTE *pbEncoded, DWORD cbEncoded,
2522 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2524 BOOL ret;
2525 DWORD dataLen;
2527 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2528 pvStructInfo, *pcbStructInfo, pcbDecoded);
2530 /* The caller has already checked the tag, no need to check it again.
2531 * Check the outer length is valid:
2533 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
2535 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2536 DWORD innerLen;
2538 pbEncoded += 1 + lenBytes;
2539 cbEncoded -= 1 + lenBytes;
2540 if (dataLen == CMSG_INDEFINITE_LENGTH)
2541 cbEncoded -= 2; /* space for 0 TLV */
2542 /* Check the inner length is valid: */
2543 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &innerLen)))
2545 DWORD decodedLen;
2547 ret = CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags,
2548 pvStructInfo, pcbStructInfo, &decodedLen);
2549 if (dataLen == CMSG_INDEFINITE_LENGTH)
2551 if (*(pbEncoded + decodedLen) != 0 ||
2552 *(pbEncoded + decodedLen + 1) != 0)
2554 TRACE("expected 0 TLV, got {%02x,%02x}\n",
2555 *(pbEncoded + decodedLen),
2556 *(pbEncoded + decodedLen + 1));
2557 SetLastError(CRYPT_E_ASN1_CORRUPT);
2558 ret = FALSE;
2560 else
2561 decodedLen += 2;
2563 if (ret && pcbDecoded)
2565 *pcbDecoded = 1 + lenBytes + decodedLen;
2566 TRACE("decoded %d bytes\n", *pcbDecoded);
2570 return ret;
2573 static BOOL CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE *pbEncoded,
2574 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2575 DWORD *pcbDecoded)
2577 CRYPT_CONTENT_INFO *info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2578 struct AsnDecodeSequenceItem items[] = {
2579 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
2580 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2581 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
2582 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
2583 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
2584 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
2585 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
2587 BOOL ret;
2589 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2590 pvStructInfo, *pcbStructInfo, pcbDecoded);
2592 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2593 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2594 pcbDecoded, info ? info->pszObjId : NULL);
2595 return ret;
2598 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
2599 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2600 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2602 BOOL ret = FALSE;
2604 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2605 pDecodePara, pvStructInfo, *pcbStructInfo);
2607 __TRY
2609 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, cbEncoded,
2610 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
2611 if (ret && pvStructInfo)
2613 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
2614 pcbStructInfo, *pcbStructInfo);
2615 if (ret)
2617 CRYPT_CONTENT_INFO *info;
2619 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2620 pvStructInfo = *(BYTE **)pvStructInfo;
2621 info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2622 info->pszObjId = (LPSTR)((BYTE *)info +
2623 sizeof(CRYPT_CONTENT_INFO));
2624 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded,
2625 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2626 pcbStructInfo, NULL);
2630 __EXCEPT_PAGE_FAULT
2632 SetLastError(STATUS_ACCESS_VIOLATION);
2634 __ENDTRY
2635 return ret;
2638 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
2639 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2640 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
2642 BOOL ret;
2643 struct AsnDecodeSequenceItem items[] = {
2644 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version),
2645 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2646 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
2647 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2648 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
2649 0 },
2650 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
2651 CRYPT_AsnDecodePKCSContentInfoInternal,
2652 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
2653 ContentInfo.pszObjId), 0 },
2654 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
2655 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
2656 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
2659 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2660 pbEncoded, cbEncoded, dwFlags, pDecodePara, digestedData, pcbDigestedData,
2661 NULL, NULL);
2662 return ret;
2665 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
2666 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2667 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2669 BOOL ret = TRUE;
2671 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2672 pDecodePara, pvStructInfo, *pcbStructInfo);
2674 __TRY
2676 DWORD bytesNeeded;
2678 if ((ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
2679 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2681 if (!pvStructInfo)
2682 *pcbStructInfo = bytesNeeded;
2683 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2684 pvStructInfo, pcbStructInfo, bytesNeeded)))
2686 CERT_ALT_NAME_INFO *name;
2688 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2689 pvStructInfo = *(BYTE **)pvStructInfo;
2690 name = (CERT_ALT_NAME_INFO *)pvStructInfo;
2691 name->rgAltEntry = (PCERT_ALT_NAME_ENTRY)
2692 ((BYTE *)pvStructInfo + sizeof(CERT_ALT_NAME_INFO));
2693 ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
2694 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2695 &bytesNeeded, NULL);
2699 __EXCEPT_PAGE_FAULT
2701 SetLastError(STATUS_ACCESS_VIOLATION);
2702 ret = FALSE;
2704 __ENDTRY
2705 return ret;
2708 struct PATH_LEN_CONSTRAINT
2710 BOOL fPathLenConstraint;
2711 DWORD dwPathLenConstraint;
2714 static BOOL CRYPT_AsnDecodePathLenConstraint(const BYTE *pbEncoded,
2715 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2716 DWORD *pcbDecoded)
2718 BOOL ret = TRUE;
2719 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT), size;
2721 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2722 pvStructInfo, *pcbStructInfo, pcbDecoded);
2724 if (!pvStructInfo)
2726 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, NULL,
2727 &size, pcbDecoded);
2728 *pcbStructInfo = bytesNeeded;
2730 else if (*pcbStructInfo < bytesNeeded)
2732 SetLastError(ERROR_MORE_DATA);
2733 *pcbStructInfo = bytesNeeded;
2734 ret = FALSE;
2736 else
2738 struct PATH_LEN_CONSTRAINT *constraint =
2739 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
2741 size = sizeof(constraint->dwPathLenConstraint);
2742 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
2743 &constraint->dwPathLenConstraint, &size, pcbDecoded);
2744 if (ret)
2745 constraint->fPathLenConstraint = TRUE;
2746 TRACE("got an int, dwPathLenConstraint is %d\n",
2747 constraint->dwPathLenConstraint);
2749 TRACE("returning %d (%08x)\n", ret, GetLastError());
2750 return ret;
2753 static BOOL CRYPT_AsnDecodeSubtreeConstraints(const BYTE *pbEncoded,
2754 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2755 DWORD *pcbDecoded)
2757 BOOL ret;
2758 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2759 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
2760 offsetof(CERT_NAME_BLOB, pbData) };
2761 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2763 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2764 pvStructInfo, *pcbStructInfo, pcbDecoded);
2766 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2767 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2768 entries ? entries->rgItems : NULL);
2769 TRACE("Returning %d (%08x)\n", ret, GetLastError());
2770 return ret;
2773 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
2774 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2775 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2777 BOOL ret;
2779 __TRY
2781 struct AsnDecodeSequenceItem items[] = {
2782 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
2783 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2784 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
2785 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2786 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2787 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2788 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2789 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
2790 sizeof(struct GenericArray), TRUE, TRUE,
2791 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
2794 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2795 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2796 pcbStructInfo, NULL, NULL);
2798 __EXCEPT_PAGE_FAULT
2800 SetLastError(STATUS_ACCESS_VIOLATION);
2801 ret = FALSE;
2803 __ENDTRY
2804 return ret;
2807 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
2808 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2809 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2811 BOOL ret;
2813 __TRY
2815 struct AsnDecodeSequenceItem items[] = {
2816 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
2817 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
2818 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
2819 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2820 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2823 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2824 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2825 pcbStructInfo, NULL, NULL);
2827 __EXCEPT_PAGE_FAULT
2829 SetLastError(STATUS_ACCESS_VIOLATION);
2830 ret = FALSE;
2832 __ENDTRY
2833 return ret;
2836 #define RSA1_MAGIC 0x31415352
2838 struct DECODED_RSA_PUB_KEY
2840 DWORD pubexp;
2841 CRYPT_INTEGER_BLOB modulus;
2844 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(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 __TRY
2852 struct AsnDecodeSequenceItem items[] = {
2853 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
2854 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2855 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
2856 0 },
2857 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
2858 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2860 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
2861 DWORD size = 0;
2863 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2864 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
2865 &size, NULL, NULL);
2866 if (ret)
2868 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2869 decodedKey->modulus.cbData;
2871 if (!pvStructInfo)
2873 *pcbStructInfo = bytesNeeded;
2874 ret = TRUE;
2876 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2877 pvStructInfo, pcbStructInfo, bytesNeeded)))
2879 BLOBHEADER *hdr;
2880 RSAPUBKEY *rsaPubKey;
2882 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2883 pvStructInfo = *(BYTE **)pvStructInfo;
2884 hdr = (BLOBHEADER *)pvStructInfo;
2885 hdr->bType = PUBLICKEYBLOB;
2886 hdr->bVersion = CUR_BLOB_VERSION;
2887 hdr->reserved = 0;
2888 hdr->aiKeyAlg = CALG_RSA_KEYX;
2889 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
2890 sizeof(BLOBHEADER));
2891 rsaPubKey->magic = RSA1_MAGIC;
2892 rsaPubKey->pubexp = decodedKey->pubexp;
2893 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
2894 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
2895 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
2896 decodedKey->modulus.cbData);
2898 LocalFree(decodedKey);
2901 __EXCEPT_PAGE_FAULT
2903 SetLastError(STATUS_ACCESS_VIOLATION);
2904 ret = FALSE;
2906 __ENDTRY
2907 return ret;
2910 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
2911 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2912 DWORD *pcbDecoded)
2914 BOOL ret;
2915 DWORD bytesNeeded, dataLen;
2917 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2918 pvStructInfo, *pcbStructInfo, pcbDecoded);
2920 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2922 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2924 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2925 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
2926 else
2927 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
2928 if (pcbDecoded)
2929 *pcbDecoded = 1 + lenBytes + dataLen;
2930 if (!pvStructInfo)
2931 *pcbStructInfo = bytesNeeded;
2932 else if (*pcbStructInfo < bytesNeeded)
2934 SetLastError(ERROR_MORE_DATA);
2935 *pcbStructInfo = bytesNeeded;
2936 ret = FALSE;
2938 else
2940 CRYPT_DATA_BLOB *blob;
2942 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2943 blob->cbData = dataLen;
2944 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2945 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
2946 else
2948 assert(blob->pbData);
2949 if (blob->cbData)
2950 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
2951 blob->cbData);
2955 return ret;
2958 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
2959 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2960 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2962 BOOL ret;
2964 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2965 pDecodePara, pvStructInfo, *pcbStructInfo);
2967 __TRY
2969 DWORD bytesNeeded;
2971 if (!cbEncoded)
2973 SetLastError(CRYPT_E_ASN1_CORRUPT);
2974 ret = FALSE;
2976 else if (pbEncoded[0] != ASN_OCTETSTRING)
2978 SetLastError(CRYPT_E_ASN1_BADTAG);
2979 ret = FALSE;
2981 else if ((ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
2982 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2984 if (!pvStructInfo)
2985 *pcbStructInfo = bytesNeeded;
2986 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2987 pvStructInfo, pcbStructInfo, bytesNeeded)))
2989 CRYPT_DATA_BLOB *blob;
2991 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2992 pvStructInfo = *(BYTE **)pvStructInfo;
2993 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2994 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
2995 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
2996 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2997 &bytesNeeded, NULL);
3001 __EXCEPT_PAGE_FAULT
3003 SetLastError(STATUS_ACCESS_VIOLATION);
3004 ret = FALSE;
3006 __ENDTRY
3007 return ret;
3010 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3011 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3013 BOOL ret;
3015 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
3016 pvStructInfo, *pcbStructInfo, pcbDecoded);
3018 if (pbEncoded[0] == ASN_BITSTRING)
3020 DWORD bytesNeeded, dataLen;
3021 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3023 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3025 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3026 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
3027 else
3028 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
3029 if (pcbDecoded)
3030 *pcbDecoded = 1 + lenBytes + dataLen;
3031 if (!pvStructInfo)
3032 *pcbStructInfo = bytesNeeded;
3033 else if (*pcbStructInfo < bytesNeeded)
3035 *pcbStructInfo = bytesNeeded;
3036 SetLastError(ERROR_MORE_DATA);
3037 ret = FALSE;
3039 else
3041 CRYPT_BIT_BLOB *blob;
3043 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
3044 blob->cbData = dataLen - 1;
3045 blob->cUnusedBits = *(pbEncoded + 1 + lenBytes);
3046 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3048 blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes;
3050 else
3052 assert(blob->pbData);
3053 if (blob->cbData)
3055 BYTE mask = 0xff << blob->cUnusedBits;
3057 memcpy(blob->pbData, pbEncoded + 2 + lenBytes,
3058 blob->cbData);
3059 blob->pbData[blob->cbData - 1] &= mask;
3065 else
3067 SetLastError(CRYPT_E_ASN1_BADTAG);
3068 ret = FALSE;
3070 TRACE("returning %d (%08x)\n", ret, GetLastError());
3071 return ret;
3074 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
3075 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3076 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3078 BOOL ret;
3080 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
3081 pDecodePara, pvStructInfo, pcbStructInfo);
3083 __TRY
3085 DWORD bytesNeeded;
3087 if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3088 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3090 if (!pvStructInfo)
3091 *pcbStructInfo = bytesNeeded;
3092 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3093 pvStructInfo, pcbStructInfo, bytesNeeded)))
3095 CRYPT_BIT_BLOB *blob;
3097 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3098 pvStructInfo = *(BYTE **)pvStructInfo;
3099 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
3100 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
3101 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3102 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3103 &bytesNeeded, NULL);
3107 __EXCEPT_PAGE_FAULT
3109 SetLastError(STATUS_ACCESS_VIOLATION);
3110 ret = FALSE;
3112 __ENDTRY
3113 TRACE("returning %d (%08x)\n", ret, GetLastError());
3114 return ret;
3117 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3118 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3120 BOOL ret;
3121 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
3122 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
3123 DWORD size = sizeof(buf);
3125 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
3126 if (pbEncoded[0] != ASN_INTEGER)
3128 SetLastError(CRYPT_E_ASN1_BADTAG);
3129 ret = FALSE;
3131 else
3132 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded, 0, &buf,
3133 &size, pcbDecoded);
3134 if (ret)
3136 if (!pvStructInfo)
3137 *pcbStructInfo = sizeof(int);
3138 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int))))
3140 int val, i;
3142 if (blob->pbData[blob->cbData - 1] & 0x80)
3144 /* initialize to a negative value to sign-extend */
3145 val = -1;
3147 else
3148 val = 0;
3149 for (i = 0; i < blob->cbData; i++)
3151 val <<= 8;
3152 val |= blob->pbData[blob->cbData - i - 1];
3154 memcpy(pvStructInfo, &val, sizeof(int));
3157 else if (GetLastError() == ERROR_MORE_DATA)
3158 SetLastError(CRYPT_E_ASN1_LARGE);
3159 return ret;
3162 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
3163 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3164 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3166 BOOL ret;
3168 __TRY
3170 DWORD bytesNeeded;
3172 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3173 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3174 if (ret)
3176 if (!pvStructInfo)
3177 *pcbStructInfo = bytesNeeded;
3178 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3179 pvStructInfo, pcbStructInfo, bytesNeeded)))
3181 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3182 pvStructInfo = *(BYTE **)pvStructInfo;
3183 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3184 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3185 &bytesNeeded, NULL);
3189 __EXCEPT_PAGE_FAULT
3191 SetLastError(STATUS_ACCESS_VIOLATION);
3192 ret = FALSE;
3194 __ENDTRY
3195 return ret;
3198 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
3199 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3200 DWORD *pcbDecoded)
3202 BOOL ret;
3203 DWORD bytesNeeded, dataLen;
3205 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3207 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3209 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3210 if (pcbDecoded)
3211 *pcbDecoded = 1 + lenBytes + dataLen;
3212 if (!pvStructInfo)
3213 *pcbStructInfo = bytesNeeded;
3214 else if (*pcbStructInfo < bytesNeeded)
3216 *pcbStructInfo = bytesNeeded;
3217 SetLastError(ERROR_MORE_DATA);
3218 ret = FALSE;
3220 else
3222 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3224 blob->cbData = dataLen;
3225 assert(blob->pbData);
3226 if (blob->cbData)
3228 DWORD i;
3230 for (i = 0; i < blob->cbData; i++)
3232 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3233 dataLen - i - 1);
3238 return ret;
3241 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
3242 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3243 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3245 BOOL ret;
3247 __TRY
3249 DWORD bytesNeeded;
3251 if (pbEncoded[0] != ASN_INTEGER)
3253 SetLastError(CRYPT_E_ASN1_BADTAG);
3254 ret = FALSE;
3256 else
3257 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3258 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3259 if (ret)
3261 if (!pvStructInfo)
3262 *pcbStructInfo = bytesNeeded;
3263 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3264 pvStructInfo, pcbStructInfo, bytesNeeded)))
3266 CRYPT_INTEGER_BLOB *blob;
3268 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3269 pvStructInfo = *(BYTE **)pvStructInfo;
3270 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3271 blob->pbData = (BYTE *)pvStructInfo +
3272 sizeof(CRYPT_INTEGER_BLOB);
3273 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3274 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
3275 &bytesNeeded, NULL);
3279 __EXCEPT_PAGE_FAULT
3281 SetLastError(STATUS_ACCESS_VIOLATION);
3282 ret = FALSE;
3284 __ENDTRY
3285 return ret;
3288 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
3289 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3290 DWORD *pcbDecoded)
3292 BOOL ret;
3294 if (pbEncoded[0] == ASN_INTEGER)
3296 DWORD bytesNeeded, dataLen;
3298 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3300 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3302 if (pcbDecoded)
3303 *pcbDecoded = 1 + lenBytes + dataLen;
3304 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3305 if (!pvStructInfo)
3306 *pcbStructInfo = bytesNeeded;
3307 else if (*pcbStructInfo < bytesNeeded)
3309 *pcbStructInfo = bytesNeeded;
3310 SetLastError(ERROR_MORE_DATA);
3311 ret = FALSE;
3313 else
3315 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3317 blob->cbData = dataLen;
3318 assert(blob->pbData);
3319 /* remove leading zero byte if it exists */
3320 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
3322 blob->cbData--;
3323 blob->pbData++;
3325 if (blob->cbData)
3327 DWORD i;
3329 for (i = 0; i < blob->cbData; i++)
3331 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3332 dataLen - i - 1);
3338 else
3340 SetLastError(CRYPT_E_ASN1_BADTAG);
3341 ret = FALSE;
3343 return ret;
3346 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
3347 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3348 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3350 BOOL ret;
3352 __TRY
3354 DWORD bytesNeeded;
3356 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded,
3357 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3359 if (!pvStructInfo)
3360 *pcbStructInfo = bytesNeeded;
3361 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3362 pvStructInfo, pcbStructInfo, bytesNeeded)))
3364 CRYPT_INTEGER_BLOB *blob;
3366 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3367 pvStructInfo = *(BYTE **)pvStructInfo;
3368 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3369 blob->pbData = (BYTE *)pvStructInfo +
3370 sizeof(CRYPT_INTEGER_BLOB);
3371 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded,
3372 cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
3373 &bytesNeeded, NULL);
3377 __EXCEPT_PAGE_FAULT
3379 SetLastError(STATUS_ACCESS_VIOLATION);
3380 ret = FALSE;
3382 __ENDTRY
3383 return ret;
3386 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
3387 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3388 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3390 BOOL ret;
3392 if (!pvStructInfo)
3394 *pcbStructInfo = sizeof(int);
3395 return TRUE;
3397 __TRY
3399 if (pbEncoded[0] == ASN_ENUMERATED)
3401 unsigned int val = 0, i;
3403 if (cbEncoded <= 1)
3405 SetLastError(CRYPT_E_ASN1_EOD);
3406 ret = FALSE;
3408 else if (pbEncoded[1] == 0)
3410 SetLastError(CRYPT_E_ASN1_CORRUPT);
3411 ret = FALSE;
3413 else
3415 /* A little strange looking, but we have to accept a sign byte:
3416 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
3417 * assuming a small length is okay here, it has to be in short
3418 * form.
3420 if (pbEncoded[1] > sizeof(unsigned int) + 1)
3422 SetLastError(CRYPT_E_ASN1_LARGE);
3423 return FALSE;
3425 for (i = 0; i < pbEncoded[1]; i++)
3427 val <<= 8;
3428 val |= pbEncoded[2 + i];
3430 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3431 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
3433 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3434 pvStructInfo = *(BYTE **)pvStructInfo;
3435 memcpy(pvStructInfo, &val, sizeof(unsigned int));
3439 else
3441 SetLastError(CRYPT_E_ASN1_BADTAG);
3442 ret = FALSE;
3445 __EXCEPT_PAGE_FAULT
3447 SetLastError(STATUS_ACCESS_VIOLATION);
3448 ret = FALSE;
3450 __ENDTRY
3451 return ret;
3454 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
3455 * if it fails.
3457 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
3458 do { \
3459 BYTE i; \
3461 (word) = 0; \
3462 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
3464 if (!isdigit(*(pbEncoded))) \
3466 SetLastError(CRYPT_E_ASN1_CORRUPT); \
3467 ret = FALSE; \
3469 else \
3471 (word) *= 10; \
3472 (word) += *(pbEncoded)++ - '0'; \
3475 } while (0)
3477 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
3478 SYSTEMTIME *sysTime)
3480 BOOL ret = TRUE;
3482 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
3484 WORD hours, minutes = 0;
3485 BYTE sign = *pbEncoded++;
3487 len--;
3488 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
3489 if (ret && hours >= 24)
3491 SetLastError(CRYPT_E_ASN1_CORRUPT);
3492 ret = FALSE;
3494 else if (len >= 2)
3496 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
3497 if (ret && minutes >= 60)
3499 SetLastError(CRYPT_E_ASN1_CORRUPT);
3500 ret = FALSE;
3503 if (ret)
3505 if (sign == '+')
3507 sysTime->wHour += hours;
3508 sysTime->wMinute += minutes;
3510 else
3512 if (hours > sysTime->wHour)
3514 sysTime->wDay--;
3515 sysTime->wHour = 24 - (hours - sysTime->wHour);
3517 else
3518 sysTime->wHour -= hours;
3519 if (minutes > sysTime->wMinute)
3521 sysTime->wHour--;
3522 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
3524 else
3525 sysTime->wMinute -= minutes;
3529 return ret;
3532 #define MIN_ENCODED_TIME_LENGTH 10
3534 static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
3535 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3536 DWORD *pcbDecoded)
3538 BOOL ret = FALSE;
3540 if (pbEncoded[0] == ASN_UTCTIME)
3542 if (cbEncoded <= 1)
3543 SetLastError(CRYPT_E_ASN1_EOD);
3544 else if (pbEncoded[1] > 0x7f)
3546 /* long-form date strings really can't be valid */
3547 SetLastError(CRYPT_E_ASN1_CORRUPT);
3549 else
3551 SYSTEMTIME sysTime = { 0 };
3552 BYTE len = pbEncoded[1];
3554 if (len < MIN_ENCODED_TIME_LENGTH)
3555 SetLastError(CRYPT_E_ASN1_CORRUPT);
3556 else
3558 ret = TRUE;
3559 if (pcbDecoded)
3560 *pcbDecoded = 2 + len;
3561 pbEncoded += 2;
3562 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
3563 if (sysTime.wYear >= 50)
3564 sysTime.wYear += 1900;
3565 else
3566 sysTime.wYear += 2000;
3567 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3568 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3569 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3570 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
3571 if (ret && len > 0)
3573 if (len >= 2 && isdigit(*pbEncoded) &&
3574 isdigit(*(pbEncoded + 1)))
3575 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3576 sysTime.wSecond);
3577 else if (isdigit(*pbEncoded))
3578 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
3579 sysTime.wSecond);
3580 if (ret)
3581 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3582 &sysTime);
3584 if (ret)
3586 if (!pvStructInfo)
3587 *pcbStructInfo = sizeof(FILETIME);
3588 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
3589 sizeof(FILETIME))))
3590 ret = SystemTimeToFileTime(&sysTime,
3591 (FILETIME *)pvStructInfo);
3596 else
3597 SetLastError(CRYPT_E_ASN1_BADTAG);
3598 return ret;
3601 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
3602 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3603 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3605 BOOL ret = FALSE;
3607 __TRY
3609 DWORD bytesNeeded;
3611 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
3612 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3613 if (ret)
3615 if (!pvStructInfo)
3616 *pcbStructInfo = bytesNeeded;
3617 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
3618 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
3620 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3621 pvStructInfo = *(BYTE **)pvStructInfo;
3622 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
3623 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3624 &bytesNeeded, NULL);
3628 __EXCEPT_PAGE_FAULT
3630 SetLastError(STATUS_ACCESS_VIOLATION);
3632 __ENDTRY
3633 return ret;
3636 static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
3637 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3638 DWORD *pcbDecoded)
3640 BOOL ret = FALSE;
3642 if (pbEncoded[0] == ASN_GENERALTIME)
3644 if (cbEncoded <= 1)
3645 SetLastError(CRYPT_E_ASN1_EOD);
3646 else if (pbEncoded[1] > 0x7f)
3648 /* long-form date strings really can't be valid */
3649 SetLastError(CRYPT_E_ASN1_CORRUPT);
3651 else
3653 BYTE len = pbEncoded[1];
3655 if (len < MIN_ENCODED_TIME_LENGTH)
3656 SetLastError(CRYPT_E_ASN1_CORRUPT);
3657 else
3659 SYSTEMTIME sysTime = { 0 };
3661 ret = TRUE;
3662 if (pcbDecoded)
3663 *pcbDecoded = 2 + len;
3664 pbEncoded += 2;
3665 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
3666 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3667 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3668 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3669 if (ret && len > 0)
3671 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3672 sysTime.wMinute);
3673 if (ret && len > 0)
3674 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3675 sysTime.wSecond);
3676 if (ret && len > 0 && (*pbEncoded == '.' ||
3677 *pbEncoded == ','))
3679 BYTE digits;
3681 pbEncoded++;
3682 len--;
3683 /* workaround macro weirdness */
3684 digits = min(len, 3);
3685 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
3686 sysTime.wMilliseconds);
3688 if (ret)
3689 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3690 &sysTime);
3692 if (ret)
3694 if (!pvStructInfo)
3695 *pcbStructInfo = sizeof(FILETIME);
3696 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
3697 sizeof(FILETIME))))
3698 ret = SystemTimeToFileTime(&sysTime,
3699 (FILETIME *)pvStructInfo);
3704 else
3705 SetLastError(CRYPT_E_ASN1_BADTAG);
3706 return ret;
3709 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
3710 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3711 DWORD *pcbDecoded)
3713 BOOL ret;
3714 InternalDecodeFunc decode = NULL;
3716 if (pbEncoded[0] == ASN_UTCTIME)
3717 decode = CRYPT_AsnDecodeUtcTimeInternal;
3718 else if (pbEncoded[0] == ASN_GENERALTIME)
3719 decode = CRYPT_AsnDecodeGeneralizedTime;
3720 if (decode)
3721 ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
3722 pcbStructInfo, pcbDecoded);
3723 else
3725 SetLastError(CRYPT_E_ASN1_BADTAG);
3726 ret = FALSE;
3728 return ret;
3731 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
3732 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3733 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3735 BOOL ret;
3737 __TRY
3739 DWORD bytesNeeded;
3741 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
3742 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3743 if (ret)
3745 if (!pvStructInfo)
3746 *pcbStructInfo = bytesNeeded;
3747 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3748 pvStructInfo, pcbStructInfo, bytesNeeded)))
3750 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3751 pvStructInfo = *(BYTE **)pvStructInfo;
3752 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
3753 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3754 &bytesNeeded, NULL);
3758 __EXCEPT_PAGE_FAULT
3760 SetLastError(STATUS_ACCESS_VIOLATION);
3761 ret = FALSE;
3763 __ENDTRY
3764 return ret;
3767 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
3768 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3769 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3771 BOOL ret = TRUE;
3773 __TRY
3775 if (pbEncoded[0] == ASN_SEQUENCEOF)
3777 DWORD bytesNeeded, dataLen, remainingLen, cValue;
3779 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3781 BYTE lenBytes;
3782 const BYTE *ptr;
3784 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3785 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
3786 cValue = 0;
3787 ptr = pbEncoded + 1 + lenBytes;
3788 remainingLen = dataLen;
3789 while (ret && remainingLen)
3791 DWORD nextLen;
3793 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3794 if (ret)
3796 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3798 remainingLen -= 1 + nextLenBytes + nextLen;
3799 ptr += 1 + nextLenBytes + nextLen;
3800 bytesNeeded += sizeof(CRYPT_DER_BLOB);
3801 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3802 bytesNeeded += 1 + nextLenBytes + nextLen;
3803 cValue++;
3806 if (ret)
3808 CRYPT_SEQUENCE_OF_ANY *seq;
3809 BYTE *nextPtr;
3810 DWORD i;
3812 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3813 pvStructInfo, pcbStructInfo, bytesNeeded)))
3815 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3816 pvStructInfo = *(BYTE **)pvStructInfo;
3817 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
3818 seq->cValue = cValue;
3819 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
3820 sizeof(*seq));
3821 nextPtr = (BYTE *)seq->rgValue +
3822 cValue * sizeof(CRYPT_DER_BLOB);
3823 ptr = pbEncoded + 1 + lenBytes;
3824 remainingLen = dataLen;
3825 i = 0;
3826 while (ret && remainingLen)
3828 DWORD nextLen;
3830 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3831 if (ret)
3833 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3835 seq->rgValue[i].cbData = 1 + nextLenBytes +
3836 nextLen;
3837 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3838 seq->rgValue[i].pbData = (BYTE *)ptr;
3839 else
3841 seq->rgValue[i].pbData = nextPtr;
3842 memcpy(nextPtr, ptr, 1 + nextLenBytes +
3843 nextLen);
3844 nextPtr += 1 + nextLenBytes + nextLen;
3846 remainingLen -= 1 + nextLenBytes + nextLen;
3847 ptr += 1 + nextLenBytes + nextLen;
3848 i++;
3855 else
3857 SetLastError(CRYPT_E_ASN1_BADTAG);
3858 ret = FALSE;
3861 __EXCEPT_PAGE_FAULT
3863 SetLastError(STATUS_ACCESS_VIOLATION);
3864 ret = FALSE;
3866 __ENDTRY
3867 return ret;
3870 static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded,
3871 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3872 DWORD *pcbDecoded)
3874 BOOL ret;
3876 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
3878 DWORD bytesNeeded, dataLen;
3880 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3882 struct AsnArrayDescriptor arrayDesc = {
3883 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
3884 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3885 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3886 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3888 if (dataLen)
3890 DWORD nameLen;
3892 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3893 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3894 0, NULL, NULL, &nameLen, NULL, NULL);
3895 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen;
3897 else
3898 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
3899 if (pcbDecoded)
3900 *pcbDecoded = 1 + lenBytes + dataLen;
3901 if (!pvStructInfo)
3902 *pcbStructInfo = bytesNeeded;
3903 else if (*pcbStructInfo < bytesNeeded)
3905 *pcbStructInfo = bytesNeeded;
3906 SetLastError(ERROR_MORE_DATA);
3907 ret = FALSE;
3909 else
3911 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
3913 if (dataLen)
3915 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3916 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3917 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3918 0, NULL, &name->u.FullName, pcbStructInfo, NULL,
3919 name->u.FullName.rgAltEntry);
3921 else
3922 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3926 else
3928 SetLastError(CRYPT_E_ASN1_BADTAG);
3929 ret = FALSE;
3931 return ret;
3934 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
3935 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3937 struct AsnDecodeSequenceItem items[] = {
3938 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
3939 DistPointName), CRYPT_AsnDecodeDistPointName,
3940 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
3941 DistPointName.u.FullName.rgAltEntry), 0 },
3942 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
3943 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
3944 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
3945 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
3946 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
3947 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
3949 BOOL ret;
3951 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3952 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3953 pcbDecoded, NULL);
3954 return ret;
3957 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
3958 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3959 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3961 BOOL ret;
3963 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3964 pDecodePara, pvStructInfo, *pcbStructInfo);
3966 __TRY
3968 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3969 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
3970 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
3972 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3973 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
3975 __EXCEPT_PAGE_FAULT
3977 SetLastError(STATUS_ACCESS_VIOLATION);
3978 ret = FALSE;
3980 __ENDTRY
3981 return ret;
3984 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3985 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3986 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3988 BOOL ret;
3990 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3991 pDecodePara, pvStructInfo, *pcbStructInfo);
3993 __TRY
3995 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3996 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
3998 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3999 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
4001 __EXCEPT_PAGE_FAULT
4003 SetLastError(STATUS_ACCESS_VIOLATION);
4004 ret = FALSE;
4006 __ENDTRY
4007 return ret;
4010 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
4011 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4012 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4014 BOOL ret;
4016 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4017 pDecodePara, pvStructInfo, *pcbStructInfo);
4019 __TRY
4021 struct AsnDecodeSequenceItem items[] = {
4022 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
4023 DistPointName), CRYPT_AsnDecodeDistPointName,
4024 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
4025 offsetof(CRL_ISSUING_DIST_POINT,
4026 DistPointName.u.FullName.rgAltEntry), 0 },
4027 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
4028 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4029 FALSE, 0 },
4030 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
4031 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4032 FALSE, 0 },
4033 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
4034 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
4035 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
4036 OnlySomeReasonFlags.pbData), 0 },
4037 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
4038 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
4041 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4042 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
4043 pcbStructInfo, NULL, NULL);
4045 __EXCEPT_PAGE_FAULT
4047 SetLastError(STATUS_ACCESS_VIOLATION);
4048 ret = FALSE;
4050 __ENDTRY
4051 return ret;
4054 static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded,
4055 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4056 DWORD *pcbDecoded)
4058 BOOL ret;
4059 struct AsnDecodeSequenceItem items[] = {
4060 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
4061 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
4062 Issuer.pbData) },
4063 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
4064 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
4065 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
4067 CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
4068 (CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
4070 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4071 pvStructInfo, *pcbStructInfo, pcbDecoded);
4073 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4074 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4075 pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL);
4076 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
4078 SetLastError(CRYPT_E_ASN1_CORRUPT);
4079 ret = FALSE;
4081 TRACE("returning %d\n", ret);
4082 return ret;
4085 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
4086 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4087 DWORD *pcbDecoded)
4089 CMSG_SIGNER_INFO *info = (CMSG_SIGNER_INFO *)pvStructInfo;
4090 struct AsnDecodeSequenceItem items[] = {
4091 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
4092 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4093 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
4094 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
4095 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
4096 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
4097 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4098 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
4099 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4100 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
4101 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4102 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
4103 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
4104 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4105 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
4106 HashEncryptionAlgorithm.pszObjId), 0 },
4107 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
4108 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
4109 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
4110 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4111 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
4112 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4113 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
4115 BOOL ret;
4117 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4118 pvStructInfo, *pcbStructInfo);
4120 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4121 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4122 pcbDecoded, info ? info->Issuer.pbData : NULL);
4123 return ret;
4126 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
4127 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4128 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4130 BOOL ret = FALSE;
4132 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4133 pDecodePara, pvStructInfo, *pcbStructInfo);
4135 __TRY
4137 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
4138 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
4139 if (ret && pvStructInfo)
4141 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
4142 pcbStructInfo, *pcbStructInfo);
4143 if (ret)
4145 CMSG_SIGNER_INFO *info;
4147 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4148 pvStructInfo = *(BYTE **)pvStructInfo;
4149 info = (CMSG_SIGNER_INFO *)pvStructInfo;
4150 info->Issuer.pbData = ((BYTE *)info +
4151 sizeof(CMSG_SIGNER_INFO));
4152 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
4153 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4154 pcbStructInfo, NULL);
4158 __EXCEPT_PAGE_FAULT
4160 SetLastError(STATUS_ACCESS_VIOLATION);
4162 __ENDTRY
4163 TRACE("returning %d\n", ret);
4164 return ret;
4167 static BOOL CRYPT_DecodeSignerArray(const BYTE *pbEncoded, DWORD cbEncoded,
4168 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4170 BOOL ret;
4171 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
4172 CRYPT_AsnDecodePKCSSignerInfoInternal, sizeof(CMSG_SIGNER_INFO), TRUE,
4173 offsetof(CMSG_SIGNER_INFO, Issuer.pbData) };
4174 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
4176 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4177 pvStructInfo, *pcbStructInfo, pcbDecoded);
4179 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4180 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
4181 array ? array->rgItems : NULL);
4182 return ret;
4185 BOOL CRYPT_AsnDecodePKCSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
4186 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
4187 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
4189 BOOL ret = FALSE;
4190 struct AsnDecodeSequenceItem items[] = {
4191 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version),
4192 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4193 /* Placeholder for the hash algorithms - redundant with those in the
4194 * signers, so just ignore them.
4196 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
4197 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
4198 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
4199 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
4200 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4201 offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
4202 CRYPT_DecodeDERArray, sizeof(struct GenericArray), TRUE, TRUE,
4203 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
4204 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4205 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_DecodeDERArray,
4206 sizeof(struct GenericArray), TRUE, TRUE,
4207 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
4208 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
4209 CRYPT_DecodeSignerArray, sizeof(struct GenericArray), TRUE, TRUE,
4210 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
4213 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4214 pDecodePara, signedInfo, *pcbSignedInfo);
4216 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4217 pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo,
4218 NULL, NULL);
4219 TRACE("returning %d\n", ret);
4220 return ret;
4223 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
4224 LPCSTR lpszStructType)
4226 CryptDecodeObjectExFunc decodeFunc = NULL;
4228 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
4229 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
4231 SetLastError(ERROR_FILE_NOT_FOUND);
4232 return NULL;
4234 if (!HIWORD(lpszStructType))
4236 switch (LOWORD(lpszStructType))
4238 case (WORD)X509_CERT:
4239 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
4240 break;
4241 case (WORD)X509_CERT_TO_BE_SIGNED:
4242 decodeFunc = CRYPT_AsnDecodeCert;
4243 break;
4244 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
4245 decodeFunc = CRYPT_AsnDecodeCRL;
4246 break;
4247 case (WORD)X509_EXTENSIONS:
4248 decodeFunc = CRYPT_AsnDecodeExtensions;
4249 break;
4250 case (WORD)X509_NAME_VALUE:
4251 decodeFunc = CRYPT_AsnDecodeNameValue;
4252 break;
4253 case (WORD)X509_NAME:
4254 decodeFunc = CRYPT_AsnDecodeName;
4255 break;
4256 case (WORD)X509_PUBLIC_KEY_INFO:
4257 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
4258 break;
4259 case (WORD)X509_AUTHORITY_KEY_ID:
4260 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4261 break;
4262 case (WORD)X509_ALTERNATE_NAME:
4263 decodeFunc = CRYPT_AsnDecodeAltName;
4264 break;
4265 case (WORD)X509_BASIC_CONSTRAINTS:
4266 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4267 break;
4268 case (WORD)X509_BASIC_CONSTRAINTS2:
4269 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4270 break;
4271 case (WORD)RSA_CSP_PUBLICKEYBLOB:
4272 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
4273 break;
4274 case (WORD)X509_UNICODE_NAME:
4275 decodeFunc = CRYPT_AsnDecodeUnicodeName;
4276 break;
4277 case (WORD)PKCS_ATTRIBUTE:
4278 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
4279 break;
4280 case (WORD)X509_UNICODE_NAME_VALUE:
4281 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
4282 break;
4283 case (WORD)X509_OCTET_STRING:
4284 decodeFunc = CRYPT_AsnDecodeOctets;
4285 break;
4286 case (WORD)X509_BITS:
4287 case (WORD)X509_KEY_USAGE:
4288 decodeFunc = CRYPT_AsnDecodeBits;
4289 break;
4290 case (WORD)X509_INTEGER:
4291 decodeFunc = CRYPT_AsnDecodeInt;
4292 break;
4293 case (WORD)X509_MULTI_BYTE_INTEGER:
4294 decodeFunc = CRYPT_AsnDecodeInteger;
4295 break;
4296 case (WORD)X509_MULTI_BYTE_UINT:
4297 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
4298 break;
4299 case (WORD)X509_ENUMERATED:
4300 decodeFunc = CRYPT_AsnDecodeEnumerated;
4301 break;
4302 case (WORD)X509_CHOICE_OF_TIME:
4303 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
4304 break;
4305 case (WORD)X509_AUTHORITY_KEY_ID2:
4306 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4307 break;
4308 case (WORD)PKCS_CONTENT_INFO:
4309 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
4310 break;
4311 case (WORD)X509_SEQUENCE_OF_ANY:
4312 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
4313 break;
4314 case (WORD)PKCS_UTC_TIME:
4315 decodeFunc = CRYPT_AsnDecodeUtcTime;
4316 break;
4317 case (WORD)X509_CRL_DIST_POINTS:
4318 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4319 break;
4320 case (WORD)X509_ENHANCED_KEY_USAGE:
4321 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4322 break;
4323 case (WORD)PKCS_ATTRIBUTES:
4324 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
4325 break;
4326 case (WORD)X509_ISSUING_DIST_POINT:
4327 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4328 break;
4329 case (WORD)PKCS7_SIGNER_INFO:
4330 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
4331 break;
4334 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4335 decodeFunc = CRYPT_AsnDecodeExtensions;
4336 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4337 decodeFunc = CRYPT_AsnDecodeUtcTime;
4338 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4339 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4340 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4341 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4342 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4343 decodeFunc = CRYPT_AsnDecodeEnumerated;
4344 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4345 decodeFunc = CRYPT_AsnDecodeBits;
4346 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4347 decodeFunc = CRYPT_AsnDecodeOctets;
4348 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4349 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4350 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4351 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4352 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4353 decodeFunc = CRYPT_AsnDecodeAltName;
4354 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4355 decodeFunc = CRYPT_AsnDecodeAltName;
4356 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4357 decodeFunc = CRYPT_AsnDecodeAltName;
4358 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4359 decodeFunc = CRYPT_AsnDecodeAltName;
4360 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4361 decodeFunc = CRYPT_AsnDecodeAltName;
4362 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4363 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4364 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4365 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4366 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4367 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4368 return decodeFunc;
4371 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
4372 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4374 static HCRYPTOIDFUNCSET set = NULL;
4375 CryptDecodeObjectFunc decodeFunc = NULL;
4377 if (!set)
4378 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
4379 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4380 (void **)&decodeFunc, hFunc);
4381 return decodeFunc;
4384 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
4385 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4387 static HCRYPTOIDFUNCSET set = NULL;
4388 CryptDecodeObjectExFunc decodeFunc = NULL;
4390 if (!set)
4391 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
4392 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4393 (void **)&decodeFunc, hFunc);
4394 return decodeFunc;
4397 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4398 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
4399 DWORD *pcbStructInfo)
4401 BOOL ret = FALSE;
4402 CryptDecodeObjectFunc pCryptDecodeObject = NULL;
4403 CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
4404 HCRYPTOIDFUNCADDR hFunc = NULL;
4406 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
4407 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
4408 pvStructInfo, pcbStructInfo);
4410 if (!pvStructInfo && !pcbStructInfo)
4412 SetLastError(ERROR_INVALID_PARAMETER);
4413 return FALSE;
4415 if (!cbEncoded)
4417 SetLastError(CRYPT_E_ASN1_EOD);
4418 return FALSE;
4420 if (cbEncoded > MAX_ENCODED_LEN)
4422 SetLastError(CRYPT_E_ASN1_LARGE);
4423 return FALSE;
4426 if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
4427 lpszStructType)))
4429 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4430 debugstr_a(lpszStructType));
4431 pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
4432 lpszStructType, &hFunc);
4433 if (!pCryptDecodeObject)
4434 pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
4435 lpszStructType, &hFunc);
4437 if (pCryptDecodeObject)
4438 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4439 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4440 else if (pCryptDecodeObjectEx)
4441 ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
4442 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
4443 pvStructInfo, pcbStructInfo);
4444 if (hFunc)
4445 CryptFreeOIDFunctionAddress(hFunc, 0);
4446 TRACE_(crypt)("returning %d\n", ret);
4447 return ret;
4450 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4451 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4452 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4454 BOOL ret = FALSE;
4455 CryptDecodeObjectExFunc decodeFunc;
4456 HCRYPTOIDFUNCADDR hFunc = NULL;
4458 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
4459 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
4460 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4462 if (!pvStructInfo && !pcbStructInfo)
4464 SetLastError(ERROR_INVALID_PARAMETER);
4465 return FALSE;
4467 if (!cbEncoded)
4469 SetLastError(CRYPT_E_ASN1_EOD);
4470 return FALSE;
4472 if (cbEncoded > MAX_ENCODED_LEN)
4474 SetLastError(CRYPT_E_ASN1_LARGE);
4475 return FALSE;
4478 SetLastError(NOERROR);
4479 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
4480 *(BYTE **)pvStructInfo = NULL;
4481 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
4482 if (!decodeFunc)
4484 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4485 debugstr_a(lpszStructType));
4486 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
4487 &hFunc);
4489 if (decodeFunc)
4490 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
4491 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4492 else
4494 CryptDecodeObjectFunc pCryptDecodeObject =
4495 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
4497 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
4498 * directly, as that could cause an infinite loop.
4500 if (pCryptDecodeObject)
4502 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4504 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4505 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
4506 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4507 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
4508 ret = pCryptDecodeObject(dwCertEncodingType,
4509 lpszStructType, pbEncoded, cbEncoded, dwFlags,
4510 *(BYTE **)pvStructInfo, pcbStructInfo);
4512 else
4513 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4514 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4517 if (hFunc)
4518 CryptFreeOIDFunctionAddress(hFunc, 0);
4519 TRACE_(crypt)("returning %d\n", ret);
4520 return ret;