push 52d6b63ba2f2d4f9b02b6b922d27bff05a60596f
[wine/hacks.git] / dlls / crypt32 / decode.c
blobfa1cc63de6bdd3b2513734a73d40026c5dd5ae99
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 if (items[i].size < items[i].minSize)
361 items[i].size = items[i].minSize;
362 else if (items[i].size > items[i].minSize)
364 /* Account for alignment padding */
365 items[i].size = ALIGN_DWORD_PTR(items[i].size);
367 TRACE("item %d size: %d\n", i, items[i].size);
368 if (nextData && items[i].hasPointer &&
369 items[i].size > items[i].minSize)
370 nextData += items[i].size - items[i].minSize;
371 if (itemDecoded > itemEncodedLen)
373 WARN("decoded length %d exceeds encoded %d\n",
374 itemDecoded, itemEncodedLen);
375 SetLastError(CRYPT_E_ASN1_CORRUPT);
376 ret = FALSE;
378 else
380 ptr += itemDecoded;
381 decoded += itemDecoded;
382 TRACE("item %d: decoded %d bytes\n", i,
383 itemDecoded);
386 else if (items[i].optional &&
387 GetLastError() == CRYPT_E_ASN1_BADTAG)
389 TRACE("skipping optional item %d\n", i);
390 items[i].size = items[i].minSize;
391 SetLastError(NOERROR);
392 ret = TRUE;
394 else
395 TRACE("item %d failed: %08x\n", i,
396 GetLastError());
398 else if (itemLen == CMSG_INDEFINITE_LENGTH)
400 ERR("can't use indefinite length encoding without a decoder\n");
401 SetLastError(CRYPT_E_ASN1_CORRUPT);
402 ret = FALSE;
404 else
406 TRACE("item %d: decoded %d bytes\n", i, itemEncodedLen);
407 ptr += itemEncodedLen;
408 decoded += itemEncodedLen;
409 items[i].size = items[i].minSize;
412 else if (items[i].optional)
414 TRACE("skipping optional item %d\n", i);
415 items[i].size = items[i].minSize;
417 else
419 TRACE("item %d: tag %02x doesn't match expected %02x\n",
420 i, ptr[0], items[i].tag);
421 SetLastError(CRYPT_E_ASN1_BADTAG);
422 ret = FALSE;
426 else if (items[i].optional)
428 TRACE("missing optional item %d, skipping\n", i);
429 items[i].size = items[i].minSize;
431 else
433 TRACE("not enough bytes for item %d, failing\n", i);
434 SetLastError(CRYPT_E_ASN1_CORRUPT);
435 ret = FALSE;
438 if (cbDecoded)
439 *cbDecoded = decoded;
440 TRACE("returning %d\n", ret);
441 return ret;
444 /* This decodes an arbitrary sequence into a contiguous block of memory
445 * (basically, a struct.) Each element being decoded is described by a struct
446 * AsnDecodeSequenceItem, see above.
447 * startingPointer is an optional pointer to the first place where dynamic
448 * data will be stored. If you know the starting offset, you may pass it
449 * here. Otherwise, pass NULL, and one will be inferred from the items.
451 static BOOL CRYPT_AsnDecodeSequence(struct AsnDecodeSequenceItem items[],
452 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
453 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
454 DWORD *pcbDecoded, void *startingPointer)
456 BOOL ret;
458 TRACE("%p, %d, %p, %d, %08x, %p, %p, %d, %p\n", items, cItem, pbEncoded,
459 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
460 startingPointer);
462 if (!cbEncoded)
464 SetLastError(CRYPT_E_ASN1_EOD);
465 return FALSE;
467 if (pbEncoded[0] == ASN_SEQUENCE)
469 DWORD dataLen;
471 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
473 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
474 const BYTE *ptr = pbEncoded + 1 + lenBytes;
475 BOOL indefinite = FALSE;
477 cbEncoded -= 1 + lenBytes;
478 if (dataLen == CMSG_INDEFINITE_LENGTH)
480 dataLen = cbEncoded;
481 indefinite = TRUE;
483 else if (cbEncoded < dataLen)
485 TRACE("dataLen %d exceeds cbEncoded %d, failing\n", dataLen,
486 cbEncoded);
487 SetLastError(CRYPT_E_ASN1_CORRUPT);
488 ret = FALSE;
490 if (ret)
492 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
493 ptr, dataLen, dwFlags, NULL, NULL, &cbDecoded);
494 if (ret && dataLen == CMSG_INDEFINITE_LENGTH)
496 if (cbDecoded > cbEncoded - 2)
498 /* Not enough space for 0 TLV */
499 SetLastError(CRYPT_E_ASN1_CORRUPT);
500 ret = FALSE;
502 else if (*(ptr + cbDecoded) != 0 ||
503 *(ptr + cbDecoded + 1) != 0)
505 TRACE("expected 0 TLV\n");
506 SetLastError(CRYPT_E_ASN1_CORRUPT);
507 ret = FALSE;
509 else
510 cbDecoded += 2;
513 if (ret && !indefinite && cbDecoded != dataLen)
515 TRACE("expected %d decoded, got %d, failing\n", dataLen,
516 cbDecoded);
517 SetLastError(CRYPT_E_ASN1_CORRUPT);
518 ret = FALSE;
520 if (ret)
522 DWORD i, bytesNeeded = 0, structSize = 0;
524 for (i = 0; i < cItem; i++)
526 bytesNeeded += items[i].size;
527 structSize = max( structSize, items[i].offset + items[i].minSize );
529 if (pcbDecoded)
530 *pcbDecoded = 1 + lenBytes + cbDecoded;
531 if (!pvStructInfo)
532 *pcbStructInfo = bytesNeeded;
533 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
534 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
536 BYTE *nextData;
538 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
539 pvStructInfo = *(BYTE **)pvStructInfo;
540 if (startingPointer)
541 nextData = startingPointer;
542 else
543 nextData = (BYTE *)pvStructInfo + structSize;
544 memset(pvStructInfo, 0, structSize);
545 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
546 ptr, dataLen, dwFlags, pvStructInfo, nextData,
547 &cbDecoded);
548 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
549 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
554 else
556 SetLastError(CRYPT_E_ASN1_BADTAG);
557 ret = FALSE;
559 TRACE("returning %d (%08x)\n", ret, GetLastError());
560 return ret;
563 /* tag:
564 * The expected tag of the entire encoded array (usually a variant
565 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
566 * regardless of the tag seen.
567 * countOffset:
568 * The offset within the outer structure at which the count exists.
569 * For example, a structure such as CRYPT_ATTRIBUTES has countOffset == 0,
570 * while CRYPT_ATTRIBUTE has countOffset ==
571 * offsetof(CRYPT_ATTRIBUTE, cValue).
572 * arrayOffset:
573 * The offset within the outer structure at which the array pointer exists.
574 * For example, CRYPT_ATTRIBUTES has arrayOffset ==
575 * offsetof(CRYPT_ATTRIBUTES, rgAttr).
576 * minArraySize:
577 * The minimum size of the decoded array. On WIN32, this is always 8:
578 * sizeof(DWORD) + sizeof(void *). On WIN64, it can be larger due to
579 * alignment.
580 * decodeFunc:
581 * used to decode each item in the array
582 * itemSize:
583 * is the minimum size of each decoded item
584 * hasPointer:
585 * indicates whether each item has a dynamic pointer
586 * pointerOffset:
587 * indicates the offset within itemSize at which the pointer exists
589 struct AsnArrayDescriptor
591 BYTE tag;
592 DWORD countOffset;
593 DWORD arrayOffset;
594 DWORD minArraySize;
595 InternalDecodeFunc decodeFunc;
596 DWORD itemSize;
597 BOOL hasPointer;
598 DWORD pointerOffset;
601 struct AsnArrayItemSize
603 DWORD encodedLen;
604 DWORD size;
607 /* Decodes an array of like types into a structure described by a struct
608 * AsnArrayDescriptor.
610 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
611 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
612 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
613 DWORD *pcbDecoded)
615 BOOL ret = TRUE;
617 TRACE("%p, %p, %d, %p, %d\n", arrayDesc, pbEncoded,
618 cbEncoded, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
620 if (!cbEncoded)
622 SetLastError(CRYPT_E_ASN1_EOD);
623 ret = FALSE;
625 else if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
627 DWORD dataLen;
629 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
631 DWORD bytesNeeded = arrayDesc->minArraySize, cItems = 0, decoded;
632 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
633 /* There can be arbitrarily many items, but there is often only one.
635 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
637 decoded = 1 + lenBytes;
638 if (dataLen)
640 const BYTE *ptr;
641 BOOL doneDecoding = FALSE;
643 for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
645 if (dataLen == CMSG_INDEFINITE_LENGTH)
647 if (ptr[0] == 0)
649 doneDecoding = TRUE;
650 if (ptr[1] != 0)
652 SetLastError(CRYPT_E_ASN1_CORRUPT);
653 ret = FALSE;
655 else
656 decoded += 2;
659 else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
660 doneDecoding = TRUE;
661 if (!doneDecoding)
663 DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
665 /* Each item decoded may not tolerate extraneous bytes,
666 * so get the length of the next element if known.
668 if ((ret = CRYPT_GetLengthIndefinite(ptr,
669 cbEncoded - (ptr - pbEncoded), &itemDataLen)))
671 if (itemDataLen == CMSG_INDEFINITE_LENGTH)
672 itemEncoded = cbEncoded - (ptr - pbEncoded);
673 else
674 itemEncoded = 1 + GET_LEN_BYTES(ptr[1]) +
675 itemDataLen;
677 if (ret)
678 ret = arrayDesc->decodeFunc(ptr, itemEncoded,
679 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size,
680 &itemDecoded);
681 if (ret)
683 cItems++;
684 if (itemSizes != &itemSize)
685 itemSizes = CryptMemRealloc(itemSizes,
686 cItems * sizeof(struct AsnArrayItemSize));
687 else if (cItems > 1)
689 itemSizes =
690 CryptMemAlloc(
691 cItems * sizeof(struct AsnArrayItemSize));
692 if (itemSizes)
693 memcpy(itemSizes, &itemSize,
694 sizeof(itemSize));
696 if (itemSizes)
698 decoded += itemDecoded;
699 itemSizes[cItems - 1].encodedLen = itemEncoded;
700 itemSizes[cItems - 1].size = size;
701 bytesNeeded += size;
702 ptr += itemEncoded;
704 else
705 ret = FALSE;
710 if (ret)
712 if (pcbDecoded)
713 *pcbDecoded = decoded;
714 if (!pvStructInfo)
715 *pcbStructInfo = bytesNeeded;
716 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
717 pvStructInfo, pcbStructInfo, bytesNeeded)))
719 DWORD i, *pcItems;
720 BYTE *nextData;
721 const BYTE *ptr;
722 void *rgItems;
724 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
725 pvStructInfo = *(void **)pvStructInfo;
726 pcItems = pvStructInfo;
727 *pcItems = cItems;
728 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
730 rgItems = (BYTE *)pvStructInfo +
731 arrayDesc->minArraySize;
732 *(void **)((BYTE *)pcItems -
733 arrayDesc->countOffset + arrayDesc->arrayOffset) =
734 rgItems;
736 else
737 rgItems = *(void **)((BYTE *)pcItems -
738 arrayDesc->countOffset + arrayDesc->arrayOffset);
739 nextData = (BYTE *)rgItems + cItems * arrayDesc->itemSize;
740 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
741 i < cItems && ptr - pbEncoded - 1 - lenBytes <
742 dataLen; i++)
744 DWORD itemDecoded;
746 if (arrayDesc->hasPointer)
747 *(BYTE **)((BYTE *)rgItems + i * arrayDesc->itemSize
748 + arrayDesc->pointerOffset) = nextData;
749 ret = arrayDesc->decodeFunc(ptr,
750 itemSizes[i].encodedLen,
751 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
752 (BYTE *)rgItems + i * arrayDesc->itemSize,
753 &itemSizes[i].size, &itemDecoded);
754 if (ret)
756 nextData += itemSizes[i].size - arrayDesc->itemSize;
757 ptr += itemDecoded;
762 if (itemSizes != &itemSize)
763 CryptMemFree(itemSizes);
766 else
768 SetLastError(CRYPT_E_ASN1_BADTAG);
769 ret = FALSE;
771 return ret;
774 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
775 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
776 * to CRYPT_E_ASN1_CORRUPT.
777 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
778 * set!
780 static BOOL CRYPT_AsnDecodeDerBlob(const BYTE *pbEncoded, DWORD cbEncoded,
781 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
783 BOOL ret;
784 DWORD dataLen;
786 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
788 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
789 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
791 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
792 bytesNeeded += 1 + lenBytes + dataLen;
794 if (pcbDecoded)
795 *pcbDecoded = 1 + lenBytes + dataLen;
796 if (!pvStructInfo)
797 *pcbStructInfo = bytesNeeded;
798 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded)))
800 CRYPT_DER_BLOB *blob;
802 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
803 pvStructInfo = *(BYTE **)pvStructInfo;
804 blob = pvStructInfo;
805 blob->cbData = 1 + lenBytes + dataLen;
806 if (blob->cbData)
808 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
809 blob->pbData = (BYTE *)pbEncoded;
810 else
812 assert(blob->pbData);
813 memcpy(blob->pbData, pbEncoded, blob->cbData);
816 else
818 SetLastError(CRYPT_E_ASN1_CORRUPT);
819 ret = FALSE;
823 return ret;
826 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
827 static BOOL CRYPT_AsnDecodeBitsSwapBytes(const BYTE *pbEncoded,
828 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
829 DWORD *pcbDecoded)
831 BOOL ret;
833 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
834 pvStructInfo, *pcbStructInfo, pcbDecoded);
836 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
837 * place.
839 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
840 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
841 pcbDecoded);
842 if (ret && pvStructInfo)
844 CRYPT_BIT_BLOB *blob = pvStructInfo;
846 if (blob->cbData)
848 DWORD i;
849 BYTE temp;
851 for (i = 0; i < blob->cbData / 2; i++)
853 temp = blob->pbData[i];
854 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
855 blob->pbData[blob->cbData - i - 1] = temp;
859 TRACE("returning %d (%08x)\n", ret, GetLastError());
860 return ret;
863 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
864 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
865 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
867 BOOL ret = TRUE;
869 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
870 pDecodePara, pvStructInfo, *pcbStructInfo);
872 __TRY
874 struct AsnDecodeSequenceItem items[] = {
875 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
876 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
877 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
878 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
879 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
880 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
881 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
882 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
883 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
884 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
887 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
888 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
889 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
890 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
891 pcbStructInfo, NULL, NULL);
893 __EXCEPT_PAGE_FAULT
895 SetLastError(STATUS_ACCESS_VIOLATION);
896 ret = FALSE;
898 __ENDTRY
900 TRACE("Returning %d (%08x)\n", ret, GetLastError());
901 return ret;
904 static BOOL CRYPT_AsnDecodeCertVersion(const BYTE *pbEncoded, DWORD cbEncoded,
905 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
907 BOOL ret;
908 DWORD dataLen;
910 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
912 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
914 ret = CRYPT_AsnDecodeIntInternal(pbEncoded + 1 + lenBytes, dataLen,
915 dwFlags, pvStructInfo, pcbStructInfo, NULL);
916 if (pcbDecoded)
917 *pcbDecoded = 1 + lenBytes + dataLen;
919 return ret;
922 static BOOL CRYPT_AsnDecodeValidity(const BYTE *pbEncoded, DWORD cbEncoded,
923 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
925 BOOL ret;
927 struct AsnDecodeSequenceItem items[] = {
928 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
929 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
930 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
931 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
934 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
935 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
936 pcbDecoded, NULL);
937 return ret;
940 static BOOL CRYPT_AsnDecodeCertExtensionsInternal(const BYTE *pbEncoded,
941 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
942 DWORD *pcbDecoded)
944 BOOL ret = TRUE;
945 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
946 offsetof(CERT_INFO, cExtension), offsetof(CERT_INFO, rgExtension),
947 FINALMEMBERSIZE(CERT_INFO, cExtension),
948 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
949 offsetof(CERT_EXTENSION, pszObjId) };
951 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
952 pvStructInfo, *pcbStructInfo, pcbDecoded);
954 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
955 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
956 return ret;
959 static BOOL CRYPT_AsnDecodeCertExtensions(const BYTE *pbEncoded,
960 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
961 DWORD *pcbDecoded)
963 BOOL ret;
964 DWORD dataLen;
966 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
968 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
970 ret = CRYPT_AsnDecodeCertExtensionsInternal(pbEncoded + 1 + lenBytes,
971 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
972 if (ret && pcbDecoded)
973 *pcbDecoded = 1 + lenBytes + dataLen;
975 return ret;
978 static BOOL CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
979 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
980 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
982 BOOL ret = TRUE;
983 struct AsnDecodeSequenceItem items[] = {
984 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
985 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
986 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
987 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
988 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
989 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
990 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
991 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
992 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
993 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
994 Issuer.pbData) },
995 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
996 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
997 FALSE, 0 },
998 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
999 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
1000 Subject.pbData) },
1001 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
1002 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
1003 FALSE, TRUE, offsetof(CERT_INFO,
1004 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
1005 { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
1006 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
1007 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
1008 { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
1009 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
1010 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
1011 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
1012 CRYPT_AsnDecodeCertExtensions, FINALMEMBERSIZE(CERT_INFO, cExtension),
1013 TRUE, TRUE, offsetof(CERT_INFO, rgExtension), 0 },
1016 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1017 pDecodePara, pvStructInfo, *pcbStructInfo);
1019 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1020 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
1021 NULL, NULL);
1022 if (ret && pvStructInfo)
1024 CERT_INFO *info;
1026 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1027 info = *(CERT_INFO **)pvStructInfo;
1028 else
1029 info = pvStructInfo;
1030 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
1031 !info->Subject.cbData)
1033 SetLastError(CRYPT_E_ASN1_CORRUPT);
1034 /* Don't need to deallocate, because it should have failed on the
1035 * first pass (and no memory was allocated.)
1037 ret = FALSE;
1041 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1042 return ret;
1045 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
1046 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1047 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1049 BOOL ret = FALSE;
1051 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1052 pDecodePara, pvStructInfo, *pcbStructInfo);
1054 __TRY
1056 DWORD size = 0;
1058 /* Unless told not to, first try to decode it as a signed cert. */
1059 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1061 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
1063 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1064 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1065 &signedCert, &size);
1066 if (ret)
1068 size = 0;
1069 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1070 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
1071 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
1072 pvStructInfo, pcbStructInfo);
1073 LocalFree(signedCert);
1076 /* Failing that, try it as an unsigned cert */
1077 if (!ret)
1079 size = 0;
1080 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1081 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
1082 pDecodePara, pvStructInfo, pcbStructInfo);
1085 __EXCEPT_PAGE_FAULT
1087 SetLastError(STATUS_ACCESS_VIOLATION);
1089 __ENDTRY
1091 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1092 return ret;
1095 static BOOL CRYPT_AsnDecodeCRLEntryExtensions(const BYTE *pbEncoded,
1096 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1097 DWORD *pcbDecoded)
1099 BOOL ret = TRUE;
1100 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1101 offsetof(CRL_ENTRY, cExtension), offsetof(CRL_ENTRY, rgExtension),
1102 FINALMEMBERSIZE(CRL_ENTRY, cExtension),
1103 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1104 offsetof(CERT_EXTENSION, pszObjId) };
1106 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1107 pvStructInfo, *pcbStructInfo, pcbDecoded);
1109 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1110 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1111 return ret;
1114 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
1115 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1117 BOOL ret;
1118 struct AsnDecodeSequenceItem items[] = {
1119 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
1120 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
1121 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
1122 { 0, offsetof(CRL_ENTRY, RevocationDate),
1123 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
1124 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
1125 CRYPT_AsnDecodeCRLEntryExtensions,
1126 FINALMEMBERSIZE(CRL_ENTRY, cExtension), TRUE, TRUE,
1127 offsetof(CRL_ENTRY, rgExtension), 0 },
1129 PCRL_ENTRY entry = pvStructInfo;
1131 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
1132 *pcbStructInfo);
1134 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1135 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, pcbDecoded,
1136 entry ? entry->SerialNumber.pbData : NULL);
1137 if (ret && entry && !entry->SerialNumber.cbData)
1139 WARN("empty CRL entry serial number\n");
1140 SetLastError(CRYPT_E_ASN1_CORRUPT);
1141 ret = FALSE;
1143 return ret;
1146 /* Warning: assumes pvStructInfo points to the cCRLEntry member of a CRL_INFO
1147 * whose rgCRLEntry member has been set prior to calling.
1149 static BOOL CRYPT_AsnDecodeCRLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
1150 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1152 BOOL ret;
1153 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1154 offsetof(CRL_INFO, cCRLEntry), offsetof(CRL_INFO, rgCRLEntry),
1155 MEMBERSIZE(CRL_INFO, cCRLEntry, cExtension),
1156 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
1157 offsetof(CRL_ENTRY, SerialNumber.pbData) };
1159 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1160 pvStructInfo, *pcbStructInfo, pcbDecoded);
1162 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1163 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1164 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1165 return ret;
1168 static BOOL CRYPT_AsnDecodeCRLExtensionsInternal(const BYTE *pbEncoded,
1169 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1170 DWORD *pcbDecoded)
1172 BOOL ret = TRUE;
1173 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1174 offsetof(CRL_INFO, cExtension), offsetof(CRL_INFO, rgExtension),
1175 FINALMEMBERSIZE(CRL_INFO, cExtension),
1176 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1177 offsetof(CERT_EXTENSION, pszObjId) };
1179 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1180 pvStructInfo, *pcbStructInfo, pcbDecoded);
1182 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1183 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1184 return ret;
1187 static BOOL CRYPT_AsnDecodeCRLExtensions(const BYTE *pbEncoded,
1188 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1189 DWORD *pcbDecoded)
1191 BOOL ret;
1192 DWORD dataLen;
1194 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1196 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1198 ret = CRYPT_AsnDecodeCRLExtensionsInternal(pbEncoded + 1 + lenBytes,
1199 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
1200 if (ret && pcbDecoded)
1201 *pcbDecoded = 1 + lenBytes + dataLen;
1203 return ret;
1206 static BOOL CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1207 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1208 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1210 struct AsnDecodeSequenceItem items[] = {
1211 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1212 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1213 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1214 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1215 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1216 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1217 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1218 Issuer.pbData) },
1219 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1220 sizeof(FILETIME), FALSE, FALSE, 0 },
1221 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1222 sizeof(FILETIME), TRUE, FALSE, 0 },
1223 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1224 CRYPT_AsnDecodeCRLEntries, MEMBERSIZE(CRL_INFO, cCRLEntry, cExtension),
1225 TRUE, TRUE, offsetof(CRL_INFO, rgCRLEntry), 0 },
1226 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1227 CRYPT_AsnDecodeCRLExtensions, FINALMEMBERSIZE(CRL_INFO, cExtension),
1228 TRUE, TRUE, offsetof(CRL_INFO, rgExtension), 0 },
1230 BOOL ret = TRUE;
1232 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1233 pDecodePara, pvStructInfo, *pcbStructInfo);
1235 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1236 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
1237 NULL, NULL);
1239 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1240 return ret;
1243 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1244 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1245 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1247 BOOL ret = FALSE;
1249 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1250 pDecodePara, pvStructInfo, *pcbStructInfo);
1252 __TRY
1254 DWORD size = 0;
1256 /* Unless told not to, first try to decode it as a signed crl. */
1257 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1259 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1261 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1262 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1263 &signedCrl, &size);
1264 if (ret)
1266 size = 0;
1267 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1268 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1269 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1270 pvStructInfo, pcbStructInfo);
1271 LocalFree(signedCrl);
1274 /* Failing that, try it as an unsigned crl */
1275 if (!ret)
1277 size = 0;
1278 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1279 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1280 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1283 __EXCEPT_PAGE_FAULT
1285 SetLastError(STATUS_ACCESS_VIOLATION);
1287 __ENDTRY
1289 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1290 return ret;
1293 static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded,
1294 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1296 BOOL ret = TRUE;
1297 DWORD dataLen;
1299 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1300 pvStructInfo, *pcbStructInfo);
1302 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1304 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1305 DWORD bytesNeeded = sizeof(LPSTR);
1307 if (dataLen)
1309 /* The largest possible string for the first two components
1310 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1312 char firstTwo[6];
1313 const BYTE *ptr;
1315 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1316 pbEncoded[1 + lenBytes] / 40,
1317 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1318 * 40);
1319 bytesNeeded += strlen(firstTwo) + 1;
1320 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1321 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1323 /* large enough for ".4000000" */
1324 char str[9];
1325 int val = 0;
1327 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1328 (*ptr & 0x80))
1330 val <<= 7;
1331 val |= *ptr & 0x7f;
1332 ptr++;
1334 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1335 (*ptr & 0x80))
1337 SetLastError(CRYPT_E_ASN1_CORRUPT);
1338 ret = FALSE;
1340 else
1342 val <<= 7;
1343 val |= *ptr++;
1344 snprintf(str, sizeof(str), ".%d", val);
1345 bytesNeeded += strlen(str);
1349 if (pcbDecoded)
1350 *pcbDecoded = 1 + lenBytes + dataLen;
1351 if (!pvStructInfo)
1352 *pcbStructInfo = bytesNeeded;
1353 else if (*pcbStructInfo < bytesNeeded)
1355 *pcbStructInfo = bytesNeeded;
1356 SetLastError(ERROR_MORE_DATA);
1357 ret = FALSE;
1359 else
1361 if (dataLen)
1363 const BYTE *ptr;
1364 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1366 *pszObjId = 0;
1367 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1368 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1369 40) * 40);
1370 pszObjId += strlen(pszObjId);
1371 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1372 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1374 int val = 0;
1376 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1377 (*ptr & 0x80))
1379 val <<= 7;
1380 val |= *ptr & 0x7f;
1381 ptr++;
1383 val <<= 7;
1384 val |= *ptr++;
1385 sprintf(pszObjId, ".%d", val);
1386 pszObjId += strlen(pszObjId);
1389 else
1390 *(LPSTR *)pvStructInfo = NULL;
1391 *pcbStructInfo = bytesNeeded;
1394 return ret;
1397 static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded,
1398 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1400 BOOL ret;
1402 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1403 pvStructInfo, *pcbStructInfo);
1405 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1406 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1407 pvStructInfo, pcbStructInfo, pcbDecoded);
1408 else
1410 SetLastError(CRYPT_E_ASN1_BADTAG);
1411 ret = FALSE;
1413 return ret;
1416 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
1417 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1419 struct AsnDecodeSequenceItem items[] = {
1420 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1421 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1422 offsetof(CERT_EXTENSION, pszObjId), 0 },
1423 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1424 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1425 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1426 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1427 offsetof(CERT_EXTENSION, Value.pbData) },
1429 BOOL ret = TRUE;
1430 PCERT_EXTENSION ext = pvStructInfo;
1432 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1433 *pcbStructInfo);
1435 if (ext)
1436 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1437 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1438 pbEncoded, cbEncoded, dwFlags, NULL, ext, pcbStructInfo,
1439 pcbDecoded, ext ? ext->pszObjId : NULL);
1440 if (ext)
1441 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1442 debugstr_a(ext->pszObjId));
1443 TRACE("returning %d (%08x)\n", ret, GetLastError());
1444 return ret;
1447 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1448 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1449 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1451 BOOL ret = TRUE;
1453 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1454 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
1456 __TRY
1458 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1459 offsetof(CERT_EXTENSIONS, cExtension),
1460 offsetof(CERT_EXTENSIONS, rgExtension),
1461 sizeof(CERT_EXTENSIONS),
1462 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1463 offsetof(CERT_EXTENSION, pszObjId) };
1465 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1466 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1468 __EXCEPT_PAGE_FAULT
1470 SetLastError(STATUS_ACCESS_VIOLATION);
1471 ret = FALSE;
1473 __ENDTRY
1474 return ret;
1477 /* Warning: this assumes the address of value->Value.pbData is already set, in
1478 * order to avoid overwriting memory. (In some cases, it may change it, if it
1479 * doesn't copy anything to memory.) Be sure to set it correctly!
1481 static BOOL CRYPT_AsnDecodeNameValueInternal(const BYTE *pbEncoded,
1482 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1483 DWORD *pcbDecoded)
1485 BOOL ret = TRUE;
1486 DWORD dataLen;
1487 CERT_NAME_VALUE *value = pvStructInfo;
1489 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1491 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1492 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1494 switch (pbEncoded[0])
1496 case ASN_OCTETSTRING:
1497 valueType = CERT_RDN_OCTET_STRING;
1498 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1499 bytesNeeded += dataLen;
1500 break;
1501 case ASN_NUMERICSTRING:
1502 valueType = CERT_RDN_NUMERIC_STRING;
1503 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1504 bytesNeeded += dataLen;
1505 break;
1506 case ASN_PRINTABLESTRING:
1507 valueType = CERT_RDN_PRINTABLE_STRING;
1508 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1509 bytesNeeded += dataLen;
1510 break;
1511 case ASN_IA5STRING:
1512 valueType = CERT_RDN_IA5_STRING;
1513 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1514 bytesNeeded += dataLen;
1515 break;
1516 case ASN_T61STRING:
1517 valueType = CERT_RDN_T61_STRING;
1518 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1519 bytesNeeded += dataLen;
1520 break;
1521 case ASN_VIDEOTEXSTRING:
1522 valueType = CERT_RDN_VIDEOTEX_STRING;
1523 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1524 bytesNeeded += dataLen;
1525 break;
1526 case ASN_GRAPHICSTRING:
1527 valueType = CERT_RDN_GRAPHIC_STRING;
1528 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1529 bytesNeeded += dataLen;
1530 break;
1531 case ASN_VISIBLESTRING:
1532 valueType = CERT_RDN_VISIBLE_STRING;
1533 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1534 bytesNeeded += dataLen;
1535 break;
1536 case ASN_GENERALSTRING:
1537 valueType = CERT_RDN_GENERAL_STRING;
1538 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1539 bytesNeeded += dataLen;
1540 break;
1541 case ASN_UNIVERSALSTRING:
1542 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1543 SetLastError(CRYPT_E_ASN1_BADTAG);
1544 return FALSE;
1545 case ASN_BMPSTRING:
1546 valueType = CERT_RDN_BMP_STRING;
1547 bytesNeeded += dataLen;
1548 break;
1549 case ASN_UTF8STRING:
1550 valueType = CERT_RDN_UTF8_STRING;
1551 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1552 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1553 break;
1554 default:
1555 SetLastError(CRYPT_E_ASN1_BADTAG);
1556 return FALSE;
1559 if (pcbDecoded)
1560 *pcbDecoded = 1 + lenBytes + dataLen;
1561 if (!value)
1562 *pcbStructInfo = bytesNeeded;
1563 else if (*pcbStructInfo < bytesNeeded)
1565 *pcbStructInfo = bytesNeeded;
1566 SetLastError(ERROR_MORE_DATA);
1567 ret = FALSE;
1569 else
1571 *pcbStructInfo = bytesNeeded;
1572 value->dwValueType = valueType;
1573 if (dataLen)
1575 DWORD i;
1577 assert(value->Value.pbData);
1578 switch (pbEncoded[0])
1580 case ASN_OCTETSTRING:
1581 case ASN_NUMERICSTRING:
1582 case ASN_PRINTABLESTRING:
1583 case ASN_IA5STRING:
1584 case ASN_T61STRING:
1585 case ASN_VIDEOTEXSTRING:
1586 case ASN_GRAPHICSTRING:
1587 case ASN_VISIBLESTRING:
1588 case ASN_GENERALSTRING:
1589 value->Value.cbData = dataLen;
1590 if (dataLen)
1592 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1593 memcpy(value->Value.pbData,
1594 pbEncoded + 1 + lenBytes, dataLen);
1595 else
1596 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1597 lenBytes;
1599 break;
1600 case ASN_BMPSTRING:
1602 LPWSTR str = (LPWSTR)value->Value.pbData;
1604 value->Value.cbData = dataLen;
1605 for (i = 0; i < dataLen / 2; i++)
1606 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1607 pbEncoded[1 + lenBytes + 2 * i + 1];
1608 break;
1610 case ASN_UTF8STRING:
1612 LPWSTR str = (LPWSTR)value->Value.pbData;
1614 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1615 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1616 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1617 break;
1621 else
1623 value->Value.cbData = 0;
1624 value->Value.pbData = NULL;
1628 return ret;
1631 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1632 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1633 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1635 BOOL ret = TRUE;
1637 __TRY
1639 ret = CRYPT_AsnDecodeNameValueInternal(pbEncoded, cbEncoded,
1640 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1641 if (ret && pvStructInfo)
1643 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1644 pcbStructInfo, *pcbStructInfo);
1645 if (ret)
1647 CERT_NAME_VALUE *value;
1649 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1650 pvStructInfo = *(BYTE **)pvStructInfo;
1651 value = pvStructInfo;
1652 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1653 ret = CRYPT_AsnDecodeNameValueInternal( pbEncoded, cbEncoded,
1654 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1655 pcbStructInfo, NULL);
1659 __EXCEPT_PAGE_FAULT
1661 SetLastError(STATUS_ACCESS_VIOLATION);
1662 ret = FALSE;
1664 __ENDTRY
1665 return ret;
1668 static BOOL CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE *pbEncoded,
1669 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1670 DWORD *pcbDecoded)
1672 BOOL ret = TRUE;
1673 DWORD dataLen;
1674 CERT_NAME_VALUE *value = pvStructInfo;
1676 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1678 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1679 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1681 switch (pbEncoded[0])
1683 case ASN_NUMERICSTRING:
1684 valueType = CERT_RDN_NUMERIC_STRING;
1685 if (dataLen)
1686 bytesNeeded += (dataLen + 1) * 2;
1687 break;
1688 case ASN_PRINTABLESTRING:
1689 valueType = CERT_RDN_PRINTABLE_STRING;
1690 if (dataLen)
1691 bytesNeeded += (dataLen + 1) * 2;
1692 break;
1693 case ASN_IA5STRING:
1694 valueType = CERT_RDN_IA5_STRING;
1695 if (dataLen)
1696 bytesNeeded += (dataLen + 1) * 2;
1697 break;
1698 case ASN_T61STRING:
1699 valueType = CERT_RDN_T61_STRING;
1700 if (dataLen)
1701 bytesNeeded += (dataLen + 1) * 2;
1702 break;
1703 case ASN_VIDEOTEXSTRING:
1704 valueType = CERT_RDN_VIDEOTEX_STRING;
1705 if (dataLen)
1706 bytesNeeded += (dataLen + 1) * 2;
1707 break;
1708 case ASN_GRAPHICSTRING:
1709 valueType = CERT_RDN_GRAPHIC_STRING;
1710 if (dataLen)
1711 bytesNeeded += (dataLen + 1) * 2;
1712 break;
1713 case ASN_VISIBLESTRING:
1714 valueType = CERT_RDN_VISIBLE_STRING;
1715 if (dataLen)
1716 bytesNeeded += (dataLen + 1) * 2;
1717 break;
1718 case ASN_GENERALSTRING:
1719 valueType = CERT_RDN_GENERAL_STRING;
1720 if (dataLen)
1721 bytesNeeded += (dataLen + 1) * 2;
1722 break;
1723 case ASN_UNIVERSALSTRING:
1724 valueType = CERT_RDN_UNIVERSAL_STRING;
1725 if (dataLen)
1726 bytesNeeded += dataLen / 2 + sizeof(WCHAR);
1727 break;
1728 case ASN_BMPSTRING:
1729 valueType = CERT_RDN_BMP_STRING;
1730 if (dataLen)
1731 bytesNeeded += dataLen + sizeof(WCHAR);
1732 break;
1733 case ASN_UTF8STRING:
1734 valueType = CERT_RDN_UTF8_STRING;
1735 if (dataLen)
1736 bytesNeeded += (MultiByteToWideChar(CP_UTF8, 0,
1737 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) + 1) * 2;
1738 break;
1739 default:
1740 SetLastError(CRYPT_E_ASN1_BADTAG);
1741 return FALSE;
1744 if (pcbDecoded)
1745 *pcbDecoded = 1 + lenBytes + dataLen;
1746 if (!value)
1747 *pcbStructInfo = bytesNeeded;
1748 else if (*pcbStructInfo < bytesNeeded)
1750 *pcbStructInfo = bytesNeeded;
1751 SetLastError(ERROR_MORE_DATA);
1752 ret = FALSE;
1754 else
1756 *pcbStructInfo = bytesNeeded;
1757 value->dwValueType = valueType;
1758 if (dataLen)
1760 DWORD i;
1761 LPWSTR str = (LPWSTR)value->Value.pbData;
1763 assert(value->Value.pbData);
1764 switch (pbEncoded[0])
1766 case ASN_NUMERICSTRING:
1767 case ASN_PRINTABLESTRING:
1768 case ASN_IA5STRING:
1769 case ASN_T61STRING:
1770 case ASN_VIDEOTEXSTRING:
1771 case ASN_GRAPHICSTRING:
1772 case ASN_VISIBLESTRING:
1773 case ASN_GENERALSTRING:
1774 value->Value.cbData = dataLen * 2;
1775 for (i = 0; i < dataLen; i++)
1776 str[i] = pbEncoded[1 + lenBytes + i];
1777 str[i] = 0;
1778 break;
1779 case ASN_UNIVERSALSTRING:
1780 value->Value.cbData = dataLen / 2;
1781 for (i = 0; i < dataLen / 4; i++)
1782 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1783 | pbEncoded[1 + lenBytes + 2 * i + 3];
1784 str[i] = 0;
1785 break;
1786 case ASN_BMPSTRING:
1787 value->Value.cbData = dataLen;
1788 for (i = 0; i < dataLen / 2; i++)
1789 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1790 pbEncoded[1 + lenBytes + 2 * i + 1];
1791 str[i] = 0;
1792 break;
1793 case ASN_UTF8STRING:
1794 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1795 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1796 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * sizeof(WCHAR);
1797 *(WCHAR *)(value->Value.pbData + value->Value.cbData) = 0;
1798 value->Value.cbData += sizeof(WCHAR);
1799 break;
1802 else
1804 value->Value.cbData = 0;
1805 value->Value.pbData = NULL;
1809 return ret;
1812 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1813 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1814 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1816 BOOL ret = TRUE;
1818 __TRY
1820 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded, cbEncoded,
1821 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1822 if (ret && pvStructInfo)
1824 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1825 pcbStructInfo, *pcbStructInfo);
1826 if (ret)
1828 CERT_NAME_VALUE *value;
1830 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1831 pvStructInfo = *(BYTE **)pvStructInfo;
1832 value = pvStructInfo;
1833 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1834 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded,
1835 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1836 pcbStructInfo, NULL);
1840 __EXCEPT_PAGE_FAULT
1842 SetLastError(STATUS_ACCESS_VIOLATION);
1843 ret = FALSE;
1845 __ENDTRY
1846 return ret;
1849 static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
1850 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1852 BOOL ret;
1853 struct AsnDecodeSequenceItem items[] = {
1854 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1855 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1856 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1857 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1858 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1859 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1861 CERT_RDN_ATTR *attr = pvStructInfo;
1863 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1864 pvStructInfo, *pcbStructInfo);
1866 if (attr)
1867 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1868 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1869 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1870 attr ? attr->pszObjId : NULL);
1871 if (attr)
1873 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1874 debugstr_a(attr->pszObjId));
1875 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1877 TRACE("returning %d (%08x)\n", ret, GetLastError());
1878 return ret;
1881 static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1882 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1884 BOOL ret = TRUE;
1885 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1886 offsetof(CERT_RDN, cRDNAttr), offsetof(CERT_RDN, rgRDNAttr),
1887 sizeof(CERT_RDN),
1888 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1889 offsetof(CERT_RDN_ATTR, pszObjId) };
1891 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1892 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1893 return ret;
1896 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1897 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1898 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1900 BOOL ret = TRUE;
1902 __TRY
1904 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1905 offsetof(CERT_NAME_INFO, cRDN), offsetof(CERT_NAME_INFO, rgRDN),
1906 sizeof(CERT_NAME_INFO),
1907 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1908 offsetof(CERT_RDN, rgRDNAttr) };
1910 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1911 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1913 __EXCEPT_PAGE_FAULT
1915 SetLastError(STATUS_ACCESS_VIOLATION);
1916 ret = FALSE;
1918 __ENDTRY
1919 return ret;
1922 static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
1923 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1924 DWORD *pcbDecoded)
1926 BOOL ret;
1927 struct AsnDecodeSequenceItem items[] = {
1928 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1929 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1930 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1931 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1932 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1933 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1935 CERT_RDN_ATTR *attr = pvStructInfo;
1937 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1938 pvStructInfo, *pcbStructInfo);
1940 if (attr)
1941 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1942 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1943 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1944 attr ? attr->pszObjId : NULL);
1945 if (attr)
1947 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1948 debugstr_a(attr->pszObjId));
1949 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1951 TRACE("returning %d (%08x)\n", ret, GetLastError());
1952 return ret;
1955 static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1956 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1958 BOOL ret = TRUE;
1959 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1960 offsetof(CERT_RDN, cRDNAttr), offsetof(CERT_RDN, rgRDNAttr),
1961 sizeof(CERT_RDN),
1962 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1963 offsetof(CERT_RDN_ATTR, pszObjId) };
1965 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1966 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1967 return ret;
1970 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
1971 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1972 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1974 BOOL ret = TRUE;
1976 __TRY
1978 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1979 offsetof(CERT_NAME_INFO, cRDN), offsetof(CERT_NAME_INFO, rgRDN),
1980 sizeof(CERT_NAME_INFO),
1981 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
1982 offsetof(CERT_RDN, rgRDNAttr) };
1984 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1985 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1987 __EXCEPT_PAGE_FAULT
1989 SetLastError(STATUS_ACCESS_VIOLATION);
1990 ret = FALSE;
1992 __ENDTRY
1993 return ret;
1996 static BOOL CRYPT_FindEncodedLen(const BYTE *pbEncoded, DWORD cbEncoded,
1997 DWORD *pcbDecoded)
1999 BOOL ret = TRUE, done = FALSE;
2000 DWORD indefiniteNestingLevels = 0, decoded = 0;
2002 TRACE("(%p, %d)\n", pbEncoded, cbEncoded);
2004 do {
2005 DWORD dataLen;
2007 if (!cbEncoded)
2008 done = TRUE;
2009 else if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded,
2010 &dataLen)))
2012 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2014 if (dataLen == CMSG_INDEFINITE_LENGTH)
2016 indefiniteNestingLevels++;
2017 pbEncoded += 1 + lenBytes;
2018 cbEncoded -= 1 + lenBytes;
2019 decoded += 1 + lenBytes;
2020 TRACE("indefiniteNestingLevels = %d\n",
2021 indefiniteNestingLevels);
2023 else
2025 if (pbEncoded[0] == 0 && pbEncoded[1] == 0 &&
2026 indefiniteNestingLevels)
2028 indefiniteNestingLevels--;
2029 TRACE("indefiniteNestingLevels = %d\n",
2030 indefiniteNestingLevels);
2032 pbEncoded += 1 + lenBytes + dataLen;
2033 cbEncoded -= 1 + lenBytes + dataLen;
2034 decoded += 1 + lenBytes + dataLen;
2035 if (!indefiniteNestingLevels)
2036 done = TRUE;
2039 } while (ret && !done);
2040 /* If we haven't found all 0 TLVs, we haven't found the end */
2041 if (ret && indefiniteNestingLevels)
2043 SetLastError(CRYPT_E_ASN1_EOD);
2044 ret = FALSE;
2046 if (ret)
2047 *pcbDecoded = decoded;
2048 TRACE("returning %d (%d)\n", ret, ret ? *pcbDecoded : 0);
2049 return ret;
2052 static BOOL CRYPT_AsnDecodeCopyBytes(const BYTE *pbEncoded,
2053 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2054 DWORD *pcbDecoded)
2056 BOOL ret = TRUE;
2057 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB), encodedLen = 0;
2059 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2060 pvStructInfo, *pcbStructInfo);
2062 if ((ret = CRYPT_FindEncodedLen(pbEncoded, cbEncoded, &encodedLen)))
2064 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
2065 bytesNeeded += encodedLen;
2066 if (!pvStructInfo)
2067 *pcbStructInfo = bytesNeeded;
2068 else if (*pcbStructInfo < bytesNeeded)
2070 SetLastError(ERROR_MORE_DATA);
2071 *pcbStructInfo = bytesNeeded;
2072 ret = FALSE;
2074 else
2076 PCRYPT_OBJID_BLOB blob = pvStructInfo;
2078 *pcbStructInfo = bytesNeeded;
2079 blob->cbData = encodedLen;
2080 if (encodedLen)
2082 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2083 blob->pbData = (LPBYTE)pbEncoded;
2084 else
2086 assert(blob->pbData);
2087 memcpy(blob->pbData, pbEncoded, blob->cbData);
2090 else
2091 blob->pbData = NULL;
2093 if (pcbDecoded)
2094 *pcbDecoded = encodedLen;
2096 return ret;
2099 static BOOL CRYPT_AsnDecodeCTLUsage(const BYTE *pbEncoded, DWORD cbEncoded,
2100 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2102 BOOL ret;
2103 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2104 offsetof(CTL_USAGE, cUsageIdentifier),
2105 offsetof(CTL_USAGE, rgpszUsageIdentifier),
2106 sizeof(CTL_USAGE),
2107 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
2109 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2110 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2111 return ret;
2114 static BOOL CRYPT_AsnDecodeCTLEntryAttributes(const BYTE *pbEncoded,
2115 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2116 DWORD *pcbDecoded)
2118 struct AsnArrayDescriptor arrayDesc = { 0,
2119 offsetof(CTL_ENTRY, cAttribute), offsetof(CTL_ENTRY, rgAttribute),
2120 FINALMEMBERSIZE(CTL_ENTRY, cAttribute),
2121 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2122 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2123 BOOL ret;
2125 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2126 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2127 return ret;
2130 static BOOL CRYPT_AsnDecodeCTLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2131 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2133 struct AsnDecodeSequenceItem items[] = {
2134 { ASN_OCTETSTRING, offsetof(CTL_ENTRY, SubjectIdentifier),
2135 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE,
2136 offsetof(CTL_ENTRY, SubjectIdentifier.pbData), 0 },
2137 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CTL_ENTRY, cAttribute),
2138 CRYPT_AsnDecodeCTLEntryAttributes,
2139 FINALMEMBERSIZE(CTL_ENTRY, cAttribute), FALSE, TRUE,
2140 offsetof(CTL_ENTRY, rgAttribute), 0 },
2142 BOOL ret = TRUE;
2143 CTL_ENTRY *entry = pvStructInfo;
2145 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
2146 *pcbStructInfo);
2148 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2149 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo,
2150 pcbDecoded, entry ? entry->SubjectIdentifier.pbData : NULL);
2151 return ret;
2154 static BOOL CRYPT_AsnDecodeCTLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
2155 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2157 BOOL ret;
2158 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2159 offsetof(CTL_INFO, cCTLEntry), offsetof(CTL_INFO, rgCTLEntry),
2160 FINALMEMBERSIZE(CTL_INFO, cExtension),
2161 CRYPT_AsnDecodeCTLEntry, sizeof(CTL_ENTRY), TRUE,
2162 offsetof(CTL_ENTRY, SubjectIdentifier.pbData) };
2164 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2165 pvStructInfo, *pcbStructInfo, pcbDecoded);
2167 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2168 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2169 return ret;
2172 static BOOL CRYPT_AsnDecodeCTLExtensionsInternal(const BYTE *pbEncoded,
2173 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2174 DWORD *pcbDecoded)
2176 BOOL ret = TRUE;
2177 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2178 offsetof(CTL_INFO, cExtension), offsetof(CTL_INFO, rgExtension),
2179 FINALMEMBERSIZE(CTL_INFO, cExtension),
2180 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
2181 offsetof(CERT_EXTENSION, pszObjId) };
2183 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2184 pvStructInfo, *pcbStructInfo, pcbDecoded);
2186 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2187 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2188 return ret;
2191 static BOOL CRYPT_AsnDecodeCTLExtensions(const BYTE *pbEncoded,
2192 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2193 DWORD *pcbDecoded)
2195 BOOL ret;
2196 DWORD dataLen;
2198 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2200 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2202 ret = CRYPT_AsnDecodeCTLExtensionsInternal(pbEncoded + 1 + lenBytes,
2203 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
2204 if (ret && pcbDecoded)
2205 *pcbDecoded = 1 + lenBytes + dataLen;
2207 return ret;
2210 static BOOL WINAPI CRYPT_AsnDecodeCTL(DWORD dwCertEncodingType,
2211 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2212 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2214 BOOL ret = FALSE;
2216 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2217 pDecodePara, pvStructInfo, *pcbStructInfo);
2219 __TRY
2221 struct AsnDecodeSequenceItem items[] = {
2222 { ASN_INTEGER, offsetof(CTL_INFO, dwVersion),
2223 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
2224 { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectUsage),
2225 CRYPT_AsnDecodeCTLUsage, sizeof(CTL_USAGE), FALSE, TRUE,
2226 offsetof(CTL_INFO, SubjectUsage.rgpszUsageIdentifier), 0 },
2227 { ASN_OCTETSTRING, offsetof(CTL_INFO, ListIdentifier),
2228 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), TRUE,
2229 TRUE, offsetof(CTL_INFO, ListIdentifier.pbData), 0 },
2230 { ASN_INTEGER, offsetof(CTL_INFO, SequenceNumber),
2231 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2232 TRUE, TRUE, offsetof(CTL_INFO, SequenceNumber.pbData), 0 },
2233 { 0, offsetof(CTL_INFO, ThisUpdate),
2234 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE,
2235 0 },
2236 { 0, offsetof(CTL_INFO, NextUpdate),
2237 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), TRUE, FALSE,
2238 0 },
2239 { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectAlgorithm),
2240 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2241 FALSE, TRUE, offsetof(CTL_INFO, SubjectAlgorithm.pszObjId), 0 },
2242 { ASN_SEQUENCEOF, offsetof(CTL_INFO, cCTLEntry),
2243 CRYPT_AsnDecodeCTLEntries,
2244 MEMBERSIZE(CTL_INFO, cCTLEntry, cExtension),
2245 TRUE, TRUE, offsetof(CTL_INFO, rgCTLEntry), 0 },
2246 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CTL_INFO, cExtension),
2247 CRYPT_AsnDecodeCTLExtensions, FINALMEMBERSIZE(CTL_INFO, cExtension),
2248 TRUE, TRUE, offsetof(CTL_INFO, rgExtension), 0 },
2251 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2252 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2253 pcbStructInfo, NULL, NULL);
2255 __EXCEPT_PAGE_FAULT
2257 SetLastError(STATUS_ACCESS_VIOLATION);
2259 __ENDTRY
2260 return ret;
2263 static BOOL CRYPT_AsnDecodeSMIMECapability(const BYTE *pbEncoded,
2264 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2265 DWORD *pcbDecoded)
2267 BOOL ret;
2268 struct AsnDecodeSequenceItem items[] = {
2269 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_SMIME_CAPABILITY, pszObjId),
2270 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2271 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId), 0 },
2272 { 0, offsetof(CRYPT_SMIME_CAPABILITY, Parameters),
2273 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2274 offsetof(CRYPT_SMIME_CAPABILITY, Parameters.pbData), 0 },
2276 PCRYPT_SMIME_CAPABILITY capability = pvStructInfo;
2278 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2279 pvStructInfo, *pcbStructInfo);
2281 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2282 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2283 pcbDecoded, capability ? capability->pszObjId : NULL);
2284 TRACE("returning %d\n", ret);
2285 return ret;
2288 static BOOL WINAPI CRYPT_AsnDecodeSMIMECapabilities(DWORD dwCertEncodingType,
2289 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2290 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2292 BOOL ret = FALSE;
2294 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2295 pDecodePara, pvStructInfo, *pcbStructInfo);
2297 __TRY
2299 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2300 offsetof(CRYPT_SMIME_CAPABILITIES, cCapability),
2301 offsetof(CRYPT_SMIME_CAPABILITIES, rgCapability),
2302 sizeof(CRYPT_SMIME_CAPABILITIES),
2303 CRYPT_AsnDecodeSMIMECapability, sizeof(CRYPT_SMIME_CAPABILITY), TRUE,
2304 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId) };
2306 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2307 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2309 __EXCEPT_PAGE_FAULT
2311 SetLastError(STATUS_ACCESS_VIOLATION);
2313 __ENDTRY
2314 TRACE("returning %d\n", ret);
2315 return ret;
2318 static BOOL CRYPT_AsnDecodeIA5String(const BYTE *pbEncoded,
2319 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2320 DWORD *pcbDecoded)
2322 BOOL ret = TRUE;
2323 DWORD dataLen;
2324 LPSTR *pStr = pvStructInfo;
2326 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2328 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2329 DWORD bytesNeeded = sizeof(LPSTR) + sizeof(char);
2331 if (pbEncoded[0] != ASN_IA5STRING)
2333 SetLastError(CRYPT_E_ASN1_CORRUPT);
2334 ret = FALSE;
2336 else
2338 bytesNeeded += dataLen;
2339 if (pcbDecoded)
2340 *pcbDecoded = 1 + lenBytes + dataLen;
2341 if (!pvStructInfo)
2342 *pcbStructInfo = bytesNeeded;
2343 else if (*pcbStructInfo < bytesNeeded)
2345 *pcbStructInfo = bytesNeeded;
2346 SetLastError(ERROR_MORE_DATA);
2347 ret = FALSE;
2349 else
2351 *pcbStructInfo = bytesNeeded;
2352 if (dataLen)
2354 LPSTR str = *pStr;
2356 assert(str);
2357 memcpy(str, pbEncoded + 1 + lenBytes, dataLen);
2358 str[dataLen] = 0;
2360 else
2361 *pStr = NULL;
2365 return ret;
2368 static BOOL CRYPT_AsnDecodeNoticeNumbers(const BYTE *pbEncoded,
2369 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2370 DWORD *pcbDecoded)
2372 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2373 offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers),
2374 offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, rgNoticeNumbers),
2375 FINALMEMBERSIZE(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers),
2376 CRYPT_AsnDecodeIntInternal, sizeof(int), FALSE, 0 };
2377 BOOL ret;
2379 TRACE("(%p, %d, %08x, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2380 pvStructInfo, pvStructInfo ? *pcbDecoded : 0);
2382 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2383 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2384 TRACE("returning %d\n", ret);
2385 return ret;
2388 static BOOL CRYPT_AsnDecodeNoticeReference(const BYTE *pbEncoded,
2389 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2390 DWORD *pcbDecoded)
2392 BOOL ret;
2393 struct AsnDecodeSequenceItem items[] = {
2394 { ASN_IA5STRING, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2395 pszOrganization), CRYPT_AsnDecodeIA5String, sizeof(LPSTR), FALSE, TRUE,
2396 offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, pszOrganization), 0 },
2397 { ASN_SEQUENCEOF, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2398 cNoticeNumbers), CRYPT_AsnDecodeNoticeNumbers,
2399 FINALMEMBERSIZE(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers),
2400 FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2401 rgNoticeNumbers), 0 },
2403 DWORD bytesNeeded;
2405 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2406 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
2408 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2409 pbEncoded, cbEncoded, dwFlags, NULL, NULL, &bytesNeeded, pcbDecoded,
2410 NULL);
2411 if (ret)
2413 /* The caller is expecting a pointer to a
2414 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE to be decoded, whereas
2415 * CRYPT_AsnDecodeSequence is decoding a
2416 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE. Increment the bytes
2417 * needed, and decode again if the requisite space is available.
2419 bytesNeeded += sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE);
2420 if (!pvStructInfo)
2421 *pcbStructInfo = bytesNeeded;
2422 else if (*pcbStructInfo < bytesNeeded)
2424 *pcbStructInfo = bytesNeeded;
2425 SetLastError(ERROR_MORE_DATA);
2426 ret = FALSE;
2428 else
2430 PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE noticeRef;
2432 *pcbStructInfo = bytesNeeded;
2433 /* The pointer (pvStructInfo) passed in points to the first dynamic
2434 * pointer, so use it as the pointer to the
2435 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, and create the
2436 * appropriate offset for the first dynamic pointer within the
2437 * notice reference by pointing to the first memory location past
2438 * the CERT_POLICY_QUALIFIER_NOTICE_REFERENCE.
2440 noticeRef =
2441 *(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE *)pvStructInfo;
2442 noticeRef->pszOrganization = (LPSTR)((LPBYTE)noticeRef +
2443 sizeof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE));
2444 ret = CRYPT_AsnDecodeSequence(items,
2445 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2446 NULL, noticeRef, &bytesNeeded, pcbDecoded,
2447 noticeRef->pszOrganization);
2450 TRACE("returning %d\n", ret);
2451 return ret;
2454 static BOOL CRYPT_AsnDecodeUnicodeString(const BYTE *pbEncoded,
2455 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2456 DWORD *pcbDecoded)
2458 BOOL ret = TRUE;
2459 DWORD dataLen;
2461 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2463 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2464 DWORD bytesNeeded = sizeof(LPWSTR);
2466 switch (pbEncoded[0])
2468 case ASN_NUMERICSTRING:
2469 if (dataLen)
2470 bytesNeeded += (dataLen + 1) * 2;
2471 break;
2472 case ASN_PRINTABLESTRING:
2473 if (dataLen)
2474 bytesNeeded += (dataLen + 1) * 2;
2475 break;
2476 case ASN_IA5STRING:
2477 if (dataLen)
2478 bytesNeeded += (dataLen + 1) * 2;
2479 break;
2480 case ASN_T61STRING:
2481 if (dataLen)
2482 bytesNeeded += (dataLen + 1) * 2;
2483 break;
2484 case ASN_VIDEOTEXSTRING:
2485 if (dataLen)
2486 bytesNeeded += (dataLen + 1) * 2;
2487 break;
2488 case ASN_GRAPHICSTRING:
2489 if (dataLen)
2490 bytesNeeded += (dataLen + 1) * 2;
2491 break;
2492 case ASN_VISIBLESTRING:
2493 if (dataLen)
2494 bytesNeeded += (dataLen + 1) * 2;
2495 break;
2496 case ASN_GENERALSTRING:
2497 if (dataLen)
2498 bytesNeeded += (dataLen + 1) * 2;
2499 break;
2500 case ASN_UNIVERSALSTRING:
2501 if (dataLen)
2502 bytesNeeded += dataLen / 2 + sizeof(WCHAR);
2503 break;
2504 case ASN_BMPSTRING:
2505 if (dataLen)
2506 bytesNeeded += dataLen + sizeof(WCHAR);
2507 break;
2508 case ASN_UTF8STRING:
2509 if (dataLen)
2510 bytesNeeded += (MultiByteToWideChar(CP_UTF8, 0,
2511 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) + 1) * 2;
2512 break;
2513 default:
2514 SetLastError(CRYPT_E_ASN1_BADTAG);
2515 return FALSE;
2518 if (pcbDecoded)
2519 *pcbDecoded = 1 + lenBytes + dataLen;
2520 if (!pvStructInfo)
2521 *pcbStructInfo = bytesNeeded;
2522 else if (*pcbStructInfo < bytesNeeded)
2524 *pcbStructInfo = bytesNeeded;
2525 SetLastError(ERROR_MORE_DATA);
2526 ret = FALSE;
2528 else
2530 LPWSTR *pStr = pvStructInfo;
2532 *pcbStructInfo = bytesNeeded;
2533 if (dataLen)
2535 DWORD i;
2536 LPWSTR str = *(LPWSTR *)pStr;
2538 assert(str);
2539 switch (pbEncoded[0])
2541 case ASN_NUMERICSTRING:
2542 case ASN_PRINTABLESTRING:
2543 case ASN_IA5STRING:
2544 case ASN_T61STRING:
2545 case ASN_VIDEOTEXSTRING:
2546 case ASN_GRAPHICSTRING:
2547 case ASN_VISIBLESTRING:
2548 case ASN_GENERALSTRING:
2549 for (i = 0; i < dataLen; i++)
2550 str[i] = pbEncoded[1 + lenBytes + i];
2551 str[i] = 0;
2552 break;
2553 case ASN_UNIVERSALSTRING:
2554 for (i = 0; i < dataLen / 4; i++)
2555 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
2556 | pbEncoded[1 + lenBytes + 2 * i + 3];
2557 str[i] = 0;
2558 break;
2559 case ASN_BMPSTRING:
2560 for (i = 0; i < dataLen / 2; i++)
2561 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
2562 pbEncoded[1 + lenBytes + 2 * i + 1];
2563 str[i] = 0;
2564 break;
2565 case ASN_UTF8STRING:
2567 int len = MultiByteToWideChar(CP_UTF8, 0,
2568 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
2569 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
2570 str[len] = 0;
2571 break;
2575 else
2576 *pStr = NULL;
2579 return ret;
2582 static BOOL CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(
2583 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
2584 DWORD *pcbStructInfo, DWORD *pcbDecoded)
2586 BOOL ret;
2587 struct AsnDecodeSequenceItem items[] = {
2588 { ASN_SEQUENCE, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE,
2589 pNoticeReference), CRYPT_AsnDecodeNoticeReference,
2590 sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE), TRUE, TRUE,
2591 offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pNoticeReference), 0 },
2592 { 0, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pszDisplayText),
2593 CRYPT_AsnDecodeUnicodeString, sizeof(LPWSTR), TRUE, TRUE,
2594 offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pszDisplayText), 0 },
2596 PCERT_POLICY_QUALIFIER_USER_NOTICE notice = pvStructInfo;
2598 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2599 pvStructInfo, *pcbStructInfo);
2601 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2602 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2603 pcbDecoded, notice ? notice->pNoticeReference : NULL);
2604 TRACE("returning %d\n", ret);
2605 return ret;
2608 static BOOL WINAPI CRYPT_AsnDecodePolicyQualifierUserNotice(
2609 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2610 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2611 void *pvStructInfo, DWORD *pcbStructInfo)
2613 BOOL ret = FALSE;
2615 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2616 pDecodePara, pvStructInfo, *pcbStructInfo);
2618 __TRY
2620 DWORD bytesNeeded;
2622 ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(pbEncoded,
2623 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2624 NULL);
2625 if (ret)
2627 if (!pvStructInfo)
2628 *pcbStructInfo = bytesNeeded;
2629 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2630 pvStructInfo, pcbStructInfo, bytesNeeded)))
2632 PCERT_POLICY_QUALIFIER_USER_NOTICE notice;
2634 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2635 pvStructInfo = *(BYTE **)pvStructInfo;
2636 notice = pvStructInfo;
2637 notice->pNoticeReference =
2638 (PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE)
2639 ((BYTE *)pvStructInfo +
2640 sizeof(CERT_POLICY_QUALIFIER_USER_NOTICE));
2641 ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(
2642 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
2643 pvStructInfo, &bytesNeeded, NULL);
2647 __EXCEPT_PAGE_FAULT
2649 SetLastError(STATUS_ACCESS_VIOLATION);
2651 __ENDTRY
2652 TRACE("returning %d\n", ret);
2653 return ret;
2656 static BOOL CRYPT_AsnDecodePKCSAttributeValue(const BYTE *pbEncoded,
2657 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2658 DWORD *pcbDecoded)
2660 BOOL ret;
2661 struct AsnArrayDescriptor arrayDesc = { 0,
2662 offsetof(CRYPT_ATTRIBUTE, cValue), offsetof(CRYPT_ATTRIBUTE, rgValue),
2663 FINALMEMBERSIZE(CRYPT_ATTRIBUTE, cValue),
2664 CRYPT_AsnDecodeCopyBytes,
2665 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
2667 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2668 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
2670 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2671 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2672 return ret;
2675 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
2676 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2677 DWORD *pcbDecoded)
2679 BOOL ret;
2680 struct AsnDecodeSequenceItem items[] = {
2681 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
2682 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2683 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
2684 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
2685 CRYPT_AsnDecodePKCSAttributeValue,
2686 FINALMEMBERSIZE(CRYPT_ATTRIBUTE, cValue), FALSE,
2687 TRUE, offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
2689 PCRYPT_ATTRIBUTE attr = pvStructInfo;
2691 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2692 pvStructInfo, *pcbStructInfo);
2694 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2695 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2696 pcbDecoded, attr ? attr->pszObjId : NULL);
2697 TRACE("returning %d\n", ret);
2698 return ret;
2701 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
2702 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2703 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2705 BOOL ret = FALSE;
2707 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2708 pDecodePara, pvStructInfo, *pcbStructInfo);
2710 __TRY
2712 DWORD bytesNeeded;
2714 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2715 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
2716 if (ret)
2718 if (!pvStructInfo)
2719 *pcbStructInfo = bytesNeeded;
2720 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2721 pvStructInfo, pcbStructInfo, bytesNeeded)))
2723 PCRYPT_ATTRIBUTE attr;
2725 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2726 pvStructInfo = *(BYTE **)pvStructInfo;
2727 attr = pvStructInfo;
2728 attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
2729 sizeof(CRYPT_ATTRIBUTE));
2730 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2731 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
2732 NULL);
2736 __EXCEPT_PAGE_FAULT
2738 SetLastError(STATUS_ACCESS_VIOLATION);
2740 __ENDTRY
2741 TRACE("returning %d\n", ret);
2742 return ret;
2745 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
2746 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2747 DWORD *pcbDecoded)
2749 struct AsnArrayDescriptor arrayDesc = { 0,
2750 offsetof(CRYPT_ATTRIBUTES, cAttr), offsetof(CRYPT_ATTRIBUTES, rgAttr),
2751 sizeof(CRYPT_ATTRIBUTES),
2752 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2753 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2754 BOOL ret;
2756 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2757 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2758 return ret;
2761 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
2762 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2763 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2765 BOOL ret = FALSE;
2767 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2768 pDecodePara, pvStructInfo, *pcbStructInfo);
2770 __TRY
2772 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
2773 offsetof(CRYPT_ATTRIBUTES, cAttr), offsetof(CRYPT_ATTRIBUTES, rgAttr),
2774 sizeof(CRYPT_ATTRIBUTES),
2775 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE),
2776 TRUE, offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2778 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2779 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2781 __EXCEPT_PAGE_FAULT
2783 SetLastError(STATUS_ACCESS_VIOLATION);
2785 __ENDTRY
2786 TRACE("returning %d\n", ret);
2787 return ret;
2790 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
2791 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2793 CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
2794 BOOL ret = TRUE;
2795 struct AsnDecodeSequenceItem items[] = {
2796 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
2797 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2798 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
2799 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
2800 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2801 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
2804 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2805 pvStructInfo, *pcbStructInfo, pcbDecoded);
2807 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2808 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2809 pcbDecoded, algo ? algo->pszObjId : NULL);
2810 if (ret && pvStructInfo)
2812 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
2813 debugstr_a(algo->pszObjId));
2815 return ret;
2818 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
2819 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2820 DWORD *pcbDecoded)
2822 BOOL ret = TRUE;
2823 struct AsnDecodeSequenceItem items[] = {
2824 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
2825 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2826 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
2827 Algorithm.pszObjId) },
2828 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
2829 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2830 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
2832 PCERT_PUBLIC_KEY_INFO info = pvStructInfo;
2834 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2835 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2836 pcbDecoded, info ? info->Algorithm.Parameters.pbData : NULL);
2837 return ret;
2840 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2841 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2842 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2844 BOOL ret = TRUE;
2846 __TRY
2848 DWORD bytesNeeded;
2850 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2851 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2853 if (!pvStructInfo)
2854 *pcbStructInfo = bytesNeeded;
2855 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2856 pvStructInfo, pcbStructInfo, bytesNeeded)))
2858 PCERT_PUBLIC_KEY_INFO info;
2860 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2861 pvStructInfo = *(BYTE **)pvStructInfo;
2862 info = pvStructInfo;
2863 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2864 sizeof(CERT_PUBLIC_KEY_INFO);
2865 ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2866 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2867 &bytesNeeded, NULL);
2871 __EXCEPT_PAGE_FAULT
2873 SetLastError(STATUS_ACCESS_VIOLATION);
2874 ret = FALSE;
2876 __ENDTRY
2877 return ret;
2880 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
2881 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2883 BOOL ret;
2885 if (cbEncoded < 3)
2887 SetLastError(CRYPT_E_ASN1_CORRUPT);
2888 return FALSE;
2890 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2892 SetLastError(CRYPT_E_ASN1_CORRUPT);
2893 return FALSE;
2895 if (pbEncoded[1] > 1)
2897 SetLastError(CRYPT_E_ASN1_CORRUPT);
2898 return FALSE;
2900 if (pcbDecoded)
2901 *pcbDecoded = 3;
2902 if (!pvStructInfo)
2904 *pcbStructInfo = sizeof(BOOL);
2905 ret = TRUE;
2907 else if (*pcbStructInfo < sizeof(BOOL))
2909 *pcbStructInfo = sizeof(BOOL);
2910 SetLastError(ERROR_MORE_DATA);
2911 ret = FALSE;
2913 else
2915 *pcbStructInfo = sizeof(BOOL);
2916 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2917 ret = TRUE;
2919 TRACE("returning %d (%08x)\n", ret, GetLastError());
2920 return ret;
2923 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2924 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2926 PCERT_ALT_NAME_ENTRY entry = pvStructInfo;
2927 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2928 BOOL ret;
2930 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2931 pvStructInfo, *pcbStructInfo);
2933 if (cbEncoded < 2)
2935 SetLastError(CRYPT_E_ASN1_CORRUPT);
2936 return FALSE;
2938 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2939 if (1 + lenBytes > cbEncoded)
2941 SetLastError(CRYPT_E_ASN1_CORRUPT);
2942 return FALSE;
2944 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2946 switch (pbEncoded[0] & ASN_TYPE_MASK)
2948 case 1: /* rfc822Name */
2949 case 2: /* dNSName */
2950 case 6: /* uniformResourceIdentifier */
2951 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
2952 break;
2953 case 4: /* directoryName */
2954 case 7: /* iPAddress */
2955 bytesNeeded += dataLen;
2956 break;
2957 case 8: /* registeredID */
2958 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
2959 &dataLen, NULL);
2960 if (ret)
2962 /* FIXME: ugly, shouldn't need to know internals of OID decode
2963 * function to use it.
2965 bytesNeeded += dataLen - sizeof(LPSTR);
2967 break;
2968 case 0: /* otherName */
2969 FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
2970 SetLastError(CRYPT_E_ASN1_BADTAG);
2971 ret = FALSE;
2972 break;
2973 case 3: /* x400Address, unimplemented */
2974 case 5: /* ediPartyName, unimplemented */
2975 TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
2976 SetLastError(CRYPT_E_ASN1_BADTAG);
2977 ret = FALSE;
2978 break;
2979 default:
2980 TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
2981 SetLastError(CRYPT_E_ASN1_CORRUPT);
2982 ret = FALSE;
2984 if (ret)
2986 if (pcbDecoded)
2987 *pcbDecoded = 1 + lenBytes + dataLen;
2988 if (!entry)
2989 *pcbStructInfo = bytesNeeded;
2990 else if (*pcbStructInfo < bytesNeeded)
2992 *pcbStructInfo = bytesNeeded;
2993 SetLastError(ERROR_MORE_DATA);
2994 ret = FALSE;
2996 else
2998 *pcbStructInfo = bytesNeeded;
2999 /* MS used values one greater than the asn1 ones.. sigh */
3000 entry->dwAltNameChoice = (pbEncoded[0] & ASN_TYPE_MASK) + 1;
3001 switch (pbEncoded[0] & ASN_TYPE_MASK)
3003 case 1: /* rfc822Name */
3004 case 2: /* dNSName */
3005 case 6: /* uniformResourceIdentifier */
3007 DWORD i;
3009 for (i = 0; i < dataLen; i++)
3010 entry->u.pwszURL[i] =
3011 (WCHAR)pbEncoded[1 + lenBytes + i];
3012 entry->u.pwszURL[i] = 0;
3013 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
3014 debugstr_w(entry->u.pwszURL));
3015 break;
3017 case 4: /* directoryName */
3018 /* The data are memory-equivalent with the IPAddress case,
3019 * fall-through
3021 case 7: /* iPAddress */
3022 /* The next data pointer is in the pwszURL spot, that is,
3023 * the first 4 bytes. Need to move it to the next spot.
3025 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
3026 entry->u.IPAddress.cbData = dataLen;
3027 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
3028 dataLen);
3029 break;
3030 case 8: /* registeredID */
3031 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
3032 &entry->u.pszRegisteredID, &dataLen, NULL);
3033 break;
3038 return ret;
3041 static BOOL CRYPT_AsnDecodeAltNameInternal(const BYTE *pbEncoded,
3042 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3043 DWORD *pcbDecoded)
3045 BOOL ret;
3046 struct AsnArrayDescriptor arrayDesc = { 0,
3047 offsetof(CERT_ALT_NAME_INFO, cAltEntry),
3048 offsetof(CERT_ALT_NAME_INFO, rgAltEntry),
3049 sizeof(CERT_ALT_NAME_INFO),
3050 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3051 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3053 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3054 pvStructInfo, *pcbStructInfo, pcbDecoded);
3056 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3057 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
3058 return ret;
3061 /* Like CRYPT_AsnDecodeIntegerInternal, but swaps the bytes */
3062 static BOOL CRYPT_AsnDecodeIntegerSwapBytes(const BYTE *pbEncoded,
3063 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3064 DWORD *pcbDecoded)
3066 BOOL ret;
3068 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
3069 pvStructInfo, *pcbStructInfo, pcbDecoded);
3071 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
3072 * place.
3074 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
3075 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
3076 pcbDecoded);
3077 if (ret && pvStructInfo)
3079 CRYPT_DATA_BLOB *blob = pvStructInfo;
3081 if (blob->cbData)
3083 DWORD i;
3084 BYTE temp;
3086 for (i = 0; i < blob->cbData / 2; i++)
3088 temp = blob->pbData[i];
3089 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
3090 blob->pbData[blob->cbData - i - 1] = temp;
3094 TRACE("returning %d (%08x)\n", ret, GetLastError());
3095 return ret;
3098 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
3099 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3100 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3102 BOOL ret;
3104 __TRY
3106 struct AsnDecodeSequenceItem items[] = {
3107 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
3108 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
3109 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
3110 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
3111 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
3112 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
3113 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
3114 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
3115 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
3116 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
3117 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
3120 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3121 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3122 pcbStructInfo, NULL, NULL);
3124 __EXCEPT_PAGE_FAULT
3126 SetLastError(STATUS_ACCESS_VIOLATION);
3127 ret = FALSE;
3129 __ENDTRY
3130 return ret;
3133 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
3134 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3135 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3137 BOOL ret;
3139 __TRY
3141 struct AsnDecodeSequenceItem items[] = {
3142 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
3143 CRYPT_AsnDecodeIntegerSwapBytes, sizeof(CRYPT_DATA_BLOB),
3144 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
3145 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
3146 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
3147 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
3148 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3149 AuthorityCertIssuer.rgAltEntry), 0 },
3150 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3151 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
3152 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
3153 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3154 AuthorityCertSerialNumber.pbData), 0 },
3157 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3158 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3159 pcbStructInfo, NULL, NULL);
3161 __EXCEPT_PAGE_FAULT
3163 SetLastError(STATUS_ACCESS_VIOLATION);
3164 ret = FALSE;
3166 __ENDTRY
3167 return ret;
3170 static BOOL CRYPT_AsnDecodeAccessDescription(const BYTE *pbEncoded,
3171 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3172 DWORD *pcbDecoded)
3174 struct AsnDecodeSequenceItem items[] = {
3175 { 0, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod),
3176 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
3177 offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod), 0 },
3178 { 0, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation),
3179 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), FALSE,
3180 TRUE, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation.u.pwszURL), 0 },
3182 CERT_ACCESS_DESCRIPTION *descr = pvStructInfo;
3184 return CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3185 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3186 pcbDecoded, descr ? descr->pszAccessMethod : NULL);
3189 static BOOL WINAPI CRYPT_AsnDecodeAuthorityInfoAccess(DWORD dwCertEncodingType,
3190 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3191 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3193 BOOL ret;
3195 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3196 pDecodePara, pvStructInfo, *pcbStructInfo);
3198 __TRY
3200 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3201 offsetof(CERT_AUTHORITY_INFO_ACCESS, cAccDescr),
3202 offsetof(CERT_AUTHORITY_INFO_ACCESS, rgAccDescr),
3203 sizeof(CERT_AUTHORITY_INFO_ACCESS),
3204 CRYPT_AsnDecodeAccessDescription, sizeof(CERT_ACCESS_DESCRIPTION),
3205 TRUE, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod) };
3207 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3208 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3210 __EXCEPT_PAGE_FAULT
3212 SetLastError(STATUS_ACCESS_VIOLATION);
3213 ret = FALSE;
3215 __ENDTRY
3216 return ret;
3219 static BOOL CRYPT_AsnDecodePKCSContent(const BYTE *pbEncoded, DWORD cbEncoded,
3220 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3222 BOOL ret;
3223 DWORD dataLen;
3225 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3226 pvStructInfo, *pcbStructInfo, pcbDecoded);
3228 /* The caller has already checked the tag, no need to check it again.
3229 * Check the outer length is valid:
3231 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
3233 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3234 DWORD innerLen;
3236 pbEncoded += 1 + lenBytes;
3237 cbEncoded -= 1 + lenBytes;
3238 if (dataLen == CMSG_INDEFINITE_LENGTH)
3239 cbEncoded -= 2; /* space for 0 TLV */
3240 /* Check the inner length is valid: */
3241 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &innerLen)))
3243 DWORD decodedLen;
3245 ret = CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags,
3246 pvStructInfo, pcbStructInfo, &decodedLen);
3247 if (dataLen == CMSG_INDEFINITE_LENGTH)
3249 if (*(pbEncoded + decodedLen) != 0 ||
3250 *(pbEncoded + decodedLen + 1) != 0)
3252 TRACE("expected 0 TLV, got {%02x,%02x}\n",
3253 *(pbEncoded + decodedLen),
3254 *(pbEncoded + decodedLen + 1));
3255 SetLastError(CRYPT_E_ASN1_CORRUPT);
3256 ret = FALSE;
3258 else
3259 decodedLen += 2;
3261 if (ret && pcbDecoded)
3263 *pcbDecoded = 1 + lenBytes + decodedLen;
3264 TRACE("decoded %d bytes\n", *pcbDecoded);
3268 return ret;
3271 static BOOL CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE *pbEncoded,
3272 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3273 DWORD *pcbDecoded)
3275 CRYPT_CONTENT_INFO *info = pvStructInfo;
3276 struct AsnDecodeSequenceItem items[] = {
3277 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
3278 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
3279 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
3280 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
3281 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
3282 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
3283 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
3285 BOOL ret;
3287 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3288 pvStructInfo, *pcbStructInfo, pcbDecoded);
3290 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3291 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3292 pcbDecoded, info ? info->pszObjId : NULL);
3293 return ret;
3296 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
3297 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3298 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3300 BOOL ret = FALSE;
3302 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3303 pDecodePara, pvStructInfo, *pcbStructInfo);
3305 __TRY
3307 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, cbEncoded,
3308 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
3309 if (ret && pvStructInfo)
3311 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
3312 pcbStructInfo, *pcbStructInfo);
3313 if (ret)
3315 CRYPT_CONTENT_INFO *info;
3317 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3318 pvStructInfo = *(BYTE **)pvStructInfo;
3319 info = pvStructInfo;
3320 info->pszObjId = (LPSTR)((BYTE *)info +
3321 sizeof(CRYPT_CONTENT_INFO));
3322 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded,
3323 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3324 pcbStructInfo, NULL);
3328 __EXCEPT_PAGE_FAULT
3330 SetLastError(STATUS_ACCESS_VIOLATION);
3332 __ENDTRY
3333 return ret;
3336 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
3337 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3338 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
3340 BOOL ret;
3341 struct AsnDecodeSequenceItem items[] = {
3342 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version),
3343 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3344 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
3345 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3346 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
3347 0 },
3348 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
3349 CRYPT_AsnDecodePKCSContentInfoInternal,
3350 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
3351 ContentInfo.pszObjId), 0 },
3352 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
3353 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
3354 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
3357 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3358 pbEncoded, cbEncoded, dwFlags, pDecodePara, digestedData, pcbDigestedData,
3359 NULL, NULL);
3360 return ret;
3363 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
3364 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3365 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3367 BOOL ret = TRUE;
3369 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3370 pDecodePara, pvStructInfo, *pcbStructInfo);
3372 __TRY
3374 DWORD bytesNeeded;
3376 if ((ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
3377 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3379 if (!pvStructInfo)
3380 *pcbStructInfo = bytesNeeded;
3381 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3382 pvStructInfo, pcbStructInfo, bytesNeeded)))
3384 CERT_ALT_NAME_INFO *name;
3386 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3387 pvStructInfo = *(BYTE **)pvStructInfo;
3388 name = pvStructInfo;
3389 name->rgAltEntry = (PCERT_ALT_NAME_ENTRY)
3390 ((BYTE *)pvStructInfo + sizeof(CERT_ALT_NAME_INFO));
3391 ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
3392 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3393 &bytesNeeded, NULL);
3397 __EXCEPT_PAGE_FAULT
3399 SetLastError(STATUS_ACCESS_VIOLATION);
3400 ret = FALSE;
3402 __ENDTRY
3403 return ret;
3406 struct PATH_LEN_CONSTRAINT
3408 BOOL fPathLenConstraint;
3409 DWORD dwPathLenConstraint;
3412 static BOOL CRYPT_AsnDecodePathLenConstraint(const BYTE *pbEncoded,
3413 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3414 DWORD *pcbDecoded)
3416 BOOL ret = TRUE;
3417 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT), size;
3419 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3420 pvStructInfo, *pcbStructInfo, pcbDecoded);
3422 if (!pvStructInfo)
3424 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, NULL,
3425 &size, pcbDecoded);
3426 *pcbStructInfo = bytesNeeded;
3428 else if (*pcbStructInfo < bytesNeeded)
3430 SetLastError(ERROR_MORE_DATA);
3431 *pcbStructInfo = bytesNeeded;
3432 ret = FALSE;
3434 else
3436 struct PATH_LEN_CONSTRAINT *constraint = pvStructInfo;
3438 *pcbStructInfo = bytesNeeded;
3439 size = sizeof(constraint->dwPathLenConstraint);
3440 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
3441 &constraint->dwPathLenConstraint, &size, pcbDecoded);
3442 if (ret)
3443 constraint->fPathLenConstraint = TRUE;
3444 TRACE("got an int, dwPathLenConstraint is %d\n",
3445 constraint->dwPathLenConstraint);
3447 TRACE("returning %d (%08x)\n", ret, GetLastError());
3448 return ret;
3451 static BOOL CRYPT_AsnDecodeSubtreeConstraints(const BYTE *pbEncoded,
3452 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3453 DWORD *pcbDecoded)
3455 BOOL ret;
3456 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3457 offsetof(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint),
3458 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint),
3459 FINALMEMBERSIZE(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint),
3460 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
3461 offsetof(CERT_NAME_BLOB, pbData) };
3463 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3464 pvStructInfo, *pcbStructInfo, pcbDecoded);
3466 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3467 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
3468 TRACE("Returning %d (%08x)\n", ret, GetLastError());
3469 return ret;
3472 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
3473 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3474 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3476 BOOL ret;
3478 __TRY
3480 struct AsnDecodeSequenceItem items[] = {
3481 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
3482 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
3483 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
3484 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3485 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3486 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3487 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3488 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
3489 FINALMEMBERSIZE(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint),
3490 TRUE, TRUE,
3491 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
3494 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3495 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3496 pcbStructInfo, NULL, NULL);
3498 __EXCEPT_PAGE_FAULT
3500 SetLastError(STATUS_ACCESS_VIOLATION);
3501 ret = FALSE;
3503 __ENDTRY
3504 return ret;
3507 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
3508 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3509 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3511 BOOL ret;
3513 __TRY
3515 struct AsnDecodeSequenceItem items[] = {
3516 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
3517 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
3518 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
3519 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3520 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3523 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3524 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3525 pcbStructInfo, NULL, NULL);
3527 __EXCEPT_PAGE_FAULT
3529 SetLastError(STATUS_ACCESS_VIOLATION);
3530 ret = FALSE;
3532 __ENDTRY
3533 return ret;
3536 static BOOL CRYPT_AsnDecodePolicyQualifier(const BYTE *pbEncoded,
3537 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3538 DWORD *pcbDecoded)
3540 struct AsnDecodeSequenceItem items[] = {
3541 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_QUALIFIER_INFO,
3542 pszPolicyQualifierId), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
3543 FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId),
3544 0 },
3545 { 0, offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier),
3546 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
3547 offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier.pbData), 0 },
3549 BOOL ret;
3550 CERT_POLICY_QUALIFIER_INFO *qualifier = pvStructInfo;
3552 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3553 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3555 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3556 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3557 pcbDecoded, qualifier ? qualifier->pszPolicyQualifierId : NULL);
3558 return ret;
3561 static BOOL CRYPT_AsnDecodePolicyQualifiers(const BYTE *pbEncoded,
3562 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3563 DWORD *pcbDecoded)
3565 BOOL ret;
3566 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3567 offsetof(CERT_POLICY_INFO, cPolicyQualifier),
3568 offsetof(CERT_POLICY_INFO, rgPolicyQualifier),
3569 FINALMEMBERSIZE(CERT_POLICY_INFO, cPolicyQualifier),
3570 CRYPT_AsnDecodePolicyQualifier, sizeof(CERT_POLICY_QUALIFIER_INFO), TRUE,
3571 offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId) };
3573 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3574 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3576 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3577 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
3578 TRACE("Returning %d (%08x)\n", ret, GetLastError());
3579 return ret;
3582 static BOOL CRYPT_AsnDecodeCertPolicy(const BYTE *pbEncoded, DWORD cbEncoded,
3583 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3585 struct AsnDecodeSequenceItem items[] = {
3586 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_INFO, pszPolicyIdentifier),
3587 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
3588 offsetof(CERT_POLICY_INFO, pszPolicyIdentifier), 0 },
3589 { ASN_SEQUENCEOF, offsetof(CERT_POLICY_INFO, cPolicyQualifier),
3590 CRYPT_AsnDecodePolicyQualifiers,
3591 FINALMEMBERSIZE(CERT_POLICY_INFO, cPolicyQualifier), TRUE,
3592 TRUE, offsetof(CERT_POLICY_INFO, rgPolicyQualifier), 0 },
3594 CERT_POLICY_INFO *info = pvStructInfo;
3595 BOOL ret;
3597 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3598 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3600 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3601 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3602 pcbDecoded, info ? info->pszPolicyIdentifier : NULL);
3603 return ret;
3606 static BOOL WINAPI CRYPT_AsnDecodeCertPolicies(DWORD dwCertEncodingType,
3607 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3608 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3610 BOOL ret = FALSE;
3612 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3613 pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3615 __TRY
3617 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3618 offsetof(CERT_POLICIES_INFO, cPolicyInfo),
3619 offsetof(CERT_POLICIES_INFO, rgPolicyInfo),
3620 sizeof(CERT_POLICIES_INFO),
3621 CRYPT_AsnDecodeCertPolicy, sizeof(CERT_POLICY_INFO), TRUE,
3622 offsetof(CERT_POLICY_INFO, pszPolicyIdentifier) };
3624 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3625 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3627 __EXCEPT_PAGE_FAULT
3629 SetLastError(STATUS_ACCESS_VIOLATION);
3631 __ENDTRY
3632 return ret;
3635 #define RSA1_MAGIC 0x31415352
3637 struct DECODED_RSA_PUB_KEY
3639 DWORD pubexp;
3640 CRYPT_INTEGER_BLOB modulus;
3643 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
3644 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3645 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3647 BOOL ret;
3649 __TRY
3651 struct AsnDecodeSequenceItem items[] = {
3652 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
3653 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3654 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
3655 0 },
3656 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
3657 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3659 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
3660 DWORD size = 0;
3662 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3663 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
3664 &size, NULL, NULL);
3665 if (ret)
3667 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
3668 decodedKey->modulus.cbData;
3670 if (!pvStructInfo)
3672 *pcbStructInfo = bytesNeeded;
3673 ret = TRUE;
3675 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3676 pvStructInfo, pcbStructInfo, bytesNeeded)))
3678 BLOBHEADER *hdr;
3679 RSAPUBKEY *rsaPubKey;
3681 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3682 pvStructInfo = *(BYTE **)pvStructInfo;
3683 hdr = pvStructInfo;
3684 hdr->bType = PUBLICKEYBLOB;
3685 hdr->bVersion = CUR_BLOB_VERSION;
3686 hdr->reserved = 0;
3687 hdr->aiKeyAlg = CALG_RSA_KEYX;
3688 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
3689 sizeof(BLOBHEADER));
3690 rsaPubKey->magic = RSA1_MAGIC;
3691 rsaPubKey->pubexp = decodedKey->pubexp;
3692 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
3693 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
3694 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
3695 decodedKey->modulus.cbData);
3697 LocalFree(decodedKey);
3700 __EXCEPT_PAGE_FAULT
3702 SetLastError(STATUS_ACCESS_VIOLATION);
3703 ret = FALSE;
3705 __ENDTRY
3706 return ret;
3709 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
3710 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3711 DWORD *pcbDecoded)
3713 BOOL ret;
3714 DWORD bytesNeeded, dataLen;
3716 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3717 pvStructInfo, *pcbStructInfo, pcbDecoded);
3719 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3721 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3723 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3724 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
3725 else
3726 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
3727 if (pcbDecoded)
3728 *pcbDecoded = 1 + lenBytes + dataLen;
3729 if (!pvStructInfo)
3730 *pcbStructInfo = bytesNeeded;
3731 else if (*pcbStructInfo < bytesNeeded)
3733 SetLastError(ERROR_MORE_DATA);
3734 *pcbStructInfo = bytesNeeded;
3735 ret = FALSE;
3737 else
3739 CRYPT_DATA_BLOB *blob;
3741 *pcbStructInfo = bytesNeeded;
3742 blob = pvStructInfo;
3743 blob->cbData = dataLen;
3744 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3745 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
3746 else
3748 assert(blob->pbData);
3749 if (blob->cbData)
3750 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
3751 blob->cbData);
3755 return ret;
3758 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
3759 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3760 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3762 BOOL ret;
3764 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3765 pDecodePara, pvStructInfo, *pcbStructInfo);
3767 __TRY
3769 DWORD bytesNeeded;
3771 if (!cbEncoded)
3773 SetLastError(CRYPT_E_ASN1_CORRUPT);
3774 ret = FALSE;
3776 else if (pbEncoded[0] != ASN_OCTETSTRING)
3778 SetLastError(CRYPT_E_ASN1_BADTAG);
3779 ret = FALSE;
3781 else if ((ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
3782 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3784 if (!pvStructInfo)
3785 *pcbStructInfo = bytesNeeded;
3786 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3787 pvStructInfo, pcbStructInfo, bytesNeeded)))
3789 CRYPT_DATA_BLOB *blob;
3791 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3792 pvStructInfo = *(BYTE **)pvStructInfo;
3793 blob = pvStructInfo;
3794 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
3795 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
3796 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3797 &bytesNeeded, NULL);
3801 __EXCEPT_PAGE_FAULT
3803 SetLastError(STATUS_ACCESS_VIOLATION);
3804 ret = FALSE;
3806 __ENDTRY
3807 return ret;
3810 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3811 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3813 BOOL ret;
3814 DWORD bytesNeeded, dataLen;
3815 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3817 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
3818 pvStructInfo, *pcbStructInfo, pcbDecoded);
3820 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3822 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3823 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
3824 else
3825 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
3826 if (pcbDecoded)
3827 *pcbDecoded = 1 + lenBytes + dataLen;
3828 if (!pvStructInfo)
3829 *pcbStructInfo = bytesNeeded;
3830 else if (*pcbStructInfo < bytesNeeded)
3832 *pcbStructInfo = bytesNeeded;
3833 SetLastError(ERROR_MORE_DATA);
3834 ret = FALSE;
3836 else
3838 CRYPT_BIT_BLOB *blob;
3840 *pcbStructInfo = bytesNeeded;
3841 blob = pvStructInfo;
3842 blob->cbData = dataLen - 1;
3843 blob->cUnusedBits = *(pbEncoded + 1 + lenBytes);
3844 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3846 blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes;
3848 else
3850 assert(blob->pbData);
3851 if (blob->cbData)
3853 BYTE mask = 0xff << blob->cUnusedBits;
3855 memcpy(blob->pbData, pbEncoded + 2 + lenBytes,
3856 blob->cbData);
3857 blob->pbData[blob->cbData - 1] &= mask;
3862 return ret;
3865 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
3866 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3867 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3869 BOOL ret;
3871 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
3872 pDecodePara, pvStructInfo, pcbStructInfo);
3874 __TRY
3876 DWORD bytesNeeded;
3878 if (!cbEncoded)
3880 SetLastError(CRYPT_E_ASN1_CORRUPT);
3881 ret = FALSE;
3883 else if (pbEncoded[0] != ASN_BITSTRING)
3885 SetLastError(CRYPT_E_ASN1_BADTAG);
3886 ret = FALSE;
3888 else if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3889 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3891 if (!pvStructInfo)
3892 *pcbStructInfo = bytesNeeded;
3893 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3894 pvStructInfo, pcbStructInfo, bytesNeeded)))
3896 CRYPT_BIT_BLOB *blob;
3898 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3899 pvStructInfo = *(BYTE **)pvStructInfo;
3900 blob = pvStructInfo;
3901 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
3902 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
3903 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3904 &bytesNeeded, NULL);
3908 __EXCEPT_PAGE_FAULT
3910 SetLastError(STATUS_ACCESS_VIOLATION);
3911 ret = FALSE;
3913 __ENDTRY
3914 TRACE("returning %d (%08x)\n", ret, GetLastError());
3915 return ret;
3918 /* Ignores tag. Only allows integers 4 bytes or smaller in size. */
3919 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
3920 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3922 BOOL ret;
3923 DWORD dataLen;
3925 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3927 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3929 if (pcbDecoded)
3930 *pcbDecoded = 1 + lenBytes + dataLen;
3931 if (dataLen > sizeof(int))
3933 SetLastError(CRYPT_E_ASN1_LARGE);
3934 ret = FALSE;
3936 else if (!pvStructInfo)
3937 *pcbStructInfo = sizeof(int);
3938 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int))))
3940 int val, i;
3942 if (dataLen && pbEncoded[1 + lenBytes] & 0x80)
3944 /* initialize to a negative value to sign-extend */
3945 val = -1;
3947 else
3948 val = 0;
3949 for (i = 0; i < dataLen; i++)
3951 val <<= 8;
3952 val |= pbEncoded[1 + lenBytes + i];
3954 memcpy(pvStructInfo, &val, sizeof(int));
3957 return ret;
3960 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
3961 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3962 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3964 BOOL ret;
3966 __TRY
3968 DWORD bytesNeeded;
3970 if (!cbEncoded)
3972 SetLastError(CRYPT_E_ASN1_EOD);
3973 ret = FALSE;
3975 else if (pbEncoded[0] != ASN_INTEGER)
3977 SetLastError(CRYPT_E_ASN1_BADTAG);
3978 ret = FALSE;
3980 else
3981 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3982 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
3983 if (ret)
3985 if (!pvStructInfo)
3986 *pcbStructInfo = bytesNeeded;
3987 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3988 pvStructInfo, pcbStructInfo, bytesNeeded)))
3990 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3991 pvStructInfo = *(BYTE **)pvStructInfo;
3992 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
3993 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3994 &bytesNeeded, NULL);
3998 __EXCEPT_PAGE_FAULT
4000 SetLastError(STATUS_ACCESS_VIOLATION);
4001 ret = FALSE;
4003 __ENDTRY
4004 return ret;
4007 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
4008 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4009 DWORD *pcbDecoded)
4011 BOOL ret;
4012 DWORD bytesNeeded, dataLen;
4014 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4016 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4018 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
4019 if (pcbDecoded)
4020 *pcbDecoded = 1 + lenBytes + dataLen;
4021 if (!pvStructInfo)
4022 *pcbStructInfo = bytesNeeded;
4023 else if (*pcbStructInfo < bytesNeeded)
4025 *pcbStructInfo = bytesNeeded;
4026 SetLastError(ERROR_MORE_DATA);
4027 ret = FALSE;
4029 else
4031 CRYPT_INTEGER_BLOB *blob = pvStructInfo;
4033 *pcbStructInfo = bytesNeeded;
4034 blob->cbData = dataLen;
4035 assert(blob->pbData);
4036 if (blob->cbData)
4038 DWORD i;
4040 for (i = 0; i < blob->cbData; i++)
4042 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
4043 dataLen - i - 1);
4048 return ret;
4051 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
4052 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4053 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4055 BOOL ret;
4057 __TRY
4059 DWORD bytesNeeded;
4061 if (pbEncoded[0] != ASN_INTEGER)
4063 SetLastError(CRYPT_E_ASN1_BADTAG);
4064 ret = FALSE;
4066 else
4067 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
4068 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4069 if (ret)
4071 if (!pvStructInfo)
4072 *pcbStructInfo = bytesNeeded;
4073 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4074 pvStructInfo, pcbStructInfo, bytesNeeded)))
4076 CRYPT_INTEGER_BLOB *blob;
4078 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4079 pvStructInfo = *(BYTE **)pvStructInfo;
4080 blob = pvStructInfo;
4081 blob->pbData = (BYTE *)pvStructInfo +
4082 sizeof(CRYPT_INTEGER_BLOB);
4083 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
4084 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
4085 &bytesNeeded, NULL);
4089 __EXCEPT_PAGE_FAULT
4091 SetLastError(STATUS_ACCESS_VIOLATION);
4092 ret = FALSE;
4094 __ENDTRY
4095 return ret;
4098 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
4099 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4100 DWORD *pcbDecoded)
4102 BOOL ret;
4104 if (pbEncoded[0] == ASN_INTEGER)
4106 DWORD bytesNeeded, dataLen;
4108 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4110 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4112 if (pcbDecoded)
4113 *pcbDecoded = 1 + lenBytes + dataLen;
4114 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
4115 if (!pvStructInfo)
4116 *pcbStructInfo = bytesNeeded;
4117 else if (*pcbStructInfo < bytesNeeded)
4119 *pcbStructInfo = bytesNeeded;
4120 SetLastError(ERROR_MORE_DATA);
4121 ret = FALSE;
4123 else
4125 CRYPT_INTEGER_BLOB *blob = pvStructInfo;
4127 *pcbStructInfo = bytesNeeded;
4128 blob->cbData = dataLen;
4129 assert(blob->pbData);
4130 /* remove leading zero byte if it exists */
4131 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
4133 blob->cbData--;
4134 blob->pbData++;
4136 if (blob->cbData)
4138 DWORD i;
4140 for (i = 0; i < blob->cbData; i++)
4142 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
4143 dataLen - i - 1);
4149 else
4151 SetLastError(CRYPT_E_ASN1_BADTAG);
4152 ret = FALSE;
4154 return ret;
4157 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
4158 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4159 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4161 BOOL ret;
4163 __TRY
4165 DWORD bytesNeeded;
4167 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded,
4168 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4170 if (!pvStructInfo)
4171 *pcbStructInfo = bytesNeeded;
4172 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4173 pvStructInfo, pcbStructInfo, bytesNeeded)))
4175 CRYPT_INTEGER_BLOB *blob;
4177 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4178 pvStructInfo = *(BYTE **)pvStructInfo;
4179 blob = pvStructInfo;
4180 blob->pbData = (BYTE *)pvStructInfo +
4181 sizeof(CRYPT_INTEGER_BLOB);
4182 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded,
4183 cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
4184 &bytesNeeded, NULL);
4188 __EXCEPT_PAGE_FAULT
4190 SetLastError(STATUS_ACCESS_VIOLATION);
4191 ret = FALSE;
4193 __ENDTRY
4194 return ret;
4197 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
4198 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4199 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4201 BOOL ret;
4203 if (!pvStructInfo)
4205 *pcbStructInfo = sizeof(int);
4206 return TRUE;
4208 __TRY
4210 if (pbEncoded[0] == ASN_ENUMERATED)
4212 unsigned int val = 0, i;
4214 if (cbEncoded <= 1)
4216 SetLastError(CRYPT_E_ASN1_EOD);
4217 ret = FALSE;
4219 else if (pbEncoded[1] == 0)
4221 SetLastError(CRYPT_E_ASN1_CORRUPT);
4222 ret = FALSE;
4224 else
4226 /* A little strange looking, but we have to accept a sign byte:
4227 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
4228 * assuming a small length is okay here, it has to be in short
4229 * form.
4231 if (pbEncoded[1] > sizeof(unsigned int) + 1)
4233 SetLastError(CRYPT_E_ASN1_LARGE);
4234 return FALSE;
4236 for (i = 0; i < pbEncoded[1]; i++)
4238 val <<= 8;
4239 val |= pbEncoded[2 + i];
4241 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4242 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
4244 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4245 pvStructInfo = *(BYTE **)pvStructInfo;
4246 memcpy(pvStructInfo, &val, sizeof(unsigned int));
4250 else
4252 SetLastError(CRYPT_E_ASN1_BADTAG);
4253 ret = FALSE;
4256 __EXCEPT_PAGE_FAULT
4258 SetLastError(STATUS_ACCESS_VIOLATION);
4259 ret = FALSE;
4261 __ENDTRY
4262 return ret;
4265 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
4266 * if it fails.
4268 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
4269 do { \
4270 BYTE i; \
4272 (word) = 0; \
4273 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
4275 if (!isdigit(*(pbEncoded))) \
4277 SetLastError(CRYPT_E_ASN1_CORRUPT); \
4278 ret = FALSE; \
4280 else \
4282 (word) *= 10; \
4283 (word) += *(pbEncoded)++ - '0'; \
4286 } while (0)
4288 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
4289 SYSTEMTIME *sysTime)
4291 BOOL ret = TRUE;
4293 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
4295 WORD hours, minutes = 0;
4296 BYTE sign = *pbEncoded++;
4298 len--;
4299 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
4300 if (ret && hours >= 24)
4302 SetLastError(CRYPT_E_ASN1_CORRUPT);
4303 ret = FALSE;
4305 else if (len >= 2)
4307 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
4308 if (ret && minutes >= 60)
4310 SetLastError(CRYPT_E_ASN1_CORRUPT);
4311 ret = FALSE;
4314 if (ret)
4316 if (sign == '+')
4318 sysTime->wHour += hours;
4319 sysTime->wMinute += minutes;
4321 else
4323 if (hours > sysTime->wHour)
4325 sysTime->wDay--;
4326 sysTime->wHour = 24 - (hours - sysTime->wHour);
4328 else
4329 sysTime->wHour -= hours;
4330 if (minutes > sysTime->wMinute)
4332 sysTime->wHour--;
4333 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
4335 else
4336 sysTime->wMinute -= minutes;
4340 return ret;
4343 #define MIN_ENCODED_TIME_LENGTH 10
4345 static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
4346 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4347 DWORD *pcbDecoded)
4349 BOOL ret = FALSE;
4351 if (pbEncoded[0] == ASN_UTCTIME)
4353 if (cbEncoded <= 1)
4354 SetLastError(CRYPT_E_ASN1_EOD);
4355 else if (pbEncoded[1] > 0x7f)
4357 /* long-form date strings really can't be valid */
4358 SetLastError(CRYPT_E_ASN1_CORRUPT);
4360 else
4362 SYSTEMTIME sysTime = { 0 };
4363 BYTE len = pbEncoded[1];
4365 if (len < MIN_ENCODED_TIME_LENGTH)
4366 SetLastError(CRYPT_E_ASN1_CORRUPT);
4367 else
4369 ret = TRUE;
4370 if (pcbDecoded)
4371 *pcbDecoded = 2 + len;
4372 pbEncoded += 2;
4373 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
4374 if (sysTime.wYear >= 50)
4375 sysTime.wYear += 1900;
4376 else
4377 sysTime.wYear += 2000;
4378 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
4379 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
4380 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
4381 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
4382 if (ret && len > 0)
4384 if (len >= 2 && isdigit(*pbEncoded) &&
4385 isdigit(*(pbEncoded + 1)))
4386 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4387 sysTime.wSecond);
4388 else if (isdigit(*pbEncoded))
4389 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
4390 sysTime.wSecond);
4391 if (ret)
4392 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
4393 &sysTime);
4395 if (ret)
4397 if (!pvStructInfo)
4398 *pcbStructInfo = sizeof(FILETIME);
4399 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
4400 sizeof(FILETIME))))
4401 ret = SystemTimeToFileTime(&sysTime, pvStructInfo);
4406 else
4407 SetLastError(CRYPT_E_ASN1_BADTAG);
4408 return ret;
4411 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
4412 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4413 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4415 BOOL ret = FALSE;
4417 __TRY
4419 DWORD bytesNeeded;
4421 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
4422 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4423 if (ret)
4425 if (!pvStructInfo)
4426 *pcbStructInfo = bytesNeeded;
4427 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
4428 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
4430 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4431 pvStructInfo = *(BYTE **)pvStructInfo;
4432 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
4433 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4434 &bytesNeeded, NULL);
4438 __EXCEPT_PAGE_FAULT
4440 SetLastError(STATUS_ACCESS_VIOLATION);
4442 __ENDTRY
4443 return ret;
4446 static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
4447 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4448 DWORD *pcbDecoded)
4450 BOOL ret = FALSE;
4452 if (pbEncoded[0] == ASN_GENERALTIME)
4454 if (cbEncoded <= 1)
4455 SetLastError(CRYPT_E_ASN1_EOD);
4456 else if (pbEncoded[1] > 0x7f)
4458 /* long-form date strings really can't be valid */
4459 SetLastError(CRYPT_E_ASN1_CORRUPT);
4461 else
4463 BYTE len = pbEncoded[1];
4465 if (len < MIN_ENCODED_TIME_LENGTH)
4466 SetLastError(CRYPT_E_ASN1_CORRUPT);
4467 else
4469 SYSTEMTIME sysTime = { 0 };
4471 ret = TRUE;
4472 if (pcbDecoded)
4473 *pcbDecoded = 2 + len;
4474 pbEncoded += 2;
4475 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
4476 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
4477 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
4478 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
4479 if (ret && len > 0)
4481 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4482 sysTime.wMinute);
4483 if (ret && len > 0)
4484 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4485 sysTime.wSecond);
4486 if (ret && len > 0 && (*pbEncoded == '.' ||
4487 *pbEncoded == ','))
4489 BYTE digits;
4491 pbEncoded++;
4492 len--;
4493 /* workaround macro weirdness */
4494 digits = min(len, 3);
4495 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
4496 sysTime.wMilliseconds);
4498 if (ret)
4499 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
4500 &sysTime);
4502 if (ret)
4504 if (!pvStructInfo)
4505 *pcbStructInfo = sizeof(FILETIME);
4506 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
4507 sizeof(FILETIME))))
4508 ret = SystemTimeToFileTime(&sysTime, pvStructInfo);
4513 else
4514 SetLastError(CRYPT_E_ASN1_BADTAG);
4515 return ret;
4518 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
4519 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4520 DWORD *pcbDecoded)
4522 BOOL ret;
4523 InternalDecodeFunc decode = NULL;
4525 if (pbEncoded[0] == ASN_UTCTIME)
4526 decode = CRYPT_AsnDecodeUtcTimeInternal;
4527 else if (pbEncoded[0] == ASN_GENERALTIME)
4528 decode = CRYPT_AsnDecodeGeneralizedTime;
4529 if (decode)
4530 ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
4531 pcbStructInfo, pcbDecoded);
4532 else
4534 SetLastError(CRYPT_E_ASN1_BADTAG);
4535 ret = FALSE;
4537 return ret;
4540 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
4541 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4542 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4544 BOOL ret;
4546 __TRY
4548 DWORD bytesNeeded;
4550 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
4551 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4552 if (ret)
4554 if (!pvStructInfo)
4555 *pcbStructInfo = bytesNeeded;
4556 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4557 pvStructInfo, pcbStructInfo, bytesNeeded)))
4559 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4560 pvStructInfo = *(BYTE **)pvStructInfo;
4561 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
4562 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4563 &bytesNeeded, NULL);
4567 __EXCEPT_PAGE_FAULT
4569 SetLastError(STATUS_ACCESS_VIOLATION);
4570 ret = FALSE;
4572 __ENDTRY
4573 return ret;
4576 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
4577 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4578 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4580 BOOL ret = TRUE;
4582 __TRY
4584 if (pbEncoded[0] == ASN_SEQUENCEOF)
4586 DWORD bytesNeeded, dataLen, remainingLen, cValue;
4588 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4590 BYTE lenBytes;
4591 const BYTE *ptr;
4593 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4594 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
4595 cValue = 0;
4596 ptr = pbEncoded + 1 + lenBytes;
4597 remainingLen = dataLen;
4598 while (ret && remainingLen)
4600 DWORD nextLen;
4602 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
4603 if (ret)
4605 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
4607 remainingLen -= 1 + nextLenBytes + nextLen;
4608 ptr += 1 + nextLenBytes + nextLen;
4609 bytesNeeded += sizeof(CRYPT_DER_BLOB);
4610 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
4611 bytesNeeded += 1 + nextLenBytes + nextLen;
4612 cValue++;
4615 if (ret)
4617 CRYPT_SEQUENCE_OF_ANY *seq;
4618 BYTE *nextPtr;
4619 DWORD i;
4621 if (!pvStructInfo)
4622 *pcbStructInfo = bytesNeeded;
4623 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4624 pvStructInfo, pcbStructInfo, bytesNeeded)))
4626 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4627 pvStructInfo = *(BYTE **)pvStructInfo;
4628 seq = pvStructInfo;
4629 seq->cValue = cValue;
4630 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
4631 sizeof(*seq));
4632 nextPtr = (BYTE *)seq->rgValue +
4633 cValue * sizeof(CRYPT_DER_BLOB);
4634 ptr = pbEncoded + 1 + lenBytes;
4635 remainingLen = dataLen;
4636 i = 0;
4637 while (ret && remainingLen)
4639 DWORD nextLen;
4641 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
4642 if (ret)
4644 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
4646 seq->rgValue[i].cbData = 1 + nextLenBytes +
4647 nextLen;
4648 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4649 seq->rgValue[i].pbData = (BYTE *)ptr;
4650 else
4652 seq->rgValue[i].pbData = nextPtr;
4653 memcpy(nextPtr, ptr, 1 + nextLenBytes +
4654 nextLen);
4655 nextPtr += 1 + nextLenBytes + nextLen;
4657 remainingLen -= 1 + nextLenBytes + nextLen;
4658 ptr += 1 + nextLenBytes + nextLen;
4659 i++;
4666 else
4668 SetLastError(CRYPT_E_ASN1_BADTAG);
4669 ret = FALSE;
4672 __EXCEPT_PAGE_FAULT
4674 SetLastError(STATUS_ACCESS_VIOLATION);
4675 ret = FALSE;
4677 __ENDTRY
4678 return ret;
4681 static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded,
4682 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4683 DWORD *pcbDecoded)
4685 BOOL ret;
4687 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
4689 DWORD bytesNeeded, dataLen;
4691 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4693 struct AsnArrayDescriptor arrayDesc = {
4694 ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
4695 offsetof(CRL_DIST_POINT_NAME, u.FullName.cAltEntry),
4696 offsetof(CRL_DIST_POINT_NAME, u.FullName.rgAltEntry),
4697 FINALMEMBERSIZE(CRL_DIST_POINT_NAME, u),
4698 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
4699 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
4700 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4701 DWORD nameLen;
4703 if (dataLen)
4705 ret = CRYPT_AsnDecodeArray(&arrayDesc,
4706 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
4707 dwFlags, NULL, NULL, &nameLen, NULL);
4708 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen -
4709 FINALMEMBERSIZE(CRL_DIST_POINT_NAME, u);
4711 else
4712 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
4713 if (pcbDecoded)
4714 *pcbDecoded = 1 + lenBytes + dataLen;
4715 if (!pvStructInfo)
4716 *pcbStructInfo = bytesNeeded;
4717 else if (*pcbStructInfo < bytesNeeded)
4719 *pcbStructInfo = bytesNeeded;
4720 SetLastError(ERROR_MORE_DATA);
4721 ret = FALSE;
4723 else
4725 CRL_DIST_POINT_NAME *name = pvStructInfo;
4727 *pcbStructInfo = bytesNeeded;
4728 if (dataLen)
4730 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
4731 ret = CRYPT_AsnDecodeArray(&arrayDesc,
4732 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
4733 dwFlags, NULL, &name->u.FullName.cAltEntry, &nameLen,
4734 NULL);
4736 else
4737 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
4741 else
4743 SetLastError(CRYPT_E_ASN1_BADTAG);
4744 ret = FALSE;
4746 return ret;
4749 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
4750 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4752 struct AsnDecodeSequenceItem items[] = {
4753 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
4754 DistPointName), CRYPT_AsnDecodeDistPointName,
4755 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
4756 DistPointName.u.FullName.rgAltEntry), 0 },
4757 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
4758 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
4759 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
4760 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
4761 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
4762 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
4764 CRL_DIST_POINT *point = pvStructInfo;
4765 BOOL ret;
4767 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4768 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4769 pcbDecoded, point ? point->DistPointName.u.FullName.rgAltEntry : NULL);
4770 return ret;
4773 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
4774 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4775 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4777 BOOL ret;
4779 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4780 pDecodePara, pvStructInfo, *pcbStructInfo);
4782 __TRY
4784 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
4785 offsetof(CRL_DIST_POINTS_INFO, cDistPoint),
4786 offsetof(CRL_DIST_POINTS_INFO, rgDistPoint),
4787 sizeof(CRL_DIST_POINTS_INFO),
4788 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
4789 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
4791 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
4792 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
4794 __EXCEPT_PAGE_FAULT
4796 SetLastError(STATUS_ACCESS_VIOLATION);
4797 ret = FALSE;
4799 __ENDTRY
4800 return ret;
4803 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
4804 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4805 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4807 BOOL ret;
4809 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4810 pDecodePara, pvStructInfo, *pcbStructInfo);
4812 __TRY
4814 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
4815 offsetof(CERT_ENHKEY_USAGE, cUsageIdentifier),
4816 offsetof(CERT_ENHKEY_USAGE, rgpszUsageIdentifier),
4817 sizeof(CERT_ENHKEY_USAGE),
4818 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
4820 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
4821 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
4823 __EXCEPT_PAGE_FAULT
4825 SetLastError(STATUS_ACCESS_VIOLATION);
4826 ret = FALSE;
4828 __ENDTRY
4829 return ret;
4832 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
4833 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4834 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4836 BOOL ret;
4838 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
4839 pDecodePara, pvStructInfo, *pcbStructInfo);
4841 __TRY
4843 struct AsnDecodeSequenceItem items[] = {
4844 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
4845 DistPointName), CRYPT_AsnDecodeDistPointName,
4846 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
4847 offsetof(CRL_ISSUING_DIST_POINT,
4848 DistPointName.u.FullName.rgAltEntry), 0 },
4849 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
4850 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4851 FALSE, 0 },
4852 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
4853 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
4854 FALSE, 0 },
4855 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
4856 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
4857 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
4858 OnlySomeReasonFlags.pbData), 0 },
4859 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
4860 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
4863 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4864 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
4865 pcbStructInfo, NULL, NULL);
4867 __EXCEPT_PAGE_FAULT
4869 SetLastError(STATUS_ACCESS_VIOLATION);
4870 ret = FALSE;
4872 __ENDTRY
4873 return ret;
4876 static BOOL CRYPT_AsnDecodeMaximum(const BYTE *pbEncoded,
4877 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4878 DWORD *pcbDecoded)
4880 BOOL ret;
4881 DWORD max, size = sizeof(max);
4883 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4884 pvStructInfo, *pcbStructInfo, pcbDecoded);
4886 if (!cbEncoded)
4888 SetLastError(CRYPT_E_ASN1_EOD);
4889 return FALSE;
4891 if (pbEncoded[0] != (ASN_CONTEXT | 1))
4893 SetLastError(CRYPT_E_ASN1_BADTAG);
4894 return FALSE;
4896 if ((ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
4897 &max, &size, pcbDecoded)))
4899 DWORD bytesNeeded = FINALMEMBERSIZE(CERT_GENERAL_SUBTREE, fMaximum);
4901 if (!pvStructInfo)
4902 *pcbStructInfo = bytesNeeded;
4903 else if (*pcbStructInfo < bytesNeeded)
4905 *pcbStructInfo = bytesNeeded;
4906 SetLastError(ERROR_MORE_DATA);
4907 ret = FALSE;
4909 else
4911 CERT_GENERAL_SUBTREE *subtree = (CERT_GENERAL_SUBTREE *)
4912 ((BYTE *)pvStructInfo - offsetof(CERT_GENERAL_SUBTREE, fMaximum));
4914 *pcbStructInfo = bytesNeeded;
4915 /* The BOOL is implicit: if the integer is present, then it's
4916 * TRUE.
4918 subtree->fMaximum = TRUE;
4919 subtree->dwMaximum = max;
4922 TRACE("returning %d\n", ret);
4923 return ret;
4926 static BOOL CRYPT_AsnDecodeSubtree(const BYTE *pbEncoded,
4927 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4928 DWORD *pcbDecoded)
4930 BOOL ret;
4931 struct AsnDecodeSequenceItem items[] = {
4932 { 0, offsetof(CERT_GENERAL_SUBTREE, Base),
4933 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE, TRUE,
4934 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL), 0 },
4935 { ASN_CONTEXT | 0, offsetof(CERT_GENERAL_SUBTREE, dwMinimum),
4936 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
4937 { ASN_CONTEXT | 1, offsetof(CERT_GENERAL_SUBTREE, fMaximum),
4938 CRYPT_AsnDecodeMaximum, FINALMEMBERSIZE(CERT_GENERAL_SUBTREE, fMaximum),
4939 TRUE, FALSE, 0, 0 },
4941 CERT_GENERAL_SUBTREE *subtree = pvStructInfo;
4943 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4944 pvStructInfo, *pcbStructInfo, pcbDecoded);
4946 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
4947 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
4948 pcbDecoded, subtree ? subtree->Base.u.pwszURL : NULL);
4949 if (pcbDecoded)
4951 TRACE("%d\n", *pcbDecoded);
4952 if (*pcbDecoded < cbEncoded)
4953 TRACE("%02x %02x\n", *(pbEncoded + *pcbDecoded),
4954 *(pbEncoded + *pcbDecoded + 1));
4956 TRACE("returning %d\n", ret);
4957 return ret;
4960 static BOOL CRYPT_AsnDecodePermittedSubtree(const BYTE *pbEncoded,
4961 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4962 DWORD *pcbDecoded)
4964 BOOL ret = TRUE;
4965 struct AsnArrayDescriptor arrayDesc = { 0,
4966 offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
4967 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree),
4968 MEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree,
4969 cExcludedSubtree),
4970 CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
4971 offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
4973 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4974 pvStructInfo, *pcbStructInfo, pcbDecoded);
4976 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
4977 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
4978 return ret;
4981 static BOOL CRYPT_AsnDecodeExcludedSubtree(const BYTE *pbEncoded,
4982 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4983 DWORD *pcbDecoded)
4985 BOOL ret = TRUE;
4986 struct AsnArrayDescriptor arrayDesc = { 0,
4987 offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
4988 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree),
4989 FINALMEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
4990 CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
4991 offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
4993 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
4994 pvStructInfo, *pcbStructInfo, pcbDecoded);
4996 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
4997 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
4998 return ret;
5001 static BOOL WINAPI CRYPT_AsnDecodeNameConstraints(DWORD dwCertEncodingType,
5002 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5003 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5005 BOOL ret = FALSE;
5007 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5008 pDecodePara, pvStructInfo, *pcbStructInfo);
5010 __TRY
5012 struct AsnDecodeSequenceItem items[] = {
5013 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
5014 offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
5015 CRYPT_AsnDecodePermittedSubtree,
5016 MEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree,
5017 cExcludedSubtree), TRUE, TRUE,
5018 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree), 0 },
5019 { ASN_CONTEXT | ASN_CONSTRUCTOR | 1,
5020 offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5021 CRYPT_AsnDecodeExcludedSubtree,
5022 FINALMEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5023 TRUE, TRUE,
5024 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree), 0 },
5027 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5028 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
5029 pcbStructInfo, NULL, NULL);
5031 __EXCEPT_PAGE_FAULT
5033 SetLastError(STATUS_ACCESS_VIOLATION);
5035 __ENDTRY
5036 return ret;
5039 static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded,
5040 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5041 DWORD *pcbDecoded)
5043 BOOL ret;
5044 struct AsnDecodeSequenceItem items[] = {
5045 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
5046 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
5047 Issuer.pbData) },
5048 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
5049 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
5050 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
5052 CERT_ISSUER_SERIAL_NUMBER *issuerSerial = pvStructInfo;
5054 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5055 pvStructInfo, *pcbStructInfo, pcbDecoded);
5057 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5058 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5059 pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL);
5060 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
5062 SetLastError(CRYPT_E_ASN1_CORRUPT);
5063 ret = FALSE;
5065 TRACE("returning %d\n", ret);
5066 return ret;
5069 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
5070 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5071 DWORD *pcbDecoded)
5073 CMSG_SIGNER_INFO *info = pvStructInfo;
5074 struct AsnDecodeSequenceItem items[] = {
5075 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
5076 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5077 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
5078 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
5079 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
5080 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
5081 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5082 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
5083 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5084 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
5085 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5086 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
5087 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
5088 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5089 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
5090 HashEncryptionAlgorithm.pszObjId), 0 },
5091 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
5092 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
5093 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
5094 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5095 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
5096 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5097 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
5099 BOOL ret;
5101 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5102 pvStructInfo, *pcbStructInfo);
5104 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5105 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5106 pcbDecoded, info ? info->Issuer.pbData : NULL);
5107 return ret;
5110 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
5111 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5112 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5114 BOOL ret = FALSE;
5116 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5117 pDecodePara, pvStructInfo, *pcbStructInfo);
5119 __TRY
5121 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
5122 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
5123 if (ret && pvStructInfo)
5125 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
5126 pcbStructInfo, *pcbStructInfo);
5127 if (ret)
5129 CMSG_SIGNER_INFO *info;
5131 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5132 pvStructInfo = *(BYTE **)pvStructInfo;
5133 info = pvStructInfo;
5134 info->Issuer.pbData = ((BYTE *)info +
5135 sizeof(CMSG_SIGNER_INFO));
5136 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
5137 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5138 pcbStructInfo, NULL);
5142 __EXCEPT_PAGE_FAULT
5144 SetLastError(STATUS_ACCESS_VIOLATION);
5146 __ENDTRY
5147 TRACE("returning %d\n", ret);
5148 return ret;
5151 static BOOL CRYPT_AsnDecodeCMSCertEncoded(const BYTE *pbEncoded,
5152 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5153 DWORD *pcbDecoded)
5155 BOOL ret;
5156 struct AsnArrayDescriptor arrayDesc = { 0,
5157 offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
5158 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded),
5159 MEMBERSIZE(CRYPT_SIGNED_INFO, cCertEncoded, cCrlEncoded),
5160 CRYPT_AsnDecodeCopyBytes,
5161 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
5163 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5164 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
5166 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5167 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5168 return ret;
5171 static BOOL CRYPT_AsnDecodeCMSCrlEncoded(const BYTE *pbEncoded,
5172 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5173 DWORD *pcbDecoded)
5175 BOOL ret;
5176 struct AsnArrayDescriptor arrayDesc = { 0,
5177 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded),
5178 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded),
5179 MEMBERSIZE(CRYPT_SIGNED_INFO, cCrlEncoded, content),
5180 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_DER_BLOB),
5181 TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
5183 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5184 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
5186 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5187 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5188 return ret;
5191 static BOOL CRYPT_AsnDecodeCMSSignerId(const BYTE *pbEncoded,
5192 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5193 DWORD *pcbDecoded)
5195 CERT_ID *id = pvStructInfo;
5196 BOOL ret = FALSE;
5198 if (*pbEncoded == ASN_SEQUENCEOF)
5200 ret = CRYPT_AsnDecodeIssuerSerialNumber(pbEncoded, cbEncoded, dwFlags,
5201 id ? &id->u.IssuerSerialNumber : NULL, pcbStructInfo, pcbDecoded);
5202 if (ret)
5204 if (id)
5205 id->dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
5206 if (*pcbStructInfo > sizeof(CERT_ISSUER_SERIAL_NUMBER))
5207 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
5208 sizeof(CERT_ISSUER_SERIAL_NUMBER);
5209 else
5210 *pcbStructInfo = sizeof(CERT_ID);
5213 else if (*pbEncoded == (ASN_CONTEXT | 0))
5215 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded, dwFlags,
5216 id ? &id->u.KeyId : NULL, pcbStructInfo, pcbDecoded);
5217 if (ret)
5219 if (id)
5220 id->dwIdChoice = CERT_ID_KEY_IDENTIFIER;
5221 if (*pcbStructInfo > sizeof(CRYPT_DATA_BLOB))
5222 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
5223 sizeof(CRYPT_DATA_BLOB);
5224 else
5225 *pcbStructInfo = sizeof(CERT_ID);
5228 else
5229 SetLastError(CRYPT_E_ASN1_BADTAG);
5230 return ret;
5233 static BOOL CRYPT_AsnDecodeCMSSignerInfoInternal(const BYTE *pbEncoded,
5234 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5235 DWORD *pcbDecoded)
5237 CMSG_CMS_SIGNER_INFO *info = pvStructInfo;
5238 struct AsnDecodeSequenceItem items[] = {
5239 { ASN_INTEGER, offsetof(CMSG_CMS_SIGNER_INFO, dwVersion),
5240 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5241 { 0, offsetof(CMSG_CMS_SIGNER_INFO, SignerId),
5242 CRYPT_AsnDecodeCMSSignerId, sizeof(CERT_ID), FALSE, TRUE,
5243 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData), 0 },
5244 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm),
5245 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5246 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
5247 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5248 offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs),
5249 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5250 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
5251 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashEncryptionAlgorithm),
5252 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5253 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO,
5254 HashEncryptionAlgorithm.pszObjId), 0 },
5255 { ASN_OCTETSTRING, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash),
5256 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
5257 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash.pbData), 0 },
5258 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5259 offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs),
5260 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5261 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
5263 BOOL ret;
5265 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5266 pvStructInfo, *pcbStructInfo);
5268 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5269 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5270 pcbDecoded, info ? info->SignerId.u.KeyId.pbData : NULL);
5271 return ret;
5274 static BOOL WINAPI CRYPT_AsnDecodeCMSSignerInfo(DWORD dwCertEncodingType,
5275 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5276 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5278 BOOL ret = FALSE;
5280 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5281 pDecodePara, pvStructInfo, *pcbStructInfo);
5283 __TRY
5285 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded, cbEncoded,
5286 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
5287 if (ret && pvStructInfo)
5289 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
5290 pcbStructInfo, *pcbStructInfo);
5291 if (ret)
5293 CMSG_CMS_SIGNER_INFO *info;
5295 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5296 pvStructInfo = *(BYTE **)pvStructInfo;
5297 info = pvStructInfo;
5298 info->SignerId.u.KeyId.pbData = ((BYTE *)info +
5299 sizeof(CMSG_CMS_SIGNER_INFO));
5300 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded,
5301 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5302 pcbStructInfo, NULL);
5306 __EXCEPT_PAGE_FAULT
5308 SetLastError(STATUS_ACCESS_VIOLATION);
5310 __ENDTRY
5311 TRACE("returning %d\n", ret);
5312 return ret;
5315 static BOOL CRYPT_DecodeSignerArray(const BYTE *pbEncoded, DWORD cbEncoded,
5316 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5318 BOOL ret;
5319 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
5320 offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
5321 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo),
5322 FINALMEMBERSIZE(CRYPT_SIGNED_INFO, cSignerInfo),
5323 CRYPT_AsnDecodeCMSSignerInfoInternal, sizeof(CMSG_CMS_SIGNER_INFO), TRUE,
5324 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData) };
5326 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5327 pvStructInfo, *pcbStructInfo, pcbDecoded);
5329 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5330 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5331 return ret;
5334 BOOL CRYPT_AsnDecodeCMSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
5335 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
5336 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
5338 BOOL ret = FALSE;
5339 struct AsnDecodeSequenceItem items[] = {
5340 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version),
5341 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5342 /* Placeholder for the hash algorithms - redundant with those in the
5343 * signers, so just ignore them.
5345 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
5346 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
5347 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
5348 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
5349 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5350 offsetof(CRYPT_SIGNED_INFO, cCertEncoded), CRYPT_AsnDecodeCMSCertEncoded,
5351 MEMBERSIZE(CRYPT_SIGNED_INFO, cCertEncoded, cCrlEncoded), TRUE, TRUE,
5352 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
5353 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5354 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_AsnDecodeCMSCrlEncoded,
5355 MEMBERSIZE(CRYPT_SIGNED_INFO, cCrlEncoded, content), TRUE, TRUE,
5356 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
5357 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
5358 CRYPT_DecodeSignerArray,
5359 FINALMEMBERSIZE(CRYPT_SIGNED_INFO, cSignerInfo), TRUE, TRUE,
5360 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
5363 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5364 pDecodePara, signedInfo, *pcbSignedInfo);
5366 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5367 pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo,
5368 NULL, NULL);
5369 TRACE("returning %d\n", ret);
5370 return ret;
5373 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
5374 LPCSTR lpszStructType)
5376 CryptDecodeObjectExFunc decodeFunc = NULL;
5378 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
5379 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
5381 SetLastError(ERROR_FILE_NOT_FOUND);
5382 return NULL;
5384 if (!HIWORD(lpszStructType))
5386 switch (LOWORD(lpszStructType))
5388 case LOWORD(X509_CERT):
5389 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
5390 break;
5391 case LOWORD(X509_CERT_TO_BE_SIGNED):
5392 decodeFunc = CRYPT_AsnDecodeCert;
5393 break;
5394 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
5395 decodeFunc = CRYPT_AsnDecodeCRL;
5396 break;
5397 case LOWORD(X509_EXTENSIONS):
5398 decodeFunc = CRYPT_AsnDecodeExtensions;
5399 break;
5400 case LOWORD(X509_NAME_VALUE):
5401 decodeFunc = CRYPT_AsnDecodeNameValue;
5402 break;
5403 case LOWORD(X509_NAME):
5404 decodeFunc = CRYPT_AsnDecodeName;
5405 break;
5406 case LOWORD(X509_PUBLIC_KEY_INFO):
5407 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
5408 break;
5409 case LOWORD(X509_AUTHORITY_KEY_ID):
5410 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
5411 break;
5412 case LOWORD(X509_ALTERNATE_NAME):
5413 decodeFunc = CRYPT_AsnDecodeAltName;
5414 break;
5415 case LOWORD(X509_BASIC_CONSTRAINTS):
5416 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
5417 break;
5418 case LOWORD(X509_BASIC_CONSTRAINTS2):
5419 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
5420 break;
5421 case LOWORD(X509_CERT_POLICIES):
5422 decodeFunc = CRYPT_AsnDecodeCertPolicies;
5423 break;
5424 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
5425 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
5426 break;
5427 case LOWORD(X509_UNICODE_NAME):
5428 decodeFunc = CRYPT_AsnDecodeUnicodeName;
5429 break;
5430 case LOWORD(PKCS_ATTRIBUTE):
5431 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
5432 break;
5433 case LOWORD(X509_UNICODE_NAME_VALUE):
5434 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
5435 break;
5436 case LOWORD(X509_OCTET_STRING):
5437 decodeFunc = CRYPT_AsnDecodeOctets;
5438 break;
5439 case LOWORD(X509_BITS):
5440 case LOWORD(X509_KEY_USAGE):
5441 decodeFunc = CRYPT_AsnDecodeBits;
5442 break;
5443 case LOWORD(X509_INTEGER):
5444 decodeFunc = CRYPT_AsnDecodeInt;
5445 break;
5446 case LOWORD(X509_MULTI_BYTE_INTEGER):
5447 decodeFunc = CRYPT_AsnDecodeInteger;
5448 break;
5449 case LOWORD(X509_MULTI_BYTE_UINT):
5450 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
5451 break;
5452 case LOWORD(X509_ENUMERATED):
5453 decodeFunc = CRYPT_AsnDecodeEnumerated;
5454 break;
5455 case LOWORD(X509_CHOICE_OF_TIME):
5456 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
5457 break;
5458 case LOWORD(X509_AUTHORITY_KEY_ID2):
5459 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
5460 break;
5461 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
5462 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
5463 break;
5464 case LOWORD(PKCS_CONTENT_INFO):
5465 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
5466 break;
5467 case LOWORD(X509_SEQUENCE_OF_ANY):
5468 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
5469 break;
5470 case LOWORD(PKCS_UTC_TIME):
5471 decodeFunc = CRYPT_AsnDecodeUtcTime;
5472 break;
5473 case LOWORD(X509_CRL_DIST_POINTS):
5474 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
5475 break;
5476 case LOWORD(X509_ENHANCED_KEY_USAGE):
5477 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
5478 break;
5479 case LOWORD(PKCS_CTL):
5480 decodeFunc = CRYPT_AsnDecodeCTL;
5481 break;
5482 case LOWORD(PKCS_SMIME_CAPABILITIES):
5483 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
5484 break;
5485 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE):
5486 decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
5487 break;
5488 case LOWORD(PKCS_ATTRIBUTES):
5489 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
5490 break;
5491 case LOWORD(X509_ISSUING_DIST_POINT):
5492 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
5493 break;
5494 case LOWORD(X509_NAME_CONSTRAINTS):
5495 decodeFunc = CRYPT_AsnDecodeNameConstraints;
5496 break;
5497 case LOWORD(PKCS7_SIGNER_INFO):
5498 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
5499 break;
5500 case LOWORD(CMS_SIGNER_INFO):
5501 decodeFunc = CRYPT_AsnDecodeCMSSignerInfo;
5502 break;
5505 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
5506 decodeFunc = CRYPT_AsnDecodeExtensions;
5507 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
5508 decodeFunc = CRYPT_AsnDecodeUtcTime;
5509 else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
5510 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
5511 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
5512 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
5513 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
5514 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
5515 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
5516 decodeFunc = CRYPT_AsnDecodeEnumerated;
5517 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
5518 decodeFunc = CRYPT_AsnDecodeBits;
5519 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
5520 decodeFunc = CRYPT_AsnDecodeOctets;
5521 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
5522 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
5523 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
5524 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
5525 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
5526 decodeFunc = CRYPT_AsnDecodeAltName;
5527 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
5528 decodeFunc = CRYPT_AsnDecodeAltName;
5529 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
5530 decodeFunc = CRYPT_AsnDecodeAltName;
5531 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
5532 decodeFunc = CRYPT_AsnDecodeAltName;
5533 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
5534 decodeFunc = CRYPT_AsnDecodeAltName;
5535 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
5536 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
5537 else if (!strcmp(lpszStructType, szOID_CERT_POLICIES))
5538 decodeFunc = CRYPT_AsnDecodeCertPolicies;
5539 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
5540 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
5541 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
5542 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
5543 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
5544 decodeFunc = CRYPT_AsnDecodeNameConstraints;
5545 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
5546 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
5547 else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
5548 decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
5549 else if (!strcmp(lpszStructType, szOID_CTL))
5550 decodeFunc = CRYPT_AsnDecodeCTL;
5551 return decodeFunc;
5554 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
5555 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
5557 static HCRYPTOIDFUNCSET set = NULL;
5558 CryptDecodeObjectFunc decodeFunc = NULL;
5560 if (!set)
5561 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
5562 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
5563 (void **)&decodeFunc, hFunc);
5564 return decodeFunc;
5567 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
5568 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
5570 static HCRYPTOIDFUNCSET set = NULL;
5571 CryptDecodeObjectExFunc decodeFunc = NULL;
5573 if (!set)
5574 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
5575 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
5576 (void **)&decodeFunc, hFunc);
5577 return decodeFunc;
5580 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
5581 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
5582 DWORD *pcbStructInfo)
5584 BOOL ret = FALSE;
5585 CryptDecodeObjectFunc pCryptDecodeObject = NULL;
5586 CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
5587 HCRYPTOIDFUNCADDR hFunc = NULL;
5589 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
5590 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
5591 pvStructInfo, pcbStructInfo);
5593 if (!pvStructInfo && !pcbStructInfo)
5595 SetLastError(ERROR_INVALID_PARAMETER);
5596 return FALSE;
5598 if (cbEncoded > MAX_ENCODED_LEN)
5600 SetLastError(CRYPT_E_ASN1_LARGE);
5601 return FALSE;
5604 if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
5605 lpszStructType)))
5607 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
5608 debugstr_a(lpszStructType));
5609 pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
5610 lpszStructType, &hFunc);
5611 if (!pCryptDecodeObject)
5612 pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
5613 lpszStructType, &hFunc);
5615 if (pCryptDecodeObject)
5616 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5617 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
5618 else if (pCryptDecodeObjectEx)
5619 ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
5620 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
5621 pvStructInfo, pcbStructInfo);
5622 if (hFunc)
5623 CryptFreeOIDFunctionAddress(hFunc, 0);
5624 TRACE_(crypt)("returning %d\n", ret);
5625 return ret;
5628 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
5629 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5630 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5632 BOOL ret = FALSE;
5633 CryptDecodeObjectExFunc decodeFunc;
5634 HCRYPTOIDFUNCADDR hFunc = NULL;
5636 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
5637 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
5638 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
5640 if (!pvStructInfo && !pcbStructInfo)
5642 SetLastError(ERROR_INVALID_PARAMETER);
5643 return FALSE;
5645 if (cbEncoded > MAX_ENCODED_LEN)
5647 SetLastError(CRYPT_E_ASN1_LARGE);
5648 return FALSE;
5651 SetLastError(NOERROR);
5652 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG && pvStructInfo)
5653 *(BYTE **)pvStructInfo = NULL;
5654 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
5655 if (!decodeFunc)
5657 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
5658 debugstr_a(lpszStructType));
5659 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
5660 &hFunc);
5662 if (decodeFunc)
5663 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
5664 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
5665 else
5667 CryptDecodeObjectFunc pCryptDecodeObject =
5668 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
5670 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
5671 * directly, as that could cause an infinite loop.
5673 if (pCryptDecodeObject)
5675 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5677 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5678 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
5679 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
5680 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
5681 ret = pCryptDecodeObject(dwCertEncodingType,
5682 lpszStructType, pbEncoded, cbEncoded, dwFlags,
5683 *(BYTE **)pvStructInfo, pcbStructInfo);
5685 else
5686 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5687 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
5690 if (hFunc)
5691 CryptFreeOIDFunctionAddress(hFunc, 0);
5692 TRACE_(crypt)("returning %d\n", ret);
5693 return ret;
5696 BOOL WINAPI PFXIsPFXBlob(CRYPT_DATA_BLOB *pPFX)
5698 BOOL ret;
5700 TRACE_(crypt)("(%p)\n", pPFX);
5702 /* A PFX blob is an asn.1-encoded sequence, consisting of at least a
5703 * version integer of length 1 (3 encoded byes) and at least one other
5704 * datum (two encoded bytes), plus at least two bytes for the outer
5705 * sequence. Thus, even an empty PFX blob is at least 7 bytes in length.
5707 if (pPFX->cbData < 7)
5708 ret = FALSE;
5709 else if (pPFX->pbData[0] == ASN_SEQUENCE)
5711 DWORD len;
5713 if ((ret = CRYPT_GetLengthIndefinite(pPFX->pbData, pPFX->cbData, &len)))
5715 BYTE lenLen = GET_LEN_BYTES(pPFX->pbData[1]);
5717 /* Need at least three bytes for the integer version */
5718 if (pPFX->cbData < 1 + lenLen + 3)
5719 ret = FALSE;
5720 else if (pPFX->pbData[1 + lenLen] != ASN_INTEGER || /* Tag */
5721 pPFX->pbData[1 + lenLen + 1] != 1 || /* Definite length */
5722 pPFX->pbData[1 + lenLen + 2] != 3) /* PFX version */
5723 ret = FALSE;
5726 else
5727 ret = FALSE;
5728 return ret;
5731 HCERTSTORE WINAPI PFXImportCertStore(CRYPT_DATA_BLOB *pPFX, LPCWSTR szPassword,
5732 DWORD dwFlags)
5734 FIXME_(crypt)("(%p, %p, %08x): stub\n", pPFX, szPassword, dwFlags);
5735 return NULL;