crypt32: Fix an invalid alignment assumption decoding a subtree's maximum.
[wine/multimedia.git] / dlls / crypt32 / decode.c
blob32e61cc78003c9abd26c8f71ede1e527245c0144
1 /*
2 * Copyright 2005-2009 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 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
62 DWORD, DWORD, void *, DWORD *);
63 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
64 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
66 /* Internal decoders don't do memory allocation or exception handling, and
67 * they report how many bytes they decoded.
69 typedef BOOL (*InternalDecodeFunc)(const BYTE *pbEncoded, DWORD cbEncoded,
70 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
72 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
73 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
74 DWORD *pcbDecoded);
75 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
76 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
77 DWORD *pcbDecoded);
78 /* Assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set ahead of time.
80 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
81 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
82 /* Assumes algo->Parameters.pbData is set ahead of time. */
83 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
84 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
85 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
86 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
87 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
88 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
89 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
90 DWORD *pcbDecoded);
91 /* Doesn't check the tag, assumes the caller does so */
92 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
93 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
94 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
95 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
96 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
97 * member has been initialized, doesn't do exception handling, and doesn't do
98 * memory allocation. Also doesn't check tag, assumes the caller has checked
99 * it.
101 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
102 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
103 DWORD *pcbDecoded);
104 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
105 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
106 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
107 DWORD *pcbDecoded);
108 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
109 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
110 DWORD *pcbDecoded);
112 /* Gets the number of length bytes from the given (leading) length byte */
113 #define GET_LEN_BYTES(b) ((b) <= 0x80 ? 1 : 1 + ((b) & 0x7f))
115 /* Helper function to get the encoded length of the data starting at pbEncoded,
116 * where pbEncoded[0] is the tag. If the data are too short to contain a
117 * length or if the length is too large for cbEncoded, sets an appropriate
118 * error code and returns FALSE. If the encoded length is unknown due to
119 * indefinite length encoding, *len is set to CMSG_INDEFINITE_LENGTH.
121 static BOOL CRYPT_GetLengthIndefinite(const BYTE *pbEncoded, DWORD cbEncoded,
122 DWORD *len)
124 BOOL ret;
126 if (cbEncoded <= 1)
128 SetLastError(CRYPT_E_ASN1_CORRUPT);
129 ret = FALSE;
131 else if (pbEncoded[1] <= 0x7f)
133 if (pbEncoded[1] + 1 > cbEncoded)
135 SetLastError(CRYPT_E_ASN1_EOD);
136 ret = FALSE;
138 else
140 *len = pbEncoded[1];
141 ret = TRUE;
144 else if (pbEncoded[1] == 0x80)
146 *len = CMSG_INDEFINITE_LENGTH;
147 ret = TRUE;
149 else
151 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
153 if (lenLen > sizeof(DWORD) + 1)
155 SetLastError(CRYPT_E_ASN1_LARGE);
156 ret = FALSE;
158 else if (lenLen + 2 > cbEncoded)
160 SetLastError(CRYPT_E_ASN1_CORRUPT);
161 ret = FALSE;
163 else
165 DWORD out = 0;
167 pbEncoded += 2;
168 while (--lenLen)
170 out <<= 8;
171 out |= *pbEncoded++;
173 if (out + lenLen + 1 > cbEncoded)
175 SetLastError(CRYPT_E_ASN1_EOD);
176 ret = FALSE;
178 else
180 *len = out;
181 ret = TRUE;
185 return ret;
188 /* Like CRYPT_GetLengthIndefinite, but disallows indefinite-length encoding. */
189 static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
191 BOOL ret;
193 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, len)) &&
194 *len == CMSG_INDEFINITE_LENGTH)
196 SetLastError(CRYPT_E_ASN1_CORRUPT);
197 ret = FALSE;
199 return ret;
202 /* Helper function to check *pcbStructInfo, set it to the required size, and
203 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
204 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
205 * pointer to the newly allocated memory.
207 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
208 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
209 DWORD bytesNeeded)
211 BOOL ret = TRUE;
213 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
215 if (pDecodePara && pDecodePara->pfnAlloc)
216 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
217 else
218 *(BYTE **)pvStructInfo = LocalAlloc(0, bytesNeeded);
219 if (!*(BYTE **)pvStructInfo)
220 ret = FALSE;
221 else
222 *pcbStructInfo = bytesNeeded;
224 else if (*pcbStructInfo < bytesNeeded)
226 *pcbStructInfo = bytesNeeded;
227 SetLastError(ERROR_MORE_DATA);
228 ret = FALSE;
230 else
231 *pcbStructInfo = bytesNeeded;
232 return ret;
235 static void CRYPT_FreeSpace(PCRYPT_DECODE_PARA pDecodePara, LPVOID pv)
237 if (pDecodePara && pDecodePara->pfnFree)
238 pDecodePara->pfnFree(pv);
239 else
240 LocalFree(pv);
243 /* Helper function to check *pcbStructInfo and set it to the required size.
244 * Assumes pvStructInfo is not NULL.
246 static BOOL CRYPT_DecodeCheckSpace(DWORD *pcbStructInfo, DWORD bytesNeeded)
248 BOOL ret;
250 if (*pcbStructInfo < bytesNeeded)
252 *pcbStructInfo = bytesNeeded;
253 SetLastError(ERROR_MORE_DATA);
254 ret = FALSE;
256 else
258 *pcbStructInfo = bytesNeeded;
259 ret = TRUE;
261 return ret;
264 /* tag:
265 * The expected tag of the item. If tag is 0, decodeFunc is called
266 * regardless of the tag value seen.
267 * offset:
268 * A sequence is decoded into a struct. The offset member is the
269 * offset of this item within that struct.
270 * decodeFunc:
271 * The decoder function to use. If this is NULL, then the member isn't
272 * decoded, but minSize space is reserved for it.
273 * minSize:
274 * The minimum amount of space occupied after decoding. You must set this.
275 * optional:
276 * If true, and the tag doesn't match the expected tag for this item,
277 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
278 * filled with 0 for this member.
279 * hasPointer, pointerOffset:
280 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
281 * the offset within the struct of the data pointer (or to the
282 * first data pointer, if more than one exist).
283 * size:
284 * Used by CRYPT_AsnDecodeSequence, not for your use.
286 struct AsnDecodeSequenceItem
288 BYTE tag;
289 DWORD offset;
290 InternalDecodeFunc decodeFunc;
291 DWORD minSize;
292 BOOL optional;
293 BOOL hasPointer;
294 DWORD pointerOffset;
295 DWORD size;
298 #define FINALMEMBERSIZE(s, member) (sizeof(s) - offsetof(s, member))
299 #define MEMBERSIZE(s, member, nextmember) \
300 (offsetof(s, nextmember) - offsetof(s, member))
302 /* Decodes the items in a sequence, where the items are described in items,
303 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
304 * pvStructInfo. nextData is a pointer to the memory location at which the
305 * first decoded item with a dynamic pointer should point.
306 * Upon decoding, *cbDecoded is the total number of bytes decoded.
307 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
309 static BOOL CRYPT_AsnDecodeSequenceItems(struct AsnDecodeSequenceItem items[],
310 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
311 void *pvStructInfo, BYTE *nextData, DWORD *cbDecoded)
313 BOOL ret;
314 DWORD i, decoded = 0;
315 const BYTE *ptr = pbEncoded;
317 TRACE("%p, %d, %p, %d, %08x, %p, %p, %p\n", items, cItem, pbEncoded,
318 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
320 for (i = 0, ret = TRUE; ret && i < cItem; i++)
322 if (cbEncoded - (ptr - pbEncoded) != 0)
324 DWORD itemLen;
326 if ((ret = CRYPT_GetLengthIndefinite(ptr,
327 cbEncoded - (ptr - pbEncoded), &itemLen)))
329 BYTE itemLenBytes = GET_LEN_BYTES(ptr[1]);
331 if (ptr[0] == items[i].tag || !items[i].tag)
333 DWORD itemEncodedLen;
335 if (itemLen == CMSG_INDEFINITE_LENGTH)
336 itemEncodedLen = cbEncoded - (ptr - pbEncoded);
337 else
338 itemEncodedLen = 1 + itemLenBytes + itemLen;
339 if (nextData && pvStructInfo && items[i].hasPointer)
341 TRACE("Setting next pointer to %p\n",
342 nextData);
343 *(BYTE **)((BYTE *)pvStructInfo +
344 items[i].pointerOffset) = nextData;
346 if (items[i].decodeFunc)
348 DWORD itemDecoded;
350 if (pvStructInfo)
351 TRACE("decoding item %d\n", i);
352 else
353 TRACE("sizing item %d\n", i);
354 ret = items[i].decodeFunc(ptr, itemEncodedLen,
355 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
356 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
357 : NULL, &items[i].size, &itemDecoded);
358 if (ret)
360 /* Account for alignment padding */
361 items[i].size = ALIGN_DWORD_PTR(items[i].size);
362 TRACE("item %d size: %d\n", i, items[i].size);
363 if (nextData && items[i].hasPointer &&
364 items[i].size > items[i].minSize)
365 nextData += items[i].size - items[i].minSize;
366 if (itemDecoded > itemEncodedLen)
368 WARN("decoded length %d exceeds encoded %d\n",
369 itemDecoded, itemEncodedLen);
370 SetLastError(CRYPT_E_ASN1_CORRUPT);
371 ret = FALSE;
373 else
375 ptr += itemDecoded;
376 decoded += itemDecoded;
377 TRACE("item %d: decoded %d bytes\n", i,
378 itemDecoded);
381 else if (items[i].optional &&
382 GetLastError() == CRYPT_E_ASN1_BADTAG)
384 TRACE("skipping optional item %d\n", i);
385 items[i].size = items[i].minSize;
386 SetLastError(NOERROR);
387 ret = TRUE;
389 else
390 TRACE("item %d failed: %08x\n", i,
391 GetLastError());
393 else if (itemLen == CMSG_INDEFINITE_LENGTH)
395 ERR("can't use indefinite length encoding without a decoder\n");
396 SetLastError(CRYPT_E_ASN1_CORRUPT);
397 ret = FALSE;
399 else
401 TRACE("item %d: decoded %d bytes\n", i, itemEncodedLen);
402 ptr += itemEncodedLen;
403 decoded += itemEncodedLen;
404 items[i].size = items[i].minSize;
407 else if (items[i].optional)
409 TRACE("skipping optional item %d\n", i);
410 items[i].size = items[i].minSize;
412 else
414 TRACE("item %d: tag %02x doesn't match expected %02x\n",
415 i, ptr[0], items[i].tag);
416 SetLastError(CRYPT_E_ASN1_BADTAG);
417 ret = FALSE;
421 else if (items[i].optional)
423 TRACE("missing optional item %d, skipping\n", i);
424 items[i].size = items[i].minSize;
426 else
428 TRACE("not enough bytes for item %d, failing\n", i);
429 SetLastError(CRYPT_E_ASN1_CORRUPT);
430 ret = FALSE;
433 if (cbDecoded)
434 *cbDecoded = decoded;
435 TRACE("returning %d\n", ret);
436 return ret;
439 /* This decodes an arbitrary sequence into a contiguous block of memory
440 * (basically, a struct.) Each element being decoded is described by a struct
441 * AsnDecodeSequenceItem, see above.
442 * startingPointer is an optional pointer to the first place where dynamic
443 * data will be stored. If you know the starting offset, you may pass it
444 * here. Otherwise, pass NULL, and one will be inferred from the items.
446 static BOOL CRYPT_AsnDecodeSequence(struct AsnDecodeSequenceItem items[],
447 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
448 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
449 DWORD *pcbDecoded, void *startingPointer)
451 BOOL ret;
453 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
454 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
455 startingPointer);
457 if (!cbEncoded)
459 SetLastError(CRYPT_E_ASN1_EOD);
460 return FALSE;
462 if (pbEncoded[0] == ASN_SEQUENCE)
464 DWORD dataLen;
466 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
468 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
469 const BYTE *ptr = pbEncoded + 1 + lenBytes;
470 BOOL indefinite = FALSE;
472 cbEncoded -= 1 + lenBytes;
473 if (dataLen == CMSG_INDEFINITE_LENGTH)
475 dataLen = cbEncoded;
476 indefinite = TRUE;
478 else if (cbEncoded < dataLen)
480 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
481 cbEncoded);
482 SetLastError(CRYPT_E_ASN1_CORRUPT);
483 ret = FALSE;
485 if (ret)
487 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
488 ptr, dataLen, dwFlags, NULL, NULL, &cbDecoded);
489 if (ret && dataLen == CMSG_INDEFINITE_LENGTH)
491 if (cbDecoded > cbEncoded - 2)
493 /* Not enough space for 0 TLV */
494 SetLastError(CRYPT_E_ASN1_CORRUPT);
495 ret = FALSE;
497 else if (*(ptr + cbDecoded) != 0 ||
498 *(ptr + cbDecoded + 1) != 0)
500 TRACE("expected 0 TLV\n");
501 SetLastError(CRYPT_E_ASN1_CORRUPT);
502 ret = FALSE;
504 else
505 cbDecoded += 2;
508 if (ret && !indefinite && cbDecoded != dataLen)
510 TRACE("expected %d decoded, got %d, failing\n", dataLen,
511 cbDecoded);
512 SetLastError(CRYPT_E_ASN1_CORRUPT);
513 ret = FALSE;
515 if (ret)
517 DWORD i, bytesNeeded = 0, structSize = 0;
519 for (i = 0; i < cItem; i++)
521 bytesNeeded += items[i].size;
522 structSize = max( structSize, items[i].offset + items[i].minSize );
524 if (pcbDecoded)
525 *pcbDecoded = 1 + lenBytes + cbDecoded;
526 if (!pvStructInfo)
527 *pcbStructInfo = bytesNeeded;
528 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
529 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
531 BYTE *nextData;
533 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
534 pvStructInfo = *(BYTE **)pvStructInfo;
535 if (startingPointer)
536 nextData = startingPointer;
537 else
538 nextData = (BYTE *)pvStructInfo + structSize;
539 memset(pvStructInfo, 0, structSize);
540 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
541 ptr, dataLen, dwFlags, pvStructInfo, nextData,
542 &cbDecoded);
543 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
544 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
549 else
551 SetLastError(CRYPT_E_ASN1_BADTAG);
552 ret = FALSE;
554 TRACE("returning %d (%08x)\n", ret, GetLastError());
555 return ret;
558 /* tag:
559 * The expected tag of the entire encoded array (usually a variant
560 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
561 * regardless of the tag seen.
562 * countOffset:
563 * The offset within the outer structure at which the count exists.
564 * For example, a structure such as CRYPT_ATTRIBUTES has countOffset == 0,
565 * while CRYPT_ATTRIBUTE has countOffset ==
566 * offsetof(CRYPT_ATTRIBUTE, cValue).
567 * arrayOffset:
568 * The offset within the outer structure at which the array pointer exists.
569 * For example, CRYPT_ATTRIBUTES has arrayOffset ==
570 * offsetof(CRYPT_ATTRIBUTES, rgAttr).
571 * minArraySize:
572 * The minimum size of the decoded array. On WIN32, this is always 8:
573 * sizeof(DWORD) + sizeof(void *). On WIN64, it can be larger due to
574 * alignment.
575 * decodeFunc:
576 * used to decode each item in the array
577 * itemSize:
578 * is the minimum size of each decoded item
579 * hasPointer:
580 * indicates whether each item has a dynamic pointer
581 * pointerOffset:
582 * indicates the offset within itemSize at which the pointer exists
584 struct AsnArrayDescriptor
586 BYTE tag;
587 DWORD countOffset;
588 DWORD arrayOffset;
589 DWORD minArraySize;
590 InternalDecodeFunc decodeFunc;
591 DWORD itemSize;
592 BOOL hasPointer;
593 DWORD pointerOffset;
596 struct AsnArrayItemSize
598 DWORD encodedLen;
599 DWORD size;
602 /* Decodes an array of like types into a structure described by a struct
603 * AsnArrayDescriptor.
605 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
606 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
607 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
608 DWORD *pcbDecoded)
610 BOOL ret = TRUE;
612 TRACE("%p, %p, %d, %p, %d\n", arrayDesc, pbEncoded,
613 cbEncoded, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
615 if (!cbEncoded)
617 SetLastError(CRYPT_E_ASN1_EOD);
618 ret = FALSE;
620 else if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
622 DWORD dataLen;
624 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
626 DWORD bytesNeeded = arrayDesc->minArraySize, cItems = 0, decoded;
627 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
628 /* There can be arbitrarily many items, but there is often only one.
630 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
632 decoded = 1 + lenBytes;
633 if (dataLen)
635 const BYTE *ptr;
636 BOOL doneDecoding = FALSE;
638 for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
640 if (dataLen == CMSG_INDEFINITE_LENGTH)
642 if (ptr[0] == 0)
644 doneDecoding = TRUE;
645 if (ptr[1] != 0)
647 SetLastError(CRYPT_E_ASN1_CORRUPT);
648 ret = FALSE;
650 else
651 decoded += 2;
654 else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
655 doneDecoding = TRUE;
656 if (!doneDecoding)
658 DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
660 /* Each item decoded may not tolerate extraneous bytes,
661 * so get the length of the next element if known.
663 if ((ret = CRYPT_GetLengthIndefinite(ptr,
664 cbEncoded - (ptr - pbEncoded), &itemDataLen)))
666 if (itemDataLen == CMSG_INDEFINITE_LENGTH)
667 itemEncoded = cbEncoded - (ptr - pbEncoded);
668 else
669 itemEncoded = 1 + GET_LEN_BYTES(ptr[1]) +
670 itemDataLen;
672 if (ret)
673 ret = arrayDesc->decodeFunc(ptr, itemEncoded,
674 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size,
675 &itemDecoded);
676 if (ret)
678 cItems++;
679 if (itemSizes != &itemSize)
680 itemSizes = CryptMemRealloc(itemSizes,
681 cItems * sizeof(struct AsnArrayItemSize));
682 else if (cItems > 1)
684 itemSizes =
685 CryptMemAlloc(
686 cItems * sizeof(struct AsnArrayItemSize));
687 if (itemSizes)
688 memcpy(itemSizes, &itemSize,
689 sizeof(itemSize));
691 if (itemSizes)
693 decoded += itemDecoded;
694 itemSizes[cItems - 1].encodedLen = itemEncoded;
695 itemSizes[cItems - 1].size = size;
696 bytesNeeded += size;
697 ptr += itemEncoded;
699 else
700 ret = FALSE;
705 if (ret)
707 if (pcbDecoded)
708 *pcbDecoded = decoded;
709 if (!pvStructInfo)
710 *pcbStructInfo = bytesNeeded;
711 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
712 pvStructInfo, pcbStructInfo, bytesNeeded)))
714 DWORD i, *pcItems;
715 BYTE *nextData;
716 const BYTE *ptr;
717 void *rgItems;
719 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
720 pvStructInfo = *(void **)pvStructInfo;
721 pcItems = pvStructInfo;
722 *pcItems = cItems;
723 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
725 rgItems = (BYTE *)pvStructInfo +
726 arrayDesc->minArraySize;
727 *(void **)((BYTE *)pcItems -
728 arrayDesc->countOffset + arrayDesc->arrayOffset) =
729 rgItems;
731 else
732 rgItems = *(void **)((BYTE *)pcItems -
733 arrayDesc->countOffset + arrayDesc->arrayOffset);
734 nextData = (BYTE *)rgItems + cItems * arrayDesc->itemSize;
735 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
736 i < cItems && ptr - pbEncoded - 1 - lenBytes <
737 dataLen; i++)
739 DWORD itemDecoded;
741 if (arrayDesc->hasPointer)
742 *(BYTE **)((BYTE *)rgItems + i * arrayDesc->itemSize
743 + arrayDesc->pointerOffset) = nextData;
744 ret = arrayDesc->decodeFunc(ptr,
745 itemSizes[i].encodedLen,
746 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
747 (BYTE *)rgItems + i * arrayDesc->itemSize,
748 &itemSizes[i].size, &itemDecoded);
749 if (ret)
751 nextData += itemSizes[i].size - arrayDesc->itemSize;
752 ptr += itemDecoded;
757 if (itemSizes != &itemSize)
758 CryptMemFree(itemSizes);
761 else
763 SetLastError(CRYPT_E_ASN1_BADTAG);
764 ret = FALSE;
766 return ret;
769 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
770 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
771 * to CRYPT_E_ASN1_CORRUPT.
772 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
773 * set!
775 static BOOL CRYPT_AsnDecodeDerBlob(const BYTE *pbEncoded, DWORD cbEncoded,
776 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
778 BOOL ret;
779 DWORD dataLen;
781 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
783 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
784 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
786 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
787 bytesNeeded += 1 + lenBytes + dataLen;
789 if (pcbDecoded)
790 *pcbDecoded = 1 + lenBytes + dataLen;
791 if (!pvStructInfo)
792 *pcbStructInfo = bytesNeeded;
793 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded)))
795 CRYPT_DER_BLOB *blob;
797 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
798 pvStructInfo = *(BYTE **)pvStructInfo;
799 blob = pvStructInfo;
800 blob->cbData = 1 + lenBytes + dataLen;
801 if (blob->cbData)
803 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
804 blob->pbData = (BYTE *)pbEncoded;
805 else
807 assert(blob->pbData);
808 memcpy(blob->pbData, pbEncoded, blob->cbData);
811 else
813 SetLastError(CRYPT_E_ASN1_CORRUPT);
814 ret = FALSE;
818 return ret;
821 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
822 static BOOL CRYPT_AsnDecodeBitsSwapBytes(const BYTE *pbEncoded,
823 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
824 DWORD *pcbDecoded)
826 BOOL ret;
828 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
829 pvStructInfo, *pcbStructInfo, pcbDecoded);
831 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
832 * place.
834 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
835 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
836 pcbDecoded);
837 if (ret && pvStructInfo)
839 CRYPT_BIT_BLOB *blob = pvStructInfo;
841 if (blob->cbData)
843 DWORD i;
844 BYTE temp;
846 for (i = 0; i < blob->cbData / 2; i++)
848 temp = blob->pbData[i];
849 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
850 blob->pbData[blob->cbData - i - 1] = temp;
854 TRACE("returning %d (%08x)\n", ret, GetLastError());
855 return ret;
858 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
859 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
860 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
862 BOOL ret = TRUE;
864 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
865 pDecodePara, pvStructInfo, *pcbStructInfo);
867 __TRY
869 struct AsnDecodeSequenceItem items[] = {
870 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
871 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
872 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
873 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
874 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
875 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
876 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
877 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
878 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
879 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
882 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
883 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
884 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
885 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
886 pcbStructInfo, NULL, NULL);
888 __EXCEPT_PAGE_FAULT
890 SetLastError(STATUS_ACCESS_VIOLATION);
891 ret = FALSE;
893 __ENDTRY
895 TRACE("Returning %d (%08x)\n", ret, GetLastError());
896 return ret;
899 static BOOL CRYPT_AsnDecodeCertVersion(const BYTE *pbEncoded, DWORD cbEncoded,
900 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
902 BOOL ret;
903 DWORD dataLen;
905 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
907 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
909 ret = CRYPT_AsnDecodeIntInternal(pbEncoded + 1 + lenBytes, dataLen,
910 dwFlags, pvStructInfo, pcbStructInfo, NULL);
911 if (pcbDecoded)
912 *pcbDecoded = 1 + lenBytes + dataLen;
914 return ret;
917 static BOOL CRYPT_AsnDecodeValidity(const BYTE *pbEncoded, DWORD cbEncoded,
918 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
920 BOOL ret;
922 struct AsnDecodeSequenceItem items[] = {
923 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
924 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
925 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
926 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
929 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
930 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
931 pcbDecoded, NULL);
932 return ret;
935 static BOOL CRYPT_AsnDecodeCertExtensionsInternal(const BYTE *pbEncoded,
936 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
937 DWORD *pcbDecoded)
939 BOOL ret = TRUE;
940 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
941 offsetof(CERT_INFO, cExtension), offsetof(CERT_INFO, rgExtension),
942 FINALMEMBERSIZE(CERT_INFO, cExtension),
943 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
944 offsetof(CERT_EXTENSION, pszObjId) };
946 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
947 pvStructInfo, *pcbStructInfo, pcbDecoded);
949 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
950 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
951 return ret;
954 static BOOL CRYPT_AsnDecodeCertExtensions(const BYTE *pbEncoded,
955 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
956 DWORD *pcbDecoded)
958 BOOL ret;
959 DWORD dataLen;
961 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
963 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
965 ret = CRYPT_AsnDecodeCertExtensionsInternal(pbEncoded + 1 + lenBytes,
966 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
967 if (ret && pcbDecoded)
968 *pcbDecoded = 1 + lenBytes + dataLen;
970 return ret;
973 static BOOL CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
974 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
975 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
977 BOOL ret = TRUE;
978 struct AsnDecodeSequenceItem items[] = {
979 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
980 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
981 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
982 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
983 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
984 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
985 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
986 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
987 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
988 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
989 Issuer.pbData) },
990 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
991 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
992 FALSE, 0 },
993 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
994 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
995 Subject.pbData) },
996 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
997 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
998 FALSE, TRUE, offsetof(CERT_INFO,
999 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
1000 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
1001 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
1002 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
1003 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
1004 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
1005 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
1006 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
1007 CRYPT_AsnDecodeCertExtensions, FINALMEMBERSIZE(CERT_INFO, cExtension),
1008 TRUE, TRUE, offsetof(CERT_INFO, rgExtension), 0 },
1011 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1012 pDecodePara, pvStructInfo, *pcbStructInfo);
1014 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1015 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
1016 NULL, NULL);
1017 if (ret && pvStructInfo)
1019 CERT_INFO *info;
1021 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1022 info = *(CERT_INFO **)pvStructInfo;
1023 else
1024 info = pvStructInfo;
1025 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
1026 !info->Subject.cbData)
1028 SetLastError(CRYPT_E_ASN1_CORRUPT);
1029 /* Don't need to deallocate, because it should have failed on the
1030 * first pass (and no memory was allocated.)
1032 ret = FALSE;
1036 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1037 return ret;
1040 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
1041 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1042 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1044 BOOL ret = FALSE;
1046 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1047 pDecodePara, pvStructInfo, *pcbStructInfo);
1049 __TRY
1051 DWORD size = 0;
1053 /* Unless told not to, first try to decode it as a signed cert. */
1054 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1056 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
1058 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1059 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1060 &signedCert, &size);
1061 if (ret)
1063 size = 0;
1064 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1065 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
1066 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
1067 pvStructInfo, pcbStructInfo);
1068 LocalFree(signedCert);
1071 /* Failing that, try it as an unsigned cert */
1072 if (!ret)
1074 size = 0;
1075 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1076 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
1077 pDecodePara, pvStructInfo, pcbStructInfo);
1080 __EXCEPT_PAGE_FAULT
1082 SetLastError(STATUS_ACCESS_VIOLATION);
1084 __ENDTRY
1086 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1087 return ret;
1090 static BOOL CRYPT_AsnDecodeCRLEntryExtensions(const BYTE *pbEncoded,
1091 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1092 DWORD *pcbDecoded)
1094 BOOL ret = TRUE;
1095 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1096 offsetof(CRL_ENTRY, cExtension), offsetof(CRL_ENTRY, rgExtension),
1097 FINALMEMBERSIZE(CRL_ENTRY, cExtension),
1098 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1099 offsetof(CERT_EXTENSION, pszObjId) };
1101 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1102 pvStructInfo, *pcbStructInfo, pcbDecoded);
1104 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1105 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1106 return ret;
1109 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
1110 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1112 BOOL ret;
1113 struct AsnDecodeSequenceItem items[] = {
1114 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
1115 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
1116 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
1117 { 0, offsetof(CRL_ENTRY, RevocationDate),
1118 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
1119 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
1120 CRYPT_AsnDecodeCRLEntryExtensions,
1121 FINALMEMBERSIZE(CRL_ENTRY, cExtension), TRUE, TRUE,
1122 offsetof(CRL_ENTRY, rgExtension), 0 },
1124 PCRL_ENTRY entry = pvStructInfo;
1126 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
1127 *pcbStructInfo);
1129 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1130 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, pcbDecoded,
1131 entry ? entry->SerialNumber.pbData : NULL);
1132 if (ret && entry && !entry->SerialNumber.cbData)
1134 WARN("empty CRL entry serial number\n");
1135 SetLastError(CRYPT_E_ASN1_CORRUPT);
1136 ret = FALSE;
1138 return ret;
1141 /* Warning: assumes pvStructInfo points to the cCRLEntry member of a CRL_INFO
1142 * whose rgCRLEntry member has been set prior to calling.
1144 static BOOL CRYPT_AsnDecodeCRLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
1145 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1147 BOOL ret;
1148 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1149 offsetof(CRL_INFO, cCRLEntry), offsetof(CRL_INFO, rgCRLEntry),
1150 MEMBERSIZE(CRL_INFO, cCRLEntry, cExtension),
1151 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
1152 offsetof(CRL_ENTRY, SerialNumber.pbData) };
1154 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1155 pvStructInfo, *pcbStructInfo, pcbDecoded);
1157 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1158 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1159 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1160 return ret;
1163 static BOOL CRYPT_AsnDecodeCRLExtensionsInternal(const BYTE *pbEncoded,
1164 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1165 DWORD *pcbDecoded)
1167 BOOL ret = TRUE;
1168 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1169 offsetof(CRL_INFO, cExtension), offsetof(CRL_INFO, rgExtension),
1170 FINALMEMBERSIZE(CRL_INFO, cExtension),
1171 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1172 offsetof(CERT_EXTENSION, pszObjId) };
1174 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1175 pvStructInfo, *pcbStructInfo, pcbDecoded);
1177 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1178 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1179 return ret;
1182 static BOOL CRYPT_AsnDecodeCRLExtensions(const BYTE *pbEncoded,
1183 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1184 DWORD *pcbDecoded)
1186 BOOL ret;
1187 DWORD dataLen;
1189 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1191 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1193 ret = CRYPT_AsnDecodeCRLExtensionsInternal(pbEncoded + 1 + lenBytes,
1194 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
1195 if (ret && pcbDecoded)
1196 *pcbDecoded = 1 + lenBytes + dataLen;
1198 return ret;
1201 static BOOL CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1202 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1203 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1205 struct AsnDecodeSequenceItem items[] = {
1206 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1207 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1208 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1209 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1210 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1211 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1212 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1213 Issuer.pbData) },
1214 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1215 sizeof(FILETIME), FALSE, FALSE, 0 },
1216 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1217 sizeof(FILETIME), TRUE, FALSE, 0 },
1218 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1219 CRYPT_AsnDecodeCRLEntries, MEMBERSIZE(CRL_INFO, cCRLEntry, cExtension),
1220 TRUE, TRUE, offsetof(CRL_INFO, rgCRLEntry), 0 },
1221 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1222 CRYPT_AsnDecodeCRLExtensions, FINALMEMBERSIZE(CRL_INFO, cExtension),
1223 TRUE, TRUE, offsetof(CRL_INFO, rgExtension), 0 },
1225 BOOL ret = TRUE;
1227 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1228 pDecodePara, pvStructInfo, *pcbStructInfo);
1230 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1231 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
1232 NULL, NULL);
1234 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1235 return ret;
1238 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1239 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1240 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1242 BOOL ret = FALSE;
1244 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1245 pDecodePara, pvStructInfo, *pcbStructInfo);
1247 __TRY
1249 DWORD size = 0;
1251 /* Unless told not to, first try to decode it as a signed crl. */
1252 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1254 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1256 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1257 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1258 &signedCrl, &size);
1259 if (ret)
1261 size = 0;
1262 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1263 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1264 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1265 pvStructInfo, pcbStructInfo);
1266 LocalFree(signedCrl);
1269 /* Failing that, try it as an unsigned crl */
1270 if (!ret)
1272 size = 0;
1273 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1274 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1275 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1278 __EXCEPT_PAGE_FAULT
1280 SetLastError(STATUS_ACCESS_VIOLATION);
1282 __ENDTRY
1284 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1285 return ret;
1288 static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded,
1289 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1291 BOOL ret = TRUE;
1292 DWORD dataLen;
1294 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1295 pvStructInfo, *pcbStructInfo);
1297 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1299 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1300 DWORD bytesNeeded = sizeof(LPSTR);
1302 if (dataLen)
1304 /* The largest possible string for the first two components
1305 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1307 char firstTwo[6];
1308 const BYTE *ptr;
1310 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1311 pbEncoded[1 + lenBytes] / 40,
1312 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1313 * 40);
1314 bytesNeeded += strlen(firstTwo) + 1;
1315 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1316 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1318 /* large enough for ".4000000" */
1319 char str[9];
1320 int val = 0;
1322 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1323 (*ptr & 0x80))
1325 val <<= 7;
1326 val |= *ptr & 0x7f;
1327 ptr++;
1329 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1330 (*ptr & 0x80))
1332 SetLastError(CRYPT_E_ASN1_CORRUPT);
1333 ret = FALSE;
1335 else
1337 val <<= 7;
1338 val |= *ptr++;
1339 snprintf(str, sizeof(str), ".%d", val);
1340 bytesNeeded += strlen(str);
1344 if (pcbDecoded)
1345 *pcbDecoded = 1 + lenBytes + dataLen;
1346 if (!pvStructInfo)
1347 *pcbStructInfo = bytesNeeded;
1348 else if (*pcbStructInfo < bytesNeeded)
1350 *pcbStructInfo = bytesNeeded;
1351 SetLastError(ERROR_MORE_DATA);
1352 ret = FALSE;
1354 else
1356 if (dataLen)
1358 const BYTE *ptr;
1359 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1361 *pszObjId = 0;
1362 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1363 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1364 40) * 40);
1365 pszObjId += strlen(pszObjId);
1366 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1367 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1369 int val = 0;
1371 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1372 (*ptr & 0x80))
1374 val <<= 7;
1375 val |= *ptr & 0x7f;
1376 ptr++;
1378 val <<= 7;
1379 val |= *ptr++;
1380 sprintf(pszObjId, ".%d", val);
1381 pszObjId += strlen(pszObjId);
1384 else
1385 *(LPSTR *)pvStructInfo = NULL;
1386 *pcbStructInfo = bytesNeeded;
1389 return ret;
1392 static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded,
1393 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1395 BOOL ret;
1397 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1398 pvStructInfo, *pcbStructInfo);
1400 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1401 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1402 pvStructInfo, pcbStructInfo, pcbDecoded);
1403 else
1405 SetLastError(CRYPT_E_ASN1_BADTAG);
1406 ret = FALSE;
1408 return ret;
1411 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
1412 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1414 struct AsnDecodeSequenceItem items[] = {
1415 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1416 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1417 offsetof(CERT_EXTENSION, pszObjId), 0 },
1418 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1419 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1420 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1421 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1422 offsetof(CERT_EXTENSION, Value.pbData) },
1424 BOOL ret = TRUE;
1425 PCERT_EXTENSION ext = pvStructInfo;
1427 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1428 *pcbStructInfo);
1430 if (ext)
1431 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1432 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1433 pbEncoded, cbEncoded, dwFlags, NULL, ext, pcbStructInfo,
1434 pcbDecoded, ext ? ext->pszObjId : NULL);
1435 if (ext)
1436 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1437 debugstr_a(ext->pszObjId));
1438 TRACE("returning %d (%08x)\n", ret, GetLastError());
1439 return ret;
1442 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1443 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1444 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1446 BOOL ret = TRUE;
1448 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1449 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
1451 __TRY
1453 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1454 offsetof(CERT_EXTENSIONS, cExtension),
1455 offsetof(CERT_EXTENSIONS, rgExtension),
1456 sizeof(CERT_EXTENSIONS),
1457 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1458 offsetof(CERT_EXTENSION, pszObjId) };
1460 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1461 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1463 __EXCEPT_PAGE_FAULT
1465 SetLastError(STATUS_ACCESS_VIOLATION);
1466 ret = FALSE;
1468 __ENDTRY
1469 return ret;
1472 /* Warning: this assumes the address of value->Value.pbData is already set, in
1473 * order to avoid overwriting memory. (In some cases, it may change it, if it
1474 * doesn't copy anything to memory.) Be sure to set it correctly!
1476 static BOOL CRYPT_AsnDecodeNameValueInternal(const BYTE *pbEncoded,
1477 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1478 DWORD *pcbDecoded)
1480 BOOL ret = TRUE;
1481 DWORD dataLen;
1482 CERT_NAME_VALUE *value = pvStructInfo;
1484 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1486 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1487 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1489 switch (pbEncoded[0])
1491 case ASN_OCTETSTRING:
1492 valueType = CERT_RDN_OCTET_STRING;
1493 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1494 bytesNeeded += dataLen;
1495 break;
1496 case ASN_NUMERICSTRING:
1497 valueType = CERT_RDN_NUMERIC_STRING;
1498 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1499 bytesNeeded += dataLen;
1500 break;
1501 case ASN_PRINTABLESTRING:
1502 valueType = CERT_RDN_PRINTABLE_STRING;
1503 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1504 bytesNeeded += dataLen;
1505 break;
1506 case ASN_IA5STRING:
1507 valueType = CERT_RDN_IA5_STRING;
1508 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1509 bytesNeeded += dataLen;
1510 break;
1511 case ASN_T61STRING:
1512 valueType = CERT_RDN_T61_STRING;
1513 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1514 bytesNeeded += dataLen;
1515 break;
1516 case ASN_VIDEOTEXSTRING:
1517 valueType = CERT_RDN_VIDEOTEX_STRING;
1518 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1519 bytesNeeded += dataLen;
1520 break;
1521 case ASN_GRAPHICSTRING:
1522 valueType = CERT_RDN_GRAPHIC_STRING;
1523 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1524 bytesNeeded += dataLen;
1525 break;
1526 case ASN_VISIBLESTRING:
1527 valueType = CERT_RDN_VISIBLE_STRING;
1528 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1529 bytesNeeded += dataLen;
1530 break;
1531 case ASN_GENERALSTRING:
1532 valueType = CERT_RDN_GENERAL_STRING;
1533 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1534 bytesNeeded += dataLen;
1535 break;
1536 case ASN_UNIVERSALSTRING:
1537 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1538 SetLastError(CRYPT_E_ASN1_BADTAG);
1539 return FALSE;
1540 case ASN_BMPSTRING:
1541 valueType = CERT_RDN_BMP_STRING;
1542 bytesNeeded += dataLen;
1543 break;
1544 case ASN_UTF8STRING:
1545 valueType = CERT_RDN_UTF8_STRING;
1546 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1547 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1548 break;
1549 default:
1550 SetLastError(CRYPT_E_ASN1_BADTAG);
1551 return FALSE;
1554 if (pcbDecoded)
1555 *pcbDecoded = 1 + lenBytes + dataLen;
1556 if (!value)
1557 *pcbStructInfo = bytesNeeded;
1558 else if (*pcbStructInfo < bytesNeeded)
1560 *pcbStructInfo = bytesNeeded;
1561 SetLastError(ERROR_MORE_DATA);
1562 ret = FALSE;
1564 else
1566 *pcbStructInfo = bytesNeeded;
1567 value->dwValueType = valueType;
1568 if (dataLen)
1570 DWORD i;
1572 assert(value->Value.pbData);
1573 switch (pbEncoded[0])
1575 case ASN_OCTETSTRING:
1576 case ASN_NUMERICSTRING:
1577 case ASN_PRINTABLESTRING:
1578 case ASN_IA5STRING:
1579 case ASN_T61STRING:
1580 case ASN_VIDEOTEXSTRING:
1581 case ASN_GRAPHICSTRING:
1582 case ASN_VISIBLESTRING:
1583 case ASN_GENERALSTRING:
1584 value->Value.cbData = dataLen;
1585 if (dataLen)
1587 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1588 memcpy(value->Value.pbData,
1589 pbEncoded + 1 + lenBytes, dataLen);
1590 else
1591 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1592 lenBytes;
1594 break;
1595 case ASN_BMPSTRING:
1597 LPWSTR str = (LPWSTR)value->Value.pbData;
1599 value->Value.cbData = dataLen;
1600 for (i = 0; i < dataLen / 2; i++)
1601 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1602 pbEncoded[1 + lenBytes + 2 * i + 1];
1603 break;
1605 case ASN_UTF8STRING:
1607 LPWSTR str = (LPWSTR)value->Value.pbData;
1609 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1610 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1611 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1612 break;
1616 else
1618 value->Value.cbData = 0;
1619 value->Value.pbData = NULL;
1623 return ret;
1626 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1627 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1628 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1630 BOOL ret = TRUE;
1632 __TRY
1634 ret = CRYPT_AsnDecodeNameValueInternal(pbEncoded, cbEncoded,
1635 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1636 if (ret && pvStructInfo)
1638 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1639 pcbStructInfo, *pcbStructInfo);
1640 if (ret)
1642 CERT_NAME_VALUE *value;
1644 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1645 pvStructInfo = *(BYTE **)pvStructInfo;
1646 value = pvStructInfo;
1647 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1648 ret = CRYPT_AsnDecodeNameValueInternal( pbEncoded, cbEncoded,
1649 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1650 pcbStructInfo, NULL);
1654 __EXCEPT_PAGE_FAULT
1656 SetLastError(STATUS_ACCESS_VIOLATION);
1657 ret = FALSE;
1659 __ENDTRY
1660 return ret;
1663 static BOOL CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE *pbEncoded,
1664 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1665 DWORD *pcbDecoded)
1667 BOOL ret = TRUE;
1668 DWORD dataLen;
1669 CERT_NAME_VALUE *value = pvStructInfo;
1671 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1673 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1674 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1676 switch (pbEncoded[0])
1678 case ASN_NUMERICSTRING:
1679 valueType = CERT_RDN_NUMERIC_STRING;
1680 if (dataLen)
1681 bytesNeeded += (dataLen + 1) * 2;
1682 break;
1683 case ASN_PRINTABLESTRING:
1684 valueType = CERT_RDN_PRINTABLE_STRING;
1685 if (dataLen)
1686 bytesNeeded += (dataLen + 1) * 2;
1687 break;
1688 case ASN_IA5STRING:
1689 valueType = CERT_RDN_IA5_STRING;
1690 if (dataLen)
1691 bytesNeeded += (dataLen + 1) * 2;
1692 break;
1693 case ASN_T61STRING:
1694 valueType = CERT_RDN_T61_STRING;
1695 if (dataLen)
1696 bytesNeeded += (dataLen + 1) * 2;
1697 break;
1698 case ASN_VIDEOTEXSTRING:
1699 valueType = CERT_RDN_VIDEOTEX_STRING;
1700 if (dataLen)
1701 bytesNeeded += (dataLen + 1) * 2;
1702 break;
1703 case ASN_GRAPHICSTRING:
1704 valueType = CERT_RDN_GRAPHIC_STRING;
1705 if (dataLen)
1706 bytesNeeded += (dataLen + 1) * 2;
1707 break;
1708 case ASN_VISIBLESTRING:
1709 valueType = CERT_RDN_VISIBLE_STRING;
1710 if (dataLen)
1711 bytesNeeded += (dataLen + 1) * 2;
1712 break;
1713 case ASN_GENERALSTRING:
1714 valueType = CERT_RDN_GENERAL_STRING;
1715 if (dataLen)
1716 bytesNeeded += (dataLen + 1) * 2;
1717 break;
1718 case ASN_UNIVERSALSTRING:
1719 valueType = CERT_RDN_UNIVERSAL_STRING;
1720 if (dataLen)
1721 bytesNeeded += dataLen / 2 + sizeof(WCHAR);
1722 break;
1723 case ASN_BMPSTRING:
1724 valueType = CERT_RDN_BMP_STRING;
1725 if (dataLen)
1726 bytesNeeded += dataLen + sizeof(WCHAR);
1727 break;
1728 case ASN_UTF8STRING:
1729 valueType = CERT_RDN_UTF8_STRING;
1730 if (dataLen)
1731 bytesNeeded += (MultiByteToWideChar(CP_UTF8, 0,
1732 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) + 1) * 2;
1733 break;
1734 default:
1735 SetLastError(CRYPT_E_ASN1_BADTAG);
1736 return FALSE;
1739 if (pcbDecoded)
1740 *pcbDecoded = 1 + lenBytes + dataLen;
1741 if (!value)
1742 *pcbStructInfo = bytesNeeded;
1743 else if (*pcbStructInfo < bytesNeeded)
1745 *pcbStructInfo = bytesNeeded;
1746 SetLastError(ERROR_MORE_DATA);
1747 ret = FALSE;
1749 else
1751 *pcbStructInfo = bytesNeeded;
1752 value->dwValueType = valueType;
1753 if (dataLen)
1755 DWORD i;
1756 LPWSTR str = (LPWSTR)value->Value.pbData;
1758 assert(value->Value.pbData);
1759 switch (pbEncoded[0])
1761 case ASN_NUMERICSTRING:
1762 case ASN_PRINTABLESTRING:
1763 case ASN_IA5STRING:
1764 case ASN_T61STRING:
1765 case ASN_VIDEOTEXSTRING:
1766 case ASN_GRAPHICSTRING:
1767 case ASN_VISIBLESTRING:
1768 case ASN_GENERALSTRING:
1769 value->Value.cbData = dataLen * 2;
1770 for (i = 0; i < dataLen; i++)
1771 str[i] = pbEncoded[1 + lenBytes + i];
1772 str[i] = 0;
1773 break;
1774 case ASN_UNIVERSALSTRING:
1775 value->Value.cbData = dataLen / 2;
1776 for (i = 0; i < dataLen / 4; i++)
1777 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1778 | pbEncoded[1 + lenBytes + 2 * i + 3];
1779 str[i] = 0;
1780 break;
1781 case ASN_BMPSTRING:
1782 value->Value.cbData = dataLen;
1783 for (i = 0; i < dataLen / 2; i++)
1784 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1785 pbEncoded[1 + lenBytes + 2 * i + 1];
1786 str[i] = 0;
1787 break;
1788 case ASN_UTF8STRING:
1789 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1790 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1791 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * sizeof(WCHAR);
1792 *(WCHAR *)(value->Value.pbData + value->Value.cbData) = 0;
1793 value->Value.cbData += sizeof(WCHAR);
1794 break;
1797 else
1799 value->Value.cbData = 0;
1800 value->Value.pbData = NULL;
1804 return ret;
1807 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1808 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1809 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1811 BOOL ret = TRUE;
1813 __TRY
1815 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded, cbEncoded,
1816 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1817 if (ret && pvStructInfo)
1819 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1820 pcbStructInfo, *pcbStructInfo);
1821 if (ret)
1823 CERT_NAME_VALUE *value;
1825 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1826 pvStructInfo = *(BYTE **)pvStructInfo;
1827 value = pvStructInfo;
1828 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1829 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded,
1830 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1831 pcbStructInfo, NULL);
1835 __EXCEPT_PAGE_FAULT
1837 SetLastError(STATUS_ACCESS_VIOLATION);
1838 ret = FALSE;
1840 __ENDTRY
1841 return ret;
1844 static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
1845 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1847 BOOL ret;
1848 struct AsnDecodeSequenceItem items[] = {
1849 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1850 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1851 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1852 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1853 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1854 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1856 CERT_RDN_ATTR *attr = pvStructInfo;
1858 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1859 pvStructInfo, *pcbStructInfo);
1861 if (attr)
1862 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1863 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1864 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1865 attr ? attr->pszObjId : NULL);
1866 if (attr)
1868 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1869 debugstr_a(attr->pszObjId));
1870 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1872 TRACE("returning %d (%08x)\n", ret, GetLastError());
1873 return ret;
1876 static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1877 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1879 BOOL ret = TRUE;
1880 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1881 offsetof(CERT_RDN, cRDNAttr), offsetof(CERT_RDN, rgRDNAttr),
1882 sizeof(CERT_RDN),
1883 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1884 offsetof(CERT_RDN_ATTR, pszObjId) };
1886 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1887 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1888 return ret;
1891 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1892 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1893 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1895 BOOL ret = TRUE;
1897 __TRY
1899 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1900 offsetof(CERT_NAME_INFO, cRDN), offsetof(CERT_NAME_INFO, rgRDN),
1901 sizeof(CERT_NAME_INFO),
1902 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1903 offsetof(CERT_RDN, rgRDNAttr) };
1905 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1906 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1908 __EXCEPT_PAGE_FAULT
1910 SetLastError(STATUS_ACCESS_VIOLATION);
1911 ret = FALSE;
1913 __ENDTRY
1914 return ret;
1917 static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
1918 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1919 DWORD *pcbDecoded)
1921 BOOL ret;
1922 struct AsnDecodeSequenceItem items[] = {
1923 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1924 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1925 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1926 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1927 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1928 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1930 CERT_RDN_ATTR *attr = pvStructInfo;
1932 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1933 pvStructInfo, *pcbStructInfo);
1935 if (attr)
1936 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1937 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1938 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1939 attr ? attr->pszObjId : NULL);
1940 if (attr)
1942 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1943 debugstr_a(attr->pszObjId));
1944 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1946 TRACE("returning %d (%08x)\n", ret, GetLastError());
1947 return ret;
1950 static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1951 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1953 BOOL ret = TRUE;
1954 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1955 offsetof(CERT_RDN, cRDNAttr), offsetof(CERT_RDN, rgRDNAttr),
1956 sizeof(CERT_RDN),
1957 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1958 offsetof(CERT_RDN_ATTR, pszObjId) };
1960 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1961 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1962 return ret;
1965 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1966 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1967 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1969 BOOL ret = TRUE;
1971 __TRY
1973 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1974 offsetof(CERT_NAME_INFO, cRDN), offsetof(CERT_NAME_INFO, rgRDN),
1975 sizeof(CERT_NAME_INFO),
1976 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1977 offsetof(CERT_RDN, rgRDNAttr) };
1979 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1980 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1982 __EXCEPT_PAGE_FAULT
1984 SetLastError(STATUS_ACCESS_VIOLATION);
1985 ret = FALSE;
1987 __ENDTRY
1988 return ret;
1991 static BOOL CRYPT_FindEncodedLen(const BYTE *pbEncoded, DWORD cbEncoded,
1992 DWORD *pcbDecoded)
1994 BOOL ret = TRUE, done = FALSE;
1995 DWORD indefiniteNestingLevels = 0, decoded = 0;
1997 TRACE("(%p, %d)\n", pbEncoded, cbEncoded);
1999 do {
2000 DWORD dataLen;
2002 if (!cbEncoded)
2003 done = TRUE;
2004 else if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded,
2005 &dataLen)))
2007 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2009 if (dataLen == CMSG_INDEFINITE_LENGTH)
2011 indefiniteNestingLevels++;
2012 pbEncoded += 1 + lenBytes;
2013 cbEncoded -= 1 + lenBytes;
2014 decoded += 1 + lenBytes;
2015 TRACE("indefiniteNestingLevels = %d\n",
2016 indefiniteNestingLevels);
2018 else
2020 if (pbEncoded[0] == 0 && pbEncoded[1] == 0 &&
2021 indefiniteNestingLevels)
2023 indefiniteNestingLevels--;
2024 TRACE("indefiniteNestingLevels = %d\n",
2025 indefiniteNestingLevels);
2027 pbEncoded += 1 + lenBytes + dataLen;
2028 cbEncoded -= 1 + lenBytes + dataLen;
2029 decoded += 1 + lenBytes + dataLen;
2030 if (!indefiniteNestingLevels)
2031 done = TRUE;
2034 } while (ret && !done);
2035 /* If we haven't found all 0 TLVs, we haven't found the end */
2036 if (ret && indefiniteNestingLevels)
2038 SetLastError(CRYPT_E_ASN1_EOD);
2039 ret = FALSE;
2041 if (ret)
2042 *pcbDecoded = decoded;
2043 TRACE("returning %d (%d)\n", ret, ret ? *pcbDecoded : 0);
2044 return ret;
2047 static BOOL CRYPT_AsnDecodeCopyBytes(const BYTE *pbEncoded,
2048 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2049 DWORD *pcbDecoded)
2051 BOOL ret = TRUE;
2052 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB), encodedLen = 0;
2054 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2055 pvStructInfo, *pcbStructInfo);
2057 if ((ret = CRYPT_FindEncodedLen(pbEncoded, cbEncoded, &encodedLen)))
2059 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
2060 bytesNeeded += encodedLen;
2061 if (!pvStructInfo)
2062 *pcbStructInfo = bytesNeeded;
2063 else if (*pcbStructInfo < bytesNeeded)
2065 SetLastError(ERROR_MORE_DATA);
2066 *pcbStructInfo = bytesNeeded;
2067 ret = FALSE;
2069 else
2071 PCRYPT_OBJID_BLOB blob = pvStructInfo;
2073 *pcbStructInfo = bytesNeeded;
2074 blob->cbData = encodedLen;
2075 if (encodedLen)
2077 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2078 blob->pbData = (LPBYTE)pbEncoded;
2079 else
2081 assert(blob->pbData);
2082 memcpy(blob->pbData, pbEncoded, blob->cbData);
2085 else
2086 blob->pbData = NULL;
2088 if (pcbDecoded)
2089 *pcbDecoded = encodedLen;
2091 return ret;
2094 static BOOL CRYPT_AsnDecodeCTLUsage(const BYTE *pbEncoded, DWORD cbEncoded,
2095 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2097 BOOL ret;
2098 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2099 offsetof(CTL_USAGE, cUsageIdentifier),
2100 offsetof(CTL_USAGE, rgpszUsageIdentifier),
2101 sizeof(CTL_USAGE),
2102 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
2104 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2105 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2106 return ret;
2109 static BOOL CRYPT_AsnDecodeCTLEntryAttributes(const BYTE *pbEncoded,
2110 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2111 DWORD *pcbDecoded)
2113 struct AsnArrayDescriptor arrayDesc = { 0,
2114 offsetof(CTL_ENTRY, cAttribute), offsetof(CTL_ENTRY, rgAttribute),
2115 FINALMEMBERSIZE(CTL_ENTRY, cAttribute),
2116 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2117 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2118 BOOL ret;
2120 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2121 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2122 return ret;
2125 static BOOL CRYPT_AsnDecodeCTLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2126 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2128 struct AsnDecodeSequenceItem items[] = {
2129 { ASN_OCTETSTRING, offsetof(CTL_ENTRY, SubjectIdentifier),
2130 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE,
2131 offsetof(CTL_ENTRY, SubjectIdentifier.pbData), 0 },
2132 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CTL_ENTRY, cAttribute),
2133 CRYPT_AsnDecodeCTLEntryAttributes,
2134 FINALMEMBERSIZE(CTL_ENTRY, cAttribute), FALSE, TRUE,
2135 offsetof(CTL_ENTRY, rgAttribute), 0 },
2137 BOOL ret = TRUE;
2138 CTL_ENTRY *entry = pvStructInfo;
2140 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
2141 *pcbStructInfo);
2143 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2144 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo,
2145 pcbDecoded, entry ? entry->SubjectIdentifier.pbData : NULL);
2146 return ret;
2149 static BOOL CRYPT_AsnDecodeCTLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
2150 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2152 BOOL ret;
2153 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2154 offsetof(CTL_INFO, cCTLEntry), offsetof(CTL_INFO, rgCTLEntry),
2155 FINALMEMBERSIZE(CTL_INFO, cExtension),
2156 CRYPT_AsnDecodeCTLEntry, sizeof(CTL_ENTRY), TRUE,
2157 offsetof(CTL_ENTRY, SubjectIdentifier.pbData) };
2159 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2160 pvStructInfo, *pcbStructInfo, pcbDecoded);
2162 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2163 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2164 return ret;
2167 static BOOL CRYPT_AsnDecodeCTLExtensionsInternal(const BYTE *pbEncoded,
2168 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2169 DWORD *pcbDecoded)
2171 BOOL ret = TRUE;
2172 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2173 offsetof(CTL_INFO, cExtension), offsetof(CTL_INFO, rgExtension),
2174 FINALMEMBERSIZE(CTL_INFO, cExtension),
2175 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
2176 offsetof(CERT_EXTENSION, pszObjId) };
2178 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2179 pvStructInfo, *pcbStructInfo, pcbDecoded);
2181 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2182 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2183 return ret;
2186 static BOOL CRYPT_AsnDecodeCTLExtensions(const BYTE *pbEncoded,
2187 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2188 DWORD *pcbDecoded)
2190 BOOL ret;
2191 DWORD dataLen;
2193 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2195 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2197 ret = CRYPT_AsnDecodeCTLExtensionsInternal(pbEncoded + 1 + lenBytes,
2198 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
2199 if (ret && pcbDecoded)
2200 *pcbDecoded = 1 + lenBytes + dataLen;
2202 return ret;
2205 static BOOL WINAPI CRYPT_AsnDecodeCTL(DWORD dwCertEncodingType,
2206 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2207 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2209 BOOL ret = FALSE;
2211 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2212 pDecodePara, pvStructInfo, *pcbStructInfo);
2214 __TRY
2216 struct AsnDecodeSequenceItem items[] = {
2217 { ASN_INTEGER, offsetof(CTL_INFO, dwVersion),
2218 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
2219 { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectUsage),
2220 CRYPT_AsnDecodeCTLUsage, sizeof(CTL_USAGE), FALSE, TRUE,
2221 offsetof(CTL_INFO, SubjectUsage.rgpszUsageIdentifier), 0 },
2222 { ASN_OCTETSTRING, offsetof(CTL_INFO, ListIdentifier),
2223 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), TRUE,
2224 TRUE, offsetof(CTL_INFO, ListIdentifier.pbData), 0 },
2225 { ASN_INTEGER, offsetof(CTL_INFO, SequenceNumber),
2226 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2227 TRUE, TRUE, offsetof(CTL_INFO, SequenceNumber.pbData), 0 },
2228 { 0, offsetof(CTL_INFO, ThisUpdate),
2229 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE,
2230 0 },
2231 { 0, offsetof(CTL_INFO, NextUpdate),
2232 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), TRUE, FALSE,
2233 0 },
2234 { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectAlgorithm),
2235 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2236 FALSE, TRUE, offsetof(CTL_INFO, SubjectAlgorithm.pszObjId), 0 },
2237 { ASN_SEQUENCEOF, offsetof(CTL_INFO, cCTLEntry),
2238 CRYPT_AsnDecodeCTLEntries,
2239 MEMBERSIZE(CTL_INFO, cCTLEntry, cExtension),
2240 TRUE, TRUE, offsetof(CTL_INFO, rgCTLEntry), 0 },
2241 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CTL_INFO, cExtension),
2242 CRYPT_AsnDecodeCTLExtensions, FINALMEMBERSIZE(CTL_INFO, cExtension),
2243 TRUE, TRUE, offsetof(CTL_INFO, rgExtension), 0 },
2246 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2247 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2248 pcbStructInfo, NULL, NULL);
2250 __EXCEPT_PAGE_FAULT
2252 SetLastError(STATUS_ACCESS_VIOLATION);
2254 __ENDTRY
2255 return ret;
2258 static BOOL CRYPT_AsnDecodeSMIMECapability(const BYTE *pbEncoded,
2259 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2260 DWORD *pcbDecoded)
2262 BOOL ret;
2263 struct AsnDecodeSequenceItem items[] = {
2264 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_SMIME_CAPABILITY, pszObjId),
2265 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2266 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId), 0 },
2267 { 0, offsetof(CRYPT_SMIME_CAPABILITY, Parameters),
2268 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2269 offsetof(CRYPT_SMIME_CAPABILITY, Parameters.pbData), 0 },
2271 PCRYPT_SMIME_CAPABILITY capability = pvStructInfo;
2273 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2274 pvStructInfo, *pcbStructInfo);
2276 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2277 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2278 pcbDecoded, capability ? capability->pszObjId : NULL);
2279 TRACE("returning %d\n", ret);
2280 return ret;
2283 static BOOL WINAPI CRYPT_AsnDecodeSMIMECapabilities(DWORD dwCertEncodingType,
2284 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2285 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2287 BOOL ret = FALSE;
2289 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2290 pDecodePara, pvStructInfo, *pcbStructInfo);
2292 __TRY
2294 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2295 offsetof(CRYPT_SMIME_CAPABILITIES, cCapability),
2296 offsetof(CRYPT_SMIME_CAPABILITIES, rgCapability),
2297 sizeof(CRYPT_SMIME_CAPABILITIES),
2298 CRYPT_AsnDecodeSMIMECapability, sizeof(CRYPT_SMIME_CAPABILITY), TRUE,
2299 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId) };
2301 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2302 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2304 __EXCEPT_PAGE_FAULT
2306 SetLastError(STATUS_ACCESS_VIOLATION);
2308 __ENDTRY
2309 TRACE("returning %d\n", ret);
2310 return ret;
2313 static BOOL CRYPT_AsnDecodeIA5String(const BYTE *pbEncoded,
2314 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2315 DWORD *pcbDecoded)
2317 BOOL ret = TRUE;
2318 DWORD dataLen;
2319 LPSTR *pStr = pvStructInfo;
2321 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2323 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2324 DWORD bytesNeeded = sizeof(LPSTR) + sizeof(char);
2326 if (pbEncoded[0] != ASN_IA5STRING)
2328 SetLastError(CRYPT_E_ASN1_CORRUPT);
2329 ret = FALSE;
2331 else
2333 bytesNeeded += dataLen;
2334 if (pcbDecoded)
2335 *pcbDecoded = 1 + lenBytes + dataLen;
2336 if (!pvStructInfo)
2337 *pcbStructInfo = bytesNeeded;
2338 else if (*pcbStructInfo < bytesNeeded)
2340 *pcbStructInfo = bytesNeeded;
2341 SetLastError(ERROR_MORE_DATA);
2342 ret = FALSE;
2344 else
2346 *pcbStructInfo = bytesNeeded;
2347 if (dataLen)
2349 LPSTR str = *pStr;
2351 assert(str);
2352 memcpy(str, pbEncoded + 1 + lenBytes, dataLen);
2353 str[dataLen] = 0;
2355 else
2356 *pStr = NULL;
2360 return ret;
2363 static BOOL CRYPT_AsnDecodeNoticeNumbers(const BYTE *pbEncoded,
2364 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2365 DWORD *pcbDecoded)
2367 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2368 offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers),
2369 offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, rgNoticeNumbers),
2370 FINALMEMBERSIZE(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers),
2371 CRYPT_AsnDecodeIntInternal, sizeof(int), FALSE, 0 };
2372 BOOL ret;
2374 TRACE("(%p, %d, %08x, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2375 pvStructInfo, pvStructInfo ? *pcbDecoded : 0);
2377 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2378 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2379 TRACE("returning %d\n", ret);
2380 return ret;
2383 static BOOL CRYPT_AsnDecodeNoticeReference(const BYTE *pbEncoded,
2384 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2385 DWORD *pcbDecoded)
2387 BOOL ret;
2388 struct AsnDecodeSequenceItem items[] = {
2389 { ASN_IA5STRING, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2390 pszOrganization), CRYPT_AsnDecodeIA5String, sizeof(LPSTR), FALSE, TRUE,
2391 offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, pszOrganization), 0 },
2392 { ASN_SEQUENCEOF, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2393 cNoticeNumbers), CRYPT_AsnDecodeNoticeNumbers,
2394 FINALMEMBERSIZE(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers),
2395 FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2396 rgNoticeNumbers), 0 },
2398 DWORD bytesNeeded;
2400 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2401 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
2403 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2404 pbEncoded, cbEncoded, dwFlags, NULL, NULL, &bytesNeeded, pcbDecoded,
2405 NULL);
2406 if (ret)
2408 /* The caller is expecting a pointer to a
2409 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE to be decoded, whereas
2410 * CRYPT_AsnDecodeSequence is decoding a
2411 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE. Increment the bytes
2412 * needed, and decode again if the requisite space is available.
2414 bytesNeeded += sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE);
2415 if (!pvStructInfo)
2416 *pcbStructInfo = bytesNeeded;
2417 else if (*pcbStructInfo < bytesNeeded)
2419 *pcbStructInfo = bytesNeeded;
2420 SetLastError(ERROR_MORE_DATA);
2421 ret = FALSE;
2423 else
2425 PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE noticeRef;
2427 *pcbStructInfo = bytesNeeded;
2428 /* The pointer (pvStructInfo) passed in points to the first dynamic
2429 * pointer, so use it as the pointer to the
2430 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, and create the
2431 * appropriate offset for the first dynamic pointer within the
2432 * notice reference by pointing to the first memory location past
2433 * the CERT_POLICY_QUALIFIER_NOTICE_REFERENCE.
2435 noticeRef =
2436 *(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE *)pvStructInfo;
2437 noticeRef->pszOrganization = (LPSTR)((LPBYTE)noticeRef +
2438 sizeof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE));
2439 ret = CRYPT_AsnDecodeSequence(items,
2440 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2441 NULL, noticeRef, &bytesNeeded, pcbDecoded,
2442 noticeRef->pszOrganization);
2445 TRACE("returning %d\n", ret);
2446 return ret;
2449 static BOOL CRYPT_AsnDecodeUnicodeString(const BYTE *pbEncoded,
2450 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2451 DWORD *pcbDecoded)
2453 BOOL ret = TRUE;
2454 DWORD dataLen;
2456 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2458 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2459 DWORD bytesNeeded = sizeof(LPWSTR);
2461 switch (pbEncoded[0])
2463 case ASN_NUMERICSTRING:
2464 if (dataLen)
2465 bytesNeeded += (dataLen + 1) * 2;
2466 break;
2467 case ASN_PRINTABLESTRING:
2468 if (dataLen)
2469 bytesNeeded += (dataLen + 1) * 2;
2470 break;
2471 case ASN_IA5STRING:
2472 if (dataLen)
2473 bytesNeeded += (dataLen + 1) * 2;
2474 break;
2475 case ASN_T61STRING:
2476 if (dataLen)
2477 bytesNeeded += (dataLen + 1) * 2;
2478 break;
2479 case ASN_VIDEOTEXSTRING:
2480 if (dataLen)
2481 bytesNeeded += (dataLen + 1) * 2;
2482 break;
2483 case ASN_GRAPHICSTRING:
2484 if (dataLen)
2485 bytesNeeded += (dataLen + 1) * 2;
2486 break;
2487 case ASN_VISIBLESTRING:
2488 if (dataLen)
2489 bytesNeeded += (dataLen + 1) * 2;
2490 break;
2491 case ASN_GENERALSTRING:
2492 if (dataLen)
2493 bytesNeeded += (dataLen + 1) * 2;
2494 break;
2495 case ASN_UNIVERSALSTRING:
2496 if (dataLen)
2497 bytesNeeded += dataLen / 2 + sizeof(WCHAR);
2498 break;
2499 case ASN_BMPSTRING:
2500 if (dataLen)
2501 bytesNeeded += dataLen + sizeof(WCHAR);
2502 break;
2503 case ASN_UTF8STRING:
2504 if (dataLen)
2505 bytesNeeded += (MultiByteToWideChar(CP_UTF8, 0,
2506 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) + 1) * 2;
2507 break;
2508 default:
2509 SetLastError(CRYPT_E_ASN1_BADTAG);
2510 return FALSE;
2513 if (pcbDecoded)
2514 *pcbDecoded = 1 + lenBytes + dataLen;
2515 if (!pvStructInfo)
2516 *pcbStructInfo = bytesNeeded;
2517 else if (*pcbStructInfo < bytesNeeded)
2519 *pcbStructInfo = bytesNeeded;
2520 SetLastError(ERROR_MORE_DATA);
2521 ret = FALSE;
2523 else
2525 LPWSTR *pStr = pvStructInfo;
2527 *pcbStructInfo = bytesNeeded;
2528 if (dataLen)
2530 DWORD i;
2531 LPWSTR str = *(LPWSTR *)pStr;
2533 assert(str);
2534 switch (pbEncoded[0])
2536 case ASN_NUMERICSTRING:
2537 case ASN_PRINTABLESTRING:
2538 case ASN_IA5STRING:
2539 case ASN_T61STRING:
2540 case ASN_VIDEOTEXSTRING:
2541 case ASN_GRAPHICSTRING:
2542 case ASN_VISIBLESTRING:
2543 case ASN_GENERALSTRING:
2544 for (i = 0; i < dataLen; i++)
2545 str[i] = pbEncoded[1 + lenBytes + i];
2546 str[i] = 0;
2547 break;
2548 case ASN_UNIVERSALSTRING:
2549 for (i = 0; i < dataLen / 4; i++)
2550 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
2551 | pbEncoded[1 + lenBytes + 2 * i + 3];
2552 str[i] = 0;
2553 break;
2554 case ASN_BMPSTRING:
2555 for (i = 0; i < dataLen / 2; i++)
2556 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
2557 pbEncoded[1 + lenBytes + 2 * i + 1];
2558 str[i] = 0;
2559 break;
2560 case ASN_UTF8STRING:
2562 int len = MultiByteToWideChar(CP_UTF8, 0,
2563 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
2564 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
2565 str[len] = 0;
2566 break;
2570 else
2571 *pStr = NULL;
2574 return ret;
2577 static BOOL CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(
2578 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
2579 DWORD *pcbStructInfo, DWORD *pcbDecoded)
2581 BOOL ret;
2582 struct AsnDecodeSequenceItem items[] = {
2583 { ASN_SEQUENCE, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE,
2584 pNoticeReference), CRYPT_AsnDecodeNoticeReference,
2585 sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE), TRUE, TRUE,
2586 offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pNoticeReference), 0 },
2587 { 0, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pszDisplayText),
2588 CRYPT_AsnDecodeUnicodeString, sizeof(LPWSTR), TRUE, TRUE,
2589 offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pszDisplayText), 0 },
2591 PCERT_POLICY_QUALIFIER_USER_NOTICE notice = pvStructInfo;
2593 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2594 pvStructInfo, *pcbStructInfo);
2596 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2597 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2598 pcbDecoded, notice ? notice->pNoticeReference : NULL);
2599 TRACE("returning %d\n", ret);
2600 return ret;
2603 static BOOL WINAPI CRYPT_AsnDecodePolicyQualifierUserNotice(
2604 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2605 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2606 void *pvStructInfo, DWORD *pcbStructInfo)
2608 BOOL ret = FALSE;
2610 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2611 pDecodePara, pvStructInfo, *pcbStructInfo);
2613 __TRY
2615 DWORD bytesNeeded;
2617 ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(pbEncoded,
2618 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2619 NULL);
2620 if (ret)
2622 if (!pvStructInfo)
2623 *pcbStructInfo = bytesNeeded;
2624 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2625 pvStructInfo, pcbStructInfo, bytesNeeded)))
2627 PCERT_POLICY_QUALIFIER_USER_NOTICE notice;
2629 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2630 pvStructInfo = *(BYTE **)pvStructInfo;
2631 notice = pvStructInfo;
2632 notice->pNoticeReference =
2633 (PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE)
2634 ((BYTE *)pvStructInfo +
2635 sizeof(CERT_POLICY_QUALIFIER_USER_NOTICE));
2636 ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(
2637 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
2638 pvStructInfo, &bytesNeeded, NULL);
2642 __EXCEPT_PAGE_FAULT
2644 SetLastError(STATUS_ACCESS_VIOLATION);
2646 __ENDTRY
2647 TRACE("returning %d\n", ret);
2648 return ret;
2651 static BOOL CRYPT_AsnDecodePKCSAttributeValue(const BYTE *pbEncoded,
2652 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2653 DWORD *pcbDecoded)
2655 BOOL ret;
2656 struct AsnArrayDescriptor arrayDesc = { 0,
2657 offsetof(CRYPT_ATTRIBUTE, cValue), offsetof(CRYPT_ATTRIBUTE, rgValue),
2658 FINALMEMBERSIZE(CRYPT_ATTRIBUTE, cValue),
2659 CRYPT_AsnDecodeCopyBytes,
2660 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
2662 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2663 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
2665 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2666 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2667 return ret;
2670 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
2671 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2672 DWORD *pcbDecoded)
2674 BOOL ret;
2675 struct AsnDecodeSequenceItem items[] = {
2676 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
2677 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2678 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
2679 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
2680 CRYPT_AsnDecodePKCSAttributeValue,
2681 FINALMEMBERSIZE(CRYPT_ATTRIBUTE, cValue), FALSE,
2682 TRUE, offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
2684 PCRYPT_ATTRIBUTE attr = pvStructInfo;
2686 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2687 pvStructInfo, *pcbStructInfo);
2689 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2690 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2691 pcbDecoded, attr ? attr->pszObjId : NULL);
2692 TRACE("returning %d\n", ret);
2693 return ret;
2696 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
2697 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2698 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2700 BOOL ret = FALSE;
2702 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2703 pDecodePara, pvStructInfo, *pcbStructInfo);
2705 __TRY
2707 DWORD bytesNeeded;
2709 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2710 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
2711 if (ret)
2713 if (!pvStructInfo)
2714 *pcbStructInfo = bytesNeeded;
2715 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2716 pvStructInfo, pcbStructInfo, bytesNeeded)))
2718 PCRYPT_ATTRIBUTE attr;
2720 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2721 pvStructInfo = *(BYTE **)pvStructInfo;
2722 attr = pvStructInfo;
2723 attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
2724 sizeof(CRYPT_ATTRIBUTE));
2725 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2726 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
2727 NULL);
2731 __EXCEPT_PAGE_FAULT
2733 SetLastError(STATUS_ACCESS_VIOLATION);
2735 __ENDTRY
2736 TRACE("returning %d\n", ret);
2737 return ret;
2740 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
2741 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2742 DWORD *pcbDecoded)
2744 struct AsnArrayDescriptor arrayDesc = { 0,
2745 offsetof(CRYPT_ATTRIBUTES, cAttr), offsetof(CRYPT_ATTRIBUTES, rgAttr),
2746 sizeof(CRYPT_ATTRIBUTES),
2747 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2748 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2749 BOOL ret;
2751 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2752 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2753 return ret;
2756 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
2757 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2758 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2760 BOOL ret = FALSE;
2762 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2763 pDecodePara, pvStructInfo, *pcbStructInfo);
2765 __TRY
2767 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
2768 offsetof(CRYPT_ATTRIBUTES, cAttr), offsetof(CRYPT_ATTRIBUTES, rgAttr),
2769 sizeof(CRYPT_ATTRIBUTES),
2770 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE),
2771 TRUE, offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2773 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2774 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2776 __EXCEPT_PAGE_FAULT
2778 SetLastError(STATUS_ACCESS_VIOLATION);
2780 __ENDTRY
2781 TRACE("returning %d\n", ret);
2782 return ret;
2785 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
2786 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2788 CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
2789 BOOL ret = TRUE;
2790 struct AsnDecodeSequenceItem items[] = {
2791 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
2792 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2793 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
2794 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
2795 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2796 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
2799 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2800 pvStructInfo, *pcbStructInfo, pcbDecoded);
2802 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2803 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2804 pcbDecoded, algo ? algo->pszObjId : NULL);
2805 if (ret && pvStructInfo)
2807 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
2808 debugstr_a(algo->pszObjId));
2810 return ret;
2813 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
2814 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2815 DWORD *pcbDecoded)
2817 BOOL ret = TRUE;
2818 struct AsnDecodeSequenceItem items[] = {
2819 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
2820 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2821 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
2822 Algorithm.pszObjId) },
2823 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
2824 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2825 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
2827 PCERT_PUBLIC_KEY_INFO info = pvStructInfo;
2829 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2830 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2831 pcbDecoded, info ? info->Algorithm.Parameters.pbData : NULL);
2832 return ret;
2835 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2836 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2837 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2839 BOOL ret = TRUE;
2841 __TRY
2843 DWORD bytesNeeded;
2845 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2846 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2848 if (!pvStructInfo)
2849 *pcbStructInfo = bytesNeeded;
2850 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2851 pvStructInfo, pcbStructInfo, bytesNeeded)))
2853 PCERT_PUBLIC_KEY_INFO info;
2855 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2856 pvStructInfo = *(BYTE **)pvStructInfo;
2857 info = pvStructInfo;
2858 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2859 sizeof(CERT_PUBLIC_KEY_INFO);
2860 ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2861 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2862 &bytesNeeded, NULL);
2866 __EXCEPT_PAGE_FAULT
2868 SetLastError(STATUS_ACCESS_VIOLATION);
2869 ret = FALSE;
2871 __ENDTRY
2872 return ret;
2875 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
2876 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2878 BOOL ret;
2880 if (cbEncoded < 3)
2882 SetLastError(CRYPT_E_ASN1_CORRUPT);
2883 return FALSE;
2885 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2887 SetLastError(CRYPT_E_ASN1_CORRUPT);
2888 return FALSE;
2890 if (pbEncoded[1] > 1)
2892 SetLastError(CRYPT_E_ASN1_CORRUPT);
2893 return FALSE;
2895 if (pcbDecoded)
2896 *pcbDecoded = 3;
2897 if (!pvStructInfo)
2899 *pcbStructInfo = sizeof(BOOL);
2900 ret = TRUE;
2902 else if (*pcbStructInfo < sizeof(BOOL))
2904 *pcbStructInfo = sizeof(BOOL);
2905 SetLastError(ERROR_MORE_DATA);
2906 ret = FALSE;
2908 else
2910 *pcbStructInfo = sizeof(BOOL);
2911 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2912 ret = TRUE;
2914 TRACE("returning %d (%08x)\n", ret, GetLastError());
2915 return ret;
2918 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2919 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2921 PCERT_ALT_NAME_ENTRY entry = pvStructInfo;
2922 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2923 BOOL ret;
2925 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2926 pvStructInfo, *pcbStructInfo);
2928 if (cbEncoded < 2)
2930 SetLastError(CRYPT_E_ASN1_CORRUPT);
2931 return FALSE;
2933 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2934 if (1 + lenBytes > cbEncoded)
2936 SetLastError(CRYPT_E_ASN1_CORRUPT);
2937 return FALSE;
2939 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2941 switch (pbEncoded[0] & ASN_TYPE_MASK)
2943 case 1: /* rfc822Name */
2944 case 2: /* dNSName */
2945 case 6: /* uniformResourceIdentifier */
2946 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
2947 break;
2948 case 4: /* directoryName */
2949 case 7: /* iPAddress */
2950 bytesNeeded += dataLen;
2951 break;
2952 case 8: /* registeredID */
2953 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
2954 &dataLen, NULL);
2955 if (ret)
2957 /* FIXME: ugly, shouldn't need to know internals of OID decode
2958 * function to use it.
2960 bytesNeeded += dataLen - sizeof(LPSTR);
2962 break;
2963 case 0: /* otherName */
2964 FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
2965 SetLastError(CRYPT_E_ASN1_BADTAG);
2966 ret = FALSE;
2967 break;
2968 case 3: /* x400Address, unimplemented */
2969 case 5: /* ediPartyName, unimplemented */
2970 TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
2971 SetLastError(CRYPT_E_ASN1_BADTAG);
2972 ret = FALSE;
2973 break;
2974 default:
2975 TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
2976 SetLastError(CRYPT_E_ASN1_CORRUPT);
2977 ret = FALSE;
2979 if (ret)
2981 if (pcbDecoded)
2982 *pcbDecoded = 1 + lenBytes + dataLen;
2983 if (!entry)
2984 *pcbStructInfo = bytesNeeded;
2985 else if (*pcbStructInfo < bytesNeeded)
2987 *pcbStructInfo = bytesNeeded;
2988 SetLastError(ERROR_MORE_DATA);
2989 ret = FALSE;
2991 else
2993 *pcbStructInfo = bytesNeeded;
2994 /* MS used values one greater than the asn1 ones.. sigh */
2995 entry->dwAltNameChoice = (pbEncoded[0] & ASN_TYPE_MASK) + 1;
2996 switch (pbEncoded[0] & ASN_TYPE_MASK)
2998 case 1: /* rfc822Name */
2999 case 2: /* dNSName */
3000 case 6: /* uniformResourceIdentifier */
3002 DWORD i;
3004 for (i = 0; i < dataLen; i++)
3005 entry->u.pwszURL[i] =
3006 (WCHAR)pbEncoded[1 + lenBytes + i];
3007 entry->u.pwszURL[i] = 0;
3008 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
3009 debugstr_w(entry->u.pwszURL));
3010 break;
3012 case 4: /* directoryName */
3013 /* The data are memory-equivalent with the IPAddress case,
3014 * fall-through
3016 case 7: /* iPAddress */
3017 /* The next data pointer is in the pwszURL spot, that is,
3018 * the first 4 bytes. Need to move it to the next spot.
3020 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
3021 entry->u.IPAddress.cbData = dataLen;
3022 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
3023 dataLen);
3024 break;
3025 case 8: /* registeredID */
3026 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
3027 &entry->u.pszRegisteredID, &dataLen, NULL);
3028 break;
3033 return ret;
3036 static BOOL CRYPT_AsnDecodeAltNameInternal(const BYTE *pbEncoded,
3037 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3038 DWORD *pcbDecoded)
3040 BOOL ret;
3041 struct AsnArrayDescriptor arrayDesc = { 0,
3042 offsetof(CERT_ALT_NAME_INFO, cAltEntry),
3043 offsetof(CERT_ALT_NAME_INFO, rgAltEntry),
3044 sizeof(CERT_ALT_NAME_INFO),
3045 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3046 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3048 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3049 pvStructInfo, *pcbStructInfo, pcbDecoded);
3051 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3052 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
3053 return ret;
3056 /* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */
3057 static BOOL CRYPT_AsnDecodeIntegerSwapBytes(const BYTE *pbEncoded,
3058 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3059 DWORD *pcbDecoded)
3061 BOOL ret;
3063 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
3064 pvStructInfo, *pcbStructInfo, pcbDecoded);
3066 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
3067 * place.
3069 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3070 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
3071 pcbDecoded);
3072 if (ret && pvStructInfo)
3074 CRYPT_DATA_BLOB *blob = pvStructInfo;
3076 if (blob->cbData)
3078 DWORD i;
3079 BYTE temp;
3081 for (i = 0; i < blob->cbData / 2; i++)
3083 temp = blob->pbData[i];
3084 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
3085 blob->pbData[blob->cbData - i - 1] = temp;
3089 TRACE("returning %d (%08x)\n", ret, GetLastError());
3090 return ret;
3093 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
3094 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3095 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3097 BOOL ret;
3099 __TRY
3101 struct AsnDecodeSequenceItem items[] = {
3102 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
3103 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
3104 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
3105 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
3106 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
3107 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
3108 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
3109 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
3110 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
3111 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
3112 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
3115 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3116 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3117 pcbStructInfo, NULL, NULL);
3119 __EXCEPT_PAGE_FAULT
3121 SetLastError(STATUS_ACCESS_VIOLATION);
3122 ret = FALSE;
3124 __ENDTRY
3125 return ret;
3128 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
3129 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3130 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3132 BOOL ret;
3134 __TRY
3136 struct AsnDecodeSequenceItem items[] = {
3137 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
3138 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
3139 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
3140 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
3141 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
3142 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
3143 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3144 AuthorityCertIssuer.rgAltEntry), 0 },
3145 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3146 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
3147 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
3148 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3149 AuthorityCertSerialNumber.pbData), 0 },
3152 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3153 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3154 pcbStructInfo, NULL, NULL);
3156 __EXCEPT_PAGE_FAULT
3158 SetLastError(STATUS_ACCESS_VIOLATION);
3159 ret = FALSE;
3161 __ENDTRY
3162 return ret;
3165 static BOOL CRYPT_AsnDecodeAccessDescription(const BYTE *pbEncoded,
3166 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3167 DWORD *pcbDecoded)
3169 struct AsnDecodeSequenceItem items[] = {
3170 { 0, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod),
3171 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
3172 offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod), 0 },
3173 { 0, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation),
3174 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), FALSE,
3175 TRUE, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation.u.pwszURL), 0 },
3177 CERT_ACCESS_DESCRIPTION *descr = pvStructInfo;
3179 return CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3180 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3181 pcbDecoded, descr ? descr->pszAccessMethod : NULL);
3184 static BOOL WINAPI CRYPT_AsnDecodeAuthorityInfoAccess(DWORD dwCertEncodingType,
3185 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3186 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3188 BOOL ret;
3190 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3191 pDecodePara, pvStructInfo, *pcbStructInfo);
3193 __TRY
3195 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3196 offsetof(CERT_AUTHORITY_INFO_ACCESS, cAccDescr),
3197 offsetof(CERT_AUTHORITY_INFO_ACCESS, rgAccDescr),
3198 sizeof(CERT_AUTHORITY_INFO_ACCESS),
3199 CRYPT_AsnDecodeAccessDescription, sizeof(CERT_ACCESS_DESCRIPTION),
3200 TRUE, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod) };
3202 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3203 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3205 __EXCEPT_PAGE_FAULT
3207 SetLastError(STATUS_ACCESS_VIOLATION);
3208 ret = FALSE;
3210 __ENDTRY
3211 return ret;
3214 static BOOL CRYPT_AsnDecodePKCSContent(const BYTE *pbEncoded, DWORD cbEncoded,
3215 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3217 BOOL ret;
3218 DWORD dataLen;
3220 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3221 pvStructInfo, *pcbStructInfo, pcbDecoded);
3223 /* The caller has already checked the tag, no need to check it again.
3224 * Check the outer length is valid:
3226 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
3228 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3229 DWORD innerLen;
3231 pbEncoded += 1 + lenBytes;
3232 cbEncoded -= 1 + lenBytes;
3233 if (dataLen == CMSG_INDEFINITE_LENGTH)
3234 cbEncoded -= 2; /* space for 0 TLV */
3235 /* Check the inner length is valid: */
3236 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &innerLen)))
3238 DWORD decodedLen;
3240 ret = CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags,
3241 pvStructInfo, pcbStructInfo, &decodedLen);
3242 if (dataLen == CMSG_INDEFINITE_LENGTH)
3244 if (*(pbEncoded + decodedLen) != 0 ||
3245 *(pbEncoded + decodedLen + 1) != 0)
3247 TRACE("expected 0 TLV, got {%02x,%02x}\n",
3248 *(pbEncoded + decodedLen),
3249 *(pbEncoded + decodedLen + 1));
3250 SetLastError(CRYPT_E_ASN1_CORRUPT);
3251 ret = FALSE;
3253 else
3254 decodedLen += 2;
3256 if (ret && pcbDecoded)
3258 *pcbDecoded = 1 + lenBytes + decodedLen;
3259 TRACE("decoded %d bytes\n", *pcbDecoded);
3263 return ret;
3266 static BOOL CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE *pbEncoded,
3267 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3268 DWORD *pcbDecoded)
3270 CRYPT_CONTENT_INFO *info = pvStructInfo;
3271 struct AsnDecodeSequenceItem items[] = {
3272 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
3273 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
3274 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
3275 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
3276 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
3277 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
3278 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
3280 BOOL ret;
3282 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3283 pvStructInfo, *pcbStructInfo, pcbDecoded);
3285 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3286 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3287 pcbDecoded, info ? info->pszObjId : NULL);
3288 return ret;
3291 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
3292 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3293 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3295 BOOL ret = FALSE;
3297 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3298 pDecodePara, pvStructInfo, *pcbStructInfo);
3300 __TRY
3302 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, cbEncoded,
3303 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
3304 if (ret && pvStructInfo)
3306 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
3307 pcbStructInfo, *pcbStructInfo);
3308 if (ret)
3310 CRYPT_CONTENT_INFO *info;
3312 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3313 pvStructInfo = *(BYTE **)pvStructInfo;
3314 info = pvStructInfo;
3315 info->pszObjId = (LPSTR)((BYTE *)info +
3316 sizeof(CRYPT_CONTENT_INFO));
3317 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded,
3318 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3319 pcbStructInfo, NULL);
3323 __EXCEPT_PAGE_FAULT
3325 SetLastError(STATUS_ACCESS_VIOLATION);
3327 __ENDTRY
3328 return ret;
3331 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
3332 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3333 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
3335 BOOL ret;
3336 struct AsnDecodeSequenceItem items[] = {
3337 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version),
3338 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3339 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
3340 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3341 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
3342 0 },
3343 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
3344 CRYPT_AsnDecodePKCSContentInfoInternal,
3345 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
3346 ContentInfo.pszObjId), 0 },
3347 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
3348 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
3349 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
3352 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3353 pbEncoded, cbEncoded, dwFlags, pDecodePara, digestedData, pcbDigestedData,
3354 NULL, NULL);
3355 return ret;
3358 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
3359 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3360 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3362 BOOL ret = TRUE;
3364 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3365 pDecodePara, pvStructInfo, *pcbStructInfo);
3367 __TRY
3369 DWORD bytesNeeded;
3371 if ((ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
3372 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3374 if (!pvStructInfo)
3375 *pcbStructInfo = bytesNeeded;
3376 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3377 pvStructInfo, pcbStructInfo, bytesNeeded)))
3379 CERT_ALT_NAME_INFO *name;
3381 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3382 pvStructInfo = *(BYTE **)pvStructInfo;
3383 name = pvStructInfo;
3384 name->rgAltEntry = (PCERT_ALT_NAME_ENTRY)
3385 ((BYTE *)pvStructInfo + sizeof(CERT_ALT_NAME_INFO));
3386 ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
3387 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3388 &bytesNeeded, NULL);
3392 __EXCEPT_PAGE_FAULT
3394 SetLastError(STATUS_ACCESS_VIOLATION);
3395 ret = FALSE;
3397 __ENDTRY
3398 return ret;
3401 struct PATH_LEN_CONSTRAINT
3403 BOOL fPathLenConstraint;
3404 DWORD dwPathLenConstraint;
3407 static BOOL CRYPT_AsnDecodePathLenConstraint(const BYTE *pbEncoded,
3408 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3409 DWORD *pcbDecoded)
3411 BOOL ret = TRUE;
3412 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT), size;
3414 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3415 pvStructInfo, *pcbStructInfo, pcbDecoded);
3417 if (!pvStructInfo)
3419 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, NULL,
3420 &size, pcbDecoded);
3421 *pcbStructInfo = bytesNeeded;
3423 else if (*pcbStructInfo < bytesNeeded)
3425 SetLastError(ERROR_MORE_DATA);
3426 *pcbStructInfo = bytesNeeded;
3427 ret = FALSE;
3429 else
3431 struct PATH_LEN_CONSTRAINT *constraint = pvStructInfo;
3433 *pcbStructInfo = bytesNeeded;
3434 size = sizeof(constraint->dwPathLenConstraint);
3435 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
3436 &constraint->dwPathLenConstraint, &size, pcbDecoded);
3437 if (ret)
3438 constraint->fPathLenConstraint = TRUE;
3439 TRACE("got an int, dwPathLenConstraint is %d\n",
3440 constraint->dwPathLenConstraint);
3442 TRACE("returning %d (%08x)\n", ret, GetLastError());
3443 return ret;
3446 static BOOL CRYPT_AsnDecodeSubtreeConstraints(const BYTE *pbEncoded,
3447 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3448 DWORD *pcbDecoded)
3450 BOOL ret;
3451 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3452 offsetof(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint),
3453 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint),
3454 FINALMEMBERSIZE(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint),
3455 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
3456 offsetof(CERT_NAME_BLOB, pbData) };
3458 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3459 pvStructInfo, *pcbStructInfo, pcbDecoded);
3461 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3462 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
3463 TRACE("Returning %d (%08x)\n", ret, GetLastError());
3464 return ret;
3467 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
3468 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3469 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3471 BOOL ret;
3473 __TRY
3475 struct AsnDecodeSequenceItem items[] = {
3476 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
3477 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
3478 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
3479 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3480 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3481 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3482 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3483 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
3484 FINALMEMBERSIZE(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint),
3485 TRUE, TRUE,
3486 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
3489 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3490 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3491 pcbStructInfo, NULL, NULL);
3493 __EXCEPT_PAGE_FAULT
3495 SetLastError(STATUS_ACCESS_VIOLATION);
3496 ret = FALSE;
3498 __ENDTRY
3499 return ret;
3502 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
3503 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3504 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3506 BOOL ret;
3508 __TRY
3510 struct AsnDecodeSequenceItem items[] = {
3511 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
3512 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
3513 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
3514 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3515 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3518 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3519 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3520 pcbStructInfo, NULL, NULL);
3522 __EXCEPT_PAGE_FAULT
3524 SetLastError(STATUS_ACCESS_VIOLATION);
3525 ret = FALSE;
3527 __ENDTRY
3528 return ret;
3531 static BOOL CRYPT_AsnDecodePolicyQualifier(const BYTE *pbEncoded,
3532 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3533 DWORD *pcbDecoded)
3535 struct AsnDecodeSequenceItem items[] = {
3536 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_QUALIFIER_INFO,
3537 pszPolicyQualifierId), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
3538 FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId),
3539 0 },
3540 { 0, offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier),
3541 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
3542 offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier.pbData), 0 },
3544 BOOL ret;
3545 CERT_POLICY_QUALIFIER_INFO *qualifier = pvStructInfo;
3547 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3548 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3550 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3551 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3552 pcbDecoded, qualifier ? qualifier->pszPolicyQualifierId : NULL);
3553 return ret;
3556 static BOOL CRYPT_AsnDecodePolicyQualifiers(const BYTE *pbEncoded,
3557 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3558 DWORD *pcbDecoded)
3560 BOOL ret;
3561 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3562 offsetof(CERT_POLICY_INFO, cPolicyQualifier),
3563 offsetof(CERT_POLICY_INFO, rgPolicyQualifier),
3564 FINALMEMBERSIZE(CERT_POLICY_INFO, cPolicyQualifier),
3565 CRYPT_AsnDecodePolicyQualifier, sizeof(CERT_POLICY_QUALIFIER_INFO), TRUE,
3566 offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId) };
3568 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3569 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3571 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3572 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
3573 TRACE("Returning %d (%08x)\n", ret, GetLastError());
3574 return ret;
3577 static BOOL CRYPT_AsnDecodeCertPolicy(const BYTE *pbEncoded, DWORD cbEncoded,
3578 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3580 struct AsnDecodeSequenceItem items[] = {
3581 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_INFO, pszPolicyIdentifier),
3582 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
3583 offsetof(CERT_POLICY_INFO, pszPolicyIdentifier), 0 },
3584 { ASN_SEQUENCEOF, offsetof(CERT_POLICY_INFO, cPolicyQualifier),
3585 CRYPT_AsnDecodePolicyQualifiers,
3586 FINALMEMBERSIZE(CERT_POLICY_INFO, cPolicyQualifier), TRUE,
3587 TRUE, offsetof(CERT_POLICY_INFO, rgPolicyQualifier), 0 },
3589 CERT_POLICY_INFO *info = pvStructInfo;
3590 BOOL ret;
3592 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3593 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3595 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3596 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3597 pcbDecoded, info ? info->pszPolicyIdentifier : NULL);
3598 return ret;
3601 static BOOL WINAPI CRYPT_AsnDecodeCertPolicies(DWORD dwCertEncodingType,
3602 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3603 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3605 BOOL ret = FALSE;
3607 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3608 pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3610 __TRY
3612 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3613 offsetof(CERT_POLICIES_INFO, cPolicyInfo),
3614 offsetof(CERT_POLICIES_INFO, rgPolicyInfo),
3615 sizeof(CERT_POLICIES_INFO),
3616 CRYPT_AsnDecodeCertPolicy, sizeof(CERT_POLICY_INFO), TRUE,
3617 offsetof(CERT_POLICY_INFO, pszPolicyIdentifier) };
3619 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3620 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3622 __EXCEPT_PAGE_FAULT
3624 SetLastError(STATUS_ACCESS_VIOLATION);
3626 __ENDTRY
3627 return ret;
3630 #define RSA1_MAGIC 0x31415352
3632 struct DECODED_RSA_PUB_KEY
3634 DWORD pubexp;
3635 CRYPT_INTEGER_BLOB modulus;
3638 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
3639 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3640 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3642 BOOL ret;
3644 __TRY
3646 struct AsnDecodeSequenceItem items[] = {
3647 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
3648 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3649 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
3650 0 },
3651 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
3652 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3654 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
3655 DWORD size = 0;
3657 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3658 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
3659 &size, NULL, NULL);
3660 if (ret)
3662 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
3663 decodedKey->modulus.cbData;
3665 if (!pvStructInfo)
3667 *pcbStructInfo = bytesNeeded;
3668 ret = TRUE;
3670 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3671 pvStructInfo, pcbStructInfo, bytesNeeded)))
3673 BLOBHEADER *hdr;
3674 RSAPUBKEY *rsaPubKey;
3676 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3677 pvStructInfo = *(BYTE **)pvStructInfo;
3678 hdr = pvStructInfo;
3679 hdr->bType = PUBLICKEYBLOB;
3680 hdr->bVersion = CUR_BLOB_VERSION;
3681 hdr->reserved = 0;
3682 hdr->aiKeyAlg = CALG_RSA_KEYX;
3683 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
3684 sizeof(BLOBHEADER));
3685 rsaPubKey->magic = RSA1_MAGIC;
3686 rsaPubKey->pubexp = decodedKey->pubexp;
3687 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
3688 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
3689 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
3690 decodedKey->modulus.cbData);
3692 LocalFree(decodedKey);
3695 __EXCEPT_PAGE_FAULT
3697 SetLastError(STATUS_ACCESS_VIOLATION);
3698 ret = FALSE;
3700 __ENDTRY
3701 return ret;
3704 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
3705 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3706 DWORD *pcbDecoded)
3708 BOOL ret;
3709 DWORD bytesNeeded, dataLen;
3711 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3712 pvStructInfo, *pcbStructInfo, pcbDecoded);
3714 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3716 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3718 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3719 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
3720 else
3721 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
3722 if (pcbDecoded)
3723 *pcbDecoded = 1 + lenBytes + dataLen;
3724 if (!pvStructInfo)
3725 *pcbStructInfo = bytesNeeded;
3726 else if (*pcbStructInfo < bytesNeeded)
3728 SetLastError(ERROR_MORE_DATA);
3729 *pcbStructInfo = bytesNeeded;
3730 ret = FALSE;
3732 else
3734 CRYPT_DATA_BLOB *blob;
3736 *pcbStructInfo = bytesNeeded;
3737 blob = pvStructInfo;
3738 blob->cbData = dataLen;
3739 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3740 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
3741 else
3743 assert(blob->pbData);
3744 if (blob->cbData)
3745 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
3746 blob->cbData);
3750 return ret;
3753 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
3754 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3755 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3757 BOOL ret;
3759 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3760 pDecodePara, pvStructInfo, *pcbStructInfo);
3762 __TRY
3764 DWORD bytesNeeded;
3766 if (!cbEncoded)
3768 SetLastError(CRYPT_E_ASN1_CORRUPT);
3769 ret = FALSE;
3771 else if (pbEncoded[0] != ASN_OCTETSTRING)
3773 SetLastError(CRYPT_E_ASN1_BADTAG);
3774 ret = FALSE;
3776 else if ((ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
3777 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3779 if (!pvStructInfo)
3780 *pcbStructInfo = bytesNeeded;
3781 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3782 pvStructInfo, pcbStructInfo, bytesNeeded)))
3784 CRYPT_DATA_BLOB *blob;
3786 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3787 pvStructInfo = *(BYTE **)pvStructInfo;
3788 blob = pvStructInfo;
3789 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
3790 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
3791 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3792 &bytesNeeded, NULL);
3796 __EXCEPT_PAGE_FAULT
3798 SetLastError(STATUS_ACCESS_VIOLATION);
3799 ret = FALSE;
3801 __ENDTRY
3802 return ret;
3805 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3806 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3808 BOOL ret;
3809 DWORD bytesNeeded, dataLen;
3810 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3812 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
3813 pvStructInfo, *pcbStructInfo, pcbDecoded);
3815 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3817 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3818 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
3819 else
3820 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
3821 if (pcbDecoded)
3822 *pcbDecoded = 1 + lenBytes + dataLen;
3823 if (!pvStructInfo)
3824 *pcbStructInfo = bytesNeeded;
3825 else if (*pcbStructInfo < bytesNeeded)
3827 *pcbStructInfo = bytesNeeded;
3828 SetLastError(ERROR_MORE_DATA);
3829 ret = FALSE;
3831 else
3833 CRYPT_BIT_BLOB *blob;
3835 *pcbStructInfo = bytesNeeded;
3836 blob = pvStructInfo;
3837 blob->cbData = dataLen - 1;
3838 blob->cUnusedBits = *(pbEncoded + 1 + lenBytes);
3839 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3841 blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes;
3843 else
3845 assert(blob->pbData);
3846 if (blob->cbData)
3848 BYTE mask = 0xff << blob->cUnusedBits;
3850 memcpy(blob->pbData, pbEncoded + 2 + lenBytes,
3851 blob->cbData);
3852 blob->pbData[blob->cbData - 1] &= mask;
3857 return ret;
3860 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
3861 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3862 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3864 BOOL ret;
3866 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
3867 pDecodePara, pvStructInfo, pcbStructInfo);
3869 __TRY
3871 DWORD bytesNeeded;
3873 if (!cbEncoded)
3875 SetLastError(CRYPT_E_ASN1_CORRUPT);
3876 ret = FALSE;
3878 else if (pbEncoded[0] != ASN_BITSTRING)
3880 SetLastError(CRYPT_E_ASN1_BADTAG);
3881 ret = FALSE;
3883 else if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3884 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3886 if (!pvStructInfo)
3887 *pcbStructInfo = bytesNeeded;
3888 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3889 pvStructInfo, pcbStructInfo, bytesNeeded)))
3891 CRYPT_BIT_BLOB *blob;
3893 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3894 pvStructInfo = *(BYTE **)pvStructInfo;
3895 blob = pvStructInfo;
3896 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
3897 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3898 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3899 &bytesNeeded, NULL);
3903 __EXCEPT_PAGE_FAULT
3905 SetLastError(STATUS_ACCESS_VIOLATION);
3906 ret = FALSE;
3908 __ENDTRY
3909 TRACE("returning %d (%08x)\n", ret, GetLastError());
3910 return ret;
3913 /* Ignores tag. Only allows integers 4 bytes or smaller in size. */
3914 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3915 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3917 BOOL ret;
3918 DWORD dataLen;
3920 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3922 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3924 if (pcbDecoded)
3925 *pcbDecoded = 1 + lenBytes + dataLen;
3926 if (dataLen > sizeof(int))
3928 SetLastError(CRYPT_E_ASN1_LARGE);
3929 ret = FALSE;
3931 else if (!pvStructInfo)
3932 *pcbStructInfo = sizeof(int);
3933 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int))))
3935 int val, i;
3937 if (dataLen && pbEncoded[1 + lenBytes] & 0x80)
3939 /* initialize to a negative value to sign-extend */
3940 val = -1;
3942 else
3943 val = 0;
3944 for (i = 0; i < dataLen; i++)
3946 val <<= 8;
3947 val |= pbEncoded[1 + lenBytes + i];
3949 memcpy(pvStructInfo, &val, sizeof(int));
3952 return ret;
3955 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
3956 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3957 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3959 BOOL ret;
3961 __TRY
3963 DWORD bytesNeeded;
3965 if (!cbEncoded)
3967 SetLastError(CRYPT_E_ASN1_EOD);
3968 ret = FALSE;
3970 else if (pbEncoded[0] != ASN_INTEGER)
3972 SetLastError(CRYPT_E_ASN1_BADTAG);
3973 ret = FALSE;
3975 else
3976 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3977 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3978 if (ret)
3980 if (!pvStructInfo)
3981 *pcbStructInfo = bytesNeeded;
3982 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3983 pvStructInfo, pcbStructInfo, bytesNeeded)))
3985 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3986 pvStructInfo = *(BYTE **)pvStructInfo;
3987 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3988 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3989 &bytesNeeded, NULL);
3993 __EXCEPT_PAGE_FAULT
3995 SetLastError(STATUS_ACCESS_VIOLATION);
3996 ret = FALSE;
3998 __ENDTRY
3999 return ret;
4002 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
4003 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4004 DWORD *pcbDecoded)
4006 BOOL ret;
4007 DWORD bytesNeeded, dataLen;
4009 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4011 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4013 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
4014 if (pcbDecoded)
4015 *pcbDecoded = 1 + lenBytes + dataLen;
4016 if (!pvStructInfo)
4017 *pcbStructInfo = bytesNeeded;
4018 else if (*pcbStructInfo < bytesNeeded)
4020 *pcbStructInfo = bytesNeeded;
4021 SetLastError(ERROR_MORE_DATA);
4022 ret = FALSE;
4024 else
4026 CRYPT_INTEGER_BLOB *blob = pvStructInfo;
4028 *pcbStructInfo = bytesNeeded;
4029 blob->cbData = dataLen;
4030 assert(blob->pbData);
4031 if (blob->cbData)
4033 DWORD i;
4035 for (i = 0; i < blob->cbData; i++)
4037 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
4038 dataLen - i - 1);
4043 return ret;
4046 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
4047 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4048 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4050 BOOL ret;
4052 __TRY
4054 DWORD bytesNeeded;
4056 if (pbEncoded[0] != ASN_INTEGER)
4058 SetLastError(CRYPT_E_ASN1_BADTAG);
4059 ret = FALSE;
4061 else
4062 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
4063 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4064 if (ret)
4066 if (!pvStructInfo)
4067 *pcbStructInfo = bytesNeeded;
4068 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4069 pvStructInfo, pcbStructInfo, bytesNeeded)))
4071 CRYPT_INTEGER_BLOB *blob;
4073 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4074 pvStructInfo = *(BYTE **)pvStructInfo;
4075 blob = pvStructInfo;
4076 blob->pbData = (BYTE *)pvStructInfo +
4077 sizeof(CRYPT_INTEGER_BLOB);
4078 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
4079 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
4080 &bytesNeeded, NULL);
4084 __EXCEPT_PAGE_FAULT
4086 SetLastError(STATUS_ACCESS_VIOLATION);
4087 ret = FALSE;
4089 __ENDTRY
4090 return ret;
4093 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
4094 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4095 DWORD *pcbDecoded)
4097 BOOL ret;
4099 if (pbEncoded[0] == ASN_INTEGER)
4101 DWORD bytesNeeded, dataLen;
4103 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4105 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4107 if (pcbDecoded)
4108 *pcbDecoded = 1 + lenBytes + dataLen;
4109 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
4110 if (!pvStructInfo)
4111 *pcbStructInfo = bytesNeeded;
4112 else if (*pcbStructInfo < bytesNeeded)
4114 *pcbStructInfo = bytesNeeded;
4115 SetLastError(ERROR_MORE_DATA);
4116 ret = FALSE;
4118 else
4120 CRYPT_INTEGER_BLOB *blob = pvStructInfo;
4122 *pcbStructInfo = bytesNeeded;
4123 blob->cbData = dataLen;
4124 assert(blob->pbData);
4125 /* remove leading zero byte if it exists */
4126 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
4128 blob->cbData--;
4129 blob->pbData++;
4131 if (blob->cbData)
4133 DWORD i;
4135 for (i = 0; i < blob->cbData; i++)
4137 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
4138 dataLen - i - 1);
4144 else
4146 SetLastError(CRYPT_E_ASN1_BADTAG);
4147 ret = FALSE;
4149 return ret;
4152 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
4153 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4154 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4156 BOOL ret;
4158 __TRY
4160 DWORD bytesNeeded;
4162 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded,
4163 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4165 if (!pvStructInfo)
4166 *pcbStructInfo = bytesNeeded;
4167 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4168 pvStructInfo, pcbStructInfo, bytesNeeded)))
4170 CRYPT_INTEGER_BLOB *blob;
4172 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4173 pvStructInfo = *(BYTE **)pvStructInfo;
4174 blob = pvStructInfo;
4175 blob->pbData = (BYTE *)pvStructInfo +
4176 sizeof(CRYPT_INTEGER_BLOB);
4177 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded,
4178 cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
4179 &bytesNeeded, NULL);
4183 __EXCEPT_PAGE_FAULT
4185 SetLastError(STATUS_ACCESS_VIOLATION);
4186 ret = FALSE;
4188 __ENDTRY
4189 return ret;
4192 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
4193 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4194 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4196 BOOL ret;
4198 if (!pvStructInfo)
4200 *pcbStructInfo = sizeof(int);
4201 return TRUE;
4203 __TRY
4205 if (pbEncoded[0] == ASN_ENUMERATED)
4207 unsigned int val = 0, i;
4209 if (cbEncoded <= 1)
4211 SetLastError(CRYPT_E_ASN1_EOD);
4212 ret = FALSE;
4214 else if (pbEncoded[1] == 0)
4216 SetLastError(CRYPT_E_ASN1_CORRUPT);
4217 ret = FALSE;
4219 else
4221 /* A little strange looking, but we have to accept a sign byte:
4222 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
4223 * assuming a small length is okay here, it has to be in short
4224 * form.
4226 if (pbEncoded[1] > sizeof(unsigned int) + 1)
4228 SetLastError(CRYPT_E_ASN1_LARGE);
4229 return FALSE;
4231 for (i = 0; i < pbEncoded[1]; i++)
4233 val <<= 8;
4234 val |= pbEncoded[2 + i];
4236 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4237 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
4239 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4240 pvStructInfo = *(BYTE **)pvStructInfo;
4241 memcpy(pvStructInfo, &val, sizeof(unsigned int));
4245 else
4247 SetLastError(CRYPT_E_ASN1_BADTAG);
4248 ret = FALSE;
4251 __EXCEPT_PAGE_FAULT
4253 SetLastError(STATUS_ACCESS_VIOLATION);
4254 ret = FALSE;
4256 __ENDTRY
4257 return ret;
4260 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
4261 * if it fails.
4263 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
4264 do { \
4265 BYTE i; \
4267 (word) = 0; \
4268 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
4270 if (!isdigit(*(pbEncoded))) \
4272 SetLastError(CRYPT_E_ASN1_CORRUPT); \
4273 ret = FALSE; \
4275 else \
4277 (word) *= 10; \
4278 (word) += *(pbEncoded)++ - '0'; \
4281 } while (0)
4283 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
4284 SYSTEMTIME *sysTime)
4286 BOOL ret = TRUE;
4288 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
4290 WORD hours, minutes = 0;
4291 BYTE sign = *pbEncoded++;
4293 len--;
4294 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
4295 if (ret && hours >= 24)
4297 SetLastError(CRYPT_E_ASN1_CORRUPT);
4298 ret = FALSE;
4300 else if (len >= 2)
4302 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
4303 if (ret && minutes >= 60)
4305 SetLastError(CRYPT_E_ASN1_CORRUPT);
4306 ret = FALSE;
4309 if (ret)
4311 if (sign == '+')
4313 sysTime->wHour += hours;
4314 sysTime->wMinute += minutes;
4316 else
4318 if (hours > sysTime->wHour)
4320 sysTime->wDay--;
4321 sysTime->wHour = 24 - (hours - sysTime->wHour);
4323 else
4324 sysTime->wHour -= hours;
4325 if (minutes > sysTime->wMinute)
4327 sysTime->wHour--;
4328 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
4330 else
4331 sysTime->wMinute -= minutes;
4335 return ret;
4338 #define MIN_ENCODED_TIME_LENGTH 10
4340 static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
4341 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4342 DWORD *pcbDecoded)
4344 BOOL ret = FALSE;
4346 if (pbEncoded[0] == ASN_UTCTIME)
4348 if (cbEncoded <= 1)
4349 SetLastError(CRYPT_E_ASN1_EOD);
4350 else if (pbEncoded[1] > 0x7f)
4352 /* long-form date strings really can't be valid */
4353 SetLastError(CRYPT_E_ASN1_CORRUPT);
4355 else
4357 SYSTEMTIME sysTime = { 0 };
4358 BYTE len = pbEncoded[1];
4360 if (len < MIN_ENCODED_TIME_LENGTH)
4361 SetLastError(CRYPT_E_ASN1_CORRUPT);
4362 else
4364 ret = TRUE;
4365 if (pcbDecoded)
4366 *pcbDecoded = 2 + len;
4367 pbEncoded += 2;
4368 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
4369 if (sysTime.wYear >= 50)
4370 sysTime.wYear += 1900;
4371 else
4372 sysTime.wYear += 2000;
4373 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
4374 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
4375 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
4376 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
4377 if (ret && len > 0)
4379 if (len >= 2 && isdigit(*pbEncoded) &&
4380 isdigit(*(pbEncoded + 1)))
4381 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4382 sysTime.wSecond);
4383 else if (isdigit(*pbEncoded))
4384 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
4385 sysTime.wSecond);
4386 if (ret)
4387 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
4388 &sysTime);
4390 if (ret)
4392 if (!pvStructInfo)
4393 *pcbStructInfo = sizeof(FILETIME);
4394 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
4395 sizeof(FILETIME))))
4396 ret = SystemTimeToFileTime(&sysTime, pvStructInfo);
4401 else
4402 SetLastError(CRYPT_E_ASN1_BADTAG);
4403 return ret;
4406 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
4407 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4408 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4410 BOOL ret = FALSE;
4412 __TRY
4414 DWORD bytesNeeded;
4416 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
4417 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4418 if (ret)
4420 if (!pvStructInfo)
4421 *pcbStructInfo = bytesNeeded;
4422 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
4423 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
4425 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4426 pvStructInfo = *(BYTE **)pvStructInfo;
4427 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
4428 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4429 &bytesNeeded, NULL);
4433 __EXCEPT_PAGE_FAULT
4435 SetLastError(STATUS_ACCESS_VIOLATION);
4437 __ENDTRY
4438 return ret;
4441 static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
4442 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4443 DWORD *pcbDecoded)
4445 BOOL ret = FALSE;
4447 if (pbEncoded[0] == ASN_GENERALTIME)
4449 if (cbEncoded <= 1)
4450 SetLastError(CRYPT_E_ASN1_EOD);
4451 else if (pbEncoded[1] > 0x7f)
4453 /* long-form date strings really can't be valid */
4454 SetLastError(CRYPT_E_ASN1_CORRUPT);
4456 else
4458 BYTE len = pbEncoded[1];
4460 if (len < MIN_ENCODED_TIME_LENGTH)
4461 SetLastError(CRYPT_E_ASN1_CORRUPT);
4462 else
4464 SYSTEMTIME sysTime = { 0 };
4466 ret = TRUE;
4467 if (pcbDecoded)
4468 *pcbDecoded = 2 + len;
4469 pbEncoded += 2;
4470 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
4471 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
4472 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
4473 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
4474 if (ret && len > 0)
4476 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4477 sysTime.wMinute);
4478 if (ret && len > 0)
4479 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4480 sysTime.wSecond);
4481 if (ret && len > 0 && (*pbEncoded == '.' ||
4482 *pbEncoded == ','))
4484 BYTE digits;
4486 pbEncoded++;
4487 len--;
4488 /* workaround macro weirdness */
4489 digits = min(len, 3);
4490 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
4491 sysTime.wMilliseconds);
4493 if (ret)
4494 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
4495 &sysTime);
4497 if (ret)
4499 if (!pvStructInfo)
4500 *pcbStructInfo = sizeof(FILETIME);
4501 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
4502 sizeof(FILETIME))))
4503 ret = SystemTimeToFileTime(&sysTime, pvStructInfo);
4508 else
4509 SetLastError(CRYPT_E_ASN1_BADTAG);
4510 return ret;
4513 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
4514 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4515 DWORD *pcbDecoded)
4517 BOOL ret;
4518 InternalDecodeFunc decode = NULL;
4520 if (pbEncoded[0] == ASN_UTCTIME)
4521 decode = CRYPT_AsnDecodeUtcTimeInternal;
4522 else if (pbEncoded[0] == ASN_GENERALTIME)
4523 decode = CRYPT_AsnDecodeGeneralizedTime;
4524 if (decode)
4525 ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
4526 pcbStructInfo, pcbDecoded);
4527 else
4529 SetLastError(CRYPT_E_ASN1_BADTAG);
4530 ret = FALSE;
4532 return ret;
4535 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
4536 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4537 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4539 BOOL ret;
4541 __TRY
4543 DWORD bytesNeeded;
4545 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
4546 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4547 if (ret)
4549 if (!pvStructInfo)
4550 *pcbStructInfo = bytesNeeded;
4551 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4552 pvStructInfo, pcbStructInfo, bytesNeeded)))
4554 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4555 pvStructInfo = *(BYTE **)pvStructInfo;
4556 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
4557 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4558 &bytesNeeded, NULL);
4562 __EXCEPT_PAGE_FAULT
4564 SetLastError(STATUS_ACCESS_VIOLATION);
4565 ret = FALSE;
4567 __ENDTRY
4568 return ret;
4571 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
4572 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4573 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4575 BOOL ret = TRUE;
4577 __TRY
4579 if (pbEncoded[0] == ASN_SEQUENCEOF)
4581 DWORD bytesNeeded, dataLen, remainingLen, cValue;
4583 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4585 BYTE lenBytes;
4586 const BYTE *ptr;
4588 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4589 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
4590 cValue = 0;
4591 ptr = pbEncoded + 1 + lenBytes;
4592 remainingLen = dataLen;
4593 while (ret && remainingLen)
4595 DWORD nextLen;
4597 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
4598 if (ret)
4600 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
4602 remainingLen -= 1 + nextLenBytes + nextLen;
4603 ptr += 1 + nextLenBytes + nextLen;
4604 bytesNeeded += sizeof(CRYPT_DER_BLOB);
4605 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
4606 bytesNeeded += 1 + nextLenBytes + nextLen;
4607 cValue++;
4610 if (ret)
4612 CRYPT_SEQUENCE_OF_ANY *seq;
4613 BYTE *nextPtr;
4614 DWORD i;
4616 if (!pvStructInfo)
4617 *pcbStructInfo = bytesNeeded;
4618 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4619 pvStructInfo, pcbStructInfo, bytesNeeded)))
4621 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4622 pvStructInfo = *(BYTE **)pvStructInfo;
4623 seq = pvStructInfo;
4624 seq->cValue = cValue;
4625 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
4626 sizeof(*seq));
4627 nextPtr = (BYTE *)seq->rgValue +
4628 cValue * sizeof(CRYPT_DER_BLOB);
4629 ptr = pbEncoded + 1 + lenBytes;
4630 remainingLen = dataLen;
4631 i = 0;
4632 while (ret && remainingLen)
4634 DWORD nextLen;
4636 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
4637 if (ret)
4639 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
4641 seq->rgValue[i].cbData = 1 + nextLenBytes +
4642 nextLen;
4643 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4644 seq->rgValue[i].pbData = (BYTE *)ptr;
4645 else
4647 seq->rgValue[i].pbData = nextPtr;
4648 memcpy(nextPtr, ptr, 1 + nextLenBytes +
4649 nextLen);
4650 nextPtr += 1 + nextLenBytes + nextLen;
4652 remainingLen -= 1 + nextLenBytes + nextLen;
4653 ptr += 1 + nextLenBytes + nextLen;
4654 i++;
4661 else
4663 SetLastError(CRYPT_E_ASN1_BADTAG);
4664 ret = FALSE;
4667 __EXCEPT_PAGE_FAULT
4669 SetLastError(STATUS_ACCESS_VIOLATION);
4670 ret = FALSE;
4672 __ENDTRY
4673 return ret;
4676 static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded,
4677 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4678 DWORD *pcbDecoded)
4680 BOOL ret;
4682 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
4684 DWORD bytesNeeded, dataLen;
4686 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4688 struct AsnArrayDescriptor arrayDesc = {
4689 ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
4690 offsetof(CRL_DIST_POINT_NAME, u.FullName.cAltEntry),
4691 offsetof(CRL_DIST_POINT_NAME, u.FullName.rgAltEntry),
4692 FINALMEMBERSIZE(CRL_DIST_POINT_NAME, u),
4693 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
4694 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
4695 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4696 DWORD nameLen;
4698 if (dataLen)
4700 ret = CRYPT_AsnDecodeArray(&arrayDesc,
4701 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
4702 dwFlags, NULL, NULL, &nameLen, NULL);
4703 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen -
4704 FINALMEMBERSIZE(CRL_DIST_POINT_NAME, u);
4706 else
4707 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
4708 if (pcbDecoded)
4709 *pcbDecoded = 1 + lenBytes + dataLen;
4710 if (!pvStructInfo)
4711 *pcbStructInfo = bytesNeeded;
4712 else if (*pcbStructInfo < bytesNeeded)
4714 *pcbStructInfo = bytesNeeded;
4715 SetLastError(ERROR_MORE_DATA);
4716 ret = FALSE;
4718 else
4720 CRL_DIST_POINT_NAME *name = pvStructInfo;
4722 *pcbStructInfo = bytesNeeded;
4723 if (dataLen)
4725 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
4726 ret = CRYPT_AsnDecodeArray(&arrayDesc,
4727 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
4728 dwFlags, NULL, &name->u.FullName.cAltEntry, &nameLen,
4729 NULL);
4731 else
4732 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
4736 else
4738 SetLastError(CRYPT_E_ASN1_BADTAG);
4739 ret = FALSE;
4741 return ret;
4744 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
4745 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4747 struct AsnDecodeSequenceItem items[] = {
4748 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
4749 DistPointName), CRYPT_AsnDecodeDistPointName,
4750 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
4751 DistPointName.u.FullName.rgAltEntry), 0 },
4752 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
4753 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
4754 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
4755 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
4756 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
4757 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
4759 CRL_DIST_POINT *point = pvStructInfo;
4760 BOOL ret;
4762 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4763 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4764 pcbDecoded, point ? point->DistPointName.u.FullName.rgAltEntry : NULL);
4765 return ret;
4768 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
4769 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4770 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4772 BOOL ret;
4774 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4775 pDecodePara, pvStructInfo, *pcbStructInfo);
4777 __TRY
4779 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
4780 offsetof(CRL_DIST_POINTS_INFO, cDistPoint),
4781 offsetof(CRL_DIST_POINTS_INFO, rgDistPoint),
4782 sizeof(CRL_DIST_POINTS_INFO),
4783 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
4784 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
4786 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
4787 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
4789 __EXCEPT_PAGE_FAULT
4791 SetLastError(STATUS_ACCESS_VIOLATION);
4792 ret = FALSE;
4794 __ENDTRY
4795 return ret;
4798 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
4799 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4800 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4802 BOOL ret;
4804 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4805 pDecodePara, pvStructInfo, *pcbStructInfo);
4807 __TRY
4809 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
4810 offsetof(CERT_ENHKEY_USAGE, cUsageIdentifier),
4811 offsetof(CERT_ENHKEY_USAGE, rgpszUsageIdentifier),
4812 sizeof(CERT_ENHKEY_USAGE),
4813 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
4815 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
4816 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
4818 __EXCEPT_PAGE_FAULT
4820 SetLastError(STATUS_ACCESS_VIOLATION);
4821 ret = FALSE;
4823 __ENDTRY
4824 return ret;
4827 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
4828 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4829 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4831 BOOL ret;
4833 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4834 pDecodePara, pvStructInfo, *pcbStructInfo);
4836 __TRY
4838 struct AsnDecodeSequenceItem items[] = {
4839 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
4840 DistPointName), CRYPT_AsnDecodeDistPointName,
4841 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
4842 offsetof(CRL_ISSUING_DIST_POINT,
4843 DistPointName.u.FullName.rgAltEntry), 0 },
4844 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
4845 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4846 FALSE, 0 },
4847 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
4848 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4849 FALSE, 0 },
4850 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
4851 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
4852 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
4853 OnlySomeReasonFlags.pbData), 0 },
4854 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
4855 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
4858 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4859 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
4860 pcbStructInfo, NULL, NULL);
4862 __EXCEPT_PAGE_FAULT
4864 SetLastError(STATUS_ACCESS_VIOLATION);
4865 ret = FALSE;
4867 __ENDTRY
4868 return ret;
4871 static BOOL CRYPT_AsnDecodeMaximum(const BYTE *pbEncoded,
4872 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4873 DWORD *pcbDecoded)
4875 BOOL ret;
4876 DWORD max, size = sizeof(max);
4878 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4879 pvStructInfo, *pcbStructInfo, pcbDecoded);
4881 if (!cbEncoded)
4883 SetLastError(CRYPT_E_ASN1_EOD);
4884 return FALSE;
4886 if (pbEncoded[0] != (ASN_CONTEXT | 1))
4888 SetLastError(CRYPT_E_ASN1_BADTAG);
4889 return FALSE;
4891 if ((ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
4892 &max, &size, pcbDecoded)))
4894 DWORD bytesNeeded = FINALMEMBERSIZE(CERT_GENERAL_SUBTREE, fMaximum);
4896 if (!pvStructInfo)
4897 *pcbStructInfo = bytesNeeded;
4898 else if (*pcbStructInfo < bytesNeeded)
4900 *pcbStructInfo = bytesNeeded;
4901 SetLastError(ERROR_MORE_DATA);
4902 ret = FALSE;
4904 else
4906 CERT_GENERAL_SUBTREE *subtree = (CERT_GENERAL_SUBTREE *)
4907 ((BYTE *)pvStructInfo - offsetof(CERT_GENERAL_SUBTREE, fMaximum));
4909 *pcbStructInfo = bytesNeeded;
4910 /* The BOOL is implicit: if the integer is present, then it's
4911 * TRUE.
4913 subtree->fMaximum = TRUE;
4914 subtree->dwMaximum = max;
4917 TRACE("returning %d\n", ret);
4918 return ret;
4921 static BOOL CRYPT_AsnDecodeSubtree(const BYTE *pbEncoded,
4922 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4923 DWORD *pcbDecoded)
4925 BOOL ret;
4926 struct AsnDecodeSequenceItem items[] = {
4927 { 0, offsetof(CERT_GENERAL_SUBTREE, Base),
4928 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE, TRUE,
4929 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL), 0 },
4930 { ASN_CONTEXT | 0, offsetof(CERT_GENERAL_SUBTREE, dwMinimum),
4931 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
4932 { ASN_CONTEXT | 1, offsetof(CERT_GENERAL_SUBTREE, fMaximum),
4933 CRYPT_AsnDecodeMaximum, FINALMEMBERSIZE(CERT_GENERAL_SUBTREE, fMaximum),
4934 TRUE, FALSE, 0, 0 },
4936 CERT_GENERAL_SUBTREE *subtree = pvStructInfo;
4938 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4939 pvStructInfo, *pcbStructInfo, pcbDecoded);
4941 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4942 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4943 pcbDecoded, subtree ? subtree->Base.u.pwszURL : NULL);
4944 if (pcbDecoded)
4946 TRACE("%d\n", *pcbDecoded);
4947 if (*pcbDecoded < cbEncoded)
4948 TRACE("%02x %02x\n", *(pbEncoded + *pcbDecoded),
4949 *(pbEncoded + *pcbDecoded + 1));
4951 TRACE("returning %d\n", ret);
4952 return ret;
4955 static BOOL CRYPT_AsnDecodePermittedSubtree(const BYTE *pbEncoded,
4956 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4957 DWORD *pcbDecoded)
4959 BOOL ret = TRUE;
4960 struct AsnArrayDescriptor arrayDesc = { 0,
4961 offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
4962 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree),
4963 MEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree,
4964 cExcludedSubtree),
4965 CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
4966 offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
4968 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4969 pvStructInfo, *pcbStructInfo, pcbDecoded);
4971 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
4972 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
4973 return ret;
4976 static BOOL CRYPT_AsnDecodeExcludedSubtree(const BYTE *pbEncoded,
4977 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4978 DWORD *pcbDecoded)
4980 BOOL ret = TRUE;
4981 struct AsnArrayDescriptor arrayDesc = { 0,
4982 offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
4983 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree),
4984 FINALMEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
4985 CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
4986 offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
4988 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4989 pvStructInfo, *pcbStructInfo, pcbDecoded);
4991 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
4992 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
4993 return ret;
4996 static BOOL WINAPI CRYPT_AsnDecodeNameConstraints(DWORD dwCertEncodingType,
4997 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4998 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5000 BOOL ret = FALSE;
5002 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5003 pDecodePara, pvStructInfo, *pcbStructInfo);
5005 __TRY
5007 struct AsnDecodeSequenceItem items[] = {
5008 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
5009 offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
5010 CRYPT_AsnDecodePermittedSubtree,
5011 MEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree,
5012 cExcludedSubtree), TRUE, TRUE,
5013 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree), 0 },
5014 { ASN_CONTEXT | ASN_CONSTRUCTOR | 1,
5015 offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5016 CRYPT_AsnDecodeExcludedSubtree,
5017 FINALMEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5018 TRUE, TRUE,
5019 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree), 0 },
5022 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5023 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
5024 pcbStructInfo, NULL, NULL);
5026 __EXCEPT_PAGE_FAULT
5028 SetLastError(STATUS_ACCESS_VIOLATION);
5030 __ENDTRY
5031 return ret;
5034 static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded,
5035 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5036 DWORD *pcbDecoded)
5038 BOOL ret;
5039 struct AsnDecodeSequenceItem items[] = {
5040 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
5041 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
5042 Issuer.pbData) },
5043 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
5044 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
5045 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
5047 CERT_ISSUER_SERIAL_NUMBER *issuerSerial = pvStructInfo;
5049 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5050 pvStructInfo, *pcbStructInfo, pcbDecoded);
5052 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5053 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5054 pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL);
5055 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
5057 SetLastError(CRYPT_E_ASN1_CORRUPT);
5058 ret = FALSE;
5060 TRACE("returning %d\n", ret);
5061 return ret;
5064 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
5065 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5066 DWORD *pcbDecoded)
5068 CMSG_SIGNER_INFO *info = pvStructInfo;
5069 struct AsnDecodeSequenceItem items[] = {
5070 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
5071 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5072 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
5073 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
5074 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
5075 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
5076 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5077 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
5078 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5079 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
5080 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5081 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
5082 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
5083 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5084 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
5085 HashEncryptionAlgorithm.pszObjId), 0 },
5086 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
5087 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
5088 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
5089 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5090 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
5091 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5092 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
5094 BOOL ret;
5096 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5097 pvStructInfo, *pcbStructInfo);
5099 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5100 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5101 pcbDecoded, info ? info->Issuer.pbData : NULL);
5102 return ret;
5105 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
5106 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5107 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5109 BOOL ret = FALSE;
5111 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5112 pDecodePara, pvStructInfo, *pcbStructInfo);
5114 __TRY
5116 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
5117 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
5118 if (ret && pvStructInfo)
5120 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
5121 pcbStructInfo, *pcbStructInfo);
5122 if (ret)
5124 CMSG_SIGNER_INFO *info;
5126 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5127 pvStructInfo = *(BYTE **)pvStructInfo;
5128 info = pvStructInfo;
5129 info->Issuer.pbData = ((BYTE *)info +
5130 sizeof(CMSG_SIGNER_INFO));
5131 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
5132 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5133 pcbStructInfo, NULL);
5137 __EXCEPT_PAGE_FAULT
5139 SetLastError(STATUS_ACCESS_VIOLATION);
5141 __ENDTRY
5142 TRACE("returning %d\n", ret);
5143 return ret;
5146 static BOOL CRYPT_AsnDecodeCMSCertEncoded(const BYTE *pbEncoded,
5147 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5148 DWORD *pcbDecoded)
5150 BOOL ret;
5151 struct AsnArrayDescriptor arrayDesc = { 0,
5152 offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
5153 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded),
5154 MEMBERSIZE(CRYPT_SIGNED_INFO, cCertEncoded, cCrlEncoded),
5155 CRYPT_AsnDecodeCopyBytes,
5156 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
5158 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5159 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
5161 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5162 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5163 return ret;
5166 static BOOL CRYPT_AsnDecodeCMSCrlEncoded(const BYTE *pbEncoded,
5167 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5168 DWORD *pcbDecoded)
5170 BOOL ret;
5171 struct AsnArrayDescriptor arrayDesc = { 0,
5172 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded),
5173 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded),
5174 MEMBERSIZE(CRYPT_SIGNED_INFO, cCrlEncoded, content),
5175 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_DER_BLOB),
5176 TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
5178 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5179 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
5181 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5182 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5183 return ret;
5186 static BOOL CRYPT_AsnDecodeCMSSignerId(const BYTE *pbEncoded,
5187 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5188 DWORD *pcbDecoded)
5190 CERT_ID *id = pvStructInfo;
5191 BOOL ret = FALSE;
5193 if (*pbEncoded == ASN_SEQUENCEOF)
5195 ret = CRYPT_AsnDecodeIssuerSerialNumber(pbEncoded, cbEncoded, dwFlags,
5196 id ? &id->u.IssuerSerialNumber : NULL, pcbStructInfo, pcbDecoded);
5197 if (ret)
5199 if (id)
5200 id->dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
5201 if (*pcbStructInfo > sizeof(CERT_ISSUER_SERIAL_NUMBER))
5202 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
5203 sizeof(CERT_ISSUER_SERIAL_NUMBER);
5204 else
5205 *pcbStructInfo = sizeof(CERT_ID);
5208 else if (*pbEncoded == (ASN_CONTEXT | 0))
5210 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded, dwFlags,
5211 id ? &id->u.KeyId : NULL, pcbStructInfo, pcbDecoded);
5212 if (ret)
5214 if (id)
5215 id->dwIdChoice = CERT_ID_KEY_IDENTIFIER;
5216 if (*pcbStructInfo > sizeof(CRYPT_DATA_BLOB))
5217 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
5218 sizeof(CRYPT_DATA_BLOB);
5219 else
5220 *pcbStructInfo = sizeof(CERT_ID);
5223 else
5224 SetLastError(CRYPT_E_ASN1_BADTAG);
5225 return ret;
5228 static BOOL CRYPT_AsnDecodeCMSSignerInfoInternal(const BYTE *pbEncoded,
5229 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5230 DWORD *pcbDecoded)
5232 CMSG_CMS_SIGNER_INFO *info = pvStructInfo;
5233 struct AsnDecodeSequenceItem items[] = {
5234 { ASN_INTEGER, offsetof(CMSG_CMS_SIGNER_INFO, dwVersion),
5235 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5236 { 0, offsetof(CMSG_CMS_SIGNER_INFO, SignerId),
5237 CRYPT_AsnDecodeCMSSignerId, sizeof(CERT_ID), FALSE, TRUE,
5238 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData), 0 },
5239 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm),
5240 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5241 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
5242 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5243 offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs),
5244 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5245 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
5246 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashEncryptionAlgorithm),
5247 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5248 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO,
5249 HashEncryptionAlgorithm.pszObjId), 0 },
5250 { ASN_OCTETSTRING, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash),
5251 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
5252 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash.pbData), 0 },
5253 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5254 offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs),
5255 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5256 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
5258 BOOL ret;
5260 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5261 pvStructInfo, *pcbStructInfo);
5263 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5264 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5265 pcbDecoded, info ? info->SignerId.u.KeyId.pbData : NULL);
5266 return ret;
5269 static BOOL WINAPI CRYPT_AsnDecodeCMSSignerInfo(DWORD dwCertEncodingType,
5270 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5271 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5273 BOOL ret = FALSE;
5275 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5276 pDecodePara, pvStructInfo, *pcbStructInfo);
5278 __TRY
5280 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded, cbEncoded,
5281 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
5282 if (ret && pvStructInfo)
5284 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
5285 pcbStructInfo, *pcbStructInfo);
5286 if (ret)
5288 CMSG_CMS_SIGNER_INFO *info;
5290 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5291 pvStructInfo = *(BYTE **)pvStructInfo;
5292 info = pvStructInfo;
5293 info->SignerId.u.KeyId.pbData = ((BYTE *)info +
5294 sizeof(CMSG_CMS_SIGNER_INFO));
5295 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded,
5296 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5297 pcbStructInfo, NULL);
5301 __EXCEPT_PAGE_FAULT
5303 SetLastError(STATUS_ACCESS_VIOLATION);
5305 __ENDTRY
5306 TRACE("returning %d\n", ret);
5307 return ret;
5310 static BOOL CRYPT_DecodeSignerArray(const BYTE *pbEncoded, DWORD cbEncoded,
5311 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5313 BOOL ret;
5314 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
5315 offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
5316 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo),
5317 FINALMEMBERSIZE(CRYPT_SIGNED_INFO, cSignerInfo),
5318 CRYPT_AsnDecodeCMSSignerInfoInternal, sizeof(CMSG_CMS_SIGNER_INFO), TRUE,
5319 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData) };
5321 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5322 pvStructInfo, *pcbStructInfo, pcbDecoded);
5324 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5325 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5326 return ret;
5329 BOOL CRYPT_AsnDecodeCMSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
5330 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
5331 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
5333 BOOL ret = FALSE;
5334 struct AsnDecodeSequenceItem items[] = {
5335 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version),
5336 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5337 /* Placeholder for the hash algorithms - redundant with those in the
5338 * signers, so just ignore them.
5340 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
5341 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
5342 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
5343 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
5344 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5345 offsetof(CRYPT_SIGNED_INFO, cCertEncoded), CRYPT_AsnDecodeCMSCertEncoded,
5346 MEMBERSIZE(CRYPT_SIGNED_INFO, cCertEncoded, cCrlEncoded), TRUE, TRUE,
5347 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
5348 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5349 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_AsnDecodeCMSCrlEncoded,
5350 MEMBERSIZE(CRYPT_SIGNED_INFO, cCrlEncoded, content), TRUE, TRUE,
5351 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
5352 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
5353 CRYPT_DecodeSignerArray,
5354 FINALMEMBERSIZE(CRYPT_SIGNED_INFO, cSignerInfo), TRUE, TRUE,
5355 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
5358 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5359 pDecodePara, signedInfo, *pcbSignedInfo);
5361 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5362 pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo,
5363 NULL, NULL);
5364 TRACE("returning %d\n", ret);
5365 return ret;
5368 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
5369 LPCSTR lpszStructType)
5371 CryptDecodeObjectExFunc decodeFunc = NULL;
5373 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
5374 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
5376 SetLastError(ERROR_FILE_NOT_FOUND);
5377 return NULL;
5379 if (!HIWORD(lpszStructType))
5381 switch (LOWORD(lpszStructType))
5383 case LOWORD(X509_CERT):
5384 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
5385 break;
5386 case LOWORD(X509_CERT_TO_BE_SIGNED):
5387 decodeFunc = CRYPT_AsnDecodeCert;
5388 break;
5389 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
5390 decodeFunc = CRYPT_AsnDecodeCRL;
5391 break;
5392 case LOWORD(X509_EXTENSIONS):
5393 decodeFunc = CRYPT_AsnDecodeExtensions;
5394 break;
5395 case LOWORD(X509_NAME_VALUE):
5396 decodeFunc = CRYPT_AsnDecodeNameValue;
5397 break;
5398 case LOWORD(X509_NAME):
5399 decodeFunc = CRYPT_AsnDecodeName;
5400 break;
5401 case LOWORD(X509_PUBLIC_KEY_INFO):
5402 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
5403 break;
5404 case LOWORD(X509_AUTHORITY_KEY_ID):
5405 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
5406 break;
5407 case LOWORD(X509_ALTERNATE_NAME):
5408 decodeFunc = CRYPT_AsnDecodeAltName;
5409 break;
5410 case LOWORD(X509_BASIC_CONSTRAINTS):
5411 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
5412 break;
5413 case LOWORD(X509_BASIC_CONSTRAINTS2):
5414 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
5415 break;
5416 case LOWORD(X509_CERT_POLICIES):
5417 decodeFunc = CRYPT_AsnDecodeCertPolicies;
5418 break;
5419 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
5420 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
5421 break;
5422 case LOWORD(X509_UNICODE_NAME):
5423 decodeFunc = CRYPT_AsnDecodeUnicodeName;
5424 break;
5425 case LOWORD(PKCS_ATTRIBUTE):
5426 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
5427 break;
5428 case LOWORD(X509_UNICODE_NAME_VALUE):
5429 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
5430 break;
5431 case LOWORD(X509_OCTET_STRING):
5432 decodeFunc = CRYPT_AsnDecodeOctets;
5433 break;
5434 case LOWORD(X509_BITS):
5435 case LOWORD(X509_KEY_USAGE):
5436 decodeFunc = CRYPT_AsnDecodeBits;
5437 break;
5438 case LOWORD(X509_INTEGER):
5439 decodeFunc = CRYPT_AsnDecodeInt;
5440 break;
5441 case LOWORD(X509_MULTI_BYTE_INTEGER):
5442 decodeFunc = CRYPT_AsnDecodeInteger;
5443 break;
5444 case LOWORD(X509_MULTI_BYTE_UINT):
5445 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
5446 break;
5447 case LOWORD(X509_ENUMERATED):
5448 decodeFunc = CRYPT_AsnDecodeEnumerated;
5449 break;
5450 case LOWORD(X509_CHOICE_OF_TIME):
5451 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
5452 break;
5453 case LOWORD(X509_AUTHORITY_KEY_ID2):
5454 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
5455 break;
5456 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
5457 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
5458 break;
5459 case LOWORD(PKCS_CONTENT_INFO):
5460 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
5461 break;
5462 case LOWORD(X509_SEQUENCE_OF_ANY):
5463 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
5464 break;
5465 case LOWORD(PKCS_UTC_TIME):
5466 decodeFunc = CRYPT_AsnDecodeUtcTime;
5467 break;
5468 case LOWORD(X509_CRL_DIST_POINTS):
5469 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
5470 break;
5471 case LOWORD(X509_ENHANCED_KEY_USAGE):
5472 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
5473 break;
5474 case LOWORD(PKCS_CTL):
5475 decodeFunc = CRYPT_AsnDecodeCTL;
5476 break;
5477 case LOWORD(PKCS_SMIME_CAPABILITIES):
5478 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
5479 break;
5480 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE):
5481 decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
5482 break;
5483 case LOWORD(PKCS_ATTRIBUTES):
5484 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
5485 break;
5486 case LOWORD(X509_ISSUING_DIST_POINT):
5487 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
5488 break;
5489 case LOWORD(X509_NAME_CONSTRAINTS):
5490 decodeFunc = CRYPT_AsnDecodeNameConstraints;
5491 break;
5492 case LOWORD(PKCS7_SIGNER_INFO):
5493 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
5494 break;
5495 case LOWORD(CMS_SIGNER_INFO):
5496 decodeFunc = CRYPT_AsnDecodeCMSSignerInfo;
5497 break;
5500 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
5501 decodeFunc = CRYPT_AsnDecodeExtensions;
5502 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
5503 decodeFunc = CRYPT_AsnDecodeUtcTime;
5504 else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
5505 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
5506 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
5507 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
5508 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
5509 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
5510 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
5511 decodeFunc = CRYPT_AsnDecodeEnumerated;
5512 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
5513 decodeFunc = CRYPT_AsnDecodeBits;
5514 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
5515 decodeFunc = CRYPT_AsnDecodeOctets;
5516 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
5517 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
5518 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
5519 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
5520 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
5521 decodeFunc = CRYPT_AsnDecodeAltName;
5522 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
5523 decodeFunc = CRYPT_AsnDecodeAltName;
5524 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
5525 decodeFunc = CRYPT_AsnDecodeAltName;
5526 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
5527 decodeFunc = CRYPT_AsnDecodeAltName;
5528 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
5529 decodeFunc = CRYPT_AsnDecodeAltName;
5530 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
5531 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
5532 else if (!strcmp(lpszStructType, szOID_CERT_POLICIES))
5533 decodeFunc = CRYPT_AsnDecodeCertPolicies;
5534 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
5535 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
5536 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
5537 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
5538 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
5539 decodeFunc = CRYPT_AsnDecodeNameConstraints;
5540 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
5541 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
5542 else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
5543 decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
5544 else if (!strcmp(lpszStructType, szOID_CTL))
5545 decodeFunc = CRYPT_AsnDecodeCTL;
5546 return decodeFunc;
5549 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
5550 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
5552 static HCRYPTOIDFUNCSET set = NULL;
5553 CryptDecodeObjectFunc decodeFunc = NULL;
5555 if (!set)
5556 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
5557 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
5558 (void **)&decodeFunc, hFunc);
5559 return decodeFunc;
5562 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
5563 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
5565 static HCRYPTOIDFUNCSET set = NULL;
5566 CryptDecodeObjectExFunc decodeFunc = NULL;
5568 if (!set)
5569 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
5570 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
5571 (void **)&decodeFunc, hFunc);
5572 return decodeFunc;
5575 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
5576 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
5577 DWORD *pcbStructInfo)
5579 BOOL ret = FALSE;
5580 CryptDecodeObjectFunc pCryptDecodeObject = NULL;
5581 CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
5582 HCRYPTOIDFUNCADDR hFunc = NULL;
5584 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
5585 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
5586 pvStructInfo, pcbStructInfo);
5588 if (!pvStructInfo && !pcbStructInfo)
5590 SetLastError(ERROR_INVALID_PARAMETER);
5591 return FALSE;
5593 if (cbEncoded > MAX_ENCODED_LEN)
5595 SetLastError(CRYPT_E_ASN1_LARGE);
5596 return FALSE;
5599 if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
5600 lpszStructType)))
5602 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
5603 debugstr_a(lpszStructType));
5604 pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
5605 lpszStructType, &hFunc);
5606 if (!pCryptDecodeObject)
5607 pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
5608 lpszStructType, &hFunc);
5610 if (pCryptDecodeObject)
5611 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5612 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
5613 else if (pCryptDecodeObjectEx)
5614 ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
5615 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
5616 pvStructInfo, pcbStructInfo);
5617 if (hFunc)
5618 CryptFreeOIDFunctionAddress(hFunc, 0);
5619 TRACE_(crypt)("returning %d\n", ret);
5620 return ret;
5623 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
5624 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5625 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5627 BOOL ret = FALSE;
5628 CryptDecodeObjectExFunc decodeFunc;
5629 HCRYPTOIDFUNCADDR hFunc = NULL;
5631 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
5632 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
5633 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
5635 if (!pvStructInfo && !pcbStructInfo)
5637 SetLastError(ERROR_INVALID_PARAMETER);
5638 return FALSE;
5640 if (cbEncoded > MAX_ENCODED_LEN)
5642 SetLastError(CRYPT_E_ASN1_LARGE);
5643 return FALSE;
5646 SetLastError(NOERROR);
5647 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
5648 *(BYTE **)pvStructInfo = NULL;
5649 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
5650 if (!decodeFunc)
5652 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
5653 debugstr_a(lpszStructType));
5654 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
5655 &hFunc);
5657 if (decodeFunc)
5658 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
5659 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
5660 else
5662 CryptDecodeObjectFunc pCryptDecodeObject =
5663 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
5665 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
5666 * directly, as that could cause an infinite loop.
5668 if (pCryptDecodeObject)
5670 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5672 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5673 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
5674 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
5675 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
5676 ret = pCryptDecodeObject(dwCertEncodingType,
5677 lpszStructType, pbEncoded, cbEncoded, dwFlags,
5678 *(BYTE **)pvStructInfo, pcbStructInfo);
5680 else
5681 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5682 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
5685 if (hFunc)
5686 CryptFreeOIDFunctionAddress(hFunc, 0);
5687 TRACE_(crypt)("returning %d\n", ret);
5688 return ret;
5691 BOOL WINAPI PFXIsPFXBlob(CRYPT_DATA_BLOB *pPFX)
5693 BOOL ret;
5695 TRACE_(crypt)("(%p)\n", pPFX);
5697 /* A PFX blob is an asn.1-encoded sequence, consisting of at least a
5698 * version integer of length 1 (3 encoded byes) and at least one other
5699 * datum (two encoded bytes), plus at least two bytes for the outer
5700 * sequence. Thus, even an empty PFX blob is at least 7 bytes in length.
5702 if (pPFX->cbData < 7)
5703 ret = FALSE;
5704 else if (pPFX->pbData[0] == ASN_SEQUENCE)
5706 DWORD len;
5708 if ((ret = CRYPT_GetLengthIndefinite(pPFX->pbData, pPFX->cbData, &len)))
5710 BYTE lenLen = GET_LEN_BYTES(pPFX->pbData[1]);
5712 /* Need at least three bytes for the integer version */
5713 if (pPFX->cbData < 1 + lenLen + 3)
5714 ret = FALSE;
5715 else if (pPFX->pbData[1 + lenLen] != ASN_INTEGER || /* Tag */
5716 pPFX->pbData[1 + lenLen + 1] != 1 || /* Definite length */
5717 pPFX->pbData[1 + lenLen + 2] != 3) /* PFX version */
5718 ret = FALSE;
5721 else
5722 ret = FALSE;
5723 return ret;
5726 HCERTSTORE WINAPI PFXImportCertStore(CRYPT_DATA_BLOB *pPFX, LPCWSTR szPassword,
5727 DWORD dwFlags)
5729 FIXME_(crypt)("(%p, %p, %08x): stub\n", pPFX, szPassword, dwFlags);
5730 return NULL;