push(c) 7dcddf6204ed5518706a76fe66fd836d81e70dd4
[wine/hacks.git] / dlls / crypt32 / decode.c
blob7bba04ba4768d388e2311b058c6cd8d010752e89
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;
470 BOOL indefinite = FALSE;
472 cbEncoded -= 1 + lenBytes;
473 if (dataLen == CMSG_INDEFINITE_LENGTH)
475 dataLen = cbEncoded;
476 indefinite = TRUE;
478 else if (cbEncoded < dataLen)
480 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
481 cbEncoded);
482 SetLastError(CRYPT_E_ASN1_CORRUPT);
483 ret = FALSE;
485 if (ret)
487 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
488 ptr, dataLen, dwFlags, NULL, NULL, &cbDecoded);
489 if (ret && dataLen == CMSG_INDEFINITE_LENGTH)
491 if (cbDecoded > cbEncoded - 2)
493 /* Not enough space for 0 TLV */
494 SetLastError(CRYPT_E_ASN1_CORRUPT);
495 ret = FALSE;
497 else if (*(ptr + cbDecoded) != 0 ||
498 *(ptr + cbDecoded + 1) != 0)
500 TRACE("expected 0 TLV\n");
501 SetLastError(CRYPT_E_ASN1_CORRUPT);
502 ret = FALSE;
504 else
505 cbDecoded += 2;
508 if (ret && !indefinite && cbDecoded != dataLen)
510 TRACE("expected %d decoded, got %d, failing\n", dataLen,
511 cbDecoded);
512 SetLastError(CRYPT_E_ASN1_CORRUPT);
513 ret = FALSE;
515 if (ret)
517 DWORD i, bytesNeeded = 0, structSize = 0;
519 for (i = 0; i < cItem; i++)
521 bytesNeeded += items[i].size;
522 structSize += items[i].minSize;
524 if (pcbDecoded)
525 *pcbDecoded = 1 + lenBytes + cbDecoded;
526 if (!pvStructInfo)
527 *pcbStructInfo = bytesNeeded;
528 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
529 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
531 BYTE *nextData;
533 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
534 pvStructInfo = *(BYTE **)pvStructInfo;
535 if (startingPointer)
536 nextData = (BYTE *)startingPointer;
537 else
538 nextData = (BYTE *)pvStructInfo + structSize;
539 memset(pvStructInfo, 0, structSize);
540 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
541 ptr, dataLen, dwFlags, pvStructInfo, nextData,
542 &cbDecoded);
547 else
549 SetLastError(CRYPT_E_ASN1_BADTAG);
550 ret = FALSE;
552 TRACE("returning %d (%08x)\n", ret, GetLastError());
553 return ret;
556 /* tag:
557 * The expected tag of the entire encoded array (usually a variant
558 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
559 * regardless of the tag seen.
560 * decodeFunc:
561 * used to decode each item in the array
562 * itemSize:
563 * is the minimum size of each decoded item
564 * hasPointer:
565 * indicates whether each item has a dynamic pointer
566 * pointerOffset:
567 * indicates the offset within itemSize at which the pointer exists
569 struct AsnArrayDescriptor
571 BYTE tag;
572 InternalDecodeFunc decodeFunc;
573 DWORD itemSize;
574 BOOL hasPointer;
575 DWORD pointerOffset;
578 struct AsnArrayItemSize
580 DWORD encodedLen;
581 DWORD size;
584 /* Decodes an array of like types into a struct GenericArray.
585 * The layout and decoding of the array are described by a struct
586 * AsnArrayDescriptor.
588 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
589 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
590 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
591 DWORD *pcbDecoded, void *startingPointer)
593 BOOL ret = TRUE;
595 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
596 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
597 startingPointer);
599 if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
601 DWORD dataLen;
603 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
605 DWORD bytesNeeded, cItems = 0, decoded;
606 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
607 /* There can be arbitrarily many items, but there is often only one.
609 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
611 decoded = 1 + lenBytes;
612 bytesNeeded = sizeof(struct GenericArray);
613 if (dataLen)
615 const BYTE *ptr;
616 BOOL doneDecoding = FALSE;
618 for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
620 DWORD itemLenBytes;
622 itemLenBytes = GET_LEN_BYTES(ptr[1]);
623 if (dataLen == CMSG_INDEFINITE_LENGTH)
625 if (ptr[0] == 0)
627 doneDecoding = TRUE;
628 if (itemLenBytes != 1 || ptr[1] != 0)
630 SetLastError(CRYPT_E_ASN1_CORRUPT);
631 ret = FALSE;
633 else
634 decoded += 2;
637 else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
638 doneDecoding = TRUE;
639 if (!doneDecoding)
641 DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
643 /* Each item decoded may not tolerate extraneous bytes,
644 * so get the length of the next element if known.
646 if ((ret = CRYPT_GetLengthIndefinite(ptr,
647 cbEncoded - (ptr - pbEncoded), &itemDataLen)))
649 if (itemDataLen == CMSG_INDEFINITE_LENGTH)
650 itemEncoded = cbEncoded - (ptr - pbEncoded);
651 else
652 itemEncoded = 1 + itemLenBytes + itemDataLen;
654 if (ret)
655 ret = arrayDesc->decodeFunc(ptr, itemEncoded,
656 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size,
657 &itemDecoded);
658 if (ret)
660 cItems++;
661 if (itemSizes != &itemSize)
662 itemSizes = CryptMemRealloc(itemSizes,
663 cItems * sizeof(struct AsnArrayItemSize));
664 else if (cItems > 1)
666 itemSizes =
667 CryptMemAlloc(
668 cItems * sizeof(struct AsnArrayItemSize));
669 if (itemSizes)
670 memcpy(itemSizes, &itemSize,
671 sizeof(itemSize));
673 if (itemSizes)
675 decoded += itemDecoded;
676 itemSizes[cItems - 1].encodedLen = itemEncoded;
677 itemSizes[cItems - 1].size = size;
678 bytesNeeded += size;
679 ptr += itemEncoded;
681 else
682 ret = FALSE;
687 if (ret)
689 if (pcbDecoded)
690 *pcbDecoded = decoded;
691 if (!pvStructInfo)
692 *pcbStructInfo = bytesNeeded;
693 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
694 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
696 DWORD i;
697 BYTE *nextData;
698 const BYTE *ptr;
699 struct GenericArray *array;
701 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
702 pvStructInfo = *(BYTE **)pvStructInfo;
703 array = (struct GenericArray *)pvStructInfo;
704 array->cItems = cItems;
705 if (startingPointer)
706 array->rgItems = startingPointer;
707 else
708 array->rgItems = (BYTE *)array +
709 sizeof(struct GenericArray);
710 nextData = (BYTE *)array->rgItems +
711 array->cItems * arrayDesc->itemSize;
712 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
713 i < cItems && ptr - pbEncoded - 1 - lenBytes <
714 dataLen; i++)
716 DWORD itemDecoded;
718 if (arrayDesc->hasPointer)
719 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
720 + arrayDesc->pointerOffset) = nextData;
721 ret = arrayDesc->decodeFunc(ptr,
722 itemSizes[i].encodedLen,
723 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
724 array->rgItems + i * arrayDesc->itemSize,
725 &itemSizes[i].size, &itemDecoded);
726 if (ret)
728 nextData += itemSizes[i].size - arrayDesc->itemSize;
729 ptr += itemDecoded;
734 if (itemSizes != &itemSize)
735 CryptMemFree(itemSizes);
738 else
740 SetLastError(CRYPT_E_ASN1_BADTAG);
741 ret = FALSE;
743 return ret;
746 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
747 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
748 * to CRYPT_E_ASN1_CORRUPT.
749 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
750 * set!
752 static BOOL CRYPT_AsnDecodeDerBlob(const BYTE *pbEncoded, DWORD cbEncoded,
753 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
755 BOOL ret;
756 DWORD dataLen;
758 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
760 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
761 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
763 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
764 bytesNeeded += 1 + lenBytes + dataLen;
766 if (pcbDecoded)
767 *pcbDecoded = 1 + lenBytes + dataLen;
768 if (!pvStructInfo)
769 *pcbStructInfo = bytesNeeded;
770 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded)))
772 CRYPT_DER_BLOB *blob;
774 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
775 pvStructInfo = *(BYTE **)pvStructInfo;
776 blob = (CRYPT_DER_BLOB *)pvStructInfo;
777 blob->cbData = 1 + lenBytes + dataLen;
778 if (blob->cbData)
780 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
781 blob->pbData = (BYTE *)pbEncoded;
782 else
784 assert(blob->pbData);
785 memcpy(blob->pbData, pbEncoded, blob->cbData);
788 else
790 SetLastError(CRYPT_E_ASN1_CORRUPT);
791 ret = FALSE;
795 return ret;
798 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
799 static BOOL CRYPT_AsnDecodeBitsSwapBytes(const BYTE *pbEncoded,
800 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
801 DWORD *pcbDecoded)
803 BOOL ret;
805 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
806 pvStructInfo, *pcbStructInfo, pcbDecoded);
808 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
809 * place.
811 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
812 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
813 pcbDecoded);
814 if (ret && pvStructInfo)
816 CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
818 if (blob->cbData)
820 DWORD i;
821 BYTE temp;
823 for (i = 0; i < blob->cbData / 2; i++)
825 temp = blob->pbData[i];
826 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
827 blob->pbData[blob->cbData - i - 1] = temp;
831 TRACE("returning %d (%08x)\n", ret, GetLastError());
832 return ret;
835 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
836 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
837 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
839 BOOL ret = TRUE;
841 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
842 pDecodePara, pvStructInfo, *pcbStructInfo);
844 __TRY
846 struct AsnDecodeSequenceItem items[] = {
847 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
848 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
849 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
850 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
851 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
852 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
853 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
854 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
855 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
856 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
859 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
860 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
861 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
862 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
863 pcbStructInfo, NULL, NULL);
865 __EXCEPT_PAGE_FAULT
867 SetLastError(STATUS_ACCESS_VIOLATION);
868 ret = FALSE;
870 __ENDTRY
872 TRACE("Returning %d (%08x)\n", ret, GetLastError());
873 return ret;
876 static BOOL CRYPT_AsnDecodeCertVersion(const BYTE *pbEncoded, DWORD cbEncoded,
877 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
879 BOOL ret;
880 DWORD dataLen;
882 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
884 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
886 ret = CRYPT_AsnDecodeIntInternal(pbEncoded + 1 + lenBytes, dataLen,
887 dwFlags, pvStructInfo, pcbStructInfo, NULL);
888 if (pcbDecoded)
889 *pcbDecoded = 1 + lenBytes + dataLen;
891 return ret;
894 static BOOL CRYPT_AsnDecodeValidity(const BYTE *pbEncoded, DWORD cbEncoded,
895 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
897 BOOL ret;
899 struct AsnDecodeSequenceItem items[] = {
900 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
901 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
902 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
903 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
906 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
907 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
908 pcbDecoded, NULL);
909 return ret;
912 static BOOL CRYPT_AsnDecodeCertExtensions(const BYTE *pbEncoded,
913 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
914 DWORD *pcbDecoded)
916 BOOL ret;
917 DWORD dataLen;
919 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
921 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
923 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded + 1 + lenBytes,
924 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
925 if (ret && pcbDecoded)
926 *pcbDecoded = 1 + lenBytes + dataLen;
928 return ret;
931 static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
932 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
933 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
935 BOOL ret = TRUE;
936 struct AsnDecodeSequenceItem items[] = {
937 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
938 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
939 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
940 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
941 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
942 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
943 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
944 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
945 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
946 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
947 Issuer.pbData) },
948 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
949 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
950 FALSE, 0 },
951 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
952 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
953 Subject.pbData) },
954 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
955 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
956 FALSE, TRUE, offsetof(CERT_INFO,
957 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
958 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
959 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
960 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
961 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
962 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
963 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
964 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
965 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
966 offsetof(CERT_INFO, rgExtension), 0 },
969 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
970 pDecodePara, pvStructInfo, *pcbStructInfo);
972 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
973 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
974 NULL, NULL);
975 if (ret && pvStructInfo)
977 CERT_INFO *info;
979 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
980 info = *(CERT_INFO **)pvStructInfo;
981 else
982 info = (CERT_INFO *)pvStructInfo;
983 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
984 !info->Subject.cbData)
986 SetLastError(CRYPT_E_ASN1_CORRUPT);
987 /* Don't need to deallocate, because it should have failed on the
988 * first pass (and no memory was allocated.)
990 ret = FALSE;
994 TRACE("Returning %d (%08x)\n", ret, GetLastError());
995 return ret;
998 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
999 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1000 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1002 BOOL ret = FALSE;
1004 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1005 pDecodePara, pvStructInfo, *pcbStructInfo);
1007 __TRY
1009 DWORD size = 0;
1011 /* Unless told not to, first try to decode it as a signed cert. */
1012 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1014 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
1016 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1017 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1018 (BYTE *)&signedCert, &size);
1019 if (ret)
1021 size = 0;
1022 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1023 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
1024 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
1025 pvStructInfo, pcbStructInfo);
1026 LocalFree(signedCert);
1029 /* Failing that, try it as an unsigned cert */
1030 if (!ret)
1032 size = 0;
1033 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1034 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
1035 pDecodePara, pvStructInfo, pcbStructInfo);
1038 __EXCEPT_PAGE_FAULT
1040 SetLastError(STATUS_ACCESS_VIOLATION);
1042 __ENDTRY
1044 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1045 return ret;
1048 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
1049 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1051 BOOL ret;
1052 struct AsnDecodeSequenceItem items[] = {
1053 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
1054 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
1055 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
1056 { 0, offsetof(CRL_ENTRY, RevocationDate),
1057 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
1058 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
1059 CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1060 offsetof(CRL_ENTRY, rgExtension), 0 },
1062 PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
1064 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
1065 *pcbStructInfo);
1067 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1068 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, pcbDecoded,
1069 entry ? entry->SerialNumber.pbData : NULL);
1070 return ret;
1073 /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
1074 * been set prior to calling.
1076 static BOOL CRYPT_AsnDecodeCRLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
1077 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1079 BOOL ret;
1080 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1081 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
1082 offsetof(CRL_ENTRY, SerialNumber.pbData) };
1083 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
1085 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1086 pvStructInfo, *pcbStructInfo, pcbDecoded);
1088 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1089 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1090 entries ? entries->rgItems : NULL);
1091 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1092 return ret;
1095 static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1096 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1097 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1099 struct AsnDecodeSequenceItem items[] = {
1100 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1101 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1102 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1103 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1104 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1105 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1106 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1107 Issuer.pbData) },
1108 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1109 sizeof(FILETIME), FALSE, FALSE, 0 },
1110 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1111 sizeof(FILETIME), TRUE, FALSE, 0 },
1112 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1113 CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
1114 offsetof(CRL_INFO, rgCRLEntry), 0 },
1115 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1116 CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
1117 offsetof(CRL_INFO, rgExtension), 0 },
1119 BOOL ret = TRUE;
1121 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1122 pDecodePara, pvStructInfo, *pcbStructInfo);
1124 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1125 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
1126 NULL, NULL);
1128 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1129 return ret;
1132 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1133 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1134 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1136 BOOL ret = FALSE;
1138 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1139 pDecodePara, pvStructInfo, *pcbStructInfo);
1141 __TRY
1143 DWORD size = 0;
1145 /* Unless told not to, first try to decode it as a signed crl. */
1146 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1148 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1150 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1151 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1152 (BYTE *)&signedCrl, &size);
1153 if (ret)
1155 size = 0;
1156 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1157 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1158 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1159 pvStructInfo, pcbStructInfo);
1160 LocalFree(signedCrl);
1163 /* Failing that, try it as an unsigned crl */
1164 if (!ret)
1166 size = 0;
1167 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1168 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1169 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1172 __EXCEPT_PAGE_FAULT
1174 SetLastError(STATUS_ACCESS_VIOLATION);
1176 __ENDTRY
1178 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1179 return ret;
1182 static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded,
1183 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1185 BOOL ret = TRUE;
1186 DWORD dataLen;
1188 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1189 pvStructInfo, *pcbStructInfo);
1191 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1193 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1194 DWORD bytesNeeded = sizeof(LPSTR);
1196 if (dataLen)
1198 /* The largest possible string for the first two components
1199 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1201 char firstTwo[6];
1202 const BYTE *ptr;
1204 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1205 pbEncoded[1 + lenBytes] / 40,
1206 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1207 * 40);
1208 bytesNeeded += strlen(firstTwo) + 1;
1209 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1210 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1212 /* large enough for ".4000000" */
1213 char str[9];
1214 int val = 0;
1216 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1217 (*ptr & 0x80))
1219 val <<= 7;
1220 val |= *ptr & 0x7f;
1221 ptr++;
1223 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1224 (*ptr & 0x80))
1226 SetLastError(CRYPT_E_ASN1_CORRUPT);
1227 ret = FALSE;
1229 else
1231 val <<= 7;
1232 val |= *ptr++;
1233 snprintf(str, sizeof(str), ".%d", val);
1234 bytesNeeded += strlen(str);
1238 if (pcbDecoded)
1239 *pcbDecoded = 1 + lenBytes + dataLen;
1240 if (!pvStructInfo)
1241 *pcbStructInfo = bytesNeeded;
1242 else if (*pcbStructInfo < bytesNeeded)
1244 *pcbStructInfo = bytesNeeded;
1245 SetLastError(ERROR_MORE_DATA);
1246 ret = FALSE;
1248 else
1250 if (dataLen)
1252 const BYTE *ptr;
1253 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1255 *pszObjId = 0;
1256 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1257 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1258 40) * 40);
1259 pszObjId += strlen(pszObjId);
1260 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1261 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1263 int val = 0;
1265 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1266 (*ptr & 0x80))
1268 val <<= 7;
1269 val |= *ptr & 0x7f;
1270 ptr++;
1272 val <<= 7;
1273 val |= *ptr++;
1274 sprintf(pszObjId, ".%d", val);
1275 pszObjId += strlen(pszObjId);
1278 else
1279 *(LPSTR *)pvStructInfo = NULL;
1280 *pcbStructInfo = bytesNeeded;
1283 return ret;
1286 static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded,
1287 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1289 BOOL ret;
1291 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1292 pvStructInfo, *pcbStructInfo);
1294 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1295 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1296 pvStructInfo, pcbStructInfo, pcbDecoded);
1297 else
1299 SetLastError(CRYPT_E_ASN1_BADTAG);
1300 ret = FALSE;
1302 return ret;
1305 /* Warning: assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set
1306 * ahead of time!
1308 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
1309 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1311 struct AsnDecodeSequenceItem items[] = {
1312 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1313 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1314 offsetof(CERT_EXTENSION, pszObjId), 0 },
1315 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1316 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1317 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1318 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1319 offsetof(CERT_EXTENSION, Value.pbData) },
1321 BOOL ret = TRUE;
1322 PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
1324 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1325 *pcbStructInfo);
1327 if (ext)
1328 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1329 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1330 pbEncoded, cbEncoded, dwFlags, NULL, ext, pcbStructInfo,
1331 pcbDecoded, ext ? ext->pszObjId : NULL);
1332 if (ext)
1333 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1334 debugstr_a(ext->pszObjId));
1335 TRACE("returning %d (%08x)\n", ret, GetLastError());
1336 return ret;
1339 static BOOL CRYPT_AsnDecodeExtensionsInternal(const BYTE *pbEncoded,
1340 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1341 DWORD *pcbDecoded)
1343 BOOL ret = TRUE;
1344 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1345 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1346 offsetof(CERT_EXTENSION, pszObjId) };
1347 PCERT_EXTENSIONS exts = (PCERT_EXTENSIONS)pvStructInfo;
1349 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1350 pvStructInfo, *pcbStructInfo, pcbDecoded);
1352 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1353 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1354 exts ? exts->rgExtension : NULL);
1355 return ret;
1358 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1359 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1360 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1362 BOOL ret = TRUE;
1364 __TRY
1366 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
1367 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1368 if (ret && pvStructInfo)
1370 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1371 pcbStructInfo, *pcbStructInfo);
1372 if (ret)
1374 CERT_EXTENSIONS *exts;
1376 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1377 pvStructInfo = *(BYTE **)pvStructInfo;
1378 exts = (CERT_EXTENSIONS *)pvStructInfo;
1379 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1380 sizeof(CERT_EXTENSIONS));
1381 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
1382 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1383 pcbStructInfo, NULL);
1387 __EXCEPT_PAGE_FAULT
1389 SetLastError(STATUS_ACCESS_VIOLATION);
1390 ret = FALSE;
1392 __ENDTRY
1393 return ret;
1396 /* Warning: this assumes the address of value->Value.pbData is already set, in
1397 * order to avoid overwriting memory. (In some cases, it may change it, if it
1398 * doesn't copy anything to memory.) Be sure to set it correctly!
1400 static BOOL CRYPT_AsnDecodeNameValueInternal(const BYTE *pbEncoded,
1401 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1402 DWORD *pcbDecoded)
1404 BOOL ret = TRUE;
1405 DWORD dataLen;
1406 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1408 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1410 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1411 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1413 switch (pbEncoded[0])
1415 case ASN_OCTETSTRING:
1416 valueType = CERT_RDN_OCTET_STRING;
1417 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1418 bytesNeeded += dataLen;
1419 break;
1420 case ASN_NUMERICSTRING:
1421 valueType = CERT_RDN_NUMERIC_STRING;
1422 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1423 bytesNeeded += dataLen;
1424 break;
1425 case ASN_PRINTABLESTRING:
1426 valueType = CERT_RDN_PRINTABLE_STRING;
1427 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1428 bytesNeeded += dataLen;
1429 break;
1430 case ASN_IA5STRING:
1431 valueType = CERT_RDN_IA5_STRING;
1432 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1433 bytesNeeded += dataLen;
1434 break;
1435 case ASN_T61STRING:
1436 valueType = CERT_RDN_T61_STRING;
1437 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1438 bytesNeeded += dataLen;
1439 break;
1440 case ASN_VIDEOTEXSTRING:
1441 valueType = CERT_RDN_VIDEOTEX_STRING;
1442 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1443 bytesNeeded += dataLen;
1444 break;
1445 case ASN_GRAPHICSTRING:
1446 valueType = CERT_RDN_GRAPHIC_STRING;
1447 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1448 bytesNeeded += dataLen;
1449 break;
1450 case ASN_VISIBLESTRING:
1451 valueType = CERT_RDN_VISIBLE_STRING;
1452 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1453 bytesNeeded += dataLen;
1454 break;
1455 case ASN_GENERALSTRING:
1456 valueType = CERT_RDN_GENERAL_STRING;
1457 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1458 bytesNeeded += dataLen;
1459 break;
1460 case ASN_UNIVERSALSTRING:
1461 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1462 SetLastError(CRYPT_E_ASN1_BADTAG);
1463 return FALSE;
1464 case ASN_BMPSTRING:
1465 valueType = CERT_RDN_BMP_STRING;
1466 bytesNeeded += dataLen;
1467 break;
1468 case ASN_UTF8STRING:
1469 valueType = CERT_RDN_UTF8_STRING;
1470 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1471 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1472 break;
1473 default:
1474 SetLastError(CRYPT_E_ASN1_BADTAG);
1475 return FALSE;
1478 if (pcbDecoded)
1479 *pcbDecoded = 1 + lenBytes + dataLen;
1480 if (!value)
1481 *pcbStructInfo = bytesNeeded;
1482 else if (*pcbStructInfo < bytesNeeded)
1484 *pcbStructInfo = bytesNeeded;
1485 SetLastError(ERROR_MORE_DATA);
1486 ret = FALSE;
1488 else
1490 *pcbStructInfo = bytesNeeded;
1491 value->dwValueType = valueType;
1492 if (dataLen)
1494 DWORD i;
1496 assert(value->Value.pbData);
1497 switch (pbEncoded[0])
1499 case ASN_OCTETSTRING:
1500 case ASN_NUMERICSTRING:
1501 case ASN_PRINTABLESTRING:
1502 case ASN_IA5STRING:
1503 case ASN_T61STRING:
1504 case ASN_VIDEOTEXSTRING:
1505 case ASN_GRAPHICSTRING:
1506 case ASN_VISIBLESTRING:
1507 case ASN_GENERALSTRING:
1508 value->Value.cbData = dataLen;
1509 if (dataLen)
1511 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1512 memcpy(value->Value.pbData,
1513 pbEncoded + 1 + lenBytes, dataLen);
1514 else
1515 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1516 lenBytes;
1518 break;
1519 case ASN_BMPSTRING:
1521 LPWSTR str = (LPWSTR)value->Value.pbData;
1523 value->Value.cbData = dataLen;
1524 for (i = 0; i < dataLen / 2; i++)
1525 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1526 pbEncoded[1 + lenBytes + 2 * i + 1];
1527 break;
1529 case ASN_UTF8STRING:
1531 LPWSTR str = (LPWSTR)value->Value.pbData;
1533 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1534 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1535 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1536 break;
1540 else
1542 value->Value.cbData = 0;
1543 value->Value.pbData = NULL;
1547 return ret;
1550 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1551 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1552 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1554 BOOL ret = TRUE;
1556 __TRY
1558 ret = CRYPT_AsnDecodeNameValueInternal(pbEncoded, cbEncoded,
1559 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1560 if (ret && pvStructInfo)
1562 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1563 pcbStructInfo, *pcbStructInfo);
1564 if (ret)
1566 CERT_NAME_VALUE *value;
1568 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1569 pvStructInfo = *(BYTE **)pvStructInfo;
1570 value = (CERT_NAME_VALUE *)pvStructInfo;
1571 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1572 ret = CRYPT_AsnDecodeNameValueInternal( pbEncoded, cbEncoded,
1573 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1574 pcbStructInfo, NULL);
1578 __EXCEPT_PAGE_FAULT
1580 SetLastError(STATUS_ACCESS_VIOLATION);
1581 ret = FALSE;
1583 __ENDTRY
1584 return ret;
1587 static BOOL CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE *pbEncoded,
1588 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1589 DWORD *pcbDecoded)
1591 BOOL ret = TRUE;
1592 DWORD dataLen;
1593 CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
1595 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1597 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1598 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1600 switch (pbEncoded[0])
1602 case ASN_NUMERICSTRING:
1603 valueType = CERT_RDN_NUMERIC_STRING;
1604 bytesNeeded += dataLen * 2;
1605 break;
1606 case ASN_PRINTABLESTRING:
1607 valueType = CERT_RDN_PRINTABLE_STRING;
1608 bytesNeeded += dataLen * 2;
1609 break;
1610 case ASN_IA5STRING:
1611 valueType = CERT_RDN_IA5_STRING;
1612 bytesNeeded += dataLen * 2;
1613 break;
1614 case ASN_T61STRING:
1615 valueType = CERT_RDN_T61_STRING;
1616 bytesNeeded += dataLen * 2;
1617 break;
1618 case ASN_VIDEOTEXSTRING:
1619 valueType = CERT_RDN_VIDEOTEX_STRING;
1620 bytesNeeded += dataLen * 2;
1621 break;
1622 case ASN_GRAPHICSTRING:
1623 valueType = CERT_RDN_GRAPHIC_STRING;
1624 bytesNeeded += dataLen * 2;
1625 break;
1626 case ASN_VISIBLESTRING:
1627 valueType = CERT_RDN_VISIBLE_STRING;
1628 bytesNeeded += dataLen * 2;
1629 break;
1630 case ASN_GENERALSTRING:
1631 valueType = CERT_RDN_GENERAL_STRING;
1632 bytesNeeded += dataLen * 2;
1633 break;
1634 case ASN_UNIVERSALSTRING:
1635 valueType = CERT_RDN_UNIVERSAL_STRING;
1636 bytesNeeded += dataLen / 2;
1637 break;
1638 case ASN_BMPSTRING:
1639 valueType = CERT_RDN_BMP_STRING;
1640 bytesNeeded += dataLen;
1641 break;
1642 case ASN_UTF8STRING:
1643 valueType = CERT_RDN_UTF8_STRING;
1644 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1645 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1646 break;
1647 default:
1648 SetLastError(CRYPT_E_ASN1_BADTAG);
1649 return FALSE;
1652 if (pcbDecoded)
1653 *pcbDecoded = 1 + lenBytes + dataLen;
1654 if (!value)
1655 *pcbStructInfo = bytesNeeded;
1656 else if (*pcbStructInfo < bytesNeeded)
1658 *pcbStructInfo = bytesNeeded;
1659 SetLastError(ERROR_MORE_DATA);
1660 ret = FALSE;
1662 else
1664 *pcbStructInfo = bytesNeeded;
1665 value->dwValueType = valueType;
1666 if (dataLen)
1668 DWORD i;
1669 LPWSTR str = (LPWSTR)value->Value.pbData;
1671 assert(value->Value.pbData);
1672 switch (pbEncoded[0])
1674 case ASN_NUMERICSTRING:
1675 case ASN_PRINTABLESTRING:
1676 case ASN_IA5STRING:
1677 case ASN_T61STRING:
1678 case ASN_VIDEOTEXSTRING:
1679 case ASN_GRAPHICSTRING:
1680 case ASN_VISIBLESTRING:
1681 case ASN_GENERALSTRING:
1682 value->Value.cbData = dataLen * 2;
1683 for (i = 0; i < dataLen; i++)
1684 str[i] = pbEncoded[1 + lenBytes + i];
1685 break;
1686 case ASN_UNIVERSALSTRING:
1687 value->Value.cbData = dataLen / 2;
1688 for (i = 0; i < dataLen / 4; i++)
1689 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1690 | pbEncoded[1 + lenBytes + 2 * i + 3];
1691 break;
1692 case ASN_BMPSTRING:
1693 value->Value.cbData = dataLen;
1694 for (i = 0; i < dataLen / 2; i++)
1695 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1696 pbEncoded[1 + lenBytes + 2 * i + 1];
1697 break;
1698 case ASN_UTF8STRING:
1699 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1700 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1701 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1702 break;
1705 else
1707 value->Value.cbData = 0;
1708 value->Value.pbData = NULL;
1712 return ret;
1715 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1716 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1717 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1719 BOOL ret = TRUE;
1721 __TRY
1723 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded, cbEncoded,
1724 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1725 if (ret && pvStructInfo)
1727 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1728 pcbStructInfo, *pcbStructInfo);
1729 if (ret)
1731 CERT_NAME_VALUE *value;
1733 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1734 pvStructInfo = *(BYTE **)pvStructInfo;
1735 value = (CERT_NAME_VALUE *)pvStructInfo;
1736 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1737 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded,
1738 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1739 pcbStructInfo, NULL);
1743 __EXCEPT_PAGE_FAULT
1745 SetLastError(STATUS_ACCESS_VIOLATION);
1746 ret = FALSE;
1748 __ENDTRY
1749 return ret;
1752 static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
1753 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1755 BOOL ret;
1756 struct AsnDecodeSequenceItem items[] = {
1757 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1758 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1759 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1760 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1761 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1762 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1764 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1766 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1767 pvStructInfo, *pcbStructInfo);
1769 if (attr)
1770 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1771 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1772 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1773 attr ? attr->pszObjId : NULL);
1774 if (attr)
1776 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1777 debugstr_a(attr->pszObjId));
1778 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1780 TRACE("returning %d (%08x)\n", ret, GetLastError());
1781 return ret;
1784 static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1785 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1787 BOOL ret = TRUE;
1788 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1789 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1790 offsetof(CERT_RDN_ATTR, pszObjId) };
1791 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1793 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1794 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1795 rdn ? rdn->rgRDNAttr : NULL);
1796 return ret;
1799 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1800 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1801 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1803 BOOL ret = TRUE;
1805 __TRY
1807 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1808 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1809 offsetof(CERT_RDN, rgRDNAttr) };
1811 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1812 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1814 __EXCEPT_PAGE_FAULT
1816 SetLastError(STATUS_ACCESS_VIOLATION);
1817 ret = FALSE;
1819 __ENDTRY
1820 return ret;
1823 static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
1824 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1825 DWORD *pcbDecoded)
1827 BOOL ret;
1828 struct AsnDecodeSequenceItem items[] = {
1829 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1830 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1831 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1832 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1833 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1834 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1836 CERT_RDN_ATTR *attr = (CERT_RDN_ATTR *)pvStructInfo;
1838 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1839 pvStructInfo, *pcbStructInfo);
1841 if (attr)
1842 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1843 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1844 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1845 attr ? attr->pszObjId : NULL);
1846 if (attr)
1848 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1849 debugstr_a(attr->pszObjId));
1850 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1852 TRACE("returning %d (%08x)\n", ret, GetLastError());
1853 return ret;
1856 static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1857 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1859 BOOL ret = TRUE;
1860 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1861 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1862 offsetof(CERT_RDN_ATTR, pszObjId) };
1863 PCERT_RDN rdn = (PCERT_RDN)pvStructInfo;
1865 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1866 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
1867 rdn ? rdn->rgRDNAttr : NULL);
1868 return ret;
1871 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1872 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1873 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1875 BOOL ret = TRUE;
1877 __TRY
1879 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1880 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1881 offsetof(CERT_RDN, rgRDNAttr) };
1883 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1884 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1886 __EXCEPT_PAGE_FAULT
1888 SetLastError(STATUS_ACCESS_VIOLATION);
1889 ret = FALSE;
1891 __ENDTRY
1892 return ret;
1895 static BOOL CRYPT_FindEncodedLen(const BYTE *pbEncoded, DWORD cbEncoded,
1896 DWORD *pcbDecoded)
1898 BOOL ret = TRUE, done = FALSE;
1899 DWORD indefiniteNestingLevels = 0, decoded = 0;
1901 TRACE("(%p, %d)\n", pbEncoded, cbEncoded);
1903 do {
1904 DWORD dataLen;
1906 if (!cbEncoded)
1907 done = TRUE;
1908 else if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded,
1909 &dataLen)))
1911 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1913 if (dataLen == CMSG_INDEFINITE_LENGTH)
1915 indefiniteNestingLevels++;
1916 pbEncoded += 1 + lenBytes;
1917 cbEncoded -= 1 + lenBytes;
1918 decoded += 1 + lenBytes;
1919 TRACE("indefiniteNestingLevels = %d\n",
1920 indefiniteNestingLevels);
1922 else
1924 if (pbEncoded[0] == 0 && pbEncoded[1] == 0 &&
1925 indefiniteNestingLevels)
1927 indefiniteNestingLevels--;
1928 TRACE("indefiniteNestingLevels = %d\n",
1929 indefiniteNestingLevels);
1931 pbEncoded += 1 + lenBytes + dataLen;
1932 cbEncoded -= 1 + lenBytes + dataLen;
1933 decoded += 1 + lenBytes + dataLen;
1934 if (!indefiniteNestingLevels)
1935 done = TRUE;
1938 } while (ret && !done);
1939 /* If we haven't found all 0 TLVs, we haven't found the end */
1940 if (ret && indefiniteNestingLevels)
1942 SetLastError(CRYPT_E_ASN1_EOD);
1943 ret = FALSE;
1945 if (ret)
1946 *pcbDecoded = decoded;
1947 TRACE("returning %d (%d)\n", ret, ret ? *pcbDecoded : 0);
1948 return ret;
1951 static BOOL CRYPT_AsnDecodeCopyBytes(const BYTE *pbEncoded,
1952 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1953 DWORD *pcbDecoded)
1955 BOOL ret = TRUE;
1956 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB), encodedLen = 0;
1958 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1959 pvStructInfo, *pcbStructInfo);
1961 if ((ret = CRYPT_FindEncodedLen(pbEncoded, cbEncoded, &encodedLen)))
1963 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1964 bytesNeeded += encodedLen;
1965 if (!pvStructInfo)
1966 *pcbStructInfo = bytesNeeded;
1967 else if (*pcbStructInfo < bytesNeeded)
1969 SetLastError(ERROR_MORE_DATA);
1970 *pcbStructInfo = bytesNeeded;
1971 ret = FALSE;
1973 else
1975 PCRYPT_OBJID_BLOB blob = (PCRYPT_OBJID_BLOB)pvStructInfo;
1977 *pcbStructInfo = bytesNeeded;
1978 blob->cbData = encodedLen;
1979 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
1980 blob->pbData = (LPBYTE)pbEncoded;
1981 else
1983 assert(blob->pbData);
1984 memcpy(blob->pbData, pbEncoded, blob->cbData);
1987 if (pcbDecoded)
1988 *pcbDecoded = encodedLen;
1990 return ret;
1993 static BOOL CRYPT_DecodeDERArray(const BYTE *pbEncoded, DWORD cbEncoded,
1994 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1996 BOOL ret;
1997 struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytes,
1998 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
1999 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
2001 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2002 pvStructInfo, *pcbStructInfo, pcbDecoded);
2004 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2005 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2006 array ? array->rgItems : NULL);
2007 return ret;
2010 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
2011 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2012 DWORD *pcbDecoded)
2014 BOOL ret;
2015 struct AsnDecodeSequenceItem items[] = {
2016 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
2017 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2018 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
2019 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
2020 CRYPT_DecodeDERArray, sizeof(struct GenericArray), FALSE, TRUE,
2021 offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
2023 PCRYPT_ATTRIBUTE attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
2025 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2026 pvStructInfo, *pcbStructInfo);
2028 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2029 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2030 pcbDecoded, attr ? attr->pszObjId : NULL);
2031 TRACE("returning %d\n", ret);
2032 return ret;
2035 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
2036 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2037 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2039 BOOL ret = FALSE;
2041 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2042 pDecodePara, pvStructInfo, *pcbStructInfo);
2044 __TRY
2046 DWORD bytesNeeded;
2048 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2049 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
2050 if (ret)
2052 if (!pvStructInfo)
2053 *pcbStructInfo = bytesNeeded;
2054 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2055 pvStructInfo, pcbStructInfo, bytesNeeded)))
2057 PCRYPT_ATTRIBUTE attr;
2059 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2060 pvStructInfo = *(BYTE **)pvStructInfo;
2061 attr = (PCRYPT_ATTRIBUTE)pvStructInfo;
2062 attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
2063 sizeof(CRYPT_ATTRIBUTE));
2064 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2065 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
2066 NULL);
2070 __EXCEPT_PAGE_FAULT
2072 SetLastError(STATUS_ACCESS_VIOLATION);
2074 __ENDTRY
2075 TRACE("returning %d\n", ret);
2076 return ret;
2079 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
2080 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2081 DWORD *pcbDecoded)
2083 struct AsnArrayDescriptor arrayDesc = { 0,
2084 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2085 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2086 PCRYPT_ATTRIBUTES attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
2087 BOOL ret;
2089 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2090 NULL, pvStructInfo, pcbStructInfo, pcbDecoded, attrs ? attrs->rgAttr :
2091 NULL);
2092 return ret;
2095 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
2096 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2097 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2099 BOOL ret = FALSE;
2101 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2102 pDecodePara, pvStructInfo, *pcbStructInfo);
2104 __TRY
2106 DWORD bytesNeeded;
2108 if (!cbEncoded)
2109 SetLastError(CRYPT_E_ASN1_EOD);
2110 else if (pbEncoded[0] != (ASN_CONSTRUCTOR | ASN_SETOF))
2111 SetLastError(CRYPT_E_ASN1_CORRUPT);
2112 else if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
2113 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2114 NULL)))
2116 if (!pvStructInfo)
2117 *pcbStructInfo = bytesNeeded;
2118 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2119 pvStructInfo, pcbStructInfo, bytesNeeded)))
2121 PCRYPT_ATTRIBUTES attrs;
2123 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2124 pvStructInfo = *(BYTE **)pvStructInfo;
2125 attrs = (PCRYPT_ATTRIBUTES)pvStructInfo;
2126 attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
2127 sizeof(CRYPT_ATTRIBUTES));
2128 ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
2129 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2130 &bytesNeeded, NULL);
2134 __EXCEPT_PAGE_FAULT
2136 SetLastError(STATUS_ACCESS_VIOLATION);
2138 __ENDTRY
2139 TRACE("returning %d\n", ret);
2140 return ret;
2143 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
2144 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2146 CRYPT_ALGORITHM_IDENTIFIER *algo =
2147 (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
2148 BOOL ret = TRUE;
2149 struct AsnDecodeSequenceItem items[] = {
2150 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
2151 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2152 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
2153 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
2154 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2155 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
2158 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2159 pvStructInfo, *pcbStructInfo, pcbDecoded);
2161 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2162 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2163 pcbDecoded, algo ? algo->pszObjId : NULL);
2164 if (ret && pvStructInfo)
2166 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
2167 debugstr_a(algo->pszObjId));
2169 return ret;
2172 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
2173 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2174 DWORD *pcbDecoded)
2176 BOOL ret = TRUE;
2177 struct AsnDecodeSequenceItem items[] = {
2178 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
2179 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2180 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
2181 Algorithm.pszObjId) },
2182 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
2183 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2184 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
2186 PCERT_PUBLIC_KEY_INFO info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2188 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2189 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2190 pcbDecoded, info ? info->Algorithm.Parameters.pbData : NULL);
2191 return ret;
2194 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2195 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2196 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2198 BOOL ret = TRUE;
2200 __TRY
2202 DWORD bytesNeeded;
2204 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2205 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2207 if (!pvStructInfo)
2208 *pcbStructInfo = bytesNeeded;
2209 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2210 pvStructInfo, pcbStructInfo, bytesNeeded)))
2212 PCERT_PUBLIC_KEY_INFO info;
2214 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2215 pvStructInfo = *(BYTE **)pvStructInfo;
2216 info = (PCERT_PUBLIC_KEY_INFO)pvStructInfo;
2217 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2218 sizeof(CERT_PUBLIC_KEY_INFO);
2219 ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2220 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2221 &bytesNeeded, NULL);
2225 __EXCEPT_PAGE_FAULT
2227 SetLastError(STATUS_ACCESS_VIOLATION);
2228 ret = FALSE;
2230 __ENDTRY
2231 return ret;
2234 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
2235 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2237 BOOL ret;
2239 if (cbEncoded < 3)
2241 SetLastError(CRYPT_E_ASN1_CORRUPT);
2242 return FALSE;
2244 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2246 SetLastError(CRYPT_E_ASN1_CORRUPT);
2247 return FALSE;
2249 if (pbEncoded[1] > 1)
2251 SetLastError(CRYPT_E_ASN1_CORRUPT);
2252 return FALSE;
2254 if (pcbDecoded)
2255 *pcbDecoded = 3;
2256 if (!pvStructInfo)
2258 *pcbStructInfo = sizeof(BOOL);
2259 ret = TRUE;
2261 else if (*pcbStructInfo < sizeof(BOOL))
2263 *pcbStructInfo = sizeof(BOOL);
2264 SetLastError(ERROR_MORE_DATA);
2265 ret = FALSE;
2267 else
2269 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2270 ret = TRUE;
2272 TRACE("returning %d (%08x)\n", ret, GetLastError());
2273 return ret;
2276 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2277 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2279 PCERT_ALT_NAME_ENTRY entry = (PCERT_ALT_NAME_ENTRY)pvStructInfo;
2280 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2281 BOOL ret;
2283 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2284 pvStructInfo, *pcbStructInfo);
2286 if (cbEncoded < 2)
2288 SetLastError(CRYPT_E_ASN1_CORRUPT);
2289 return FALSE;
2291 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2292 if (1 + lenBytes > cbEncoded)
2294 SetLastError(CRYPT_E_ASN1_CORRUPT);
2295 return FALSE;
2297 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2299 switch (pbEncoded[0] & ASN_TYPE_MASK)
2301 case 1: /* rfc822Name */
2302 case 2: /* dNSName */
2303 case 6: /* uniformResourceIdentifier */
2304 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
2305 break;
2306 case 4: /* directoryName */
2307 case 7: /* iPAddress */
2308 bytesNeeded += dataLen;
2309 break;
2310 case 8: /* registeredID */
2311 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
2312 &dataLen, NULL);
2313 if (ret)
2315 /* FIXME: ugly, shouldn't need to know internals of OID decode
2316 * function to use it.
2318 bytesNeeded += dataLen - sizeof(LPSTR);
2320 break;
2321 case 0: /* otherName */
2322 FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
2323 SetLastError(CRYPT_E_ASN1_BADTAG);
2324 ret = FALSE;
2325 break;
2326 case 3: /* x400Address, unimplemented */
2327 case 5: /* ediPartyName, unimplemented */
2328 TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
2329 SetLastError(CRYPT_E_ASN1_BADTAG);
2330 ret = FALSE;
2331 break;
2332 default:
2333 TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
2334 SetLastError(CRYPT_E_ASN1_CORRUPT);
2335 ret = FALSE;
2337 if (ret)
2339 if (pcbDecoded)
2340 *pcbDecoded = 1 + lenBytes + dataLen;
2341 if (!entry)
2342 *pcbStructInfo = bytesNeeded;
2343 else if (*pcbStructInfo < bytesNeeded)
2345 *pcbStructInfo = bytesNeeded;
2346 SetLastError(ERROR_MORE_DATA);
2347 ret = FALSE;
2349 else
2351 *pcbStructInfo = bytesNeeded;
2352 /* MS used values one greater than the asn1 ones.. sigh */
2353 entry->dwAltNameChoice = (pbEncoded[0] & 0x7f) + 1;
2354 switch (pbEncoded[0] & ASN_TYPE_MASK)
2356 case 1: /* rfc822Name */
2357 case 2: /* dNSName */
2358 case 6: /* uniformResourceIdentifier */
2360 DWORD i;
2362 for (i = 0; i < dataLen; i++)
2363 entry->u.pwszURL[i] =
2364 (WCHAR)pbEncoded[1 + lenBytes + i];
2365 entry->u.pwszURL[i] = 0;
2366 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
2367 debugstr_w(entry->u.pwszURL));
2368 break;
2370 case 4: /* directoryName */
2371 entry->dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
2372 /* The data are memory-equivalent with the IPAddress case,
2373 * fall-through
2375 case 7: /* iPAddress */
2376 /* The next data pointer is in the pwszURL spot, that is,
2377 * the first 4 bytes. Need to move it to the next spot.
2379 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
2380 entry->u.IPAddress.cbData = dataLen;
2381 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
2382 dataLen);
2383 break;
2384 case 8: /* registeredID */
2385 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
2386 &entry->u.pszRegisteredID, &dataLen, NULL);
2387 break;
2392 return ret;
2395 static BOOL CRYPT_AsnDecodeAltNameInternal(const BYTE *pbEncoded,
2396 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2397 DWORD *pcbDecoded)
2399 BOOL ret = TRUE;
2400 struct AsnArrayDescriptor arrayDesc = { 0,
2401 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
2402 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
2403 PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
2405 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2406 pvStructInfo, *pcbStructInfo, pcbDecoded);
2408 if (info)
2409 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
2410 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2411 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2412 info ? info->rgAltEntry : NULL);
2413 return ret;
2416 /* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */
2417 static BOOL CRYPT_AsnDecodeIntegerSwapBytes(const BYTE *pbEncoded,
2418 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2419 DWORD *pcbDecoded)
2421 BOOL ret;
2423 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
2424 pvStructInfo, *pcbStructInfo, pcbDecoded);
2426 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
2427 * place.
2429 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
2430 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
2431 pcbDecoded);
2432 if (ret && pvStructInfo)
2434 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2436 if (blob->cbData)
2438 DWORD i;
2439 BYTE temp;
2441 for (i = 0; i < blob->cbData / 2; i++)
2443 temp = blob->pbData[i];
2444 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
2445 blob->pbData[blob->cbData - i - 1] = temp;
2449 TRACE("returning %d (%08x)\n", ret, GetLastError());
2450 return ret;
2453 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
2454 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2455 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2457 BOOL ret;
2459 __TRY
2461 struct AsnDecodeSequenceItem items[] = {
2462 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
2463 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2464 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
2465 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2466 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
2467 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
2468 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
2469 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
2470 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2471 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2472 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
2475 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2476 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2477 pcbStructInfo, NULL, NULL);
2479 __EXCEPT_PAGE_FAULT
2481 SetLastError(STATUS_ACCESS_VIOLATION);
2482 ret = FALSE;
2484 __ENDTRY
2485 return ret;
2488 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
2489 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2490 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2492 BOOL ret;
2494 __TRY
2496 struct AsnDecodeSequenceItem items[] = {
2497 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
2498 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
2499 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
2500 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
2501 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
2502 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
2503 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2504 AuthorityCertIssuer.rgAltEntry), 0 },
2505 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2506 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
2507 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
2508 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
2509 AuthorityCertSerialNumber.pbData), 0 },
2512 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2513 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2514 pcbStructInfo, NULL, NULL);
2516 __EXCEPT_PAGE_FAULT
2518 SetLastError(STATUS_ACCESS_VIOLATION);
2519 ret = FALSE;
2521 __ENDTRY
2522 return ret;
2525 static BOOL CRYPT_AsnDecodePKCSContent(const BYTE *pbEncoded, DWORD cbEncoded,
2526 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2528 BOOL ret;
2529 DWORD dataLen;
2531 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2532 pvStructInfo, *pcbStructInfo, pcbDecoded);
2534 /* The caller has already checked the tag, no need to check it again.
2535 * Check the outer length is valid:
2537 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
2539 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2540 DWORD innerLen;
2542 pbEncoded += 1 + lenBytes;
2543 cbEncoded -= 1 + lenBytes;
2544 if (dataLen == CMSG_INDEFINITE_LENGTH)
2545 cbEncoded -= 2; /* space for 0 TLV */
2546 /* Check the inner length is valid: */
2547 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &innerLen)))
2549 DWORD decodedLen;
2551 ret = CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags,
2552 pvStructInfo, pcbStructInfo, &decodedLen);
2553 if (dataLen == CMSG_INDEFINITE_LENGTH)
2555 if (*(pbEncoded + decodedLen) != 0 ||
2556 *(pbEncoded + decodedLen + 1) != 0)
2558 TRACE("expected 0 TLV, got {%02x,%02x}\n",
2559 *(pbEncoded + decodedLen),
2560 *(pbEncoded + decodedLen + 1));
2561 SetLastError(CRYPT_E_ASN1_CORRUPT);
2562 ret = FALSE;
2564 else
2565 decodedLen += 2;
2567 if (ret && pcbDecoded)
2569 *pcbDecoded = 1 + lenBytes + decodedLen;
2570 TRACE("decoded %d bytes\n", *pcbDecoded);
2574 return ret;
2577 static BOOL CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE *pbEncoded,
2578 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2579 DWORD *pcbDecoded)
2581 CRYPT_CONTENT_INFO *info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2582 struct AsnDecodeSequenceItem items[] = {
2583 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
2584 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2585 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
2586 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
2587 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
2588 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
2589 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
2591 BOOL ret;
2593 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2594 pvStructInfo, *pcbStructInfo, pcbDecoded);
2596 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2597 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2598 pcbDecoded, info ? info->pszObjId : NULL);
2599 return ret;
2602 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
2603 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2604 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2606 BOOL ret = FALSE;
2608 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2609 pDecodePara, pvStructInfo, *pcbStructInfo);
2611 __TRY
2613 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, cbEncoded,
2614 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
2615 if (ret && pvStructInfo)
2617 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
2618 pcbStructInfo, *pcbStructInfo);
2619 if (ret)
2621 CRYPT_CONTENT_INFO *info;
2623 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2624 pvStructInfo = *(BYTE **)pvStructInfo;
2625 info = (CRYPT_CONTENT_INFO *)pvStructInfo;
2626 info->pszObjId = (LPSTR)((BYTE *)info +
2627 sizeof(CRYPT_CONTENT_INFO));
2628 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded,
2629 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2630 pcbStructInfo, NULL);
2634 __EXCEPT_PAGE_FAULT
2636 SetLastError(STATUS_ACCESS_VIOLATION);
2638 __ENDTRY
2639 return ret;
2642 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
2643 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2644 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
2646 BOOL ret;
2647 struct AsnDecodeSequenceItem items[] = {
2648 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version),
2649 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2650 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
2651 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2652 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
2653 0 },
2654 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
2655 CRYPT_AsnDecodePKCSContentInfoInternal,
2656 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
2657 ContentInfo.pszObjId), 0 },
2658 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
2659 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
2660 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
2663 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2664 pbEncoded, cbEncoded, dwFlags, pDecodePara, digestedData, pcbDigestedData,
2665 NULL, NULL);
2666 return ret;
2669 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
2670 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2671 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2673 BOOL ret = TRUE;
2675 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2676 pDecodePara, pvStructInfo, *pcbStructInfo);
2678 __TRY
2680 DWORD bytesNeeded;
2682 if ((ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
2683 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2685 if (!pvStructInfo)
2686 *pcbStructInfo = bytesNeeded;
2687 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2688 pvStructInfo, pcbStructInfo, bytesNeeded)))
2690 CERT_ALT_NAME_INFO *name;
2692 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2693 pvStructInfo = *(BYTE **)pvStructInfo;
2694 name = (CERT_ALT_NAME_INFO *)pvStructInfo;
2695 name->rgAltEntry = (PCERT_ALT_NAME_ENTRY)
2696 ((BYTE *)pvStructInfo + sizeof(CERT_ALT_NAME_INFO));
2697 ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
2698 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2699 &bytesNeeded, NULL);
2703 __EXCEPT_PAGE_FAULT
2705 SetLastError(STATUS_ACCESS_VIOLATION);
2706 ret = FALSE;
2708 __ENDTRY
2709 return ret;
2712 struct PATH_LEN_CONSTRAINT
2714 BOOL fPathLenConstraint;
2715 DWORD dwPathLenConstraint;
2718 static BOOL CRYPT_AsnDecodePathLenConstraint(const BYTE *pbEncoded,
2719 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2720 DWORD *pcbDecoded)
2722 BOOL ret = TRUE;
2723 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT), size;
2725 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2726 pvStructInfo, *pcbStructInfo, pcbDecoded);
2728 if (!pvStructInfo)
2730 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, NULL,
2731 &size, pcbDecoded);
2732 *pcbStructInfo = bytesNeeded;
2734 else if (*pcbStructInfo < bytesNeeded)
2736 SetLastError(ERROR_MORE_DATA);
2737 *pcbStructInfo = bytesNeeded;
2738 ret = FALSE;
2740 else
2742 struct PATH_LEN_CONSTRAINT *constraint =
2743 (struct PATH_LEN_CONSTRAINT *)pvStructInfo;
2745 size = sizeof(constraint->dwPathLenConstraint);
2746 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
2747 &constraint->dwPathLenConstraint, &size, pcbDecoded);
2748 if (ret)
2749 constraint->fPathLenConstraint = TRUE;
2750 TRACE("got an int, dwPathLenConstraint is %d\n",
2751 constraint->dwPathLenConstraint);
2753 TRACE("returning %d (%08x)\n", ret, GetLastError());
2754 return ret;
2757 static BOOL CRYPT_AsnDecodeSubtreeConstraints(const BYTE *pbEncoded,
2758 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2759 DWORD *pcbDecoded)
2761 BOOL ret;
2762 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2763 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
2764 offsetof(CERT_NAME_BLOB, pbData) };
2765 struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
2767 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2768 pvStructInfo, *pcbStructInfo, pcbDecoded);
2770 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2771 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2772 entries ? entries->rgItems : NULL);
2773 TRACE("Returning %d (%08x)\n", ret, GetLastError());
2774 return ret;
2777 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
2778 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2779 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2781 BOOL ret;
2783 __TRY
2785 struct AsnDecodeSequenceItem items[] = {
2786 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
2787 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2788 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
2789 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2790 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2791 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2792 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
2793 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
2794 sizeof(struct GenericArray), TRUE, TRUE,
2795 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
2798 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2799 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2800 pcbStructInfo, NULL, NULL);
2802 __EXCEPT_PAGE_FAULT
2804 SetLastError(STATUS_ACCESS_VIOLATION);
2805 ret = FALSE;
2807 __ENDTRY
2808 return ret;
2811 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
2812 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2813 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2815 BOOL ret;
2817 __TRY
2819 struct AsnDecodeSequenceItem items[] = {
2820 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
2821 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
2822 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
2823 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
2824 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
2827 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2828 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2829 pcbStructInfo, NULL, NULL);
2831 __EXCEPT_PAGE_FAULT
2833 SetLastError(STATUS_ACCESS_VIOLATION);
2834 ret = FALSE;
2836 __ENDTRY
2837 return ret;
2840 #define RSA1_MAGIC 0x31415352
2842 struct DECODED_RSA_PUB_KEY
2844 DWORD pubexp;
2845 CRYPT_INTEGER_BLOB modulus;
2848 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
2849 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2850 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2852 BOOL ret;
2854 __TRY
2856 struct AsnDecodeSequenceItem items[] = {
2857 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
2858 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2859 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
2860 0 },
2861 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
2862 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
2864 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
2865 DWORD size = 0;
2867 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2868 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
2869 &size, NULL, NULL);
2870 if (ret)
2872 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2873 decodedKey->modulus.cbData;
2875 if (!pvStructInfo)
2877 *pcbStructInfo = bytesNeeded;
2878 ret = TRUE;
2880 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2881 pvStructInfo, pcbStructInfo, bytesNeeded)))
2883 BLOBHEADER *hdr;
2884 RSAPUBKEY *rsaPubKey;
2886 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2887 pvStructInfo = *(BYTE **)pvStructInfo;
2888 hdr = (BLOBHEADER *)pvStructInfo;
2889 hdr->bType = PUBLICKEYBLOB;
2890 hdr->bVersion = CUR_BLOB_VERSION;
2891 hdr->reserved = 0;
2892 hdr->aiKeyAlg = CALG_RSA_KEYX;
2893 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
2894 sizeof(BLOBHEADER));
2895 rsaPubKey->magic = RSA1_MAGIC;
2896 rsaPubKey->pubexp = decodedKey->pubexp;
2897 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
2898 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
2899 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
2900 decodedKey->modulus.cbData);
2902 LocalFree(decodedKey);
2905 __EXCEPT_PAGE_FAULT
2907 SetLastError(STATUS_ACCESS_VIOLATION);
2908 ret = FALSE;
2910 __ENDTRY
2911 return ret;
2914 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
2915 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2916 DWORD *pcbDecoded)
2918 BOOL ret;
2919 DWORD bytesNeeded, dataLen;
2921 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2922 pvStructInfo, *pcbStructInfo, pcbDecoded);
2924 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2926 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2928 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2929 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
2930 else
2931 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
2932 if (pcbDecoded)
2933 *pcbDecoded = 1 + lenBytes + dataLen;
2934 if (!pvStructInfo)
2935 *pcbStructInfo = bytesNeeded;
2936 else if (*pcbStructInfo < bytesNeeded)
2938 SetLastError(ERROR_MORE_DATA);
2939 *pcbStructInfo = bytesNeeded;
2940 ret = FALSE;
2942 else
2944 CRYPT_DATA_BLOB *blob;
2946 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2947 blob->cbData = dataLen;
2948 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2949 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
2950 else
2952 assert(blob->pbData);
2953 if (blob->cbData)
2954 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
2955 blob->cbData);
2959 return ret;
2962 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
2963 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2964 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2966 BOOL ret;
2968 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2969 pDecodePara, pvStructInfo, *pcbStructInfo);
2971 __TRY
2973 DWORD bytesNeeded;
2975 if (!cbEncoded)
2977 SetLastError(CRYPT_E_ASN1_CORRUPT);
2978 ret = FALSE;
2980 else if (pbEncoded[0] != ASN_OCTETSTRING)
2982 SetLastError(CRYPT_E_ASN1_BADTAG);
2983 ret = FALSE;
2985 else if ((ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
2986 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2988 if (!pvStructInfo)
2989 *pcbStructInfo = bytesNeeded;
2990 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2991 pvStructInfo, pcbStructInfo, bytesNeeded)))
2993 CRYPT_DATA_BLOB *blob;
2995 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2996 pvStructInfo = *(BYTE **)pvStructInfo;
2997 blob = (CRYPT_DATA_BLOB *)pvStructInfo;
2998 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
2999 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
3000 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3001 &bytesNeeded, NULL);
3005 __EXCEPT_PAGE_FAULT
3007 SetLastError(STATUS_ACCESS_VIOLATION);
3008 ret = FALSE;
3010 __ENDTRY
3011 return ret;
3014 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3015 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3017 BOOL ret;
3019 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
3020 pvStructInfo, *pcbStructInfo, pcbDecoded);
3022 if (pbEncoded[0] == ASN_BITSTRING)
3024 DWORD bytesNeeded, dataLen;
3025 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3027 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3029 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3030 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
3031 else
3032 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
3033 if (pcbDecoded)
3034 *pcbDecoded = 1 + lenBytes + dataLen;
3035 if (!pvStructInfo)
3036 *pcbStructInfo = bytesNeeded;
3037 else if (*pcbStructInfo < bytesNeeded)
3039 *pcbStructInfo = bytesNeeded;
3040 SetLastError(ERROR_MORE_DATA);
3041 ret = FALSE;
3043 else
3045 CRYPT_BIT_BLOB *blob;
3047 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
3048 blob->cbData = dataLen - 1;
3049 blob->cUnusedBits = *(pbEncoded + 1 + lenBytes);
3050 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3052 blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes;
3054 else
3056 assert(blob->pbData);
3057 if (blob->cbData)
3059 BYTE mask = 0xff << blob->cUnusedBits;
3061 memcpy(blob->pbData, pbEncoded + 2 + lenBytes,
3062 blob->cbData);
3063 blob->pbData[blob->cbData - 1] &= mask;
3069 else
3071 SetLastError(CRYPT_E_ASN1_BADTAG);
3072 ret = FALSE;
3074 TRACE("returning %d (%08x)\n", ret, GetLastError());
3075 return ret;
3078 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
3079 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3080 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3082 BOOL ret;
3084 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
3085 pDecodePara, pvStructInfo, pcbStructInfo);
3087 __TRY
3089 DWORD bytesNeeded;
3091 if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3092 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3094 if (!pvStructInfo)
3095 *pcbStructInfo = bytesNeeded;
3096 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3097 pvStructInfo, pcbStructInfo, bytesNeeded)))
3099 CRYPT_BIT_BLOB *blob;
3101 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3102 pvStructInfo = *(BYTE **)pvStructInfo;
3103 blob = (CRYPT_BIT_BLOB *)pvStructInfo;
3104 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
3105 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3106 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3107 &bytesNeeded, NULL);
3111 __EXCEPT_PAGE_FAULT
3113 SetLastError(STATUS_ACCESS_VIOLATION);
3114 ret = FALSE;
3116 __ENDTRY
3117 TRACE("returning %d (%08x)\n", ret, GetLastError());
3118 return ret;
3121 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3122 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3124 BOOL ret;
3125 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
3126 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
3127 DWORD size = sizeof(buf);
3129 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
3130 if (pbEncoded[0] != ASN_INTEGER)
3132 SetLastError(CRYPT_E_ASN1_BADTAG);
3133 ret = FALSE;
3135 else
3136 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded, 0, &buf,
3137 &size, pcbDecoded);
3138 if (ret)
3140 if (!pvStructInfo)
3141 *pcbStructInfo = sizeof(int);
3142 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int))))
3144 int val, i;
3146 if (blob->pbData[blob->cbData - 1] & 0x80)
3148 /* initialize to a negative value to sign-extend */
3149 val = -1;
3151 else
3152 val = 0;
3153 for (i = 0; i < blob->cbData; i++)
3155 val <<= 8;
3156 val |= blob->pbData[blob->cbData - i - 1];
3158 memcpy(pvStructInfo, &val, sizeof(int));
3161 else if (GetLastError() == ERROR_MORE_DATA)
3162 SetLastError(CRYPT_E_ASN1_LARGE);
3163 return ret;
3166 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
3167 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3168 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3170 BOOL ret;
3172 __TRY
3174 DWORD bytesNeeded;
3176 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3177 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3178 if (ret)
3180 if (!pvStructInfo)
3181 *pcbStructInfo = bytesNeeded;
3182 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3183 pvStructInfo, pcbStructInfo, bytesNeeded)))
3185 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3186 pvStructInfo = *(BYTE **)pvStructInfo;
3187 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3188 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3189 &bytesNeeded, NULL);
3193 __EXCEPT_PAGE_FAULT
3195 SetLastError(STATUS_ACCESS_VIOLATION);
3196 ret = FALSE;
3198 __ENDTRY
3199 return ret;
3202 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
3203 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3204 DWORD *pcbDecoded)
3206 BOOL ret;
3207 DWORD bytesNeeded, dataLen;
3209 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3211 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3213 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3214 if (pcbDecoded)
3215 *pcbDecoded = 1 + lenBytes + dataLen;
3216 if (!pvStructInfo)
3217 *pcbStructInfo = bytesNeeded;
3218 else if (*pcbStructInfo < bytesNeeded)
3220 *pcbStructInfo = bytesNeeded;
3221 SetLastError(ERROR_MORE_DATA);
3222 ret = FALSE;
3224 else
3226 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3228 blob->cbData = dataLen;
3229 assert(blob->pbData);
3230 if (blob->cbData)
3232 DWORD i;
3234 for (i = 0; i < blob->cbData; i++)
3236 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3237 dataLen - i - 1);
3242 return ret;
3245 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
3246 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3247 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3249 BOOL ret;
3251 __TRY
3253 DWORD bytesNeeded;
3255 if (pbEncoded[0] != ASN_INTEGER)
3257 SetLastError(CRYPT_E_ASN1_BADTAG);
3258 ret = FALSE;
3260 else
3261 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3262 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3263 if (ret)
3265 if (!pvStructInfo)
3266 *pcbStructInfo = bytesNeeded;
3267 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3268 pvStructInfo, pcbStructInfo, bytesNeeded)))
3270 CRYPT_INTEGER_BLOB *blob;
3272 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3273 pvStructInfo = *(BYTE **)pvStructInfo;
3274 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3275 blob->pbData = (BYTE *)pvStructInfo +
3276 sizeof(CRYPT_INTEGER_BLOB);
3277 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3278 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
3279 &bytesNeeded, NULL);
3283 __EXCEPT_PAGE_FAULT
3285 SetLastError(STATUS_ACCESS_VIOLATION);
3286 ret = FALSE;
3288 __ENDTRY
3289 return ret;
3292 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
3293 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3294 DWORD *pcbDecoded)
3296 BOOL ret;
3298 if (pbEncoded[0] == ASN_INTEGER)
3300 DWORD bytesNeeded, dataLen;
3302 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3304 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3306 if (pcbDecoded)
3307 *pcbDecoded = 1 + lenBytes + dataLen;
3308 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
3309 if (!pvStructInfo)
3310 *pcbStructInfo = bytesNeeded;
3311 else if (*pcbStructInfo < bytesNeeded)
3313 *pcbStructInfo = bytesNeeded;
3314 SetLastError(ERROR_MORE_DATA);
3315 ret = FALSE;
3317 else
3319 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3321 blob->cbData = dataLen;
3322 assert(blob->pbData);
3323 /* remove leading zero byte if it exists */
3324 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
3326 blob->cbData--;
3327 blob->pbData++;
3329 if (blob->cbData)
3331 DWORD i;
3333 for (i = 0; i < blob->cbData; i++)
3335 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
3336 dataLen - i - 1);
3342 else
3344 SetLastError(CRYPT_E_ASN1_BADTAG);
3345 ret = FALSE;
3347 return ret;
3350 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
3351 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3352 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3354 BOOL ret;
3356 __TRY
3358 DWORD bytesNeeded;
3360 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded,
3361 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3363 if (!pvStructInfo)
3364 *pcbStructInfo = bytesNeeded;
3365 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3366 pvStructInfo, pcbStructInfo, bytesNeeded)))
3368 CRYPT_INTEGER_BLOB *blob;
3370 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3371 pvStructInfo = *(BYTE **)pvStructInfo;
3372 blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
3373 blob->pbData = (BYTE *)pvStructInfo +
3374 sizeof(CRYPT_INTEGER_BLOB);
3375 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded,
3376 cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
3377 &bytesNeeded, NULL);
3381 __EXCEPT_PAGE_FAULT
3383 SetLastError(STATUS_ACCESS_VIOLATION);
3384 ret = FALSE;
3386 __ENDTRY
3387 return ret;
3390 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
3391 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3392 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3394 BOOL ret;
3396 if (!pvStructInfo)
3398 *pcbStructInfo = sizeof(int);
3399 return TRUE;
3401 __TRY
3403 if (pbEncoded[0] == ASN_ENUMERATED)
3405 unsigned int val = 0, i;
3407 if (cbEncoded <= 1)
3409 SetLastError(CRYPT_E_ASN1_EOD);
3410 ret = FALSE;
3412 else if (pbEncoded[1] == 0)
3414 SetLastError(CRYPT_E_ASN1_CORRUPT);
3415 ret = FALSE;
3417 else
3419 /* A little strange looking, but we have to accept a sign byte:
3420 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
3421 * assuming a small length is okay here, it has to be in short
3422 * form.
3424 if (pbEncoded[1] > sizeof(unsigned int) + 1)
3426 SetLastError(CRYPT_E_ASN1_LARGE);
3427 return FALSE;
3429 for (i = 0; i < pbEncoded[1]; i++)
3431 val <<= 8;
3432 val |= pbEncoded[2 + i];
3434 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3435 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
3437 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3438 pvStructInfo = *(BYTE **)pvStructInfo;
3439 memcpy(pvStructInfo, &val, sizeof(unsigned int));
3443 else
3445 SetLastError(CRYPT_E_ASN1_BADTAG);
3446 ret = FALSE;
3449 __EXCEPT_PAGE_FAULT
3451 SetLastError(STATUS_ACCESS_VIOLATION);
3452 ret = FALSE;
3454 __ENDTRY
3455 return ret;
3458 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
3459 * if it fails.
3461 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
3462 do { \
3463 BYTE i; \
3465 (word) = 0; \
3466 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
3468 if (!isdigit(*(pbEncoded))) \
3470 SetLastError(CRYPT_E_ASN1_CORRUPT); \
3471 ret = FALSE; \
3473 else \
3475 (word) *= 10; \
3476 (word) += *(pbEncoded)++ - '0'; \
3479 } while (0)
3481 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
3482 SYSTEMTIME *sysTime)
3484 BOOL ret = TRUE;
3486 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
3488 WORD hours, minutes = 0;
3489 BYTE sign = *pbEncoded++;
3491 len--;
3492 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
3493 if (ret && hours >= 24)
3495 SetLastError(CRYPT_E_ASN1_CORRUPT);
3496 ret = FALSE;
3498 else if (len >= 2)
3500 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
3501 if (ret && minutes >= 60)
3503 SetLastError(CRYPT_E_ASN1_CORRUPT);
3504 ret = FALSE;
3507 if (ret)
3509 if (sign == '+')
3511 sysTime->wHour += hours;
3512 sysTime->wMinute += minutes;
3514 else
3516 if (hours > sysTime->wHour)
3518 sysTime->wDay--;
3519 sysTime->wHour = 24 - (hours - sysTime->wHour);
3521 else
3522 sysTime->wHour -= hours;
3523 if (minutes > sysTime->wMinute)
3525 sysTime->wHour--;
3526 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
3528 else
3529 sysTime->wMinute -= minutes;
3533 return ret;
3536 #define MIN_ENCODED_TIME_LENGTH 10
3538 static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
3539 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3540 DWORD *pcbDecoded)
3542 BOOL ret = FALSE;
3544 if (pbEncoded[0] == ASN_UTCTIME)
3546 if (cbEncoded <= 1)
3547 SetLastError(CRYPT_E_ASN1_EOD);
3548 else if (pbEncoded[1] > 0x7f)
3550 /* long-form date strings really can't be valid */
3551 SetLastError(CRYPT_E_ASN1_CORRUPT);
3553 else
3555 SYSTEMTIME sysTime = { 0 };
3556 BYTE len = pbEncoded[1];
3558 if (len < MIN_ENCODED_TIME_LENGTH)
3559 SetLastError(CRYPT_E_ASN1_CORRUPT);
3560 else
3562 ret = TRUE;
3563 if (pcbDecoded)
3564 *pcbDecoded = 2 + len;
3565 pbEncoded += 2;
3566 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
3567 if (sysTime.wYear >= 50)
3568 sysTime.wYear += 1900;
3569 else
3570 sysTime.wYear += 2000;
3571 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3572 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3573 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3574 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
3575 if (ret && len > 0)
3577 if (len >= 2 && isdigit(*pbEncoded) &&
3578 isdigit(*(pbEncoded + 1)))
3579 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3580 sysTime.wSecond);
3581 else if (isdigit(*pbEncoded))
3582 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
3583 sysTime.wSecond);
3584 if (ret)
3585 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3586 &sysTime);
3588 if (ret)
3590 if (!pvStructInfo)
3591 *pcbStructInfo = sizeof(FILETIME);
3592 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
3593 sizeof(FILETIME))))
3594 ret = SystemTimeToFileTime(&sysTime,
3595 (FILETIME *)pvStructInfo);
3600 else
3601 SetLastError(CRYPT_E_ASN1_BADTAG);
3602 return ret;
3605 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
3606 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3607 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3609 BOOL ret = FALSE;
3611 __TRY
3613 DWORD bytesNeeded;
3615 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
3616 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3617 if (ret)
3619 if (!pvStructInfo)
3620 *pcbStructInfo = bytesNeeded;
3621 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
3622 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
3624 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3625 pvStructInfo = *(BYTE **)pvStructInfo;
3626 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
3627 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3628 &bytesNeeded, NULL);
3632 __EXCEPT_PAGE_FAULT
3634 SetLastError(STATUS_ACCESS_VIOLATION);
3636 __ENDTRY
3637 return ret;
3640 static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
3641 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3642 DWORD *pcbDecoded)
3644 BOOL ret = FALSE;
3646 if (pbEncoded[0] == ASN_GENERALTIME)
3648 if (cbEncoded <= 1)
3649 SetLastError(CRYPT_E_ASN1_EOD);
3650 else if (pbEncoded[1] > 0x7f)
3652 /* long-form date strings really can't be valid */
3653 SetLastError(CRYPT_E_ASN1_CORRUPT);
3655 else
3657 BYTE len = pbEncoded[1];
3659 if (len < MIN_ENCODED_TIME_LENGTH)
3660 SetLastError(CRYPT_E_ASN1_CORRUPT);
3661 else
3663 SYSTEMTIME sysTime = { 0 };
3665 ret = TRUE;
3666 if (pcbDecoded)
3667 *pcbDecoded = 2 + len;
3668 pbEncoded += 2;
3669 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
3670 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
3671 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
3672 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
3673 if (ret && len > 0)
3675 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3676 sysTime.wMinute);
3677 if (ret && len > 0)
3678 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
3679 sysTime.wSecond);
3680 if (ret && len > 0 && (*pbEncoded == '.' ||
3681 *pbEncoded == ','))
3683 BYTE digits;
3685 pbEncoded++;
3686 len--;
3687 /* workaround macro weirdness */
3688 digits = min(len, 3);
3689 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
3690 sysTime.wMilliseconds);
3692 if (ret)
3693 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
3694 &sysTime);
3696 if (ret)
3698 if (!pvStructInfo)
3699 *pcbStructInfo = sizeof(FILETIME);
3700 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
3701 sizeof(FILETIME))))
3702 ret = SystemTimeToFileTime(&sysTime,
3703 (FILETIME *)pvStructInfo);
3708 else
3709 SetLastError(CRYPT_E_ASN1_BADTAG);
3710 return ret;
3713 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
3714 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3715 DWORD *pcbDecoded)
3717 BOOL ret;
3718 InternalDecodeFunc decode = NULL;
3720 if (pbEncoded[0] == ASN_UTCTIME)
3721 decode = CRYPT_AsnDecodeUtcTimeInternal;
3722 else if (pbEncoded[0] == ASN_GENERALTIME)
3723 decode = CRYPT_AsnDecodeGeneralizedTime;
3724 if (decode)
3725 ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
3726 pcbStructInfo, pcbDecoded);
3727 else
3729 SetLastError(CRYPT_E_ASN1_BADTAG);
3730 ret = FALSE;
3732 return ret;
3735 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
3736 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3737 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3739 BOOL ret;
3741 __TRY
3743 DWORD bytesNeeded;
3745 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
3746 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3747 if (ret)
3749 if (!pvStructInfo)
3750 *pcbStructInfo = bytesNeeded;
3751 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3752 pvStructInfo, pcbStructInfo, bytesNeeded)))
3754 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3755 pvStructInfo = *(BYTE **)pvStructInfo;
3756 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
3757 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3758 &bytesNeeded, NULL);
3762 __EXCEPT_PAGE_FAULT
3764 SetLastError(STATUS_ACCESS_VIOLATION);
3765 ret = FALSE;
3767 __ENDTRY
3768 return ret;
3771 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
3772 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3773 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3775 BOOL ret = TRUE;
3777 __TRY
3779 if (pbEncoded[0] == ASN_SEQUENCEOF)
3781 DWORD bytesNeeded, dataLen, remainingLen, cValue;
3783 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3785 BYTE lenBytes;
3786 const BYTE *ptr;
3788 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3789 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
3790 cValue = 0;
3791 ptr = pbEncoded + 1 + lenBytes;
3792 remainingLen = dataLen;
3793 while (ret && remainingLen)
3795 DWORD nextLen;
3797 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3798 if (ret)
3800 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3802 remainingLen -= 1 + nextLenBytes + nextLen;
3803 ptr += 1 + nextLenBytes + nextLen;
3804 bytesNeeded += sizeof(CRYPT_DER_BLOB);
3805 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
3806 bytesNeeded += 1 + nextLenBytes + nextLen;
3807 cValue++;
3810 if (ret)
3812 CRYPT_SEQUENCE_OF_ANY *seq;
3813 BYTE *nextPtr;
3814 DWORD i;
3816 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3817 pvStructInfo, pcbStructInfo, bytesNeeded)))
3819 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3820 pvStructInfo = *(BYTE **)pvStructInfo;
3821 seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
3822 seq->cValue = cValue;
3823 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
3824 sizeof(*seq));
3825 nextPtr = (BYTE *)seq->rgValue +
3826 cValue * sizeof(CRYPT_DER_BLOB);
3827 ptr = pbEncoded + 1 + lenBytes;
3828 remainingLen = dataLen;
3829 i = 0;
3830 while (ret && remainingLen)
3832 DWORD nextLen;
3834 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
3835 if (ret)
3837 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
3839 seq->rgValue[i].cbData = 1 + nextLenBytes +
3840 nextLen;
3841 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3842 seq->rgValue[i].pbData = (BYTE *)ptr;
3843 else
3845 seq->rgValue[i].pbData = nextPtr;
3846 memcpy(nextPtr, ptr, 1 + nextLenBytes +
3847 nextLen);
3848 nextPtr += 1 + nextLenBytes + nextLen;
3850 remainingLen -= 1 + nextLenBytes + nextLen;
3851 ptr += 1 + nextLenBytes + nextLen;
3852 i++;
3859 else
3861 SetLastError(CRYPT_E_ASN1_BADTAG);
3862 ret = FALSE;
3865 __EXCEPT_PAGE_FAULT
3867 SetLastError(STATUS_ACCESS_VIOLATION);
3868 ret = FALSE;
3870 __ENDTRY
3871 return ret;
3874 static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded,
3875 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3876 DWORD *pcbDecoded)
3878 BOOL ret;
3880 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
3882 DWORD bytesNeeded, dataLen;
3884 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3886 struct AsnArrayDescriptor arrayDesc = {
3887 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
3888 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3889 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3890 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3892 if (dataLen)
3894 DWORD nameLen;
3896 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3897 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3898 0, NULL, NULL, &nameLen, NULL, NULL);
3899 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen;
3901 else
3902 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
3903 if (pcbDecoded)
3904 *pcbDecoded = 1 + lenBytes + dataLen;
3905 if (!pvStructInfo)
3906 *pcbStructInfo = bytesNeeded;
3907 else if (*pcbStructInfo < bytesNeeded)
3909 *pcbStructInfo = bytesNeeded;
3910 SetLastError(ERROR_MORE_DATA);
3911 ret = FALSE;
3913 else
3915 CRL_DIST_POINT_NAME *name = (CRL_DIST_POINT_NAME *)pvStructInfo;
3917 if (dataLen)
3919 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3920 ret = CRYPT_AsnDecodeArray(&arrayDesc,
3921 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
3922 0, NULL, &name->u.FullName, pcbStructInfo, NULL,
3923 name->u.FullName.rgAltEntry);
3925 else
3926 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3930 else
3932 SetLastError(CRYPT_E_ASN1_BADTAG);
3933 ret = FALSE;
3935 return ret;
3938 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
3939 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3941 struct AsnDecodeSequenceItem items[] = {
3942 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
3943 DistPointName), CRYPT_AsnDecodeDistPointName,
3944 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
3945 DistPointName.u.FullName.rgAltEntry), 0 },
3946 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
3947 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
3948 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
3949 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
3950 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
3951 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
3953 BOOL ret;
3955 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3956 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3957 pcbDecoded, NULL);
3958 return ret;
3961 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
3962 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3963 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3965 BOOL ret;
3967 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3968 pDecodePara, pvStructInfo, *pcbStructInfo);
3970 __TRY
3972 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3973 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
3974 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
3976 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3977 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
3979 __EXCEPT_PAGE_FAULT
3981 SetLastError(STATUS_ACCESS_VIOLATION);
3982 ret = FALSE;
3984 __ENDTRY
3985 return ret;
3988 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
3989 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3990 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3992 BOOL ret;
3994 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3995 pDecodePara, pvStructInfo, *pcbStructInfo);
3997 __TRY
3999 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
4000 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
4002 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4003 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
4005 __EXCEPT_PAGE_FAULT
4007 SetLastError(STATUS_ACCESS_VIOLATION);
4008 ret = FALSE;
4010 __ENDTRY
4011 return ret;
4014 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
4015 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4016 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4018 BOOL ret;
4020 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4021 pDecodePara, pvStructInfo, *pcbStructInfo);
4023 __TRY
4025 struct AsnDecodeSequenceItem items[] = {
4026 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
4027 DistPointName), CRYPT_AsnDecodeDistPointName,
4028 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
4029 offsetof(CRL_ISSUING_DIST_POINT,
4030 DistPointName.u.FullName.rgAltEntry), 0 },
4031 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
4032 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4033 FALSE, 0 },
4034 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
4035 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4036 FALSE, 0 },
4037 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
4038 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
4039 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
4040 OnlySomeReasonFlags.pbData), 0 },
4041 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
4042 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
4045 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4046 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
4047 pcbStructInfo, NULL, NULL);
4049 __EXCEPT_PAGE_FAULT
4051 SetLastError(STATUS_ACCESS_VIOLATION);
4052 ret = FALSE;
4054 __ENDTRY
4055 return ret;
4058 static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded,
4059 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4060 DWORD *pcbDecoded)
4062 BOOL ret;
4063 struct AsnDecodeSequenceItem items[] = {
4064 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
4065 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
4066 Issuer.pbData) },
4067 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
4068 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
4069 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
4071 CERT_ISSUER_SERIAL_NUMBER *issuerSerial =
4072 (CERT_ISSUER_SERIAL_NUMBER *)pvStructInfo;
4074 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4075 pvStructInfo, *pcbStructInfo, pcbDecoded);
4077 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4078 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4079 pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL);
4080 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
4082 SetLastError(CRYPT_E_ASN1_CORRUPT);
4083 ret = FALSE;
4085 TRACE("returning %d\n", ret);
4086 return ret;
4089 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
4090 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4091 DWORD *pcbDecoded)
4093 CMSG_SIGNER_INFO *info = (CMSG_SIGNER_INFO *)pvStructInfo;
4094 struct AsnDecodeSequenceItem items[] = {
4095 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
4096 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4097 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
4098 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
4099 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
4100 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
4101 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4102 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
4103 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4104 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
4105 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4106 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
4107 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
4108 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
4109 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
4110 HashEncryptionAlgorithm.pszObjId), 0 },
4111 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
4112 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
4113 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
4114 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4115 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
4116 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
4117 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
4119 BOOL ret;
4121 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4122 pvStructInfo, *pcbStructInfo);
4124 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4125 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4126 pcbDecoded, info ? info->Issuer.pbData : NULL);
4127 return ret;
4130 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
4131 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4132 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4134 BOOL ret = FALSE;
4136 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4137 pDecodePara, pvStructInfo, *pcbStructInfo);
4139 __TRY
4141 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
4142 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
4143 if (ret && pvStructInfo)
4145 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
4146 pcbStructInfo, *pcbStructInfo);
4147 if (ret)
4149 CMSG_SIGNER_INFO *info;
4151 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4152 pvStructInfo = *(BYTE **)pvStructInfo;
4153 info = (CMSG_SIGNER_INFO *)pvStructInfo;
4154 info->Issuer.pbData = ((BYTE *)info +
4155 sizeof(CMSG_SIGNER_INFO));
4156 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
4157 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4158 pcbStructInfo, NULL);
4162 __EXCEPT_PAGE_FAULT
4164 SetLastError(STATUS_ACCESS_VIOLATION);
4166 __ENDTRY
4167 TRACE("returning %d\n", ret);
4168 return ret;
4171 static BOOL CRYPT_DecodeSignerArray(const BYTE *pbEncoded, DWORD cbEncoded,
4172 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4174 BOOL ret;
4175 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
4176 CRYPT_AsnDecodePKCSSignerInfoInternal, sizeof(CMSG_SIGNER_INFO), TRUE,
4177 offsetof(CMSG_SIGNER_INFO, Issuer.pbData) };
4178 struct GenericArray *array = (struct GenericArray *)pvStructInfo;
4180 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4181 pvStructInfo, *pcbStructInfo, pcbDecoded);
4183 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
4184 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
4185 array ? array->rgItems : NULL);
4186 return ret;
4189 BOOL CRYPT_AsnDecodePKCSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
4190 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
4191 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
4193 BOOL ret = FALSE;
4194 struct AsnDecodeSequenceItem items[] = {
4195 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version),
4196 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4197 /* Placeholder for the hash algorithms - redundant with those in the
4198 * signers, so just ignore them.
4200 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
4201 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
4202 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
4203 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
4204 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
4205 offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
4206 CRYPT_DecodeDERArray, sizeof(struct GenericArray), TRUE, TRUE,
4207 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
4208 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
4209 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_DecodeDERArray,
4210 sizeof(struct GenericArray), TRUE, TRUE,
4211 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
4212 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
4213 CRYPT_DecodeSignerArray, sizeof(struct GenericArray), TRUE, TRUE,
4214 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
4217 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4218 pDecodePara, signedInfo, *pcbSignedInfo);
4220 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4221 pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo,
4222 NULL, NULL);
4223 TRACE("returning %d\n", ret);
4224 return ret;
4227 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
4228 LPCSTR lpszStructType)
4230 CryptDecodeObjectExFunc decodeFunc = NULL;
4232 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
4233 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
4235 SetLastError(ERROR_FILE_NOT_FOUND);
4236 return NULL;
4238 if (!HIWORD(lpszStructType))
4240 switch (LOWORD(lpszStructType))
4242 case (WORD)X509_CERT:
4243 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
4244 break;
4245 case (WORD)X509_CERT_TO_BE_SIGNED:
4246 decodeFunc = CRYPT_AsnDecodeCert;
4247 break;
4248 case (WORD)X509_CERT_CRL_TO_BE_SIGNED:
4249 decodeFunc = CRYPT_AsnDecodeCRL;
4250 break;
4251 case (WORD)X509_EXTENSIONS:
4252 decodeFunc = CRYPT_AsnDecodeExtensions;
4253 break;
4254 case (WORD)X509_NAME_VALUE:
4255 decodeFunc = CRYPT_AsnDecodeNameValue;
4256 break;
4257 case (WORD)X509_NAME:
4258 decodeFunc = CRYPT_AsnDecodeName;
4259 break;
4260 case (WORD)X509_PUBLIC_KEY_INFO:
4261 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
4262 break;
4263 case (WORD)X509_AUTHORITY_KEY_ID:
4264 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4265 break;
4266 case (WORD)X509_ALTERNATE_NAME:
4267 decodeFunc = CRYPT_AsnDecodeAltName;
4268 break;
4269 case (WORD)X509_BASIC_CONSTRAINTS:
4270 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4271 break;
4272 case (WORD)X509_BASIC_CONSTRAINTS2:
4273 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4274 break;
4275 case (WORD)RSA_CSP_PUBLICKEYBLOB:
4276 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
4277 break;
4278 case (WORD)X509_UNICODE_NAME:
4279 decodeFunc = CRYPT_AsnDecodeUnicodeName;
4280 break;
4281 case (WORD)PKCS_ATTRIBUTE:
4282 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
4283 break;
4284 case (WORD)X509_UNICODE_NAME_VALUE:
4285 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
4286 break;
4287 case (WORD)X509_OCTET_STRING:
4288 decodeFunc = CRYPT_AsnDecodeOctets;
4289 break;
4290 case (WORD)X509_BITS:
4291 case (WORD)X509_KEY_USAGE:
4292 decodeFunc = CRYPT_AsnDecodeBits;
4293 break;
4294 case (WORD)X509_INTEGER:
4295 decodeFunc = CRYPT_AsnDecodeInt;
4296 break;
4297 case (WORD)X509_MULTI_BYTE_INTEGER:
4298 decodeFunc = CRYPT_AsnDecodeInteger;
4299 break;
4300 case (WORD)X509_MULTI_BYTE_UINT:
4301 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
4302 break;
4303 case (WORD)X509_ENUMERATED:
4304 decodeFunc = CRYPT_AsnDecodeEnumerated;
4305 break;
4306 case (WORD)X509_CHOICE_OF_TIME:
4307 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
4308 break;
4309 case (WORD)X509_AUTHORITY_KEY_ID2:
4310 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4311 break;
4312 case (WORD)PKCS_CONTENT_INFO:
4313 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
4314 break;
4315 case (WORD)X509_SEQUENCE_OF_ANY:
4316 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
4317 break;
4318 case (WORD)PKCS_UTC_TIME:
4319 decodeFunc = CRYPT_AsnDecodeUtcTime;
4320 break;
4321 case (WORD)X509_CRL_DIST_POINTS:
4322 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4323 break;
4324 case (WORD)X509_ENHANCED_KEY_USAGE:
4325 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4326 break;
4327 case (WORD)PKCS_ATTRIBUTES:
4328 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
4329 break;
4330 case (WORD)X509_ISSUING_DIST_POINT:
4331 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4332 break;
4333 case (WORD)PKCS7_SIGNER_INFO:
4334 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
4335 break;
4338 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
4339 decodeFunc = CRYPT_AsnDecodeExtensions;
4340 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
4341 decodeFunc = CRYPT_AsnDecodeUtcTime;
4342 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
4343 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
4344 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
4345 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
4346 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
4347 decodeFunc = CRYPT_AsnDecodeEnumerated;
4348 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
4349 decodeFunc = CRYPT_AsnDecodeBits;
4350 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
4351 decodeFunc = CRYPT_AsnDecodeOctets;
4352 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
4353 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
4354 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
4355 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
4356 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
4357 decodeFunc = CRYPT_AsnDecodeAltName;
4358 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
4359 decodeFunc = CRYPT_AsnDecodeAltName;
4360 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
4361 decodeFunc = CRYPT_AsnDecodeAltName;
4362 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
4363 decodeFunc = CRYPT_AsnDecodeAltName;
4364 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
4365 decodeFunc = CRYPT_AsnDecodeAltName;
4366 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
4367 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
4368 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
4369 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
4370 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
4371 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
4372 return decodeFunc;
4375 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
4376 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4378 static HCRYPTOIDFUNCSET set = NULL;
4379 CryptDecodeObjectFunc decodeFunc = NULL;
4381 if (!set)
4382 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
4383 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4384 (void **)&decodeFunc, hFunc);
4385 return decodeFunc;
4388 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
4389 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
4391 static HCRYPTOIDFUNCSET set = NULL;
4392 CryptDecodeObjectExFunc decodeFunc = NULL;
4394 if (!set)
4395 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
4396 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
4397 (void **)&decodeFunc, hFunc);
4398 return decodeFunc;
4401 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4402 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
4403 DWORD *pcbStructInfo)
4405 BOOL ret = FALSE;
4406 CryptDecodeObjectFunc pCryptDecodeObject = NULL;
4407 CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
4408 HCRYPTOIDFUNCADDR hFunc = NULL;
4410 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
4411 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
4412 pvStructInfo, pcbStructInfo);
4414 if (!pvStructInfo && !pcbStructInfo)
4416 SetLastError(ERROR_INVALID_PARAMETER);
4417 return FALSE;
4419 if (!cbEncoded)
4421 SetLastError(CRYPT_E_ASN1_EOD);
4422 return FALSE;
4424 if (cbEncoded > MAX_ENCODED_LEN)
4426 SetLastError(CRYPT_E_ASN1_LARGE);
4427 return FALSE;
4430 if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
4431 lpszStructType)))
4433 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4434 debugstr_a(lpszStructType));
4435 pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
4436 lpszStructType, &hFunc);
4437 if (!pCryptDecodeObject)
4438 pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
4439 lpszStructType, &hFunc);
4441 if (pCryptDecodeObject)
4442 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4443 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4444 else if (pCryptDecodeObjectEx)
4445 ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
4446 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
4447 pvStructInfo, pcbStructInfo);
4448 if (hFunc)
4449 CryptFreeOIDFunctionAddress(hFunc, 0);
4450 TRACE_(crypt)("returning %d\n", ret);
4451 return ret;
4454 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
4455 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4456 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4458 BOOL ret = FALSE;
4459 CryptDecodeObjectExFunc decodeFunc;
4460 HCRYPTOIDFUNCADDR hFunc = NULL;
4462 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
4463 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
4464 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4466 if (!pvStructInfo && !pcbStructInfo)
4468 SetLastError(ERROR_INVALID_PARAMETER);
4469 return FALSE;
4471 if (!cbEncoded)
4473 SetLastError(CRYPT_E_ASN1_EOD);
4474 return FALSE;
4476 if (cbEncoded > MAX_ENCODED_LEN)
4478 SetLastError(CRYPT_E_ASN1_LARGE);
4479 return FALSE;
4482 SetLastError(NOERROR);
4483 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
4484 *(BYTE **)pvStructInfo = NULL;
4485 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
4486 if (!decodeFunc)
4488 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
4489 debugstr_a(lpszStructType));
4490 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
4491 &hFunc);
4493 if (decodeFunc)
4494 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
4495 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
4496 else
4498 CryptDecodeObjectFunc pCryptDecodeObject =
4499 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
4501 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
4502 * directly, as that could cause an infinite loop.
4504 if (pCryptDecodeObject)
4506 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4508 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4509 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
4510 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4511 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
4512 ret = pCryptDecodeObject(dwCertEncodingType,
4513 lpszStructType, pbEncoded, cbEncoded, dwFlags,
4514 *(BYTE **)pvStructInfo, pcbStructInfo);
4516 else
4517 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
4518 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
4521 if (hFunc)
4522 CryptFreeOIDFunctionAddress(hFunc, 0);
4523 TRACE_(crypt)("returning %d\n", ret);
4524 return ret;