crypt32: Explicitly pass array pointer when decoding CTL extensions rather than assum...
[wine/hacks.git] / dlls / crypt32 / decode.c
blob5aec82d113d2bf9b70026780274bf1bd73df6988
1 /*
2 * Copyright 2005-2008 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 * This file implements ASN.1 DER decoding of a limited set of types.
19 * It isn't a full ASN.1 implementation. Microsoft implements BER
20 * encoding of many of the basic types in msasn1.dll, but that interface isn't
21 * implemented, so I implement them here.
23 * References:
24 * "A Layman's Guide to a Subset of ASN.1, BER, and DER", by Burton Kaliski
25 * (available online, look for a PDF copy as the HTML versions tend to have
26 * translation errors.)
28 * RFC3280, http://www.faqs.org/rfcs/rfc3280.html
30 * MSDN, especially "Constants for CryptEncodeObject and CryptDecodeObject"
33 #include "config.h"
34 #include "wine/port.h"
36 #include <assert.h>
37 #include <stdarg.h>
38 #include <stdio.h>
39 #include <stdlib.h>
41 #define NONAMELESSUNION
43 #include "windef.h"
44 #include "winbase.h"
45 #include "wincrypt.h"
46 #include "winnls.h"
47 #include "snmp.h"
48 #include "wine/debug.h"
49 #include "wine/exception.h"
50 #include "crypt32_private.h"
52 /* This is a bit arbitrary, but to set some limit: */
53 #define MAX_ENCODED_LEN 0x02000000
55 #define ASN_FLAGS_MASK 0xe0
56 #define ASN_TYPE_MASK 0x1f
58 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
59 WINE_DECLARE_DEBUG_CHANNEL(crypt);
61 struct GenericArray
63 DWORD cItems;
64 BYTE *rgItems;
67 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
68 DWORD, DWORD, void *, DWORD *);
69 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
70 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
72 /* Internal decoders don't do memory allocation or exception handling, and
73 * they report how many bytes they decoded.
75 typedef BOOL (*InternalDecodeFunc)(const BYTE *pbEncoded, DWORD cbEncoded,
76 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
78 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
79 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
80 DWORD *pcbDecoded);
81 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
82 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
83 DWORD *pcbDecoded);
84 /* Assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set ahead of time.
86 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
87 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
88 /* Assumes algo->Parameters.pbData is set ahead of time. */
89 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
90 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
91 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
92 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
93 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
94 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
95 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
96 DWORD *pcbDecoded);
97 /* Doesn't check the tag, assumes the caller does so */
98 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
99 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
100 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
101 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
102 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
103 * member has been initialized, doesn't do exception handling, and doesn't do
104 * memory allocation. Also doesn't check tag, assumes the caller has checked
105 * it.
107 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
108 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
109 DWORD *pcbDecoded);
110 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
111 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
112 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
113 DWORD *pcbDecoded);
114 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
115 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
116 DWORD *pcbDecoded);
118 /* Gets the number of length bytes from the given (leading) length byte */
119 #define GET_LEN_BYTES(b) ((b) <= 0x80 ? 1 : 1 + ((b) & 0x7f))
121 /* Helper function to get the encoded length of the data starting at pbEncoded,
122 * where pbEncoded[0] is the tag. If the data are too short to contain a
123 * length or if the length is too large for cbEncoded, sets an appropriate
124 * error code and returns FALSE. If the encoded length is unknown due to
125 * indefinite length encoding, *len is set to CMSG_INDEFINITE_LENGTH.
127 static BOOL CRYPT_GetLengthIndefinite(const BYTE *pbEncoded, DWORD cbEncoded,
128 DWORD *len)
130 BOOL ret;
132 if (cbEncoded <= 1)
134 SetLastError(CRYPT_E_ASN1_CORRUPT);
135 ret = FALSE;
137 else if (pbEncoded[1] <= 0x7f)
139 if (pbEncoded[1] + 1 > cbEncoded)
141 SetLastError(CRYPT_E_ASN1_EOD);
142 ret = FALSE;
144 else
146 *len = pbEncoded[1];
147 ret = TRUE;
150 else if (pbEncoded[1] == 0x80)
152 *len = CMSG_INDEFINITE_LENGTH;
153 ret = TRUE;
155 else
157 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
159 if (lenLen > sizeof(DWORD) + 1)
161 SetLastError(CRYPT_E_ASN1_LARGE);
162 ret = FALSE;
164 else if (lenLen + 2 > cbEncoded)
166 SetLastError(CRYPT_E_ASN1_CORRUPT);
167 ret = FALSE;
169 else
171 DWORD out = 0;
173 pbEncoded += 2;
174 while (--lenLen)
176 out <<= 8;
177 out |= *pbEncoded++;
179 if (out + lenLen + 1 > cbEncoded)
181 SetLastError(CRYPT_E_ASN1_EOD);
182 ret = FALSE;
184 else
186 *len = out;
187 ret = TRUE;
191 return ret;
194 /* Like CRYPT_GetLengthIndefinite, but disallows indefinite-length encoding. */
195 static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
197 BOOL ret;
199 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, len)) &&
200 *len == CMSG_INDEFINITE_LENGTH)
202 SetLastError(CRYPT_E_ASN1_CORRUPT);
203 ret = FALSE;
205 return ret;
208 /* Helper function to check *pcbStructInfo, set it to the required size, and
209 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
210 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
211 * pointer to the newly allocated memory.
213 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
214 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
215 DWORD bytesNeeded)
217 BOOL ret = TRUE;
219 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
221 if (pDecodePara && pDecodePara->pfnAlloc)
222 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
223 else
224 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
225 if (!*(BYTE **)pvStructInfo)
226 ret = FALSE;
227 else
228 *pcbStructInfo = bytesNeeded;
230 else if (*pcbStructInfo < bytesNeeded)
232 *pcbStructInfo = bytesNeeded;
233 SetLastError(ERROR_MORE_DATA);
234 ret = FALSE;
236 else
237 *pcbStructInfo = bytesNeeded;
238 return ret;
241 static void CRYPT_FreeSpace(PCRYPT_DECODE_PARA pDecodePara, LPVOID pv)
243 if (pDecodePara && pDecodePara->pfnFree)
244 pDecodePara->pfnFree(pv);
245 else
246 LocalFree(pv);
249 /* Helper function to check *pcbStructInfo and set it to the required size.
250 * Assumes pvStructInfo is not NULL.
252 static BOOL CRYPT_DecodeCheckSpace(DWORD *pcbStructInfo, DWORD bytesNeeded)
254 BOOL ret;
256 if (*pcbStructInfo < bytesNeeded)
258 *pcbStructInfo = bytesNeeded;
259 SetLastError(ERROR_MORE_DATA);
260 ret = FALSE;
262 else
264 *pcbStructInfo = bytesNeeded;
265 ret = TRUE;
267 return ret;
270 /* tag:
271 * The expected tag of the item. If tag is 0, decodeFunc is called
272 * regardless of the tag value seen.
273 * offset:
274 * A sequence is decoded into a struct. The offset member is the
275 * offset of this item within that struct.
276 * decodeFunc:
277 * The decoder function to use. If this is NULL, then the member isn't
278 * decoded, but minSize space is reserved for it.
279 * minSize:
280 * The minimum amount of space occupied after decoding. You must set this.
281 * optional:
282 * If true, and the tag doesn't match the expected tag for this item,
283 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
284 * filled with 0 for this member.
285 * hasPointer, pointerOffset:
286 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
287 * the offset within the struct of the data pointer (or to the
288 * first data pointer, if more than one exist).
289 * size:
290 * Used by CRYPT_AsnDecodeSequence, not for your use.
292 struct AsnDecodeSequenceItem
294 BYTE tag;
295 DWORD offset;
296 InternalDecodeFunc decodeFunc;
297 DWORD minSize;
298 BOOL optional;
299 BOOL hasPointer;
300 DWORD pointerOffset;
301 DWORD size;
304 #define FINALMEMBERSIZE(s, member) (sizeof(s) - offsetof(s, member))
305 #define MEMBERSIZE(s, member, nextmember) \
306 (offsetof(s, nextmember) - offsetof(s, member))
308 /* Decodes the items in a sequence, where the items are described in items,
309 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
310 * pvStructInfo. nextData is a pointer to the memory location at which the
311 * first decoded item with a dynamic pointer should point.
312 * Upon decoding, *cbDecoded is the total number of bytes decoded.
313 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
315 static BOOL CRYPT_AsnDecodeSequenceItems(struct AsnDecodeSequenceItem items[],
316 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
317 void *pvStructInfo, BYTE *nextData, DWORD *cbDecoded)
319 BOOL ret;
320 DWORD i, decoded = 0;
321 const BYTE *ptr = pbEncoded;
323 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
324 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
326 for (i = 0, ret = TRUE; ret && i < cItem; i++)
328 if (cbEncoded - (ptr - pbEncoded) != 0)
330 DWORD itemLen;
332 if ((ret = CRYPT_GetLengthIndefinite(ptr,
333 cbEncoded - (ptr - pbEncoded), &itemLen)))
335 BYTE itemLenBytes = GET_LEN_BYTES(ptr[1]);
337 if (ptr[0] == items[i].tag || !items[i].tag)
339 DWORD itemEncodedLen;
341 if (itemLen == CMSG_INDEFINITE_LENGTH)
342 itemEncodedLen = cbEncoded - (ptr - pbEncoded);
343 else
344 itemEncodedLen = 1 + itemLenBytes + itemLen;
345 if (nextData && pvStructInfo && items[i].hasPointer)
347 TRACE("Setting next pointer to %p\n",
348 nextData);
349 *(BYTE **)((BYTE *)pvStructInfo +
350 items[i].pointerOffset) = nextData;
352 if (items[i].decodeFunc)
354 DWORD itemDecoded;
356 if (pvStructInfo)
357 TRACE("decoding item %d\n", i);
358 else
359 TRACE("sizing item %d\n", i);
360 ret = items[i].decodeFunc(ptr, itemEncodedLen,
361 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
362 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
363 : NULL, &items[i].size, &itemDecoded);
364 if (ret)
366 /* Account for alignment padding */
367 items[i].size = ALIGN_DWORD_PTR(items[i].size);
368 TRACE("item %d size: %d\n", i, items[i].size);
369 if (nextData && items[i].hasPointer &&
370 items[i].size > items[i].minSize)
371 nextData += items[i].size - items[i].minSize;
372 if (itemDecoded > itemEncodedLen)
374 WARN("decoded length %d exceeds encoded %d\n",
375 itemDecoded, itemEncodedLen);
376 SetLastError(CRYPT_E_ASN1_CORRUPT);
377 ret = FALSE;
379 else
381 ptr += itemDecoded;
382 decoded += itemDecoded;
383 TRACE("item %d: decoded %d bytes\n", i,
384 itemDecoded);
387 else if (items[i].optional &&
388 GetLastError() == CRYPT_E_ASN1_BADTAG)
390 TRACE("skipping optional item %d\n", i);
391 items[i].size = items[i].minSize;
392 SetLastError(NOERROR);
393 ret = TRUE;
395 else
396 TRACE("item %d failed: %08x\n", i,
397 GetLastError());
399 else if (itemLen == CMSG_INDEFINITE_LENGTH)
401 ERR("can't use indefinite length encoding without a decoder\n");
402 SetLastError(CRYPT_E_ASN1_CORRUPT);
403 ret = FALSE;
405 else
407 TRACE("item %d: decoded %d bytes\n", i, itemEncodedLen);
408 ptr += itemEncodedLen;
409 decoded += itemEncodedLen;
410 items[i].size = items[i].minSize;
413 else if (items[i].optional)
415 TRACE("skipping optional item %d\n", i);
416 items[i].size = items[i].minSize;
418 else
420 TRACE("item %d: tag %02x doesn't match expected %02x\n",
421 i, ptr[0], items[i].tag);
422 SetLastError(CRYPT_E_ASN1_BADTAG);
423 ret = FALSE;
427 else if (items[i].optional)
429 TRACE("missing optional item %d, skipping\n", i);
430 items[i].size = items[i].minSize;
432 else
434 TRACE("not enough bytes for item %d, failing\n", i);
435 SetLastError(CRYPT_E_ASN1_CORRUPT);
436 ret = FALSE;
439 if (cbDecoded)
440 *cbDecoded = decoded;
441 TRACE("returning %d\n", ret);
442 return ret;
445 /* This decodes an arbitrary sequence into a contiguous block of memory
446 * (basically, a struct.) Each element being decoded is described by a struct
447 * AsnDecodeSequenceItem, see above.
448 * startingPointer is an optional pointer to the first place where dynamic
449 * data will be stored. If you know the starting offset, you may pass it
450 * here. Otherwise, pass NULL, and one will be inferred from the items.
452 static BOOL CRYPT_AsnDecodeSequence(struct AsnDecodeSequenceItem items[],
453 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
454 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
455 DWORD *pcbDecoded, void *startingPointer)
457 BOOL ret;
459 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
460 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
461 startingPointer);
463 if (!cbEncoded)
465 SetLastError(CRYPT_E_ASN1_EOD);
466 return FALSE;
468 if (pbEncoded[0] == ASN_SEQUENCE)
470 DWORD dataLen;
472 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
474 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
475 const BYTE *ptr = pbEncoded + 1 + lenBytes;
476 BOOL indefinite = FALSE;
478 cbEncoded -= 1 + lenBytes;
479 if (dataLen == CMSG_INDEFINITE_LENGTH)
481 dataLen = cbEncoded;
482 indefinite = TRUE;
484 else if (cbEncoded < dataLen)
486 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
487 cbEncoded);
488 SetLastError(CRYPT_E_ASN1_CORRUPT);
489 ret = FALSE;
491 if (ret)
493 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
494 ptr, dataLen, dwFlags, NULL, NULL, &cbDecoded);
495 if (ret && dataLen == CMSG_INDEFINITE_LENGTH)
497 if (cbDecoded > cbEncoded - 2)
499 /* Not enough space for 0 TLV */
500 SetLastError(CRYPT_E_ASN1_CORRUPT);
501 ret = FALSE;
503 else if (*(ptr + cbDecoded) != 0 ||
504 *(ptr + cbDecoded + 1) != 0)
506 TRACE("expected 0 TLV\n");
507 SetLastError(CRYPT_E_ASN1_CORRUPT);
508 ret = FALSE;
510 else
511 cbDecoded += 2;
514 if (ret && !indefinite && cbDecoded != dataLen)
516 TRACE("expected %d decoded, got %d, failing\n", dataLen,
517 cbDecoded);
518 SetLastError(CRYPT_E_ASN1_CORRUPT);
519 ret = FALSE;
521 if (ret)
523 DWORD i, bytesNeeded = 0, structSize = 0;
525 for (i = 0; i < cItem; i++)
527 bytesNeeded += items[i].size;
528 structSize = max( structSize, items[i].offset + items[i].minSize );
530 if (pcbDecoded)
531 *pcbDecoded = 1 + lenBytes + cbDecoded;
532 if (!pvStructInfo)
533 *pcbStructInfo = bytesNeeded;
534 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
535 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
537 BYTE *nextData;
539 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
540 pvStructInfo = *(BYTE **)pvStructInfo;
541 if (startingPointer)
542 nextData = startingPointer;
543 else
544 nextData = (BYTE *)pvStructInfo + structSize;
545 memset(pvStructInfo, 0, structSize);
546 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
547 ptr, dataLen, dwFlags, pvStructInfo, nextData,
548 &cbDecoded);
549 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
550 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
555 else
557 SetLastError(CRYPT_E_ASN1_BADTAG);
558 ret = FALSE;
560 TRACE("returning %d (%08x)\n", ret, GetLastError());
561 return ret;
564 /* tag:
565 * The expected tag of the entire encoded array (usually a variant
566 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
567 * regardless of the tag seen.
568 * decodeFunc:
569 * used to decode each item in the array
570 * itemSize:
571 * is the minimum size of each decoded item
572 * hasPointer:
573 * indicates whether each item has a dynamic pointer
574 * pointerOffset:
575 * indicates the offset within itemSize at which the pointer exists
577 struct AsnArrayDescriptor
579 BYTE tag;
580 InternalDecodeFunc decodeFunc;
581 DWORD itemSize;
582 BOOL hasPointer;
583 DWORD pointerOffset;
586 struct AsnArrayItemSize
588 DWORD encodedLen;
589 DWORD size;
592 /* Decodes an array of like types into a struct GenericArray.
593 * The layout and decoding of the array are described by a struct
594 * AsnArrayDescriptor.
596 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
597 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
598 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
599 DWORD *pcbDecoded, void *startingPointer)
601 BOOL ret = TRUE;
603 TRACE("%p, %p, %d, %08x, %p, %p, %d, %p\n", arrayDesc, pbEncoded,
604 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
605 startingPointer);
607 if (!cbEncoded)
609 SetLastError(CRYPT_E_ASN1_EOD);
610 ret = FALSE;
612 else if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
614 DWORD dataLen;
616 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
618 DWORD bytesNeeded, cItems = 0, decoded;
619 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
620 /* There can be arbitrarily many items, but there is often only one.
622 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
624 decoded = 1 + lenBytes;
625 bytesNeeded = sizeof(struct GenericArray);
626 if (dataLen)
628 const BYTE *ptr;
629 BOOL doneDecoding = FALSE;
631 for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
633 if (dataLen == CMSG_INDEFINITE_LENGTH)
635 if (ptr[0] == 0)
637 doneDecoding = TRUE;
638 if (ptr[1] != 0)
640 SetLastError(CRYPT_E_ASN1_CORRUPT);
641 ret = FALSE;
643 else
644 decoded += 2;
647 else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
648 doneDecoding = TRUE;
649 if (!doneDecoding)
651 DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
653 /* Each item decoded may not tolerate extraneous bytes,
654 * so get the length of the next element if known.
656 if ((ret = CRYPT_GetLengthIndefinite(ptr,
657 cbEncoded - (ptr - pbEncoded), &itemDataLen)))
659 if (itemDataLen == CMSG_INDEFINITE_LENGTH)
660 itemEncoded = cbEncoded - (ptr - pbEncoded);
661 else
662 itemEncoded = 1 + GET_LEN_BYTES(ptr[1]) +
663 itemDataLen;
665 if (ret)
666 ret = arrayDesc->decodeFunc(ptr, itemEncoded,
667 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size,
668 &itemDecoded);
669 if (ret)
671 cItems++;
672 if (itemSizes != &itemSize)
673 itemSizes = CryptMemRealloc(itemSizes,
674 cItems * sizeof(struct AsnArrayItemSize));
675 else if (cItems > 1)
677 itemSizes =
678 CryptMemAlloc(
679 cItems * sizeof(struct AsnArrayItemSize));
680 if (itemSizes)
681 memcpy(itemSizes, &itemSize,
682 sizeof(itemSize));
684 if (itemSizes)
686 decoded += itemDecoded;
687 itemSizes[cItems - 1].encodedLen = itemEncoded;
688 itemSizes[cItems - 1].size = size;
689 bytesNeeded += size;
690 ptr += itemEncoded;
692 else
693 ret = FALSE;
698 if (ret)
700 if (pcbDecoded)
701 *pcbDecoded = decoded;
702 if (!pvStructInfo)
703 *pcbStructInfo = bytesNeeded;
704 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
705 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
707 DWORD i;
708 BYTE *nextData;
709 const BYTE *ptr;
710 struct GenericArray *array;
712 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
713 pvStructInfo = *(BYTE **)pvStructInfo;
714 array = pvStructInfo;
715 array->cItems = cItems;
716 if (startingPointer)
717 array->rgItems = startingPointer;
718 else
719 array->rgItems = (BYTE *)array +
720 sizeof(struct GenericArray);
721 nextData = array->rgItems +
722 array->cItems * arrayDesc->itemSize;
723 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
724 i < cItems && ptr - pbEncoded - 1 - lenBytes <
725 dataLen; i++)
727 DWORD itemDecoded;
729 if (arrayDesc->hasPointer)
730 *(BYTE **)(array->rgItems + i * arrayDesc->itemSize
731 + arrayDesc->pointerOffset) = nextData;
732 ret = arrayDesc->decodeFunc(ptr,
733 itemSizes[i].encodedLen,
734 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
735 array->rgItems + i * arrayDesc->itemSize,
736 &itemSizes[i].size, &itemDecoded);
737 if (ret)
739 nextData += itemSizes[i].size - arrayDesc->itemSize;
740 ptr += itemDecoded;
743 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
744 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
747 if (itemSizes != &itemSize)
748 CryptMemFree(itemSizes);
751 else
753 SetLastError(CRYPT_E_ASN1_BADTAG);
754 ret = FALSE;
756 return ret;
759 /* Decodes an array of like types into a struct GenericArray.
760 * The layout and decoding of the array are described by a struct
761 * AsnArrayDescriptor. Doesn't allocate memory for the decoded items,
762 * leaves that up to the caller.
764 static BOOL CRYPT_AsnDecodeArrayNoAlloc(const struct AsnArrayDescriptor *arrayDesc,
765 const BYTE *pbEncoded, DWORD cbEncoded, DWORD *pcItems, void *rgItems,
766 DWORD *pcbItems, DWORD *pcbDecoded)
768 BOOL ret = TRUE;
770 TRACE("%p, %p, %d, %p, %p, %d\n", arrayDesc, pbEncoded,
771 cbEncoded, pcItems, rgItems, pcItems ? *pcbItems : 0);
773 if (!cbEncoded)
775 SetLastError(CRYPT_E_ASN1_EOD);
776 ret = FALSE;
778 else if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
780 DWORD dataLen;
782 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
784 DWORD bytesNeeded = 0, cItems = 0, decoded;
785 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
786 /* There can be arbitrarily many items, but there is often only one.
788 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
790 decoded = 1 + lenBytes;
791 if (dataLen)
793 const BYTE *ptr;
794 BOOL doneDecoding = FALSE;
796 for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
798 if (dataLen == CMSG_INDEFINITE_LENGTH)
800 if (ptr[0] == 0)
802 doneDecoding = TRUE;
803 if (ptr[1] != 0)
805 SetLastError(CRYPT_E_ASN1_CORRUPT);
806 ret = FALSE;
808 else
809 decoded += 2;
812 else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
813 doneDecoding = TRUE;
814 if (!doneDecoding)
816 DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
818 /* Each item decoded may not tolerate extraneous bytes,
819 * so get the length of the next element if known.
821 if ((ret = CRYPT_GetLengthIndefinite(ptr,
822 cbEncoded - (ptr - pbEncoded), &itemDataLen)))
824 if (itemDataLen == CMSG_INDEFINITE_LENGTH)
825 itemEncoded = cbEncoded - (ptr - pbEncoded);
826 else
827 itemEncoded = 1 + GET_LEN_BYTES(ptr[1]) +
828 itemDataLen;
830 if (ret)
831 ret = arrayDesc->decodeFunc(ptr, itemEncoded,
832 0, NULL, &size, &itemDecoded);
833 if (ret)
835 cItems++;
836 if (itemSizes != &itemSize)
837 itemSizes = CryptMemRealloc(itemSizes,
838 cItems * sizeof(struct AsnArrayItemSize));
839 else if (cItems > 1)
841 itemSizes =
842 CryptMemAlloc(
843 cItems * sizeof(struct AsnArrayItemSize));
844 if (itemSizes)
845 memcpy(itemSizes, &itemSize,
846 sizeof(itemSize));
848 if (itemSizes)
850 decoded += itemDecoded;
851 itemSizes[cItems - 1].encodedLen = itemEncoded;
852 itemSizes[cItems - 1].size = size;
853 bytesNeeded += size;
854 ptr += itemEncoded;
856 else
857 ret = FALSE;
862 if (ret)
864 if (pcbDecoded)
865 *pcbDecoded = decoded;
866 if (!pcItems)
867 *pcbItems = bytesNeeded;
868 else if ((ret = CRYPT_DecodeEnsureSpace(0, NULL, rgItems,
869 pcbItems, bytesNeeded)))
871 DWORD i;
872 BYTE *nextData;
873 const BYTE *ptr;
875 *pcItems = cItems;
876 nextData = (BYTE *)rgItems + cItems * arrayDesc->itemSize;
877 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
878 i < cItems && ptr - pbEncoded - 1 - lenBytes <
879 dataLen; i++)
881 DWORD itemDecoded;
883 if (arrayDesc->hasPointer)
884 *(BYTE **)((BYTE *)rgItems + i * arrayDesc->itemSize
885 + arrayDesc->pointerOffset) = nextData;
886 ret = arrayDesc->decodeFunc(ptr,
887 itemSizes[i].encodedLen, 0,
888 (BYTE *)rgItems + i * arrayDesc->itemSize,
889 &itemSizes[i].size, &itemDecoded);
890 if (ret)
892 nextData += itemSizes[i].size - arrayDesc->itemSize;
893 ptr += itemDecoded;
898 if (itemSizes != &itemSize)
899 CryptMemFree(itemSizes);
902 else
904 SetLastError(CRYPT_E_ASN1_BADTAG);
905 ret = FALSE;
907 return ret;
910 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
911 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
912 * to CRYPT_E_ASN1_CORRUPT.
913 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
914 * set!
916 static BOOL CRYPT_AsnDecodeDerBlob(const BYTE *pbEncoded, DWORD cbEncoded,
917 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
919 BOOL ret;
920 DWORD dataLen;
922 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
924 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
925 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
927 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
928 bytesNeeded += 1 + lenBytes + dataLen;
930 if (pcbDecoded)
931 *pcbDecoded = 1 + lenBytes + dataLen;
932 if (!pvStructInfo)
933 *pcbStructInfo = bytesNeeded;
934 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded)))
936 CRYPT_DER_BLOB *blob;
938 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
939 pvStructInfo = *(BYTE **)pvStructInfo;
940 blob = pvStructInfo;
941 blob->cbData = 1 + lenBytes + dataLen;
942 if (blob->cbData)
944 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
945 blob->pbData = (BYTE *)pbEncoded;
946 else
948 assert(blob->pbData);
949 memcpy(blob->pbData, pbEncoded, blob->cbData);
952 else
954 SetLastError(CRYPT_E_ASN1_CORRUPT);
955 ret = FALSE;
959 return ret;
962 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
963 static BOOL CRYPT_AsnDecodeBitsSwapBytes(const BYTE *pbEncoded,
964 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
965 DWORD *pcbDecoded)
967 BOOL ret;
969 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
970 pvStructInfo, *pcbStructInfo, pcbDecoded);
972 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
973 * place.
975 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
976 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
977 pcbDecoded);
978 if (ret && pvStructInfo)
980 CRYPT_BIT_BLOB *blob = pvStructInfo;
982 if (blob->cbData)
984 DWORD i;
985 BYTE temp;
987 for (i = 0; i < blob->cbData / 2; i++)
989 temp = blob->pbData[i];
990 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
991 blob->pbData[blob->cbData - i - 1] = temp;
995 TRACE("returning %d (%08x)\n", ret, GetLastError());
996 return ret;
999 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
1000 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1001 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1003 BOOL ret = TRUE;
1005 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1006 pDecodePara, pvStructInfo, *pcbStructInfo);
1008 __TRY
1010 struct AsnDecodeSequenceItem items[] = {
1011 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
1012 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
1013 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
1014 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
1015 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
1016 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
1017 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
1018 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
1019 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
1020 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
1023 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
1024 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
1025 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1026 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
1027 pcbStructInfo, NULL, NULL);
1029 __EXCEPT_PAGE_FAULT
1031 SetLastError(STATUS_ACCESS_VIOLATION);
1032 ret = FALSE;
1034 __ENDTRY
1036 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1037 return ret;
1040 static BOOL CRYPT_AsnDecodeCertVersion(const BYTE *pbEncoded, DWORD cbEncoded,
1041 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1043 BOOL ret;
1044 DWORD dataLen;
1046 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1048 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1050 ret = CRYPT_AsnDecodeIntInternal(pbEncoded + 1 + lenBytes, dataLen,
1051 dwFlags, pvStructInfo, pcbStructInfo, NULL);
1052 if (pcbDecoded)
1053 *pcbDecoded = 1 + lenBytes + dataLen;
1055 return ret;
1058 static BOOL CRYPT_AsnDecodeValidity(const BYTE *pbEncoded, DWORD cbEncoded,
1059 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1061 BOOL ret;
1063 struct AsnDecodeSequenceItem items[] = {
1064 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
1065 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
1066 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
1067 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
1070 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1071 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
1072 pcbDecoded, NULL);
1073 return ret;
1076 static BOOL CRYPT_AsnDecodeCertExtensionsInternal(const BYTE *pbEncoded,
1077 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1078 DWORD *pcbDecoded)
1080 BOOL ret = TRUE;
1081 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1082 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1083 offsetof(CERT_EXTENSION, pszObjId) };
1084 DWORD itemSize;
1086 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1087 pvStructInfo, *pcbStructInfo, pcbDecoded);
1089 ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
1090 NULL, NULL, &itemSize, pcbDecoded);
1091 if (ret)
1093 DWORD bytesNeeded;
1095 /* The size expected by the caller includes the combination of
1096 * CERT_INFO's cExtension and rgExtension, in addition to the size of
1097 * all the decoded items. CRYPT_AsnDecodeArrayNoAlloc only returns
1098 * the size of the decoded items, so add the size of cExtension and
1099 * rgExtension.
1101 bytesNeeded = FINALMEMBERSIZE(CERT_INFO, cExtension) + itemSize;
1102 if (!pvStructInfo)
1103 *pcbStructInfo = bytesNeeded;
1104 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, NULL, pvStructInfo,
1105 pcbStructInfo, bytesNeeded)))
1107 CERT_INFO *info;
1109 info = (CERT_INFO *)((BYTE *)pvStructInfo -
1110 offsetof(CERT_INFO, cExtension));
1111 ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded,
1112 cbEncoded, &info->cExtension, info->rgExtension, &itemSize,
1113 pcbDecoded);
1116 return ret;
1119 static BOOL CRYPT_AsnDecodeCertExtensions(const BYTE *pbEncoded,
1120 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1121 DWORD *pcbDecoded)
1123 BOOL ret;
1124 DWORD dataLen;
1126 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1128 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1130 ret = CRYPT_AsnDecodeCertExtensionsInternal(pbEncoded + 1 + lenBytes,
1131 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
1132 if (ret && pcbDecoded)
1133 *pcbDecoded = 1 + lenBytes + dataLen;
1135 return ret;
1138 static BOOL CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
1139 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1140 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1142 BOOL ret = TRUE;
1143 struct AsnDecodeSequenceItem items[] = {
1144 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
1145 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1146 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
1147 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
1148 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
1149 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
1150 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1151 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
1152 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1153 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
1154 Issuer.pbData) },
1155 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
1156 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
1157 FALSE, 0 },
1158 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
1159 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
1160 Subject.pbData) },
1161 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
1162 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
1163 FALSE, TRUE, offsetof(CERT_INFO,
1164 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
1165 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
1166 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
1167 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
1168 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
1169 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
1170 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
1171 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
1172 CRYPT_AsnDecodeCertExtensions, FINALMEMBERSIZE(CERT_INFO, cExtension),
1173 TRUE, TRUE, offsetof(CERT_INFO, rgExtension), 0 },
1176 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1177 pDecodePara, pvStructInfo, *pcbStructInfo);
1179 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1180 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
1181 NULL, NULL);
1182 if (ret && pvStructInfo)
1184 CERT_INFO *info;
1186 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1187 info = *(CERT_INFO **)pvStructInfo;
1188 else
1189 info = pvStructInfo;
1190 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
1191 !info->Subject.cbData)
1193 SetLastError(CRYPT_E_ASN1_CORRUPT);
1194 /* Don't need to deallocate, because it should have failed on the
1195 * first pass (and no memory was allocated.)
1197 ret = FALSE;
1201 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1202 return ret;
1205 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
1206 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1207 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1209 BOOL ret = FALSE;
1211 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1212 pDecodePara, pvStructInfo, *pcbStructInfo);
1214 __TRY
1216 DWORD size = 0;
1218 /* Unless told not to, first try to decode it as a signed cert. */
1219 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1221 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
1223 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1224 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1225 &signedCert, &size);
1226 if (ret)
1228 size = 0;
1229 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1230 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
1231 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
1232 pvStructInfo, pcbStructInfo);
1233 LocalFree(signedCert);
1236 /* Failing that, try it as an unsigned cert */
1237 if (!ret)
1239 size = 0;
1240 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1241 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
1242 pDecodePara, pvStructInfo, pcbStructInfo);
1245 __EXCEPT_PAGE_FAULT
1247 SetLastError(STATUS_ACCESS_VIOLATION);
1249 __ENDTRY
1251 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1252 return ret;
1255 static BOOL CRYPT_AsnDecodeCRLEntryExtensions(const BYTE *pbEncoded,
1256 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1257 DWORD *pcbDecoded)
1259 BOOL ret = TRUE;
1260 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1261 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1262 offsetof(CERT_EXTENSION, pszObjId) };
1263 DWORD itemSize;
1265 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1266 pvStructInfo, *pcbStructInfo, pcbDecoded);
1268 ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
1269 NULL, NULL, &itemSize, pcbDecoded);
1270 if (ret)
1272 DWORD bytesNeeded;
1274 /* The size expected by the caller includes the combination of
1275 * CRL_ENTRY's cExtension and rgExtension, in addition to the size of
1276 * all the decoded items. CRYPT_AsnDecodeArrayNoAlloc only returns
1277 * the size of the decoded items, so add the size of cExtension and
1278 * rgExtension.
1280 bytesNeeded = FINALMEMBERSIZE(CRL_ENTRY, cExtension) + itemSize;
1281 if (!pvStructInfo)
1282 *pcbStructInfo = bytesNeeded;
1283 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, NULL, pvStructInfo,
1284 pcbStructInfo, bytesNeeded)))
1286 CRL_ENTRY *entry;
1288 entry = (CRL_ENTRY *)((BYTE *)pvStructInfo -
1289 offsetof(CRL_ENTRY, cExtension));
1290 ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded,
1291 cbEncoded, &entry->cExtension, entry->rgExtension, &itemSize,
1292 pcbDecoded);
1295 return ret;
1298 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
1299 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1301 BOOL ret;
1302 struct AsnDecodeSequenceItem items[] = {
1303 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
1304 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
1305 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
1306 { 0, offsetof(CRL_ENTRY, RevocationDate),
1307 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
1308 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
1309 CRYPT_AsnDecodeCRLEntryExtensions,
1310 FINALMEMBERSIZE(CRL_ENTRY, cExtension), TRUE, TRUE,
1311 offsetof(CRL_ENTRY, rgExtension), 0 },
1313 PCRL_ENTRY entry = pvStructInfo;
1315 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
1316 *pcbStructInfo);
1318 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1319 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, pcbDecoded,
1320 entry ? entry->SerialNumber.pbData : NULL);
1321 if (ret && entry && !entry->SerialNumber.cbData)
1323 WARN("empty CRL entry serial number\n");
1324 SetLastError(CRYPT_E_ASN1_CORRUPT);
1325 ret = FALSE;
1327 return ret;
1330 /* Warning: assumes pvStructInfo points to the cCRLEntry member of a CRL_INFO
1331 * whose rgCRLEntry member has been set prior to calling.
1333 static BOOL CRYPT_AsnDecodeCRLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
1334 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1336 BOOL ret;
1337 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1338 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
1339 offsetof(CRL_ENTRY, SerialNumber.pbData) };
1340 DWORD itemSize;
1342 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1343 pvStructInfo, *pcbStructInfo, pcbDecoded);
1345 ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
1346 NULL, NULL, &itemSize, pcbDecoded);
1347 if (ret)
1349 DWORD bytesNeeded;
1351 /* The size expected by the caller includes the combination of
1352 * CRL_INFO's cCRLEntry and rgCRLEntry, in addition to the size of
1353 * all the decoded items. CRYPT_AsnDecodeArrayNoAlloc only returns
1354 * the size of the decoded items, so add the size of cCRLEntry and
1355 * rgCRLEntry.
1357 bytesNeeded = offsetof(CRL_INFO, cExtension) -
1358 offsetof(CRL_INFO, cCRLEntry) + itemSize;
1359 if (!pvStructInfo)
1360 *pcbStructInfo = bytesNeeded;
1361 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, NULL, pvStructInfo,
1362 pcbStructInfo, bytesNeeded)))
1364 CRL_INFO *info;
1366 info = (CRL_INFO *)((BYTE *)pvStructInfo -
1367 offsetof(CRL_INFO, cCRLEntry));
1368 ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded,
1369 cbEncoded, &info->cCRLEntry, info->rgCRLEntry, &itemSize,
1370 pcbDecoded);
1373 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1374 return ret;
1377 static BOOL CRYPT_AsnDecodeCRLExtensionsInternal(const BYTE *pbEncoded,
1378 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1379 DWORD *pcbDecoded)
1381 BOOL ret = TRUE;
1382 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1383 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1384 offsetof(CERT_EXTENSION, pszObjId) };
1385 DWORD itemSize;
1387 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1388 pvStructInfo, *pcbStructInfo, pcbDecoded);
1390 ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
1391 NULL, NULL, &itemSize, pcbDecoded);
1392 if (ret)
1394 DWORD bytesNeeded;
1396 /* The size expected by the caller includes the combination of
1397 * CRL_INFO's cExtension and rgExtension, in addition to the size of
1398 * all the decoded items. CRYPT_AsnDecodeArrayNoAlloc only returns
1399 * the size of the decoded items, so add the size of cExtension and
1400 * rgExtension.
1402 bytesNeeded = FINALMEMBERSIZE(CRL_INFO, cExtension) + itemSize;
1403 if (!pvStructInfo)
1404 *pcbStructInfo = bytesNeeded;
1405 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, NULL, pvStructInfo,
1406 pcbStructInfo, bytesNeeded)))
1408 CRL_INFO *info;
1410 info = (CRL_INFO *)((BYTE *)pvStructInfo -
1411 offsetof(CRL_INFO, cExtension));
1412 ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded,
1413 cbEncoded, &info->cExtension, info->rgExtension, &itemSize,
1414 pcbDecoded);
1417 return ret;
1420 static BOOL CRYPT_AsnDecodeCRLExtensions(const BYTE *pbEncoded,
1421 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1422 DWORD *pcbDecoded)
1424 BOOL ret;
1425 DWORD dataLen;
1427 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1429 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1431 ret = CRYPT_AsnDecodeCRLExtensionsInternal(pbEncoded + 1 + lenBytes,
1432 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
1433 if (ret && pcbDecoded)
1434 *pcbDecoded = 1 + lenBytes + dataLen;
1436 return ret;
1439 static BOOL CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1440 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1441 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1443 struct AsnDecodeSequenceItem items[] = {
1444 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1445 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1446 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1447 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1448 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1449 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1450 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1451 Issuer.pbData) },
1452 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1453 sizeof(FILETIME), FALSE, FALSE, 0 },
1454 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1455 sizeof(FILETIME), TRUE, FALSE, 0 },
1456 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1457 CRYPT_AsnDecodeCRLEntries, MEMBERSIZE(CRL_INFO, cCRLEntry, cExtension),
1458 TRUE, TRUE, offsetof(CRL_INFO, rgCRLEntry), 0 },
1459 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1460 CRYPT_AsnDecodeCRLExtensions, FINALMEMBERSIZE(CRL_INFO, cExtension),
1461 TRUE, TRUE, offsetof(CRL_INFO, rgExtension), 0 },
1463 BOOL ret = TRUE;
1465 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1466 pDecodePara, pvStructInfo, *pcbStructInfo);
1468 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1469 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
1470 NULL, NULL);
1472 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1473 return ret;
1476 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1477 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1478 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1480 BOOL ret = FALSE;
1482 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1483 pDecodePara, pvStructInfo, *pcbStructInfo);
1485 __TRY
1487 DWORD size = 0;
1489 /* Unless told not to, first try to decode it as a signed crl. */
1490 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1492 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1494 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1495 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1496 &signedCrl, &size);
1497 if (ret)
1499 size = 0;
1500 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1501 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1502 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1503 pvStructInfo, pcbStructInfo);
1504 LocalFree(signedCrl);
1507 /* Failing that, try it as an unsigned crl */
1508 if (!ret)
1510 size = 0;
1511 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1512 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1513 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1516 __EXCEPT_PAGE_FAULT
1518 SetLastError(STATUS_ACCESS_VIOLATION);
1520 __ENDTRY
1522 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1523 return ret;
1526 static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded,
1527 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1529 BOOL ret = TRUE;
1530 DWORD dataLen;
1532 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1533 pvStructInfo, *pcbStructInfo);
1535 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1537 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1538 DWORD bytesNeeded = sizeof(LPSTR);
1540 if (dataLen)
1542 /* The largest possible string for the first two components
1543 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1545 char firstTwo[6];
1546 const BYTE *ptr;
1548 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1549 pbEncoded[1 + lenBytes] / 40,
1550 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1551 * 40);
1552 bytesNeeded += strlen(firstTwo) + 1;
1553 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1554 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1556 /* large enough for ".4000000" */
1557 char str[9];
1558 int val = 0;
1560 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1561 (*ptr & 0x80))
1563 val <<= 7;
1564 val |= *ptr & 0x7f;
1565 ptr++;
1567 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1568 (*ptr & 0x80))
1570 SetLastError(CRYPT_E_ASN1_CORRUPT);
1571 ret = FALSE;
1573 else
1575 val <<= 7;
1576 val |= *ptr++;
1577 snprintf(str, sizeof(str), ".%d", val);
1578 bytesNeeded += strlen(str);
1582 if (pcbDecoded)
1583 *pcbDecoded = 1 + lenBytes + dataLen;
1584 if (!pvStructInfo)
1585 *pcbStructInfo = bytesNeeded;
1586 else if (*pcbStructInfo < bytesNeeded)
1588 *pcbStructInfo = bytesNeeded;
1589 SetLastError(ERROR_MORE_DATA);
1590 ret = FALSE;
1592 else
1594 if (dataLen)
1596 const BYTE *ptr;
1597 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1599 *pszObjId = 0;
1600 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1601 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1602 40) * 40);
1603 pszObjId += strlen(pszObjId);
1604 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1605 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1607 int val = 0;
1609 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1610 (*ptr & 0x80))
1612 val <<= 7;
1613 val |= *ptr & 0x7f;
1614 ptr++;
1616 val <<= 7;
1617 val |= *ptr++;
1618 sprintf(pszObjId, ".%d", val);
1619 pszObjId += strlen(pszObjId);
1622 else
1623 *(LPSTR *)pvStructInfo = NULL;
1624 *pcbStructInfo = bytesNeeded;
1627 return ret;
1630 static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded,
1631 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1633 BOOL ret;
1635 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1636 pvStructInfo, *pcbStructInfo);
1638 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1639 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1640 pvStructInfo, pcbStructInfo, pcbDecoded);
1641 else
1643 SetLastError(CRYPT_E_ASN1_BADTAG);
1644 ret = FALSE;
1646 return ret;
1649 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
1650 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1652 struct AsnDecodeSequenceItem items[] = {
1653 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1654 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1655 offsetof(CERT_EXTENSION, pszObjId), 0 },
1656 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1657 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1658 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1659 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1660 offsetof(CERT_EXTENSION, Value.pbData) },
1662 BOOL ret = TRUE;
1663 PCERT_EXTENSION ext = pvStructInfo;
1665 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1666 *pcbStructInfo);
1668 if (ext)
1669 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1670 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1671 pbEncoded, cbEncoded, dwFlags, NULL, ext, pcbStructInfo,
1672 pcbDecoded, ext ? ext->pszObjId : NULL);
1673 if (ext)
1674 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1675 debugstr_a(ext->pszObjId));
1676 TRACE("returning %d (%08x)\n", ret, GetLastError());
1677 return ret;
1680 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1681 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1682 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1684 BOOL ret = TRUE;
1686 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1687 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
1689 __TRY
1691 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1692 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1693 offsetof(CERT_EXTENSION, pszObjId) };
1694 DWORD itemSize;
1696 ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
1697 NULL, NULL, &itemSize, NULL);
1698 if (ret)
1700 DWORD bytesNeeded;
1702 /* CRYPT_AsnDecodeArrayNoAlloc only returns the size of the decoded
1703 * items, so add the size of CERT_EXTENSIONS.
1705 bytesNeeded = sizeof(CERT_EXTENSIONS) + itemSize;
1706 if (!pvStructInfo)
1707 *pcbStructInfo = bytesNeeded;
1708 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1709 pvStructInfo, pcbStructInfo, bytesNeeded)))
1711 CERT_EXTENSIONS *exts;
1713 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1714 pvStructInfo = *(BYTE **)pvStructInfo;
1715 exts = (CERT_EXTENSIONS *)pvStructInfo;
1716 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
1717 sizeof(CERT_EXTENSIONS));
1718 ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded,
1719 cbEncoded, &exts->cExtension, exts->rgExtension, &itemSize,
1720 NULL);
1724 __EXCEPT_PAGE_FAULT
1726 SetLastError(STATUS_ACCESS_VIOLATION);
1727 ret = FALSE;
1729 __ENDTRY
1730 return ret;
1733 /* Warning: this assumes the address of value->Value.pbData is already set, in
1734 * order to avoid overwriting memory. (In some cases, it may change it, if it
1735 * doesn't copy anything to memory.) Be sure to set it correctly!
1737 static BOOL CRYPT_AsnDecodeNameValueInternal(const BYTE *pbEncoded,
1738 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1739 DWORD *pcbDecoded)
1741 BOOL ret = TRUE;
1742 DWORD dataLen;
1743 CERT_NAME_VALUE *value = pvStructInfo;
1745 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1747 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1748 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1750 switch (pbEncoded[0])
1752 case ASN_OCTETSTRING:
1753 valueType = CERT_RDN_OCTET_STRING;
1754 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1755 bytesNeeded += dataLen;
1756 break;
1757 case ASN_NUMERICSTRING:
1758 valueType = CERT_RDN_NUMERIC_STRING;
1759 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1760 bytesNeeded += dataLen;
1761 break;
1762 case ASN_PRINTABLESTRING:
1763 valueType = CERT_RDN_PRINTABLE_STRING;
1764 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1765 bytesNeeded += dataLen;
1766 break;
1767 case ASN_IA5STRING:
1768 valueType = CERT_RDN_IA5_STRING;
1769 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1770 bytesNeeded += dataLen;
1771 break;
1772 case ASN_T61STRING:
1773 valueType = CERT_RDN_T61_STRING;
1774 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1775 bytesNeeded += dataLen;
1776 break;
1777 case ASN_VIDEOTEXSTRING:
1778 valueType = CERT_RDN_VIDEOTEX_STRING;
1779 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1780 bytesNeeded += dataLen;
1781 break;
1782 case ASN_GRAPHICSTRING:
1783 valueType = CERT_RDN_GRAPHIC_STRING;
1784 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1785 bytesNeeded += dataLen;
1786 break;
1787 case ASN_VISIBLESTRING:
1788 valueType = CERT_RDN_VISIBLE_STRING;
1789 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1790 bytesNeeded += dataLen;
1791 break;
1792 case ASN_GENERALSTRING:
1793 valueType = CERT_RDN_GENERAL_STRING;
1794 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1795 bytesNeeded += dataLen;
1796 break;
1797 case ASN_UNIVERSALSTRING:
1798 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1799 SetLastError(CRYPT_E_ASN1_BADTAG);
1800 return FALSE;
1801 case ASN_BMPSTRING:
1802 valueType = CERT_RDN_BMP_STRING;
1803 bytesNeeded += dataLen;
1804 break;
1805 case ASN_UTF8STRING:
1806 valueType = CERT_RDN_UTF8_STRING;
1807 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1808 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1809 break;
1810 default:
1811 SetLastError(CRYPT_E_ASN1_BADTAG);
1812 return FALSE;
1815 if (pcbDecoded)
1816 *pcbDecoded = 1 + lenBytes + dataLen;
1817 if (!value)
1818 *pcbStructInfo = bytesNeeded;
1819 else if (*pcbStructInfo < bytesNeeded)
1821 *pcbStructInfo = bytesNeeded;
1822 SetLastError(ERROR_MORE_DATA);
1823 ret = FALSE;
1825 else
1827 *pcbStructInfo = bytesNeeded;
1828 value->dwValueType = valueType;
1829 if (dataLen)
1831 DWORD i;
1833 assert(value->Value.pbData);
1834 switch (pbEncoded[0])
1836 case ASN_OCTETSTRING:
1837 case ASN_NUMERICSTRING:
1838 case ASN_PRINTABLESTRING:
1839 case ASN_IA5STRING:
1840 case ASN_T61STRING:
1841 case ASN_VIDEOTEXSTRING:
1842 case ASN_GRAPHICSTRING:
1843 case ASN_VISIBLESTRING:
1844 case ASN_GENERALSTRING:
1845 value->Value.cbData = dataLen;
1846 if (dataLen)
1848 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1849 memcpy(value->Value.pbData,
1850 pbEncoded + 1 + lenBytes, dataLen);
1851 else
1852 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1853 lenBytes;
1855 break;
1856 case ASN_BMPSTRING:
1858 LPWSTR str = (LPWSTR)value->Value.pbData;
1860 value->Value.cbData = dataLen;
1861 for (i = 0; i < dataLen / 2; i++)
1862 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1863 pbEncoded[1 + lenBytes + 2 * i + 1];
1864 break;
1866 case ASN_UTF8STRING:
1868 LPWSTR str = (LPWSTR)value->Value.pbData;
1870 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1871 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1872 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1873 break;
1877 else
1879 value->Value.cbData = 0;
1880 value->Value.pbData = NULL;
1884 return ret;
1887 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1888 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1889 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1891 BOOL ret = TRUE;
1893 __TRY
1895 ret = CRYPT_AsnDecodeNameValueInternal(pbEncoded, cbEncoded,
1896 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1897 if (ret && pvStructInfo)
1899 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1900 pcbStructInfo, *pcbStructInfo);
1901 if (ret)
1903 CERT_NAME_VALUE *value;
1905 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1906 pvStructInfo = *(BYTE **)pvStructInfo;
1907 value = pvStructInfo;
1908 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1909 ret = CRYPT_AsnDecodeNameValueInternal( pbEncoded, cbEncoded,
1910 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1911 pcbStructInfo, NULL);
1915 __EXCEPT_PAGE_FAULT
1917 SetLastError(STATUS_ACCESS_VIOLATION);
1918 ret = FALSE;
1920 __ENDTRY
1921 return ret;
1924 static BOOL CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE *pbEncoded,
1925 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1926 DWORD *pcbDecoded)
1928 BOOL ret = TRUE;
1929 DWORD dataLen;
1930 CERT_NAME_VALUE *value = pvStructInfo;
1932 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1934 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1935 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1937 switch (pbEncoded[0])
1939 case ASN_NUMERICSTRING:
1940 valueType = CERT_RDN_NUMERIC_STRING;
1941 if (dataLen)
1942 bytesNeeded += (dataLen + 1) * 2;
1943 break;
1944 case ASN_PRINTABLESTRING:
1945 valueType = CERT_RDN_PRINTABLE_STRING;
1946 if (dataLen)
1947 bytesNeeded += (dataLen + 1) * 2;
1948 break;
1949 case ASN_IA5STRING:
1950 valueType = CERT_RDN_IA5_STRING;
1951 if (dataLen)
1952 bytesNeeded += (dataLen + 1) * 2;
1953 break;
1954 case ASN_T61STRING:
1955 valueType = CERT_RDN_T61_STRING;
1956 if (dataLen)
1957 bytesNeeded += (dataLen + 1) * 2;
1958 break;
1959 case ASN_VIDEOTEXSTRING:
1960 valueType = CERT_RDN_VIDEOTEX_STRING;
1961 if (dataLen)
1962 bytesNeeded += (dataLen + 1) * 2;
1963 break;
1964 case ASN_GRAPHICSTRING:
1965 valueType = CERT_RDN_GRAPHIC_STRING;
1966 if (dataLen)
1967 bytesNeeded += (dataLen + 1) * 2;
1968 break;
1969 case ASN_VISIBLESTRING:
1970 valueType = CERT_RDN_VISIBLE_STRING;
1971 if (dataLen)
1972 bytesNeeded += (dataLen + 1) * 2;
1973 break;
1974 case ASN_GENERALSTRING:
1975 valueType = CERT_RDN_GENERAL_STRING;
1976 if (dataLen)
1977 bytesNeeded += (dataLen + 1) * 2;
1978 break;
1979 case ASN_UNIVERSALSTRING:
1980 valueType = CERT_RDN_UNIVERSAL_STRING;
1981 if (dataLen)
1982 bytesNeeded += dataLen / 2 + sizeof(WCHAR);
1983 break;
1984 case ASN_BMPSTRING:
1985 valueType = CERT_RDN_BMP_STRING;
1986 if (dataLen)
1987 bytesNeeded += dataLen + sizeof(WCHAR);
1988 break;
1989 case ASN_UTF8STRING:
1990 valueType = CERT_RDN_UTF8_STRING;
1991 if (dataLen)
1992 bytesNeeded += (MultiByteToWideChar(CP_UTF8, 0,
1993 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) + 1) * 2;
1994 break;
1995 default:
1996 SetLastError(CRYPT_E_ASN1_BADTAG);
1997 return FALSE;
2000 if (pcbDecoded)
2001 *pcbDecoded = 1 + lenBytes + dataLen;
2002 if (!value)
2003 *pcbStructInfo = bytesNeeded;
2004 else if (*pcbStructInfo < bytesNeeded)
2006 *pcbStructInfo = bytesNeeded;
2007 SetLastError(ERROR_MORE_DATA);
2008 ret = FALSE;
2010 else
2012 *pcbStructInfo = bytesNeeded;
2013 value->dwValueType = valueType;
2014 if (dataLen)
2016 DWORD i;
2017 LPWSTR str = (LPWSTR)value->Value.pbData;
2019 assert(value->Value.pbData);
2020 switch (pbEncoded[0])
2022 case ASN_NUMERICSTRING:
2023 case ASN_PRINTABLESTRING:
2024 case ASN_IA5STRING:
2025 case ASN_T61STRING:
2026 case ASN_VIDEOTEXSTRING:
2027 case ASN_GRAPHICSTRING:
2028 case ASN_VISIBLESTRING:
2029 case ASN_GENERALSTRING:
2030 value->Value.cbData = dataLen * 2;
2031 for (i = 0; i < dataLen; i++)
2032 str[i] = pbEncoded[1 + lenBytes + i];
2033 str[i] = 0;
2034 break;
2035 case ASN_UNIVERSALSTRING:
2036 value->Value.cbData = dataLen / 2;
2037 for (i = 0; i < dataLen / 4; i++)
2038 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
2039 | pbEncoded[1 + lenBytes + 2 * i + 3];
2040 str[i] = 0;
2041 break;
2042 case ASN_BMPSTRING:
2043 value->Value.cbData = dataLen;
2044 for (i = 0; i < dataLen / 2; i++)
2045 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
2046 pbEncoded[1 + lenBytes + 2 * i + 1];
2047 str[i] = 0;
2048 break;
2049 case ASN_UTF8STRING:
2050 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
2051 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
2052 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * sizeof(WCHAR);
2053 *(WCHAR *)(value->Value.pbData + value->Value.cbData) = 0;
2054 value->Value.cbData += sizeof(WCHAR);
2055 break;
2058 else
2060 value->Value.cbData = 0;
2061 value->Value.pbData = NULL;
2065 return ret;
2068 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
2069 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2070 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2072 BOOL ret = TRUE;
2074 __TRY
2076 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded, cbEncoded,
2077 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
2078 if (ret && pvStructInfo)
2080 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
2081 pcbStructInfo, *pcbStructInfo);
2082 if (ret)
2084 CERT_NAME_VALUE *value;
2086 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2087 pvStructInfo = *(BYTE **)pvStructInfo;
2088 value = pvStructInfo;
2089 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
2090 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded,
2091 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2092 pcbStructInfo, NULL);
2096 __EXCEPT_PAGE_FAULT
2098 SetLastError(STATUS_ACCESS_VIOLATION);
2099 ret = FALSE;
2101 __ENDTRY
2102 return ret;
2105 static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
2106 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2108 BOOL ret;
2109 struct AsnDecodeSequenceItem items[] = {
2110 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
2111 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2112 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
2113 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
2114 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
2115 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
2117 CERT_RDN_ATTR *attr = pvStructInfo;
2119 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2120 pvStructInfo, *pcbStructInfo);
2122 if (attr)
2123 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
2124 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2125 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
2126 attr ? attr->pszObjId : NULL);
2127 if (attr)
2129 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
2130 debugstr_a(attr->pszObjId));
2131 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
2133 TRACE("returning %d (%08x)\n", ret, GetLastError());
2134 return ret;
2137 static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
2138 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2140 BOOL ret = TRUE;
2141 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
2142 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
2143 offsetof(CERT_RDN_ATTR, pszObjId) };
2144 PCERT_RDN rdn = pvStructInfo;
2146 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2147 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2148 rdn ? rdn->rgRDNAttr : NULL);
2149 return ret;
2152 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
2153 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2154 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2156 BOOL ret = TRUE;
2158 __TRY
2160 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2161 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
2162 offsetof(CERT_RDN, rgRDNAttr) };
2164 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2165 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
2167 __EXCEPT_PAGE_FAULT
2169 SetLastError(STATUS_ACCESS_VIOLATION);
2170 ret = FALSE;
2172 __ENDTRY
2173 return ret;
2176 static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
2177 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2178 DWORD *pcbDecoded)
2180 BOOL ret;
2181 struct AsnDecodeSequenceItem items[] = {
2182 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
2183 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2184 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
2185 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
2186 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
2187 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
2189 CERT_RDN_ATTR *attr = pvStructInfo;
2191 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2192 pvStructInfo, *pcbStructInfo);
2194 if (attr)
2195 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
2196 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2197 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
2198 attr ? attr->pszObjId : NULL);
2199 if (attr)
2201 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
2202 debugstr_a(attr->pszObjId));
2203 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
2205 TRACE("returning %d (%08x)\n", ret, GetLastError());
2206 return ret;
2209 static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
2210 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2212 BOOL ret = TRUE;
2213 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
2214 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
2215 offsetof(CERT_RDN_ATTR, pszObjId) };
2216 PCERT_RDN rdn = pvStructInfo;
2218 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2219 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2220 rdn ? rdn->rgRDNAttr : NULL);
2221 return ret;
2224 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
2225 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2226 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2228 BOOL ret = TRUE;
2230 __TRY
2232 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2233 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
2234 offsetof(CERT_RDN, rgRDNAttr) };
2236 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2237 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
2239 __EXCEPT_PAGE_FAULT
2241 SetLastError(STATUS_ACCESS_VIOLATION);
2242 ret = FALSE;
2244 __ENDTRY
2245 return ret;
2248 static BOOL CRYPT_FindEncodedLen(const BYTE *pbEncoded, DWORD cbEncoded,
2249 DWORD *pcbDecoded)
2251 BOOL ret = TRUE, done = FALSE;
2252 DWORD indefiniteNestingLevels = 0, decoded = 0;
2254 TRACE("(%p, %d)\n", pbEncoded, cbEncoded);
2256 do {
2257 DWORD dataLen;
2259 if (!cbEncoded)
2260 done = TRUE;
2261 else if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded,
2262 &dataLen)))
2264 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2266 if (dataLen == CMSG_INDEFINITE_LENGTH)
2268 indefiniteNestingLevels++;
2269 pbEncoded += 1 + lenBytes;
2270 cbEncoded -= 1 + lenBytes;
2271 decoded += 1 + lenBytes;
2272 TRACE("indefiniteNestingLevels = %d\n",
2273 indefiniteNestingLevels);
2275 else
2277 if (pbEncoded[0] == 0 && pbEncoded[1] == 0 &&
2278 indefiniteNestingLevels)
2280 indefiniteNestingLevels--;
2281 TRACE("indefiniteNestingLevels = %d\n",
2282 indefiniteNestingLevels);
2284 pbEncoded += 1 + lenBytes + dataLen;
2285 cbEncoded -= 1 + lenBytes + dataLen;
2286 decoded += 1 + lenBytes + dataLen;
2287 if (!indefiniteNestingLevels)
2288 done = TRUE;
2291 } while (ret && !done);
2292 /* If we haven't found all 0 TLVs, we haven't found the end */
2293 if (ret && indefiniteNestingLevels)
2295 SetLastError(CRYPT_E_ASN1_EOD);
2296 ret = FALSE;
2298 if (ret)
2299 *pcbDecoded = decoded;
2300 TRACE("returning %d (%d)\n", ret, ret ? *pcbDecoded : 0);
2301 return ret;
2304 static BOOL CRYPT_AsnDecodeCopyBytes(const BYTE *pbEncoded,
2305 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2306 DWORD *pcbDecoded)
2308 BOOL ret = TRUE;
2309 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB), encodedLen = 0;
2311 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2312 pvStructInfo, *pcbStructInfo);
2314 if ((ret = CRYPT_FindEncodedLen(pbEncoded, cbEncoded, &encodedLen)))
2316 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
2317 bytesNeeded += encodedLen;
2318 if (!pvStructInfo)
2319 *pcbStructInfo = bytesNeeded;
2320 else if (*pcbStructInfo < bytesNeeded)
2322 SetLastError(ERROR_MORE_DATA);
2323 *pcbStructInfo = bytesNeeded;
2324 ret = FALSE;
2326 else
2328 PCRYPT_OBJID_BLOB blob = pvStructInfo;
2330 *pcbStructInfo = bytesNeeded;
2331 blob->cbData = encodedLen;
2332 if (encodedLen)
2334 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2335 blob->pbData = (LPBYTE)pbEncoded;
2336 else
2338 assert(blob->pbData);
2339 memcpy(blob->pbData, pbEncoded, blob->cbData);
2342 else
2343 blob->pbData = NULL;
2345 if (pcbDecoded)
2346 *pcbDecoded = encodedLen;
2348 return ret;
2351 static BOOL CRYPT_AsnDecodeCTLUsage(const BYTE *pbEncoded, DWORD cbEncoded,
2352 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2354 BOOL ret;
2355 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2356 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
2357 CTL_USAGE *usage = pvStructInfo;
2359 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2360 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2361 usage ? usage->rgpszUsageIdentifier : NULL);
2362 return ret;
2365 static BOOL CRYPT_AsnDecodeCTLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2366 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2368 struct AsnDecodeSequenceItem items[] = {
2369 { ASN_OCTETSTRING, offsetof(CTL_ENTRY, SubjectIdentifier),
2370 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE,
2371 offsetof(CTL_ENTRY, SubjectIdentifier.pbData), 0 },
2372 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CTL_ENTRY, cAttribute),
2373 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES), FALSE,
2374 TRUE, offsetof(CTL_ENTRY, rgAttribute), 0 },
2376 BOOL ret = TRUE;
2377 CTL_ENTRY *entry = pvStructInfo;
2379 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
2380 *pcbStructInfo);
2382 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2383 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo,
2384 pcbDecoded, entry ? entry->SubjectIdentifier.pbData : NULL);
2385 return ret;
2388 static BOOL CRYPT_AsnDecodeCTLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
2389 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2391 BOOL ret;
2392 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2393 CRYPT_AsnDecodeCTLEntry, sizeof(CTL_ENTRY), TRUE,
2394 offsetof(CTL_ENTRY, SubjectIdentifier.pbData) };
2395 DWORD bytesNeeded;
2397 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2398 pvStructInfo, *pcbStructInfo, pcbDecoded);
2400 ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
2401 NULL, NULL, &bytesNeeded, pcbDecoded);
2402 if (ret)
2404 /* The size expected by the caller includes the combination of
2405 * CTL_INFO's cCTLEntry and rgCTLEntry, in addition to the size of
2406 * all the decoded items. CRYPT_AsnDecodeArrayNoAlloc only returns
2407 * the size of the decoded items, so add the size of cCTLEntry and
2408 * rgCTLEntry.
2410 bytesNeeded += MEMBERSIZE(CTL_INFO, cCTLEntry, cExtension);
2411 if (!pvStructInfo)
2412 *pcbStructInfo = bytesNeeded;
2413 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, NULL, pvStructInfo,
2414 pcbStructInfo, bytesNeeded)))
2416 CTL_INFO *info;
2418 info = (CTL_INFO *)((BYTE *)pvStructInfo -
2419 offsetof(CTL_INFO, cCTLEntry));
2420 ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded,
2421 cbEncoded, &info->cCTLEntry, info->rgCTLEntry, &bytesNeeded,
2422 pcbDecoded);
2425 return ret;
2428 static BOOL CRYPT_AsnDecodeCTLExtensionsInternal(const BYTE *pbEncoded,
2429 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2430 DWORD *pcbDecoded)
2432 BOOL ret = TRUE;
2433 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2434 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
2435 offsetof(CERT_EXTENSION, pszObjId) };
2436 DWORD itemSize;
2438 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2439 pvStructInfo, *pcbStructInfo, pcbDecoded);
2441 ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
2442 NULL, NULL, &itemSize, pcbDecoded);
2443 if (ret)
2445 DWORD bytesNeeded;
2447 /* The size expected by the caller includes the combination of
2448 * CTL_INFO's cExtension and rgExtension, in addition to the size of
2449 * all the decoded items. CRYPT_AsnDecodeArrayNoAlloc only returns
2450 * the size of the decoded items, so add the size of cExtension and
2451 * rgExtension.
2453 bytesNeeded = FINALMEMBERSIZE(CTL_INFO, cExtension) + itemSize;
2454 if (!pvStructInfo)
2455 *pcbStructInfo = bytesNeeded;
2456 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, NULL, pvStructInfo,
2457 pcbStructInfo, bytesNeeded)))
2459 CTL_INFO *info;
2461 info = (CTL_INFO *)((BYTE *)pvStructInfo -
2462 offsetof(CTL_INFO, cExtension));
2463 ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded,
2464 cbEncoded, &info->cExtension, info->rgExtension, &itemSize,
2465 pcbDecoded);
2468 return ret;
2471 static BOOL CRYPT_AsnDecodeCTLExtensions(const BYTE *pbEncoded,
2472 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2473 DWORD *pcbDecoded)
2475 BOOL ret;
2476 DWORD dataLen;
2478 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2480 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2482 ret = CRYPT_AsnDecodeCTLExtensionsInternal(pbEncoded + 1 + lenBytes,
2483 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
2484 if (ret && pcbDecoded)
2485 *pcbDecoded = 1 + lenBytes + dataLen;
2487 return ret;
2490 static BOOL WINAPI CRYPT_AsnDecodeCTL(DWORD dwCertEncodingType,
2491 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2492 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2494 BOOL ret = FALSE;
2496 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2497 pDecodePara, pvStructInfo, *pcbStructInfo);
2499 __TRY
2501 struct AsnDecodeSequenceItem items[] = {
2502 { ASN_INTEGER, offsetof(CTL_INFO, dwVersion),
2503 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
2504 { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectUsage),
2505 CRYPT_AsnDecodeCTLUsage, sizeof(CTL_USAGE), FALSE, TRUE,
2506 offsetof(CTL_INFO, SubjectUsage.rgpszUsageIdentifier), 0 },
2507 { ASN_OCTETSTRING, offsetof(CTL_INFO, ListIdentifier),
2508 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), TRUE,
2509 TRUE, offsetof(CTL_INFO, ListIdentifier.pbData), 0 },
2510 { ASN_INTEGER, offsetof(CTL_INFO, SequenceNumber),
2511 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2512 TRUE, TRUE, offsetof(CTL_INFO, SequenceNumber.pbData), 0 },
2513 { 0, offsetof(CTL_INFO, ThisUpdate),
2514 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE,
2515 0 },
2516 { 0, offsetof(CTL_INFO, NextUpdate),
2517 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), TRUE, FALSE,
2518 0 },
2519 { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectAlgorithm),
2520 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2521 FALSE, TRUE, offsetof(CTL_INFO, SubjectAlgorithm.pszObjId), 0 },
2522 { ASN_SEQUENCEOF, offsetof(CTL_INFO, cCTLEntry),
2523 CRYPT_AsnDecodeCTLEntries,
2524 MEMBERSIZE(CTL_INFO, cCTLEntry, cExtension),
2525 TRUE, TRUE, offsetof(CTL_INFO, rgCTLEntry), 0 },
2526 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CTL_INFO, cExtension),
2527 CRYPT_AsnDecodeCTLExtensions, FINALMEMBERSIZE(CTL_INFO, cExtension),
2528 TRUE, TRUE, offsetof(CTL_INFO, rgExtension), 0 },
2531 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2532 pDecodePara, pvStructInfo, *pcbStructInfo);
2534 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2535 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2536 pcbStructInfo, NULL, NULL);
2538 __EXCEPT_PAGE_FAULT
2540 SetLastError(STATUS_ACCESS_VIOLATION);
2542 __ENDTRY
2543 return ret;
2546 static BOOL CRYPT_AsnDecodeSMIMECapability(const BYTE *pbEncoded,
2547 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2548 DWORD *pcbDecoded)
2550 BOOL ret;
2551 struct AsnDecodeSequenceItem items[] = {
2552 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_SMIME_CAPABILITY, pszObjId),
2553 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2554 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId), 0 },
2555 { 0, offsetof(CRYPT_SMIME_CAPABILITY, Parameters),
2556 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2557 offsetof(CRYPT_SMIME_CAPABILITY, Parameters.pbData), 0 },
2559 PCRYPT_SMIME_CAPABILITY capability = pvStructInfo;
2561 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2562 pvStructInfo, *pcbStructInfo);
2564 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2565 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2566 pcbDecoded, capability ? capability->pszObjId : NULL);
2567 TRACE("returning %d\n", ret);
2568 return ret;
2571 static BOOL WINAPI CRYPT_AsnDecodeSMIMECapabilities(DWORD dwCertEncodingType,
2572 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2573 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2575 BOOL ret = FALSE;
2577 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2578 pDecodePara, pvStructInfo, *pcbStructInfo);
2580 __TRY
2582 DWORD bytesNeeded;
2583 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2584 CRYPT_AsnDecodeSMIMECapability, sizeof(CRYPT_SMIME_CAPABILITY), TRUE,
2585 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId) };
2587 if ((ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
2588 NULL, NULL, &bytesNeeded, NULL)))
2590 bytesNeeded += sizeof(CRYPT_SMIME_CAPABILITIES);
2591 if (!pvStructInfo)
2592 *pcbStructInfo = bytesNeeded;
2593 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2594 pvStructInfo, pcbStructInfo, bytesNeeded)))
2596 PCRYPT_SMIME_CAPABILITIES capabilities;
2598 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2599 pvStructInfo = *(BYTE **)pvStructInfo;
2600 capabilities = pvStructInfo;
2601 capabilities->rgCapability =
2602 (PCRYPT_SMIME_CAPABILITY)((BYTE *)pvStructInfo +
2603 sizeof(CRYPT_SMIME_CAPABILITIES));
2604 ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc,
2605 pbEncoded, cbEncoded, &capabilities->cCapability,
2606 capabilities->rgCapability, pcbStructInfo, NULL);
2610 __EXCEPT_PAGE_FAULT
2612 SetLastError(STATUS_ACCESS_VIOLATION);
2614 __ENDTRY
2615 TRACE("returning %d\n", ret);
2616 return ret;
2619 static BOOL CRYPT_AsnDecodeIA5String(const BYTE *pbEncoded,
2620 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2621 DWORD *pcbDecoded)
2623 BOOL ret = TRUE;
2624 DWORD dataLen;
2625 LPSTR *pStr = pvStructInfo;
2627 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2629 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2630 DWORD bytesNeeded = sizeof(LPSTR) + sizeof(char);
2632 if (pbEncoded[0] != ASN_IA5STRING)
2634 SetLastError(CRYPT_E_ASN1_CORRUPT);
2635 ret = FALSE;
2637 else
2639 bytesNeeded += dataLen;
2640 if (pcbDecoded)
2641 *pcbDecoded = 1 + lenBytes + dataLen;
2642 if (!pvStructInfo)
2643 *pcbStructInfo = bytesNeeded;
2644 else if (*pcbStructInfo < bytesNeeded)
2646 *pcbStructInfo = bytesNeeded;
2647 SetLastError(ERROR_MORE_DATA);
2648 ret = FALSE;
2650 else
2652 *pcbStructInfo = bytesNeeded;
2653 if (dataLen)
2655 LPSTR str = *pStr;
2657 assert(str);
2658 memcpy(str, pbEncoded + 1 + lenBytes, dataLen);
2659 str[dataLen] = 0;
2661 else
2662 *pStr = NULL;
2666 return ret;
2669 static BOOL CRYPT_AsnDecodeIntArray(const BYTE *pbEncoded,
2670 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2671 DWORD *pcbDecoded)
2673 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2674 CRYPT_AsnDecodeIntInternal, sizeof(int), FALSE, 0 };
2675 struct GenericArray *array = pvStructInfo;
2676 BOOL ret;
2678 TRACE("(%p, %d, %08x, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2679 pvStructInfo, pvStructInfo ? *pcbDecoded : 0);
2681 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2682 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
2683 array ? array->rgItems : NULL);
2684 TRACE("returning %d\n", ret);
2685 return ret;
2688 static BOOL CRYPT_AsnDecodeNoticeReference(const BYTE *pbEncoded,
2689 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2690 DWORD *pcbDecoded)
2692 BOOL ret;
2693 struct AsnDecodeSequenceItem items[] = {
2694 { ASN_IA5STRING, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2695 pszOrganization), CRYPT_AsnDecodeIA5String, sizeof(LPSTR), FALSE, TRUE,
2696 offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, pszOrganization), 0 },
2697 { ASN_SEQUENCEOF, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2698 cNoticeNumbers), CRYPT_AsnDecodeIntArray, sizeof(struct GenericArray),
2699 FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2700 rgNoticeNumbers), 0 },
2702 DWORD bytesNeeded;
2704 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2705 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
2707 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2708 pbEncoded, cbEncoded, dwFlags, NULL, NULL, &bytesNeeded, pcbDecoded,
2709 NULL);
2710 if (ret)
2712 /* The caller is expecting a pointer to a
2713 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE to be decoded, whereas
2714 * CRYPT_AsnDecodeSequence is decoding a
2715 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE. Increment the bytes
2716 * needed, and decode again if the requisite space is available.
2718 bytesNeeded += sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE);
2719 if (!pvStructInfo)
2720 *pcbStructInfo = bytesNeeded;
2721 else if (*pcbStructInfo < bytesNeeded)
2723 *pcbStructInfo = bytesNeeded;
2724 SetLastError(ERROR_MORE_DATA);
2725 ret = FALSE;
2727 else
2729 PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE noticeRef;
2731 *pcbStructInfo = bytesNeeded;
2732 /* The pointer (pvStructInfo) passed in points to the first dynamic
2733 * pointer, so use it as the pointer to the
2734 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, and create the
2735 * appropriate offset for the first dynamic pointer within the
2736 * notice reference by pointing to the first memory location past
2737 * the CERT_POLICY_QUALIFIER_NOTICE_REFERENCE.
2739 noticeRef =
2740 *(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE *)pvStructInfo;
2741 noticeRef->pszOrganization = (LPSTR)((LPBYTE)noticeRef +
2742 sizeof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE));
2743 ret = CRYPT_AsnDecodeSequence(items,
2744 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2745 NULL, noticeRef, &bytesNeeded, pcbDecoded,
2746 noticeRef->pszOrganization);
2749 TRACE("returning %d\n", ret);
2750 return ret;
2753 static BOOL CRYPT_AsnDecodeUnicodeString(const BYTE *pbEncoded,
2754 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2755 DWORD *pcbDecoded)
2757 BOOL ret = TRUE;
2758 DWORD dataLen;
2760 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2762 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2763 DWORD bytesNeeded = sizeof(LPWSTR);
2765 switch (pbEncoded[0])
2767 case ASN_NUMERICSTRING:
2768 if (dataLen)
2769 bytesNeeded += (dataLen + 1) * 2;
2770 break;
2771 case ASN_PRINTABLESTRING:
2772 if (dataLen)
2773 bytesNeeded += (dataLen + 1) * 2;
2774 break;
2775 case ASN_IA5STRING:
2776 if (dataLen)
2777 bytesNeeded += (dataLen + 1) * 2;
2778 break;
2779 case ASN_T61STRING:
2780 if (dataLen)
2781 bytesNeeded += (dataLen + 1) * 2;
2782 break;
2783 case ASN_VIDEOTEXSTRING:
2784 if (dataLen)
2785 bytesNeeded += (dataLen + 1) * 2;
2786 break;
2787 case ASN_GRAPHICSTRING:
2788 if (dataLen)
2789 bytesNeeded += (dataLen + 1) * 2;
2790 break;
2791 case ASN_VISIBLESTRING:
2792 if (dataLen)
2793 bytesNeeded += (dataLen + 1) * 2;
2794 break;
2795 case ASN_GENERALSTRING:
2796 if (dataLen)
2797 bytesNeeded += (dataLen + 1) * 2;
2798 break;
2799 case ASN_UNIVERSALSTRING:
2800 if (dataLen)
2801 bytesNeeded += dataLen / 2 + sizeof(WCHAR);
2802 break;
2803 case ASN_BMPSTRING:
2804 if (dataLen)
2805 bytesNeeded += dataLen + sizeof(WCHAR);
2806 break;
2807 case ASN_UTF8STRING:
2808 if (dataLen)
2809 bytesNeeded += (MultiByteToWideChar(CP_UTF8, 0,
2810 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) + 1) * 2;
2811 break;
2812 default:
2813 SetLastError(CRYPT_E_ASN1_BADTAG);
2814 return FALSE;
2817 if (pcbDecoded)
2818 *pcbDecoded = 1 + lenBytes + dataLen;
2819 if (!pvStructInfo)
2820 *pcbStructInfo = bytesNeeded;
2821 else if (*pcbStructInfo < bytesNeeded)
2823 *pcbStructInfo = bytesNeeded;
2824 SetLastError(ERROR_MORE_DATA);
2825 ret = FALSE;
2827 else
2829 LPWSTR *pStr = pvStructInfo;
2831 *pcbStructInfo = bytesNeeded;
2832 if (dataLen)
2834 DWORD i;
2835 LPWSTR str = *(LPWSTR *)pStr;
2837 assert(str);
2838 switch (pbEncoded[0])
2840 case ASN_NUMERICSTRING:
2841 case ASN_PRINTABLESTRING:
2842 case ASN_IA5STRING:
2843 case ASN_T61STRING:
2844 case ASN_VIDEOTEXSTRING:
2845 case ASN_GRAPHICSTRING:
2846 case ASN_VISIBLESTRING:
2847 case ASN_GENERALSTRING:
2848 for (i = 0; i < dataLen; i++)
2849 str[i] = pbEncoded[1 + lenBytes + i];
2850 str[i] = 0;
2851 break;
2852 case ASN_UNIVERSALSTRING:
2853 for (i = 0; i < dataLen / 4; i++)
2854 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
2855 | pbEncoded[1 + lenBytes + 2 * i + 3];
2856 str[i] = 0;
2857 break;
2858 case ASN_BMPSTRING:
2859 for (i = 0; i < dataLen / 2; i++)
2860 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
2861 pbEncoded[1 + lenBytes + 2 * i + 1];
2862 str[i] = 0;
2863 break;
2864 case ASN_UTF8STRING:
2866 int len = MultiByteToWideChar(CP_UTF8, 0,
2867 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
2868 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
2869 str[len] = 0;
2870 break;
2874 else
2875 *pStr = NULL;
2878 return ret;
2881 static BOOL CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(
2882 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
2883 DWORD *pcbStructInfo, DWORD *pcbDecoded)
2885 BOOL ret;
2886 struct AsnDecodeSequenceItem items[] = {
2887 { ASN_SEQUENCE, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE,
2888 pNoticeReference), CRYPT_AsnDecodeNoticeReference,
2889 sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE), TRUE, TRUE,
2890 offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pNoticeReference), 0 },
2891 { 0, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pszDisplayText),
2892 CRYPT_AsnDecodeUnicodeString, sizeof(LPWSTR), TRUE, TRUE,
2893 offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pszDisplayText), 0 },
2895 PCERT_POLICY_QUALIFIER_USER_NOTICE notice = pvStructInfo;
2897 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2898 pvStructInfo, *pcbStructInfo);
2900 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2901 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2902 pcbDecoded, notice ? notice->pNoticeReference : NULL);
2903 TRACE("returning %d\n", ret);
2904 return ret;
2907 static BOOL WINAPI CRYPT_AsnDecodePolicyQualifierUserNotice(
2908 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2909 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2910 void *pvStructInfo, DWORD *pcbStructInfo)
2912 BOOL ret = FALSE;
2914 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2915 pDecodePara, pvStructInfo, *pcbStructInfo);
2917 __TRY
2919 DWORD bytesNeeded;
2921 ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(pbEncoded,
2922 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2923 NULL);
2924 if (ret)
2926 if (!pvStructInfo)
2927 *pcbStructInfo = bytesNeeded;
2928 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2929 pvStructInfo, pcbStructInfo, bytesNeeded)))
2931 PCERT_POLICY_QUALIFIER_USER_NOTICE notice;
2933 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2934 pvStructInfo = *(BYTE **)pvStructInfo;
2935 notice = pvStructInfo;
2936 notice->pNoticeReference =
2937 (PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE)
2938 ((BYTE *)pvStructInfo +
2939 sizeof(CERT_POLICY_QUALIFIER_USER_NOTICE));
2940 ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(
2941 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
2942 pvStructInfo, &bytesNeeded, NULL);
2946 __EXCEPT_PAGE_FAULT
2948 SetLastError(STATUS_ACCESS_VIOLATION);
2950 __ENDTRY
2951 TRACE("returning %d\n", ret);
2952 return ret;
2955 static BOOL CRYPT_AsnDecodePKCSAttributeValue(const BYTE *pbEncoded,
2956 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2957 DWORD *pcbDecoded)
2959 BOOL ret;
2960 struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytes,
2961 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
2962 DWORD bytesNeeded;
2964 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2965 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
2967 if ((ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
2968 NULL, NULL, &bytesNeeded, pcbDecoded)))
2970 bytesNeeded += FINALMEMBERSIZE(CRYPT_ATTRIBUTE, cValue);
2971 if (!pvStructInfo)
2972 *pcbStructInfo = bytesNeeded;
2973 else if ((ret = CRYPT_DecodeEnsureSpace(0, NULL, pvStructInfo,
2974 pcbStructInfo, bytesNeeded)))
2976 CRYPT_ATTRIBUTE *attr = (CRYPT_ATTRIBUTE *)((BYTE *)pvStructInfo -
2977 offsetof(CRYPT_ATTRIBUTE, cValue));
2979 ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
2980 &attr->cValue, attr->rgValue, pcbStructInfo, pcbDecoded);
2983 return ret;
2986 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
2987 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2988 DWORD *pcbDecoded)
2990 BOOL ret;
2991 struct AsnDecodeSequenceItem items[] = {
2992 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
2993 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2994 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
2995 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
2996 CRYPT_AsnDecodePKCSAttributeValue,
2997 FINALMEMBERSIZE(CRYPT_ATTRIBUTE, cValue), FALSE,
2998 TRUE, offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
3000 PCRYPT_ATTRIBUTE attr = pvStructInfo;
3002 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3003 pvStructInfo, *pcbStructInfo);
3005 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3006 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3007 pcbDecoded, attr ? attr->pszObjId : NULL);
3008 TRACE("returning %d\n", ret);
3009 return ret;
3012 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
3013 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3014 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3016 BOOL ret = FALSE;
3018 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3019 pDecodePara, pvStructInfo, *pcbStructInfo);
3021 __TRY
3023 DWORD bytesNeeded;
3025 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
3026 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3027 if (ret)
3029 if (!pvStructInfo)
3030 *pcbStructInfo = bytesNeeded;
3031 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3032 pvStructInfo, pcbStructInfo, bytesNeeded)))
3034 PCRYPT_ATTRIBUTE attr;
3036 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3037 pvStructInfo = *(BYTE **)pvStructInfo;
3038 attr = pvStructInfo;
3039 attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
3040 sizeof(CRYPT_ATTRIBUTE));
3041 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
3042 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
3043 NULL);
3047 __EXCEPT_PAGE_FAULT
3049 SetLastError(STATUS_ACCESS_VIOLATION);
3051 __ENDTRY
3052 TRACE("returning %d\n", ret);
3053 return ret;
3056 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
3057 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3058 DWORD *pcbDecoded)
3060 struct AsnArrayDescriptor arrayDesc = { 0,
3061 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
3062 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
3063 PCRYPT_ATTRIBUTES attrs = pvStructInfo;
3064 BOOL ret;
3066 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3067 NULL, pvStructInfo, pcbStructInfo, pcbDecoded, attrs ? attrs->rgAttr :
3068 NULL);
3069 return ret;
3072 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
3073 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3074 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3076 BOOL ret = FALSE;
3078 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3079 pDecodePara, pvStructInfo, *pcbStructInfo);
3081 __TRY
3083 DWORD bytesNeeded;
3085 if (pbEncoded[0] != (ASN_CONSTRUCTOR | ASN_SETOF))
3086 SetLastError(CRYPT_E_ASN1_CORRUPT);
3087 else if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
3088 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
3089 NULL)))
3091 if (!pvStructInfo)
3092 *pcbStructInfo = bytesNeeded;
3093 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3094 pvStructInfo, pcbStructInfo, bytesNeeded)))
3096 PCRYPT_ATTRIBUTES attrs;
3098 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3099 pvStructInfo = *(BYTE **)pvStructInfo;
3100 attrs = pvStructInfo;
3101 attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
3102 sizeof(CRYPT_ATTRIBUTES));
3103 ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
3104 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3105 &bytesNeeded, NULL);
3109 __EXCEPT_PAGE_FAULT
3111 SetLastError(STATUS_ACCESS_VIOLATION);
3113 __ENDTRY
3114 TRACE("returning %d\n", ret);
3115 return ret;
3118 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
3119 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3121 CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
3122 BOOL ret = TRUE;
3123 struct AsnDecodeSequenceItem items[] = {
3124 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
3125 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
3126 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
3127 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
3128 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
3129 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
3132 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3133 pvStructInfo, *pcbStructInfo, pcbDecoded);
3135 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3136 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3137 pcbDecoded, algo ? algo->pszObjId : NULL);
3138 if (ret && pvStructInfo)
3140 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
3141 debugstr_a(algo->pszObjId));
3143 return ret;
3146 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
3147 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3148 DWORD *pcbDecoded)
3150 BOOL ret = TRUE;
3151 struct AsnDecodeSequenceItem items[] = {
3152 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
3153 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3154 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
3155 Algorithm.pszObjId) },
3156 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
3157 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
3158 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
3160 PCERT_PUBLIC_KEY_INFO info = pvStructInfo;
3162 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3163 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3164 pcbDecoded, info ? info->Algorithm.Parameters.pbData : NULL);
3165 return ret;
3168 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
3169 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3170 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3172 BOOL ret = TRUE;
3174 __TRY
3176 DWORD bytesNeeded;
3178 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
3179 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3181 if (!pvStructInfo)
3182 *pcbStructInfo = bytesNeeded;
3183 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3184 pvStructInfo, pcbStructInfo, bytesNeeded)))
3186 PCERT_PUBLIC_KEY_INFO info;
3188 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3189 pvStructInfo = *(BYTE **)pvStructInfo;
3190 info = pvStructInfo;
3191 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
3192 sizeof(CERT_PUBLIC_KEY_INFO);
3193 ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
3194 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3195 &bytesNeeded, NULL);
3199 __EXCEPT_PAGE_FAULT
3201 SetLastError(STATUS_ACCESS_VIOLATION);
3202 ret = FALSE;
3204 __ENDTRY
3205 return ret;
3208 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
3209 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3211 BOOL ret;
3213 if (cbEncoded < 3)
3215 SetLastError(CRYPT_E_ASN1_CORRUPT);
3216 return FALSE;
3218 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
3220 SetLastError(CRYPT_E_ASN1_CORRUPT);
3221 return FALSE;
3223 if (pbEncoded[1] > 1)
3225 SetLastError(CRYPT_E_ASN1_CORRUPT);
3226 return FALSE;
3228 if (pcbDecoded)
3229 *pcbDecoded = 3;
3230 if (!pvStructInfo)
3232 *pcbStructInfo = sizeof(BOOL);
3233 ret = TRUE;
3235 else if (*pcbStructInfo < sizeof(BOOL))
3237 *pcbStructInfo = sizeof(BOOL);
3238 SetLastError(ERROR_MORE_DATA);
3239 ret = FALSE;
3241 else
3243 *pcbStructInfo = sizeof(BOOL);
3244 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
3245 ret = TRUE;
3247 TRACE("returning %d (%08x)\n", ret, GetLastError());
3248 return ret;
3251 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
3252 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3254 PCERT_ALT_NAME_ENTRY entry = pvStructInfo;
3255 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
3256 BOOL ret;
3258 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3259 pvStructInfo, *pcbStructInfo);
3261 if (cbEncoded < 2)
3263 SetLastError(CRYPT_E_ASN1_CORRUPT);
3264 return FALSE;
3266 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3267 if (1 + lenBytes > cbEncoded)
3269 SetLastError(CRYPT_E_ASN1_CORRUPT);
3270 return FALSE;
3272 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3274 switch (pbEncoded[0] & ASN_TYPE_MASK)
3276 case 1: /* rfc822Name */
3277 case 2: /* dNSName */
3278 case 6: /* uniformResourceIdentifier */
3279 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
3280 break;
3281 case 4: /* directoryName */
3282 case 7: /* iPAddress */
3283 bytesNeeded += dataLen;
3284 break;
3285 case 8: /* registeredID */
3286 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
3287 &dataLen, NULL);
3288 if (ret)
3290 /* FIXME: ugly, shouldn't need to know internals of OID decode
3291 * function to use it.
3293 bytesNeeded += dataLen - sizeof(LPSTR);
3295 break;
3296 case 0: /* otherName */
3297 FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
3298 SetLastError(CRYPT_E_ASN1_BADTAG);
3299 ret = FALSE;
3300 break;
3301 case 3: /* x400Address, unimplemented */
3302 case 5: /* ediPartyName, unimplemented */
3303 TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
3304 SetLastError(CRYPT_E_ASN1_BADTAG);
3305 ret = FALSE;
3306 break;
3307 default:
3308 TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
3309 SetLastError(CRYPT_E_ASN1_CORRUPT);
3310 ret = FALSE;
3312 if (ret)
3314 if (pcbDecoded)
3315 *pcbDecoded = 1 + lenBytes + dataLen;
3316 if (!entry)
3317 *pcbStructInfo = bytesNeeded;
3318 else if (*pcbStructInfo < bytesNeeded)
3320 *pcbStructInfo = bytesNeeded;
3321 SetLastError(ERROR_MORE_DATA);
3322 ret = FALSE;
3324 else
3326 *pcbStructInfo = bytesNeeded;
3327 /* MS used values one greater than the asn1 ones.. sigh */
3328 entry->dwAltNameChoice = (pbEncoded[0] & ASN_TYPE_MASK) + 1;
3329 switch (pbEncoded[0] & ASN_TYPE_MASK)
3331 case 1: /* rfc822Name */
3332 case 2: /* dNSName */
3333 case 6: /* uniformResourceIdentifier */
3335 DWORD i;
3337 for (i = 0; i < dataLen; i++)
3338 entry->u.pwszURL[i] =
3339 (WCHAR)pbEncoded[1 + lenBytes + i];
3340 entry->u.pwszURL[i] = 0;
3341 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
3342 debugstr_w(entry->u.pwszURL));
3343 break;
3345 case 4: /* directoryName */
3346 /* The data are memory-equivalent with the IPAddress case,
3347 * fall-through
3349 case 7: /* iPAddress */
3350 /* The next data pointer is in the pwszURL spot, that is,
3351 * the first 4 bytes. Need to move it to the next spot.
3353 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
3354 entry->u.IPAddress.cbData = dataLen;
3355 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
3356 dataLen);
3357 break;
3358 case 8: /* registeredID */
3359 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
3360 &entry->u.pszRegisteredID, &dataLen, NULL);
3361 break;
3366 return ret;
3369 static BOOL CRYPT_AsnDecodeAltNameInternal(const BYTE *pbEncoded,
3370 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3371 DWORD *pcbDecoded)
3373 BOOL ret = TRUE;
3374 struct AsnArrayDescriptor arrayDesc = { 0,
3375 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3376 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3377 PCERT_ALT_NAME_INFO info = pvStructInfo;
3379 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3380 pvStructInfo, *pcbStructInfo, pcbDecoded);
3382 if (info)
3383 TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
3384 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3385 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
3386 info ? info->rgAltEntry : NULL);
3387 return ret;
3390 /* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */
3391 static BOOL CRYPT_AsnDecodeIntegerSwapBytes(const BYTE *pbEncoded,
3392 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3393 DWORD *pcbDecoded)
3395 BOOL ret;
3397 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
3398 pvStructInfo, *pcbStructInfo, pcbDecoded);
3400 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
3401 * place.
3403 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3404 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
3405 pcbDecoded);
3406 if (ret && pvStructInfo)
3408 CRYPT_DATA_BLOB *blob = pvStructInfo;
3410 if (blob->cbData)
3412 DWORD i;
3413 BYTE temp;
3415 for (i = 0; i < blob->cbData / 2; i++)
3417 temp = blob->pbData[i];
3418 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
3419 blob->pbData[blob->cbData - i - 1] = temp;
3423 TRACE("returning %d (%08x)\n", ret, GetLastError());
3424 return ret;
3427 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
3428 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3429 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3431 BOOL ret;
3433 __TRY
3435 struct AsnDecodeSequenceItem items[] = {
3436 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
3437 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
3438 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
3439 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
3440 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
3441 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
3442 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
3443 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
3444 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
3445 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
3446 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
3449 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3450 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3451 pcbStructInfo, NULL, NULL);
3453 __EXCEPT_PAGE_FAULT
3455 SetLastError(STATUS_ACCESS_VIOLATION);
3456 ret = FALSE;
3458 __ENDTRY
3459 return ret;
3462 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
3463 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3464 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3466 BOOL ret;
3468 __TRY
3470 struct AsnDecodeSequenceItem items[] = {
3471 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
3472 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
3473 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
3474 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
3475 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
3476 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
3477 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3478 AuthorityCertIssuer.rgAltEntry), 0 },
3479 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3480 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
3481 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
3482 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3483 AuthorityCertSerialNumber.pbData), 0 },
3486 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3487 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3488 pcbStructInfo, NULL, NULL);
3490 __EXCEPT_PAGE_FAULT
3492 SetLastError(STATUS_ACCESS_VIOLATION);
3493 ret = FALSE;
3495 __ENDTRY
3496 return ret;
3499 static BOOL CRYPT_AsnDecodeAccessDescription(const BYTE *pbEncoded,
3500 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3501 DWORD *pcbDecoded)
3503 struct AsnDecodeSequenceItem items[] = {
3504 { 0, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod),
3505 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
3506 offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod), 0 },
3507 { 0, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation),
3508 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), FALSE,
3509 TRUE, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation.u.pwszURL), 0 },
3511 CERT_ACCESS_DESCRIPTION *descr = pvStructInfo;
3513 return CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3514 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3515 pcbDecoded, descr ? descr->pszAccessMethod : NULL);
3518 static BOOL WINAPI CRYPT_AsnDecodeAuthorityInfoAccess(DWORD dwCertEncodingType,
3519 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3520 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3522 BOOL ret;
3524 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3525 pDecodePara, pvStructInfo, *pcbStructInfo);
3527 __TRY
3529 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3530 CRYPT_AsnDecodeAccessDescription, sizeof(CERT_ACCESS_DESCRIPTION),
3531 TRUE, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod) };
3533 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3534 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
3536 __EXCEPT_PAGE_FAULT
3538 SetLastError(STATUS_ACCESS_VIOLATION);
3539 ret = FALSE;
3541 __ENDTRY
3542 return ret;
3545 static BOOL CRYPT_AsnDecodePKCSContent(const BYTE *pbEncoded, DWORD cbEncoded,
3546 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3548 BOOL ret;
3549 DWORD dataLen;
3551 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3552 pvStructInfo, *pcbStructInfo, pcbDecoded);
3554 /* The caller has already checked the tag, no need to check it again.
3555 * Check the outer length is valid:
3557 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
3559 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3560 DWORD innerLen;
3562 pbEncoded += 1 + lenBytes;
3563 cbEncoded -= 1 + lenBytes;
3564 if (dataLen == CMSG_INDEFINITE_LENGTH)
3565 cbEncoded -= 2; /* space for 0 TLV */
3566 /* Check the inner length is valid: */
3567 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &innerLen)))
3569 DWORD decodedLen;
3571 ret = CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags,
3572 pvStructInfo, pcbStructInfo, &decodedLen);
3573 if (dataLen == CMSG_INDEFINITE_LENGTH)
3575 if (*(pbEncoded + decodedLen) != 0 ||
3576 *(pbEncoded + decodedLen + 1) != 0)
3578 TRACE("expected 0 TLV, got {%02x,%02x}\n",
3579 *(pbEncoded + decodedLen),
3580 *(pbEncoded + decodedLen + 1));
3581 SetLastError(CRYPT_E_ASN1_CORRUPT);
3582 ret = FALSE;
3584 else
3585 decodedLen += 2;
3587 if (ret && pcbDecoded)
3589 *pcbDecoded = 1 + lenBytes + decodedLen;
3590 TRACE("decoded %d bytes\n", *pcbDecoded);
3594 return ret;
3597 static BOOL CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE *pbEncoded,
3598 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3599 DWORD *pcbDecoded)
3601 CRYPT_CONTENT_INFO *info = pvStructInfo;
3602 struct AsnDecodeSequenceItem items[] = {
3603 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
3604 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
3605 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
3606 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
3607 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
3608 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
3609 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
3611 BOOL ret;
3613 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3614 pvStructInfo, *pcbStructInfo, pcbDecoded);
3616 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3617 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3618 pcbDecoded, info ? info->pszObjId : NULL);
3619 return ret;
3622 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
3623 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3624 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3626 BOOL ret = FALSE;
3628 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3629 pDecodePara, pvStructInfo, *pcbStructInfo);
3631 __TRY
3633 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, cbEncoded,
3634 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
3635 if (ret && pvStructInfo)
3637 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
3638 pcbStructInfo, *pcbStructInfo);
3639 if (ret)
3641 CRYPT_CONTENT_INFO *info;
3643 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3644 pvStructInfo = *(BYTE **)pvStructInfo;
3645 info = pvStructInfo;
3646 info->pszObjId = (LPSTR)((BYTE *)info +
3647 sizeof(CRYPT_CONTENT_INFO));
3648 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded,
3649 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3650 pcbStructInfo, NULL);
3654 __EXCEPT_PAGE_FAULT
3656 SetLastError(STATUS_ACCESS_VIOLATION);
3658 __ENDTRY
3659 return ret;
3662 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
3663 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3664 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
3666 BOOL ret;
3667 struct AsnDecodeSequenceItem items[] = {
3668 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version),
3669 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3670 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
3671 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3672 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
3673 0 },
3674 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
3675 CRYPT_AsnDecodePKCSContentInfoInternal,
3676 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
3677 ContentInfo.pszObjId), 0 },
3678 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
3679 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
3680 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
3683 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3684 pbEncoded, cbEncoded, dwFlags, pDecodePara, digestedData, pcbDigestedData,
3685 NULL, NULL);
3686 return ret;
3689 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
3690 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3691 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3693 BOOL ret = TRUE;
3695 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3696 pDecodePara, pvStructInfo, *pcbStructInfo);
3698 __TRY
3700 DWORD bytesNeeded;
3702 if ((ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
3703 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3705 if (!pvStructInfo)
3706 *pcbStructInfo = bytesNeeded;
3707 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3708 pvStructInfo, pcbStructInfo, bytesNeeded)))
3710 CERT_ALT_NAME_INFO *name;
3712 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3713 pvStructInfo = *(BYTE **)pvStructInfo;
3714 name = pvStructInfo;
3715 name->rgAltEntry = (PCERT_ALT_NAME_ENTRY)
3716 ((BYTE *)pvStructInfo + sizeof(CERT_ALT_NAME_INFO));
3717 ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
3718 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3719 &bytesNeeded, NULL);
3723 __EXCEPT_PAGE_FAULT
3725 SetLastError(STATUS_ACCESS_VIOLATION);
3726 ret = FALSE;
3728 __ENDTRY
3729 return ret;
3732 struct PATH_LEN_CONSTRAINT
3734 BOOL fPathLenConstraint;
3735 DWORD dwPathLenConstraint;
3738 static BOOL CRYPT_AsnDecodePathLenConstraint(const BYTE *pbEncoded,
3739 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3740 DWORD *pcbDecoded)
3742 BOOL ret = TRUE;
3743 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT), size;
3745 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3746 pvStructInfo, *pcbStructInfo, pcbDecoded);
3748 if (!pvStructInfo)
3750 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, NULL,
3751 &size, pcbDecoded);
3752 *pcbStructInfo = bytesNeeded;
3754 else if (*pcbStructInfo < bytesNeeded)
3756 SetLastError(ERROR_MORE_DATA);
3757 *pcbStructInfo = bytesNeeded;
3758 ret = FALSE;
3760 else
3762 struct PATH_LEN_CONSTRAINT *constraint = pvStructInfo;
3764 *pcbStructInfo = bytesNeeded;
3765 size = sizeof(constraint->dwPathLenConstraint);
3766 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
3767 &constraint->dwPathLenConstraint, &size, pcbDecoded);
3768 if (ret)
3769 constraint->fPathLenConstraint = TRUE;
3770 TRACE("got an int, dwPathLenConstraint is %d\n",
3771 constraint->dwPathLenConstraint);
3773 TRACE("returning %d (%08x)\n", ret, GetLastError());
3774 return ret;
3777 static BOOL CRYPT_AsnDecodeSubtreeConstraints(const BYTE *pbEncoded,
3778 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3779 DWORD *pcbDecoded)
3781 BOOL ret;
3782 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3783 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
3784 offsetof(CERT_NAME_BLOB, pbData) };
3785 struct GenericArray *entries = pvStructInfo;
3787 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3788 pvStructInfo, *pcbStructInfo, pcbDecoded);
3790 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3791 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
3792 entries ? entries->rgItems : NULL);
3793 TRACE("Returning %d (%08x)\n", ret, GetLastError());
3794 return ret;
3797 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
3798 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3799 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3801 BOOL ret;
3803 __TRY
3805 struct AsnDecodeSequenceItem items[] = {
3806 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
3807 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
3808 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
3809 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3810 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3811 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3812 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3813 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
3814 sizeof(struct GenericArray), TRUE, TRUE,
3815 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
3818 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3819 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3820 pcbStructInfo, NULL, NULL);
3822 __EXCEPT_PAGE_FAULT
3824 SetLastError(STATUS_ACCESS_VIOLATION);
3825 ret = FALSE;
3827 __ENDTRY
3828 return ret;
3831 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
3832 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3833 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3835 BOOL ret;
3837 __TRY
3839 struct AsnDecodeSequenceItem items[] = {
3840 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
3841 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
3842 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
3843 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3844 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3847 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3848 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3849 pcbStructInfo, NULL, NULL);
3851 __EXCEPT_PAGE_FAULT
3853 SetLastError(STATUS_ACCESS_VIOLATION);
3854 ret = FALSE;
3856 __ENDTRY
3857 return ret;
3860 static BOOL CRYPT_AsnDecodePolicyQualifier(const BYTE *pbEncoded,
3861 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3862 DWORD *pcbDecoded)
3864 struct AsnDecodeSequenceItem items[] = {
3865 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_QUALIFIER_INFO,
3866 pszPolicyQualifierId), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
3867 FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId),
3868 0 },
3869 { 0, offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier),
3870 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
3871 offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier.pbData), 0 },
3873 BOOL ret;
3874 CERT_POLICY_QUALIFIER_INFO *qualifier = pvStructInfo;
3876 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3877 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3879 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3880 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3881 pcbDecoded, qualifier ? qualifier->pszPolicyQualifierId : NULL);
3882 return ret;
3885 static BOOL CRYPT_AsnDecodePolicyQualifiers(const BYTE *pbEncoded,
3886 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3887 DWORD *pcbDecoded)
3889 BOOL ret;
3890 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3891 CRYPT_AsnDecodePolicyQualifier, sizeof(CERT_POLICY_QUALIFIER_INFO), TRUE,
3892 offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId) };
3893 struct GenericArray *entries = pvStructInfo;
3895 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3896 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3898 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3899 NULL, pvStructInfo, pcbStructInfo, pcbDecoded,
3900 entries ? entries->rgItems : NULL);
3901 TRACE("Returning %d (%08x)\n", ret, GetLastError());
3902 return ret;
3905 static BOOL CRYPT_AsnDecodeCertPolicy(const BYTE *pbEncoded, DWORD cbEncoded,
3906 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3908 struct AsnDecodeSequenceItem items[] = {
3909 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_INFO, pszPolicyIdentifier),
3910 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
3911 offsetof(CERT_POLICY_INFO, pszPolicyIdentifier), 0 },
3912 { ASN_SEQUENCEOF, offsetof(CERT_POLICY_INFO, cPolicyQualifier),
3913 CRYPT_AsnDecodePolicyQualifiers, sizeof(struct GenericArray), TRUE,
3914 TRUE, offsetof(CERT_POLICY_INFO, rgPolicyQualifier), 0 },
3916 CERT_POLICY_INFO *info = pvStructInfo;
3917 BOOL ret;
3919 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3920 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3922 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3923 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3924 pcbDecoded, info ? info->pszPolicyIdentifier : NULL);
3925 return ret;
3928 static BOOL WINAPI CRYPT_AsnDecodeCertPolicies(DWORD dwCertEncodingType,
3929 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3930 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3932 BOOL ret = FALSE;
3934 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3935 pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3937 __TRY
3939 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3940 CRYPT_AsnDecodeCertPolicy, sizeof(CERT_POLICY_INFO), TRUE,
3941 offsetof(CERT_POLICY_INFO, pszPolicyIdentifier) };
3943 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3944 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
3946 __EXCEPT_PAGE_FAULT
3948 SetLastError(STATUS_ACCESS_VIOLATION);
3950 __ENDTRY
3951 return ret;
3954 #define RSA1_MAGIC 0x31415352
3956 struct DECODED_RSA_PUB_KEY
3958 DWORD pubexp;
3959 CRYPT_INTEGER_BLOB modulus;
3962 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
3963 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3964 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3966 BOOL ret;
3968 __TRY
3970 struct AsnDecodeSequenceItem items[] = {
3971 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
3972 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3973 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
3974 0 },
3975 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
3976 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3978 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
3979 DWORD size = 0;
3981 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3982 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
3983 &size, NULL, NULL);
3984 if (ret)
3986 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
3987 decodedKey->modulus.cbData;
3989 if (!pvStructInfo)
3991 *pcbStructInfo = bytesNeeded;
3992 ret = TRUE;
3994 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3995 pvStructInfo, pcbStructInfo, bytesNeeded)))
3997 BLOBHEADER *hdr;
3998 RSAPUBKEY *rsaPubKey;
4000 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4001 pvStructInfo = *(BYTE **)pvStructInfo;
4002 hdr = pvStructInfo;
4003 hdr->bType = PUBLICKEYBLOB;
4004 hdr->bVersion = CUR_BLOB_VERSION;
4005 hdr->reserved = 0;
4006 hdr->aiKeyAlg = CALG_RSA_KEYX;
4007 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
4008 sizeof(BLOBHEADER));
4009 rsaPubKey->magic = RSA1_MAGIC;
4010 rsaPubKey->pubexp = decodedKey->pubexp;
4011 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
4012 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
4013 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
4014 decodedKey->modulus.cbData);
4016 LocalFree(decodedKey);
4019 __EXCEPT_PAGE_FAULT
4021 SetLastError(STATUS_ACCESS_VIOLATION);
4022 ret = FALSE;
4024 __ENDTRY
4025 return ret;
4028 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
4029 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4030 DWORD *pcbDecoded)
4032 BOOL ret;
4033 DWORD bytesNeeded, dataLen;
4035 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4036 pvStructInfo, *pcbStructInfo, pcbDecoded);
4038 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4040 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4042 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4043 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
4044 else
4045 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
4046 if (pcbDecoded)
4047 *pcbDecoded = 1 + lenBytes + dataLen;
4048 if (!pvStructInfo)
4049 *pcbStructInfo = bytesNeeded;
4050 else if (*pcbStructInfo < bytesNeeded)
4052 SetLastError(ERROR_MORE_DATA);
4053 *pcbStructInfo = bytesNeeded;
4054 ret = FALSE;
4056 else
4058 CRYPT_DATA_BLOB *blob;
4060 *pcbStructInfo = bytesNeeded;
4061 blob = pvStructInfo;
4062 blob->cbData = dataLen;
4063 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4064 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
4065 else
4067 assert(blob->pbData);
4068 if (blob->cbData)
4069 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
4070 blob->cbData);
4074 return ret;
4077 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
4078 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4079 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4081 BOOL ret;
4083 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4084 pDecodePara, pvStructInfo, *pcbStructInfo);
4086 __TRY
4088 DWORD bytesNeeded;
4090 if (!cbEncoded)
4092 SetLastError(CRYPT_E_ASN1_CORRUPT);
4093 ret = FALSE;
4095 else if (pbEncoded[0] != ASN_OCTETSTRING)
4097 SetLastError(CRYPT_E_ASN1_BADTAG);
4098 ret = FALSE;
4100 else if ((ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
4101 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4103 if (!pvStructInfo)
4104 *pcbStructInfo = bytesNeeded;
4105 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4106 pvStructInfo, pcbStructInfo, bytesNeeded)))
4108 CRYPT_DATA_BLOB *blob;
4110 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4111 pvStructInfo = *(BYTE **)pvStructInfo;
4112 blob = pvStructInfo;
4113 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
4114 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
4115 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4116 &bytesNeeded, NULL);
4120 __EXCEPT_PAGE_FAULT
4122 SetLastError(STATUS_ACCESS_VIOLATION);
4123 ret = FALSE;
4125 __ENDTRY
4126 return ret;
4129 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
4130 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4132 BOOL ret;
4133 DWORD bytesNeeded, dataLen;
4134 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4136 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
4137 pvStructInfo, *pcbStructInfo, pcbDecoded);
4139 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4141 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4142 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
4143 else
4144 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
4145 if (pcbDecoded)
4146 *pcbDecoded = 1 + lenBytes + dataLen;
4147 if (!pvStructInfo)
4148 *pcbStructInfo = bytesNeeded;
4149 else if (*pcbStructInfo < bytesNeeded)
4151 *pcbStructInfo = bytesNeeded;
4152 SetLastError(ERROR_MORE_DATA);
4153 ret = FALSE;
4155 else
4157 CRYPT_BIT_BLOB *blob;
4159 *pcbStructInfo = bytesNeeded;
4160 blob = pvStructInfo;
4161 blob->cbData = dataLen - 1;
4162 blob->cUnusedBits = *(pbEncoded + 1 + lenBytes);
4163 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4165 blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes;
4167 else
4169 assert(blob->pbData);
4170 if (blob->cbData)
4172 BYTE mask = 0xff << blob->cUnusedBits;
4174 memcpy(blob->pbData, pbEncoded + 2 + lenBytes,
4175 blob->cbData);
4176 blob->pbData[blob->cbData - 1] &= mask;
4181 return ret;
4184 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
4185 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4186 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4188 BOOL ret;
4190 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
4191 pDecodePara, pvStructInfo, pcbStructInfo);
4193 __TRY
4195 DWORD bytesNeeded;
4197 if (!cbEncoded)
4199 SetLastError(CRYPT_E_ASN1_CORRUPT);
4200 ret = FALSE;
4202 else if (pbEncoded[0] != ASN_BITSTRING)
4204 SetLastError(CRYPT_E_ASN1_BADTAG);
4205 ret = FALSE;
4207 else if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
4208 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4210 if (!pvStructInfo)
4211 *pcbStructInfo = bytesNeeded;
4212 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4213 pvStructInfo, pcbStructInfo, bytesNeeded)))
4215 CRYPT_BIT_BLOB *blob;
4217 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4218 pvStructInfo = *(BYTE **)pvStructInfo;
4219 blob = pvStructInfo;
4220 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
4221 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
4222 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4223 &bytesNeeded, NULL);
4227 __EXCEPT_PAGE_FAULT
4229 SetLastError(STATUS_ACCESS_VIOLATION);
4230 ret = FALSE;
4232 __ENDTRY
4233 TRACE("returning %d (%08x)\n", ret, GetLastError());
4234 return ret;
4237 /* Ignores tag. Only allows integers 4 bytes or smaller in size. */
4238 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
4239 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4241 BOOL ret;
4242 BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
4243 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
4244 DWORD size = sizeof(buf);
4246 blob->pbData = buf + sizeof(CRYPT_INTEGER_BLOB);
4247 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded, 0, buf,
4248 &size, pcbDecoded);
4249 if (ret)
4251 if (!pvStructInfo)
4252 *pcbStructInfo = sizeof(int);
4253 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int))))
4255 int val, i;
4257 if (blob->pbData[blob->cbData - 1] & 0x80)
4259 /* initialize to a negative value to sign-extend */
4260 val = -1;
4262 else
4263 val = 0;
4264 for (i = 0; i < blob->cbData; i++)
4266 val <<= 8;
4267 val |= blob->pbData[blob->cbData - i - 1];
4269 memcpy(pvStructInfo, &val, sizeof(int));
4272 else if (GetLastError() == ERROR_MORE_DATA)
4273 SetLastError(CRYPT_E_ASN1_LARGE);
4274 return ret;
4277 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
4278 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4279 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4281 BOOL ret;
4283 __TRY
4285 DWORD bytesNeeded;
4287 if (!cbEncoded)
4289 SetLastError(CRYPT_E_ASN1_EOD);
4290 ret = FALSE;
4292 else if (pbEncoded[0] != ASN_INTEGER)
4294 SetLastError(CRYPT_E_ASN1_BADTAG);
4295 ret = FALSE;
4297 else
4298 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
4299 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4300 if (ret)
4302 if (!pvStructInfo)
4303 *pcbStructInfo = bytesNeeded;
4304 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4305 pvStructInfo, pcbStructInfo, bytesNeeded)))
4307 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4308 pvStructInfo = *(BYTE **)pvStructInfo;
4309 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
4310 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4311 &bytesNeeded, NULL);
4315 __EXCEPT_PAGE_FAULT
4317 SetLastError(STATUS_ACCESS_VIOLATION);
4318 ret = FALSE;
4320 __ENDTRY
4321 return ret;
4324 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
4325 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4326 DWORD *pcbDecoded)
4328 BOOL ret;
4329 DWORD bytesNeeded, dataLen;
4331 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4333 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4335 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
4336 if (pcbDecoded)
4337 *pcbDecoded = 1 + lenBytes + dataLen;
4338 if (!pvStructInfo)
4339 *pcbStructInfo = bytesNeeded;
4340 else if (*pcbStructInfo < bytesNeeded)
4342 *pcbStructInfo = bytesNeeded;
4343 SetLastError(ERROR_MORE_DATA);
4344 ret = FALSE;
4346 else
4348 CRYPT_INTEGER_BLOB *blob = pvStructInfo;
4350 *pcbStructInfo = bytesNeeded;
4351 blob->cbData = dataLen;
4352 assert(blob->pbData);
4353 if (blob->cbData)
4355 DWORD i;
4357 for (i = 0; i < blob->cbData; i++)
4359 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
4360 dataLen - i - 1);
4365 return ret;
4368 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
4369 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4370 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4372 BOOL ret;
4374 __TRY
4376 DWORD bytesNeeded;
4378 if (pbEncoded[0] != ASN_INTEGER)
4380 SetLastError(CRYPT_E_ASN1_BADTAG);
4381 ret = FALSE;
4383 else
4384 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
4385 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4386 if (ret)
4388 if (!pvStructInfo)
4389 *pcbStructInfo = bytesNeeded;
4390 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4391 pvStructInfo, pcbStructInfo, bytesNeeded)))
4393 CRYPT_INTEGER_BLOB *blob;
4395 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4396 pvStructInfo = *(BYTE **)pvStructInfo;
4397 blob = pvStructInfo;
4398 blob->pbData = (BYTE *)pvStructInfo +
4399 sizeof(CRYPT_INTEGER_BLOB);
4400 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
4401 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
4402 &bytesNeeded, NULL);
4406 __EXCEPT_PAGE_FAULT
4408 SetLastError(STATUS_ACCESS_VIOLATION);
4409 ret = FALSE;
4411 __ENDTRY
4412 return ret;
4415 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
4416 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4417 DWORD *pcbDecoded)
4419 BOOL ret;
4421 if (pbEncoded[0] == ASN_INTEGER)
4423 DWORD bytesNeeded, dataLen;
4425 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4427 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4429 if (pcbDecoded)
4430 *pcbDecoded = 1 + lenBytes + dataLen;
4431 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
4432 if (!pvStructInfo)
4433 *pcbStructInfo = bytesNeeded;
4434 else if (*pcbStructInfo < bytesNeeded)
4436 *pcbStructInfo = bytesNeeded;
4437 SetLastError(ERROR_MORE_DATA);
4438 ret = FALSE;
4440 else
4442 CRYPT_INTEGER_BLOB *blob = pvStructInfo;
4444 *pcbStructInfo = bytesNeeded;
4445 blob->cbData = dataLen;
4446 assert(blob->pbData);
4447 /* remove leading zero byte if it exists */
4448 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
4450 blob->cbData--;
4451 blob->pbData++;
4453 if (blob->cbData)
4455 DWORD i;
4457 for (i = 0; i < blob->cbData; i++)
4459 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
4460 dataLen - i - 1);
4466 else
4468 SetLastError(CRYPT_E_ASN1_BADTAG);
4469 ret = FALSE;
4471 return ret;
4474 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
4475 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4476 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4478 BOOL ret;
4480 __TRY
4482 DWORD bytesNeeded;
4484 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded,
4485 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4487 if (!pvStructInfo)
4488 *pcbStructInfo = bytesNeeded;
4489 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4490 pvStructInfo, pcbStructInfo, bytesNeeded)))
4492 CRYPT_INTEGER_BLOB *blob;
4494 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4495 pvStructInfo = *(BYTE **)pvStructInfo;
4496 blob = pvStructInfo;
4497 blob->pbData = (BYTE *)pvStructInfo +
4498 sizeof(CRYPT_INTEGER_BLOB);
4499 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded,
4500 cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
4501 &bytesNeeded, NULL);
4505 __EXCEPT_PAGE_FAULT
4507 SetLastError(STATUS_ACCESS_VIOLATION);
4508 ret = FALSE;
4510 __ENDTRY
4511 return ret;
4514 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
4515 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4516 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4518 BOOL ret;
4520 if (!pvStructInfo)
4522 *pcbStructInfo = sizeof(int);
4523 return TRUE;
4525 __TRY
4527 if (pbEncoded[0] == ASN_ENUMERATED)
4529 unsigned int val = 0, i;
4531 if (cbEncoded <= 1)
4533 SetLastError(CRYPT_E_ASN1_EOD);
4534 ret = FALSE;
4536 else if (pbEncoded[1] == 0)
4538 SetLastError(CRYPT_E_ASN1_CORRUPT);
4539 ret = FALSE;
4541 else
4543 /* A little strange looking, but we have to accept a sign byte:
4544 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
4545 * assuming a small length is okay here, it has to be in short
4546 * form.
4548 if (pbEncoded[1] > sizeof(unsigned int) + 1)
4550 SetLastError(CRYPT_E_ASN1_LARGE);
4551 return FALSE;
4553 for (i = 0; i < pbEncoded[1]; i++)
4555 val <<= 8;
4556 val |= pbEncoded[2 + i];
4558 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4559 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
4561 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4562 pvStructInfo = *(BYTE **)pvStructInfo;
4563 memcpy(pvStructInfo, &val, sizeof(unsigned int));
4567 else
4569 SetLastError(CRYPT_E_ASN1_BADTAG);
4570 ret = FALSE;
4573 __EXCEPT_PAGE_FAULT
4575 SetLastError(STATUS_ACCESS_VIOLATION);
4576 ret = FALSE;
4578 __ENDTRY
4579 return ret;
4582 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
4583 * if it fails.
4585 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
4586 do { \
4587 BYTE i; \
4589 (word) = 0; \
4590 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
4592 if (!isdigit(*(pbEncoded))) \
4594 SetLastError(CRYPT_E_ASN1_CORRUPT); \
4595 ret = FALSE; \
4597 else \
4599 (word) *= 10; \
4600 (word) += *(pbEncoded)++ - '0'; \
4603 } while (0)
4605 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
4606 SYSTEMTIME *sysTime)
4608 BOOL ret = TRUE;
4610 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
4612 WORD hours, minutes = 0;
4613 BYTE sign = *pbEncoded++;
4615 len--;
4616 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
4617 if (ret && hours >= 24)
4619 SetLastError(CRYPT_E_ASN1_CORRUPT);
4620 ret = FALSE;
4622 else if (len >= 2)
4624 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
4625 if (ret && minutes >= 60)
4627 SetLastError(CRYPT_E_ASN1_CORRUPT);
4628 ret = FALSE;
4631 if (ret)
4633 if (sign == '+')
4635 sysTime->wHour += hours;
4636 sysTime->wMinute += minutes;
4638 else
4640 if (hours > sysTime->wHour)
4642 sysTime->wDay--;
4643 sysTime->wHour = 24 - (hours - sysTime->wHour);
4645 else
4646 sysTime->wHour -= hours;
4647 if (minutes > sysTime->wMinute)
4649 sysTime->wHour--;
4650 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
4652 else
4653 sysTime->wMinute -= minutes;
4657 return ret;
4660 #define MIN_ENCODED_TIME_LENGTH 10
4662 static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
4663 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4664 DWORD *pcbDecoded)
4666 BOOL ret = FALSE;
4668 if (pbEncoded[0] == ASN_UTCTIME)
4670 if (cbEncoded <= 1)
4671 SetLastError(CRYPT_E_ASN1_EOD);
4672 else if (pbEncoded[1] > 0x7f)
4674 /* long-form date strings really can't be valid */
4675 SetLastError(CRYPT_E_ASN1_CORRUPT);
4677 else
4679 SYSTEMTIME sysTime = { 0 };
4680 BYTE len = pbEncoded[1];
4682 if (len < MIN_ENCODED_TIME_LENGTH)
4683 SetLastError(CRYPT_E_ASN1_CORRUPT);
4684 else
4686 ret = TRUE;
4687 if (pcbDecoded)
4688 *pcbDecoded = 2 + len;
4689 pbEncoded += 2;
4690 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
4691 if (sysTime.wYear >= 50)
4692 sysTime.wYear += 1900;
4693 else
4694 sysTime.wYear += 2000;
4695 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
4696 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
4697 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
4698 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
4699 if (ret && len > 0)
4701 if (len >= 2 && isdigit(*pbEncoded) &&
4702 isdigit(*(pbEncoded + 1)))
4703 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4704 sysTime.wSecond);
4705 else if (isdigit(*pbEncoded))
4706 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
4707 sysTime.wSecond);
4708 if (ret)
4709 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
4710 &sysTime);
4712 if (ret)
4714 if (!pvStructInfo)
4715 *pcbStructInfo = sizeof(FILETIME);
4716 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
4717 sizeof(FILETIME))))
4718 ret = SystemTimeToFileTime(&sysTime, pvStructInfo);
4723 else
4724 SetLastError(CRYPT_E_ASN1_BADTAG);
4725 return ret;
4728 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
4729 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4730 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4732 BOOL ret = FALSE;
4734 __TRY
4736 DWORD bytesNeeded;
4738 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
4739 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4740 if (ret)
4742 if (!pvStructInfo)
4743 *pcbStructInfo = bytesNeeded;
4744 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
4745 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
4747 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4748 pvStructInfo = *(BYTE **)pvStructInfo;
4749 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
4750 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4751 &bytesNeeded, NULL);
4755 __EXCEPT_PAGE_FAULT
4757 SetLastError(STATUS_ACCESS_VIOLATION);
4759 __ENDTRY
4760 return ret;
4763 static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
4764 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4765 DWORD *pcbDecoded)
4767 BOOL ret = FALSE;
4769 if (pbEncoded[0] == ASN_GENERALTIME)
4771 if (cbEncoded <= 1)
4772 SetLastError(CRYPT_E_ASN1_EOD);
4773 else if (pbEncoded[1] > 0x7f)
4775 /* long-form date strings really can't be valid */
4776 SetLastError(CRYPT_E_ASN1_CORRUPT);
4778 else
4780 BYTE len = pbEncoded[1];
4782 if (len < MIN_ENCODED_TIME_LENGTH)
4783 SetLastError(CRYPT_E_ASN1_CORRUPT);
4784 else
4786 SYSTEMTIME sysTime = { 0 };
4788 ret = TRUE;
4789 if (pcbDecoded)
4790 *pcbDecoded = 2 + len;
4791 pbEncoded += 2;
4792 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
4793 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
4794 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
4795 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
4796 if (ret && len > 0)
4798 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4799 sysTime.wMinute);
4800 if (ret && len > 0)
4801 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4802 sysTime.wSecond);
4803 if (ret && len > 0 && (*pbEncoded == '.' ||
4804 *pbEncoded == ','))
4806 BYTE digits;
4808 pbEncoded++;
4809 len--;
4810 /* workaround macro weirdness */
4811 digits = min(len, 3);
4812 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
4813 sysTime.wMilliseconds);
4815 if (ret)
4816 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
4817 &sysTime);
4819 if (ret)
4821 if (!pvStructInfo)
4822 *pcbStructInfo = sizeof(FILETIME);
4823 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
4824 sizeof(FILETIME))))
4825 ret = SystemTimeToFileTime(&sysTime, pvStructInfo);
4830 else
4831 SetLastError(CRYPT_E_ASN1_BADTAG);
4832 return ret;
4835 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
4836 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4837 DWORD *pcbDecoded)
4839 BOOL ret;
4840 InternalDecodeFunc decode = NULL;
4842 if (pbEncoded[0] == ASN_UTCTIME)
4843 decode = CRYPT_AsnDecodeUtcTimeInternal;
4844 else if (pbEncoded[0] == ASN_GENERALTIME)
4845 decode = CRYPT_AsnDecodeGeneralizedTime;
4846 if (decode)
4847 ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
4848 pcbStructInfo, pcbDecoded);
4849 else
4851 SetLastError(CRYPT_E_ASN1_BADTAG);
4852 ret = FALSE;
4854 return ret;
4857 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
4858 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4859 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4861 BOOL ret;
4863 __TRY
4865 DWORD bytesNeeded;
4867 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
4868 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4869 if (ret)
4871 if (!pvStructInfo)
4872 *pcbStructInfo = bytesNeeded;
4873 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4874 pvStructInfo, pcbStructInfo, bytesNeeded)))
4876 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4877 pvStructInfo = *(BYTE **)pvStructInfo;
4878 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
4879 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4880 &bytesNeeded, NULL);
4884 __EXCEPT_PAGE_FAULT
4886 SetLastError(STATUS_ACCESS_VIOLATION);
4887 ret = FALSE;
4889 __ENDTRY
4890 return ret;
4893 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
4894 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4895 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4897 BOOL ret = TRUE;
4899 __TRY
4901 if (pbEncoded[0] == ASN_SEQUENCEOF)
4903 DWORD bytesNeeded, dataLen, remainingLen, cValue;
4905 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4907 BYTE lenBytes;
4908 const BYTE *ptr;
4910 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4911 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
4912 cValue = 0;
4913 ptr = pbEncoded + 1 + lenBytes;
4914 remainingLen = dataLen;
4915 while (ret && remainingLen)
4917 DWORD nextLen;
4919 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
4920 if (ret)
4922 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
4924 remainingLen -= 1 + nextLenBytes + nextLen;
4925 ptr += 1 + nextLenBytes + nextLen;
4926 bytesNeeded += sizeof(CRYPT_DER_BLOB);
4927 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
4928 bytesNeeded += 1 + nextLenBytes + nextLen;
4929 cValue++;
4932 if (ret)
4934 CRYPT_SEQUENCE_OF_ANY *seq;
4935 BYTE *nextPtr;
4936 DWORD i;
4938 if (!pvStructInfo)
4939 *pcbStructInfo = bytesNeeded;
4940 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4941 pvStructInfo, pcbStructInfo, bytesNeeded)))
4943 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4944 pvStructInfo = *(BYTE **)pvStructInfo;
4945 seq = pvStructInfo;
4946 seq->cValue = cValue;
4947 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
4948 sizeof(*seq));
4949 nextPtr = (BYTE *)seq->rgValue +
4950 cValue * sizeof(CRYPT_DER_BLOB);
4951 ptr = pbEncoded + 1 + lenBytes;
4952 remainingLen = dataLen;
4953 i = 0;
4954 while (ret && remainingLen)
4956 DWORD nextLen;
4958 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
4959 if (ret)
4961 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
4963 seq->rgValue[i].cbData = 1 + nextLenBytes +
4964 nextLen;
4965 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4966 seq->rgValue[i].pbData = (BYTE *)ptr;
4967 else
4969 seq->rgValue[i].pbData = nextPtr;
4970 memcpy(nextPtr, ptr, 1 + nextLenBytes +
4971 nextLen);
4972 nextPtr += 1 + nextLenBytes + nextLen;
4974 remainingLen -= 1 + nextLenBytes + nextLen;
4975 ptr += 1 + nextLenBytes + nextLen;
4976 i++;
4983 else
4985 SetLastError(CRYPT_E_ASN1_BADTAG);
4986 ret = FALSE;
4989 __EXCEPT_PAGE_FAULT
4991 SetLastError(STATUS_ACCESS_VIOLATION);
4992 ret = FALSE;
4994 __ENDTRY
4995 return ret;
4998 static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded,
4999 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5000 DWORD *pcbDecoded)
5002 BOOL ret;
5004 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
5006 DWORD bytesNeeded, dataLen;
5008 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
5010 struct AsnArrayDescriptor arrayDesc = {
5011 ASN_CONTEXT | ASN_CONSTRUCTOR | 0, CRYPT_AsnDecodeAltNameEntry,
5012 sizeof(CERT_ALT_NAME_ENTRY), TRUE,
5013 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
5014 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
5015 DWORD nameLen;
5017 if (dataLen)
5019 ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc,
5020 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
5021 NULL, NULL, &nameLen, NULL);
5022 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen;
5024 else
5025 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
5026 if (pcbDecoded)
5027 *pcbDecoded = 1 + lenBytes + dataLen;
5028 if (!pvStructInfo)
5029 *pcbStructInfo = bytesNeeded;
5030 else if (*pcbStructInfo < bytesNeeded)
5032 *pcbStructInfo = bytesNeeded;
5033 SetLastError(ERROR_MORE_DATA);
5034 ret = FALSE;
5036 else
5038 CRL_DIST_POINT_NAME *name = pvStructInfo;
5040 *pcbStructInfo = bytesNeeded;
5041 if (dataLen)
5043 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
5044 ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc,
5045 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
5046 &name->u.FullName.cAltEntry, name->u.FullName.rgAltEntry,
5047 &nameLen, NULL);
5049 else
5050 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
5054 else
5056 SetLastError(CRYPT_E_ASN1_BADTAG);
5057 ret = FALSE;
5059 return ret;
5062 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
5063 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5065 struct AsnDecodeSequenceItem items[] = {
5066 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
5067 DistPointName), CRYPT_AsnDecodeDistPointName,
5068 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
5069 DistPointName.u.FullName.rgAltEntry), 0 },
5070 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
5071 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
5072 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
5073 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
5074 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
5075 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
5077 CRL_DIST_POINT *point = pvStructInfo;
5078 BOOL ret;
5080 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5081 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5082 pcbDecoded, point ? point->DistPointName.u.FullName.rgAltEntry : NULL);
5083 return ret;
5086 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
5087 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5088 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5090 BOOL ret;
5092 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5093 pDecodePara, pvStructInfo, *pcbStructInfo);
5095 __TRY
5097 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
5098 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
5099 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
5101 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
5102 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
5104 __EXCEPT_PAGE_FAULT
5106 SetLastError(STATUS_ACCESS_VIOLATION);
5107 ret = FALSE;
5109 __ENDTRY
5110 return ret;
5113 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
5114 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5115 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5117 BOOL ret;
5119 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5120 pDecodePara, pvStructInfo, *pcbStructInfo);
5122 __TRY
5124 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
5125 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
5127 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
5128 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
5130 __EXCEPT_PAGE_FAULT
5132 SetLastError(STATUS_ACCESS_VIOLATION);
5133 ret = FALSE;
5135 __ENDTRY
5136 return ret;
5139 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
5140 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5141 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5143 BOOL ret;
5145 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5146 pDecodePara, pvStructInfo, *pcbStructInfo);
5148 __TRY
5150 struct AsnDecodeSequenceItem items[] = {
5151 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
5152 DistPointName), CRYPT_AsnDecodeDistPointName,
5153 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
5154 offsetof(CRL_ISSUING_DIST_POINT,
5155 DistPointName.u.FullName.rgAltEntry), 0 },
5156 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
5157 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
5158 FALSE, 0 },
5159 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
5160 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
5161 FALSE, 0 },
5162 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
5163 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
5164 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
5165 OnlySomeReasonFlags.pbData), 0 },
5166 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
5167 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
5170 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5171 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
5172 pcbStructInfo, NULL, NULL);
5174 __EXCEPT_PAGE_FAULT
5176 SetLastError(STATUS_ACCESS_VIOLATION);
5177 ret = FALSE;
5179 __ENDTRY
5180 return ret;
5183 static BOOL CRYPT_AsnDecodeMaximum(const BYTE *pbEncoded,
5184 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5185 DWORD *pcbDecoded)
5187 BOOL ret = FALSE;
5189 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5190 pvStructInfo, *pcbStructInfo, pcbDecoded);
5192 if (!cbEncoded)
5194 SetLastError(CRYPT_E_ASN1_EOD);
5195 return FALSE;
5197 if (pbEncoded[0] != (ASN_CONTEXT | 1))
5199 SetLastError(CRYPT_E_ASN1_BADTAG);
5200 return FALSE;
5202 /* The BOOL is implicit: if the integer is present, then it's TRUE */
5203 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
5204 pvStructInfo ? (BYTE *)pvStructInfo + sizeof(BOOL) : NULL, pcbStructInfo,
5205 pcbDecoded);
5206 if (ret && pvStructInfo)
5207 *(BOOL *)pvStructInfo = TRUE;
5208 TRACE("returning %d\n", ret);
5209 return ret;
5212 static BOOL CRYPT_AsnDecodeSubtree(const BYTE *pbEncoded,
5213 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5214 DWORD *pcbDecoded)
5216 BOOL ret;
5217 struct AsnDecodeSequenceItem items[] = {
5218 { 0, offsetof(CERT_GENERAL_SUBTREE, Base),
5219 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE, TRUE,
5220 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL), 0 },
5221 { ASN_CONTEXT | 0, offsetof(CERT_GENERAL_SUBTREE, dwMinimum),
5222 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
5223 { ASN_CONTEXT | 1, offsetof(CERT_GENERAL_SUBTREE, fMaximum),
5224 CRYPT_AsnDecodeMaximum, sizeof(BOOL) + sizeof(DWORD), TRUE, FALSE, 0,
5225 0 },
5227 CERT_GENERAL_SUBTREE *subtree = pvStructInfo;
5229 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5230 pvStructInfo, *pcbStructInfo, pcbDecoded);
5232 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5233 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5234 pcbDecoded, subtree ? subtree->Base.u.pwszURL : NULL);
5235 if (pcbDecoded)
5237 TRACE("%d\n", *pcbDecoded);
5238 if (*pcbDecoded < cbEncoded)
5239 TRACE("%02x %02x\n", *(pbEncoded + *pcbDecoded),
5240 *(pbEncoded + *pcbDecoded + 1));
5242 TRACE("returning %d\n", ret);
5243 return ret;
5246 static BOOL CRYPT_AsnDecodePermittedSubtree(const BYTE *pbEncoded,
5247 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5248 DWORD *pcbDecoded)
5250 BOOL ret = TRUE;
5251 struct AsnArrayDescriptor arrayDesc = { 0,
5252 CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
5253 offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
5254 DWORD bytesNeeded;
5256 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5257 pvStructInfo, *pcbStructInfo, pcbDecoded);
5259 if ((ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
5260 NULL, NULL, &bytesNeeded, pcbDecoded)))
5262 bytesNeeded += MEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO,
5263 cPermittedSubtree, cExcludedSubtree);
5264 if (!pvStructInfo)
5265 *pcbStructInfo = bytesNeeded;
5266 else if ((ret = CRYPT_DecodeEnsureSpace(0, NULL, pvStructInfo,
5267 pcbStructInfo, bytesNeeded)))
5269 CERT_NAME_CONSTRAINTS_INFO *info = (CERT_NAME_CONSTRAINTS_INFO *)
5270 ((BYTE *)pvStructInfo -
5271 offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree));
5273 ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
5274 &info->cPermittedSubtree, info->rgPermittedSubtree, &bytesNeeded,
5275 pcbDecoded);
5278 return ret;
5281 static BOOL CRYPT_AsnDecodeExcludedSubtree(const BYTE *pbEncoded,
5282 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5283 DWORD *pcbDecoded)
5285 BOOL ret = TRUE;
5286 struct AsnArrayDescriptor arrayDesc = { 0,
5287 CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
5288 offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
5289 DWORD bytesNeeded;
5291 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5292 pvStructInfo, *pcbStructInfo, pcbDecoded);
5294 if ((ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
5295 NULL, NULL, &bytesNeeded, pcbDecoded)))
5297 bytesNeeded += FINALMEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO,
5298 cExcludedSubtree);
5299 if (!pvStructInfo)
5300 *pcbStructInfo = bytesNeeded;
5301 else if ((ret = CRYPT_DecodeEnsureSpace(0, NULL, pvStructInfo,
5302 pcbStructInfo, bytesNeeded)))
5304 CERT_NAME_CONSTRAINTS_INFO *info = (CERT_NAME_CONSTRAINTS_INFO *)
5305 ((BYTE *)pvStructInfo -
5306 offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree));
5308 ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
5309 &info->cExcludedSubtree, info->rgExcludedSubtree, &bytesNeeded,
5310 pcbDecoded);
5313 return ret;
5316 static BOOL WINAPI CRYPT_AsnDecodeNameConstraints(DWORD dwCertEncodingType,
5317 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5318 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5320 BOOL ret = FALSE;
5322 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5323 pDecodePara, pvStructInfo, *pcbStructInfo);
5325 __TRY
5327 struct AsnDecodeSequenceItem items[] = {
5328 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
5329 offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
5330 CRYPT_AsnDecodePermittedSubtree,
5331 MEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree,
5332 cExcludedSubtree), TRUE, TRUE,
5333 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree), 0 },
5334 { ASN_CONTEXT | ASN_CONSTRUCTOR | 1,
5335 offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5336 CRYPT_AsnDecodeExcludedSubtree,
5337 FINALMEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5338 TRUE, TRUE,
5339 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree), 0 },
5342 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5343 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
5344 pcbStructInfo, NULL, NULL);
5346 __EXCEPT_PAGE_FAULT
5348 SetLastError(STATUS_ACCESS_VIOLATION);
5350 __ENDTRY
5351 return ret;
5354 static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded,
5355 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5356 DWORD *pcbDecoded)
5358 BOOL ret;
5359 struct AsnDecodeSequenceItem items[] = {
5360 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
5361 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
5362 Issuer.pbData) },
5363 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
5364 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
5365 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
5367 CERT_ISSUER_SERIAL_NUMBER *issuerSerial = pvStructInfo;
5369 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5370 pvStructInfo, *pcbStructInfo, pcbDecoded);
5372 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5373 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5374 pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL);
5375 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
5377 SetLastError(CRYPT_E_ASN1_CORRUPT);
5378 ret = FALSE;
5380 TRACE("returning %d\n", ret);
5381 return ret;
5384 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
5385 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5386 DWORD *pcbDecoded)
5388 CMSG_SIGNER_INFO *info = pvStructInfo;
5389 struct AsnDecodeSequenceItem items[] = {
5390 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
5391 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5392 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
5393 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
5394 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
5395 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
5396 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5397 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
5398 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5399 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
5400 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5401 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
5402 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
5403 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5404 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
5405 HashEncryptionAlgorithm.pszObjId), 0 },
5406 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
5407 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
5408 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
5409 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5410 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
5411 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5412 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
5414 BOOL ret;
5416 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5417 pvStructInfo, *pcbStructInfo);
5419 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5420 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5421 pcbDecoded, info ? info->Issuer.pbData : NULL);
5422 return ret;
5425 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
5426 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5427 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5429 BOOL ret = FALSE;
5431 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5432 pDecodePara, pvStructInfo, *pcbStructInfo);
5434 __TRY
5436 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
5437 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
5438 if (ret && pvStructInfo)
5440 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
5441 pcbStructInfo, *pcbStructInfo);
5442 if (ret)
5444 CMSG_SIGNER_INFO *info;
5446 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5447 pvStructInfo = *(BYTE **)pvStructInfo;
5448 info = pvStructInfo;
5449 info->Issuer.pbData = ((BYTE *)info +
5450 sizeof(CMSG_SIGNER_INFO));
5451 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
5452 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5453 pcbStructInfo, NULL);
5457 __EXCEPT_PAGE_FAULT
5459 SetLastError(STATUS_ACCESS_VIOLATION);
5461 __ENDTRY
5462 TRACE("returning %d\n", ret);
5463 return ret;
5466 static BOOL CRYPT_AsnDecodeCMSCertEncoded(const BYTE *pbEncoded,
5467 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5468 DWORD *pcbDecoded)
5470 BOOL ret;
5471 struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytes,
5472 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
5473 DWORD bytesNeeded;
5475 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5476 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
5478 if ((ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
5479 NULL, NULL, &bytesNeeded, pcbDecoded)))
5481 bytesNeeded += MEMBERSIZE(CRYPT_SIGNED_INFO, cCertEncoded, cCrlEncoded);
5482 if (!pvStructInfo)
5483 *pcbStructInfo = bytesNeeded;
5484 else if ((ret = CRYPT_DecodeEnsureSpace(0, NULL, pvStructInfo,
5485 pcbStructInfo, bytesNeeded)))
5487 CRYPT_SIGNED_INFO *info = (CRYPT_SIGNED_INFO *)
5488 ((BYTE *)pvStructInfo - offsetof(CRYPT_SIGNED_INFO, cCertEncoded));
5490 ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
5491 &info->cCertEncoded, info->rgCertEncoded, &bytesNeeded,
5492 pcbDecoded);
5495 return ret;
5498 static BOOL CRYPT_AsnDecodeCMSCrlEncoded(const BYTE *pbEncoded,
5499 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5500 DWORD *pcbDecoded)
5502 BOOL ret;
5503 struct AsnArrayDescriptor arrayDesc = { 0, CRYPT_AsnDecodeCopyBytes,
5504 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
5505 DWORD bytesNeeded;
5507 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5508 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
5510 if ((ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
5511 NULL, NULL, &bytesNeeded, pcbDecoded)))
5513 bytesNeeded += MEMBERSIZE(CRYPT_SIGNED_INFO, cCrlEncoded, content);
5514 if (!pvStructInfo)
5515 *pcbStructInfo = bytesNeeded;
5516 else if ((ret = CRYPT_DecodeEnsureSpace(0, NULL, pvStructInfo,
5517 pcbStructInfo, bytesNeeded)))
5519 CRYPT_SIGNED_INFO *info = (CRYPT_SIGNED_INFO *)
5520 ((BYTE *)pvStructInfo - offsetof(CRYPT_SIGNED_INFO, cCrlEncoded));
5522 ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
5523 &info->cCrlEncoded, info->rgCrlEncoded, &bytesNeeded,
5524 pcbDecoded);
5527 return ret;
5530 static BOOL CRYPT_AsnDecodeCMSSignerId(const BYTE *pbEncoded,
5531 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5532 DWORD *pcbDecoded)
5534 CERT_ID *id = pvStructInfo;
5535 BOOL ret = FALSE;
5537 if (*pbEncoded == ASN_SEQUENCEOF)
5539 ret = CRYPT_AsnDecodeIssuerSerialNumber(pbEncoded, cbEncoded, dwFlags,
5540 id ? &id->u.IssuerSerialNumber : NULL, pcbStructInfo, pcbDecoded);
5541 if (ret)
5543 if (id)
5544 id->dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
5545 if (*pcbStructInfo > sizeof(CERT_ISSUER_SERIAL_NUMBER))
5546 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
5547 sizeof(CERT_ISSUER_SERIAL_NUMBER);
5548 else
5549 *pcbStructInfo = sizeof(CERT_ID);
5552 else if (*pbEncoded == (ASN_CONTEXT | 0))
5554 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded, dwFlags,
5555 id ? &id->u.KeyId : NULL, pcbStructInfo, pcbDecoded);
5556 if (ret)
5558 if (id)
5559 id->dwIdChoice = CERT_ID_KEY_IDENTIFIER;
5560 if (*pcbStructInfo > sizeof(CRYPT_DATA_BLOB))
5561 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
5562 sizeof(CRYPT_DATA_BLOB);
5563 else
5564 *pcbStructInfo = sizeof(CERT_ID);
5567 else
5568 SetLastError(CRYPT_E_ASN1_BADTAG);
5569 return ret;
5572 static BOOL CRYPT_AsnDecodeCMSSignerInfoInternal(const BYTE *pbEncoded,
5573 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5574 DWORD *pcbDecoded)
5576 CMSG_CMS_SIGNER_INFO *info = pvStructInfo;
5577 struct AsnDecodeSequenceItem items[] = {
5578 { ASN_INTEGER, offsetof(CMSG_CMS_SIGNER_INFO, dwVersion),
5579 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5580 { 0, offsetof(CMSG_CMS_SIGNER_INFO, SignerId),
5581 CRYPT_AsnDecodeCMSSignerId, sizeof(CERT_ID), FALSE, TRUE,
5582 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData), 0 },
5583 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm),
5584 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5585 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
5586 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5587 offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs),
5588 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5589 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
5590 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashEncryptionAlgorithm),
5591 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5592 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO,
5593 HashEncryptionAlgorithm.pszObjId), 0 },
5594 { ASN_OCTETSTRING, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash),
5595 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
5596 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash.pbData), 0 },
5597 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5598 offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs),
5599 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5600 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
5602 BOOL ret;
5604 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5605 pvStructInfo, *pcbStructInfo);
5607 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5608 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5609 pcbDecoded, info ? info->SignerId.u.KeyId.pbData : NULL);
5610 return ret;
5613 static BOOL WINAPI CRYPT_AsnDecodeCMSSignerInfo(DWORD dwCertEncodingType,
5614 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5615 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5617 BOOL ret = FALSE;
5619 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5620 pDecodePara, pvStructInfo, *pcbStructInfo);
5622 __TRY
5624 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded, cbEncoded,
5625 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
5626 if (ret && pvStructInfo)
5628 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
5629 pcbStructInfo, *pcbStructInfo);
5630 if (ret)
5632 CMSG_CMS_SIGNER_INFO *info;
5634 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5635 pvStructInfo = *(BYTE **)pvStructInfo;
5636 info = pvStructInfo;
5637 info->SignerId.u.KeyId.pbData = ((BYTE *)info +
5638 sizeof(CMSG_CMS_SIGNER_INFO));
5639 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded,
5640 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5641 pcbStructInfo, NULL);
5645 __EXCEPT_PAGE_FAULT
5647 SetLastError(STATUS_ACCESS_VIOLATION);
5649 __ENDTRY
5650 TRACE("returning %d\n", ret);
5651 return ret;
5654 static BOOL CRYPT_DecodeSignerArray(const BYTE *pbEncoded, DWORD cbEncoded,
5655 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5657 BOOL ret;
5658 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
5659 CRYPT_AsnDecodeCMSSignerInfoInternal, sizeof(CMSG_CMS_SIGNER_INFO), TRUE,
5660 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData) };
5661 DWORD bytesNeeded;
5663 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5664 pvStructInfo, *pcbStructInfo, pcbDecoded);
5666 if ((ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
5667 NULL, NULL, &bytesNeeded, pcbDecoded)))
5669 bytesNeeded += FINALMEMBERSIZE(CRYPT_SIGNED_INFO, cSignerInfo);
5670 if (!pvStructInfo)
5671 *pcbStructInfo = bytesNeeded;
5672 else if ((ret = CRYPT_DecodeEnsureSpace(0, NULL, pvStructInfo,
5673 pcbStructInfo, bytesNeeded)))
5675 CRYPT_SIGNED_INFO *info = (CRYPT_SIGNED_INFO *)
5676 ((BYTE *)pvStructInfo - offsetof(CRYPT_SIGNED_INFO, cSignerInfo));
5678 ret = CRYPT_AsnDecodeArrayNoAlloc(&arrayDesc, pbEncoded, cbEncoded,
5679 &info->cSignerInfo, info->rgSignerInfo, &bytesNeeded,
5680 pcbDecoded);
5683 return ret;
5686 BOOL CRYPT_AsnDecodeCMSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
5687 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
5688 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
5690 BOOL ret = FALSE;
5691 struct AsnDecodeSequenceItem items[] = {
5692 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version),
5693 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5694 /* Placeholder for the hash algorithms - redundant with those in the
5695 * signers, so just ignore them.
5697 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
5698 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
5699 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
5700 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
5701 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5702 offsetof(CRYPT_SIGNED_INFO, cCertEncoded), CRYPT_AsnDecodeCMSCertEncoded,
5703 MEMBERSIZE(CRYPT_SIGNED_INFO, cCertEncoded, cCrlEncoded), TRUE, TRUE,
5704 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
5705 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5706 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_AsnDecodeCMSCrlEncoded,
5707 MEMBERSIZE(CRYPT_SIGNED_INFO, cCrlEncoded, content), TRUE, TRUE,
5708 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
5709 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
5710 CRYPT_DecodeSignerArray,
5711 FINALMEMBERSIZE(CRYPT_SIGNED_INFO, cSignerInfo), TRUE, TRUE,
5712 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
5715 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5716 pDecodePara, signedInfo, *pcbSignedInfo);
5718 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5719 pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo,
5720 NULL, NULL);
5721 TRACE("returning %d\n", ret);
5722 return ret;
5725 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
5726 LPCSTR lpszStructType)
5728 CryptDecodeObjectExFunc decodeFunc = NULL;
5730 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
5731 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
5733 SetLastError(ERROR_FILE_NOT_FOUND);
5734 return NULL;
5736 if (!HIWORD(lpszStructType))
5738 switch (LOWORD(lpszStructType))
5740 case LOWORD(X509_CERT):
5741 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
5742 break;
5743 case LOWORD(X509_CERT_TO_BE_SIGNED):
5744 decodeFunc = CRYPT_AsnDecodeCert;
5745 break;
5746 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
5747 decodeFunc = CRYPT_AsnDecodeCRL;
5748 break;
5749 case LOWORD(X509_EXTENSIONS):
5750 decodeFunc = CRYPT_AsnDecodeExtensions;
5751 break;
5752 case LOWORD(X509_NAME_VALUE):
5753 decodeFunc = CRYPT_AsnDecodeNameValue;
5754 break;
5755 case LOWORD(X509_NAME):
5756 decodeFunc = CRYPT_AsnDecodeName;
5757 break;
5758 case LOWORD(X509_PUBLIC_KEY_INFO):
5759 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
5760 break;
5761 case LOWORD(X509_AUTHORITY_KEY_ID):
5762 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
5763 break;
5764 case LOWORD(X509_ALTERNATE_NAME):
5765 decodeFunc = CRYPT_AsnDecodeAltName;
5766 break;
5767 case LOWORD(X509_BASIC_CONSTRAINTS):
5768 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
5769 break;
5770 case LOWORD(X509_BASIC_CONSTRAINTS2):
5771 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
5772 break;
5773 case LOWORD(X509_CERT_POLICIES):
5774 decodeFunc = CRYPT_AsnDecodeCertPolicies;
5775 break;
5776 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
5777 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
5778 break;
5779 case LOWORD(X509_UNICODE_NAME):
5780 decodeFunc = CRYPT_AsnDecodeUnicodeName;
5781 break;
5782 case LOWORD(PKCS_ATTRIBUTE):
5783 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
5784 break;
5785 case LOWORD(X509_UNICODE_NAME_VALUE):
5786 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
5787 break;
5788 case LOWORD(X509_OCTET_STRING):
5789 decodeFunc = CRYPT_AsnDecodeOctets;
5790 break;
5791 case LOWORD(X509_BITS):
5792 case LOWORD(X509_KEY_USAGE):
5793 decodeFunc = CRYPT_AsnDecodeBits;
5794 break;
5795 case LOWORD(X509_INTEGER):
5796 decodeFunc = CRYPT_AsnDecodeInt;
5797 break;
5798 case LOWORD(X509_MULTI_BYTE_INTEGER):
5799 decodeFunc = CRYPT_AsnDecodeInteger;
5800 break;
5801 case LOWORD(X509_MULTI_BYTE_UINT):
5802 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
5803 break;
5804 case LOWORD(X509_ENUMERATED):
5805 decodeFunc = CRYPT_AsnDecodeEnumerated;
5806 break;
5807 case LOWORD(X509_CHOICE_OF_TIME):
5808 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
5809 break;
5810 case LOWORD(X509_AUTHORITY_KEY_ID2):
5811 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
5812 break;
5813 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
5814 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
5815 break;
5816 case LOWORD(PKCS_CONTENT_INFO):
5817 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
5818 break;
5819 case LOWORD(X509_SEQUENCE_OF_ANY):
5820 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
5821 break;
5822 case LOWORD(PKCS_UTC_TIME):
5823 decodeFunc = CRYPT_AsnDecodeUtcTime;
5824 break;
5825 case LOWORD(X509_CRL_DIST_POINTS):
5826 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
5827 break;
5828 case LOWORD(X509_ENHANCED_KEY_USAGE):
5829 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
5830 break;
5831 case LOWORD(PKCS_CTL):
5832 decodeFunc = CRYPT_AsnDecodeCTL;
5833 break;
5834 case LOWORD(PKCS_SMIME_CAPABILITIES):
5835 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
5836 break;
5837 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE):
5838 decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
5839 break;
5840 case LOWORD(PKCS_ATTRIBUTES):
5841 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
5842 break;
5843 case LOWORD(X509_ISSUING_DIST_POINT):
5844 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
5845 break;
5846 case LOWORD(X509_NAME_CONSTRAINTS):
5847 decodeFunc = CRYPT_AsnDecodeNameConstraints;
5848 break;
5849 case LOWORD(PKCS7_SIGNER_INFO):
5850 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
5851 break;
5852 case LOWORD(CMS_SIGNER_INFO):
5853 decodeFunc = CRYPT_AsnDecodeCMSSignerInfo;
5854 break;
5857 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
5858 decodeFunc = CRYPT_AsnDecodeExtensions;
5859 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
5860 decodeFunc = CRYPT_AsnDecodeUtcTime;
5861 else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
5862 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
5863 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
5864 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
5865 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
5866 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
5867 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
5868 decodeFunc = CRYPT_AsnDecodeEnumerated;
5869 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
5870 decodeFunc = CRYPT_AsnDecodeBits;
5871 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
5872 decodeFunc = CRYPT_AsnDecodeOctets;
5873 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
5874 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
5875 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
5876 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
5877 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
5878 decodeFunc = CRYPT_AsnDecodeAltName;
5879 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
5880 decodeFunc = CRYPT_AsnDecodeAltName;
5881 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
5882 decodeFunc = CRYPT_AsnDecodeAltName;
5883 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
5884 decodeFunc = CRYPT_AsnDecodeAltName;
5885 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
5886 decodeFunc = CRYPT_AsnDecodeAltName;
5887 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
5888 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
5889 else if (!strcmp(lpszStructType, szOID_CERT_POLICIES))
5890 decodeFunc = CRYPT_AsnDecodeCertPolicies;
5891 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
5892 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
5893 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
5894 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
5895 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
5896 decodeFunc = CRYPT_AsnDecodeNameConstraints;
5897 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
5898 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
5899 else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
5900 decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
5901 else if (!strcmp(lpszStructType, szOID_CTL))
5902 decodeFunc = CRYPT_AsnDecodeCTL;
5903 return decodeFunc;
5906 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
5907 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
5909 static HCRYPTOIDFUNCSET set = NULL;
5910 CryptDecodeObjectFunc decodeFunc = NULL;
5912 if (!set)
5913 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
5914 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
5915 (void **)&decodeFunc, hFunc);
5916 return decodeFunc;
5919 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
5920 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
5922 static HCRYPTOIDFUNCSET set = NULL;
5923 CryptDecodeObjectExFunc decodeFunc = NULL;
5925 if (!set)
5926 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
5927 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
5928 (void **)&decodeFunc, hFunc);
5929 return decodeFunc;
5932 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
5933 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
5934 DWORD *pcbStructInfo)
5936 BOOL ret = FALSE;
5937 CryptDecodeObjectFunc pCryptDecodeObject = NULL;
5938 CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
5939 HCRYPTOIDFUNCADDR hFunc = NULL;
5941 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
5942 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
5943 pvStructInfo, pcbStructInfo);
5945 if (!pvStructInfo && !pcbStructInfo)
5947 SetLastError(ERROR_INVALID_PARAMETER);
5948 return FALSE;
5950 if (cbEncoded > MAX_ENCODED_LEN)
5952 SetLastError(CRYPT_E_ASN1_LARGE);
5953 return FALSE;
5956 if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
5957 lpszStructType)))
5959 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
5960 debugstr_a(lpszStructType));
5961 pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
5962 lpszStructType, &hFunc);
5963 if (!pCryptDecodeObject)
5964 pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
5965 lpszStructType, &hFunc);
5967 if (pCryptDecodeObject)
5968 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5969 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
5970 else if (pCryptDecodeObjectEx)
5971 ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
5972 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
5973 pvStructInfo, pcbStructInfo);
5974 if (hFunc)
5975 CryptFreeOIDFunctionAddress(hFunc, 0);
5976 TRACE_(crypt)("returning %d\n", ret);
5977 return ret;
5980 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
5981 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5982 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5984 BOOL ret = FALSE;
5985 CryptDecodeObjectExFunc decodeFunc;
5986 HCRYPTOIDFUNCADDR hFunc = NULL;
5988 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
5989 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
5990 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
5992 if (!pvStructInfo && !pcbStructInfo)
5994 SetLastError(ERROR_INVALID_PARAMETER);
5995 return FALSE;
5997 if (cbEncoded > MAX_ENCODED_LEN)
5999 SetLastError(CRYPT_E_ASN1_LARGE);
6000 return FALSE;
6003 SetLastError(NOERROR);
6004 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
6005 *(BYTE **)pvStructInfo = NULL;
6006 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
6007 if (!decodeFunc)
6009 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
6010 debugstr_a(lpszStructType));
6011 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
6012 &hFunc);
6014 if (decodeFunc)
6015 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
6016 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
6017 else
6019 CryptDecodeObjectFunc pCryptDecodeObject =
6020 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
6022 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
6023 * directly, as that could cause an infinite loop.
6025 if (pCryptDecodeObject)
6027 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
6029 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
6030 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
6031 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
6032 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
6033 ret = pCryptDecodeObject(dwCertEncodingType,
6034 lpszStructType, pbEncoded, cbEncoded, dwFlags,
6035 *(BYTE **)pvStructInfo, pcbStructInfo);
6037 else
6038 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
6039 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
6042 if (hFunc)
6043 CryptFreeOIDFunctionAddress(hFunc, 0);
6044 TRACE_(crypt)("returning %d\n", ret);
6045 return ret;
6048 BOOL WINAPI PFXIsPFXBlob(CRYPT_DATA_BLOB *pPFX)
6050 BOOL ret;
6052 TRACE_(crypt)("(%p)\n", pPFX);
6054 /* A PFX blob is an asn.1-encoded sequence, consisting of at least a
6055 * version integer of length 1 (3 encoded byes) and at least one other
6056 * datum (two encoded bytes), plus at least two bytes for the outer
6057 * sequence. Thus, even an empty PFX blob is at least 7 bytes in length.
6059 if (pPFX->cbData < 7)
6060 ret = FALSE;
6061 else if (pPFX->pbData[0] == ASN_SEQUENCE)
6063 DWORD len;
6065 if ((ret = CRYPT_GetLengthIndefinite(pPFX->pbData, pPFX->cbData, &len)))
6067 BYTE lenLen = GET_LEN_BYTES(pPFX->pbData[1]);
6069 /* Need at least three bytes for the integer version */
6070 if (pPFX->cbData < 1 + lenLen + 3)
6071 ret = FALSE;
6072 else if (pPFX->pbData[1 + lenLen] != ASN_INTEGER || /* Tag */
6073 pPFX->pbData[1 + lenLen + 1] != 1 || /* Definite length */
6074 pPFX->pbData[1 + lenLen + 2] != 3) /* PFX version */
6075 ret = FALSE;
6078 else
6079 ret = FALSE;
6080 return ret;
6083 HCERTSTORE WINAPI PFXImportCertStore(CRYPT_DATA_BLOB *pPFX, LPCWSTR szPassword,
6084 DWORD dwFlags)
6086 FIXME_(crypt)("(%p, %p, %08x): stub\n", pPFX, szPassword, dwFlags);
6087 return NULL;