winhttp/tests: Initialize a variant with a known value.
[wine/multimedia.git] / dlls / crypt32 / decode.c
blob649ca55da8982603a36be940a880f69a6af4573a
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 const CRYPT_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(const CRYPT_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 if (items[i].size > items[i].minSize)
527 bytesNeeded += items[i].size - items[i].minSize;
528 structSize = max( structSize, items[i].offset + items[i].minSize );
530 bytesNeeded += structSize;
531 if (pcbDecoded)
532 *pcbDecoded = 1 + lenBytes + cbDecoded;
533 if (!pvStructInfo)
534 *pcbStructInfo = bytesNeeded;
535 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
536 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
538 BYTE *nextData;
540 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
541 pvStructInfo = *(BYTE **)pvStructInfo;
542 if (startingPointer)
543 nextData = startingPointer;
544 else
545 nextData = (BYTE *)pvStructInfo + structSize;
546 memset(pvStructInfo, 0, structSize);
547 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
548 ptr, dataLen, dwFlags, pvStructInfo, nextData,
549 &cbDecoded);
550 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
551 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
556 else
558 SetLastError(CRYPT_E_ASN1_BADTAG);
559 ret = FALSE;
561 TRACE("returning %d (%08x)\n", ret, GetLastError());
562 return ret;
565 /* tag:
566 * The expected tag of the entire encoded array (usually a variant
567 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
568 * regardless of the tag seen.
569 * countOffset:
570 * The offset within the outer structure at which the count exists.
571 * For example, a structure such as CRYPT_ATTRIBUTES has countOffset == 0,
572 * while CRYPT_ATTRIBUTE has countOffset ==
573 * offsetof(CRYPT_ATTRIBUTE, cValue).
574 * arrayOffset:
575 * The offset within the outer structure at which the array pointer exists.
576 * For example, CRYPT_ATTRIBUTES has arrayOffset ==
577 * offsetof(CRYPT_ATTRIBUTES, rgAttr).
578 * minArraySize:
579 * The minimum size of the decoded array. On WIN32, this is always 8:
580 * sizeof(DWORD) + sizeof(void *). On WIN64, it can be larger due to
581 * alignment.
582 * decodeFunc:
583 * used to decode each item in the array
584 * itemSize:
585 * is the minimum size of each decoded item
586 * hasPointer:
587 * indicates whether each item has a dynamic pointer
588 * pointerOffset:
589 * indicates the offset within itemSize at which the pointer exists
591 struct AsnArrayDescriptor
593 BYTE tag;
594 DWORD countOffset;
595 DWORD arrayOffset;
596 DWORD minArraySize;
597 InternalDecodeFunc decodeFunc;
598 DWORD itemSize;
599 BOOL hasPointer;
600 DWORD pointerOffset;
603 struct AsnArrayItemSize
605 DWORD encodedLen;
606 DWORD size;
609 /* Decodes an array of like types into a structure described by a struct
610 * AsnArrayDescriptor.
612 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
613 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
614 const CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
615 DWORD *pcbDecoded)
617 BOOL ret = TRUE;
619 TRACE("%p, %p, %d, %p, %d\n", arrayDesc, pbEncoded,
620 cbEncoded, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
622 if (!cbEncoded)
624 SetLastError(CRYPT_E_ASN1_EOD);
625 ret = FALSE;
627 else if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
629 DWORD dataLen;
631 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
633 DWORD bytesNeeded = arrayDesc->minArraySize, cItems = 0, decoded;
634 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
635 /* There can be arbitrarily many items, but there is often only one.
637 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
639 decoded = 1 + lenBytes;
640 if (dataLen)
642 const BYTE *ptr;
643 BOOL doneDecoding = FALSE;
645 for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
647 if (dataLen == CMSG_INDEFINITE_LENGTH)
649 if (ptr[0] == 0)
651 doneDecoding = TRUE;
652 if (ptr[1] != 0)
654 SetLastError(CRYPT_E_ASN1_CORRUPT);
655 ret = FALSE;
657 else
658 decoded += 2;
661 else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
662 doneDecoding = TRUE;
663 if (!doneDecoding)
665 DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
667 /* Each item decoded may not tolerate extraneous bytes,
668 * so get the length of the next element if known.
670 if ((ret = CRYPT_GetLengthIndefinite(ptr,
671 cbEncoded - (ptr - pbEncoded), &itemDataLen)))
673 if (itemDataLen == CMSG_INDEFINITE_LENGTH)
674 itemEncoded = cbEncoded - (ptr - pbEncoded);
675 else
676 itemEncoded = 1 + GET_LEN_BYTES(ptr[1]) +
677 itemDataLen;
679 if (ret)
680 ret = arrayDesc->decodeFunc(ptr, itemEncoded,
681 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size,
682 &itemDecoded);
683 if (ret)
685 cItems++;
686 if (itemSizes != &itemSize)
687 itemSizes = CryptMemRealloc(itemSizes,
688 cItems * sizeof(struct AsnArrayItemSize));
689 else if (cItems > 1)
691 itemSizes =
692 CryptMemAlloc(
693 cItems * sizeof(struct AsnArrayItemSize));
694 if (itemSizes)
695 memcpy(itemSizes, &itemSize,
696 sizeof(itemSize));
698 if (itemSizes)
700 decoded += itemDecoded;
701 itemSizes[cItems - 1].encodedLen = itemEncoded;
702 itemSizes[cItems - 1].size = size;
703 bytesNeeded += size;
704 ptr += itemEncoded;
706 else
707 ret = FALSE;
712 if (ret)
714 if (pcbDecoded)
715 *pcbDecoded = decoded;
716 if (!pvStructInfo)
717 *pcbStructInfo = bytesNeeded;
718 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
719 pvStructInfo, pcbStructInfo, bytesNeeded)))
721 DWORD i, *pcItems;
722 BYTE *nextData;
723 const BYTE *ptr;
724 void *rgItems;
726 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
727 pvStructInfo = *(void **)pvStructInfo;
728 pcItems = pvStructInfo;
729 *pcItems = cItems;
730 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
732 rgItems = (BYTE *)pvStructInfo +
733 arrayDesc->minArraySize;
734 *(void **)((BYTE *)pcItems -
735 arrayDesc->countOffset + arrayDesc->arrayOffset) =
736 rgItems;
738 else
739 rgItems = *(void **)((BYTE *)pcItems -
740 arrayDesc->countOffset + arrayDesc->arrayOffset);
741 nextData = (BYTE *)rgItems + cItems * arrayDesc->itemSize;
742 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
743 i < cItems && ptr - pbEncoded - 1 - lenBytes <
744 dataLen; i++)
746 DWORD itemDecoded;
748 if (arrayDesc->hasPointer)
749 *(BYTE **)((BYTE *)rgItems + i * arrayDesc->itemSize
750 + arrayDesc->pointerOffset) = nextData;
751 ret = arrayDesc->decodeFunc(ptr,
752 itemSizes[i].encodedLen,
753 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
754 (BYTE *)rgItems + i * arrayDesc->itemSize,
755 &itemSizes[i].size, &itemDecoded);
756 if (ret)
758 nextData += itemSizes[i].size - arrayDesc->itemSize;
759 ptr += itemDecoded;
762 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
763 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
766 if (itemSizes != &itemSize)
767 CryptMemFree(itemSizes);
770 else
772 SetLastError(CRYPT_E_ASN1_BADTAG);
773 ret = FALSE;
775 return ret;
778 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
779 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
780 * to CRYPT_E_ASN1_CORRUPT.
781 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
782 * set!
784 static BOOL CRYPT_AsnDecodeDerBlob(const BYTE *pbEncoded, DWORD cbEncoded,
785 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
787 BOOL ret;
788 DWORD dataLen;
790 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
792 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
793 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
795 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
796 bytesNeeded += 1 + lenBytes + dataLen;
798 if (pcbDecoded)
799 *pcbDecoded = 1 + lenBytes + dataLen;
800 if (!pvStructInfo)
801 *pcbStructInfo = bytesNeeded;
802 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded)))
804 CRYPT_DER_BLOB *blob;
806 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
807 pvStructInfo = *(BYTE **)pvStructInfo;
808 blob = pvStructInfo;
809 blob->cbData = 1 + lenBytes + dataLen;
810 if (blob->cbData)
812 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
813 blob->pbData = (BYTE *)pbEncoded;
814 else
816 assert(blob->pbData);
817 memcpy(blob->pbData, pbEncoded, blob->cbData);
820 else
822 SetLastError(CRYPT_E_ASN1_CORRUPT);
823 ret = FALSE;
827 return ret;
830 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
831 static BOOL CRYPT_AsnDecodeBitsSwapBytes(const BYTE *pbEncoded,
832 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
833 DWORD *pcbDecoded)
835 BOOL ret;
837 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
838 pvStructInfo, *pcbStructInfo, pcbDecoded);
840 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
841 * place.
843 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
844 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
845 pcbDecoded);
846 if (ret && pvStructInfo)
848 CRYPT_BIT_BLOB *blob = pvStructInfo;
850 if (blob->cbData)
852 DWORD i;
853 BYTE temp;
855 for (i = 0; i < blob->cbData / 2; i++)
857 temp = blob->pbData[i];
858 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
859 blob->pbData[blob->cbData - i - 1] = temp;
863 TRACE("returning %d (%08x)\n", ret, GetLastError());
864 return ret;
867 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
868 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
869 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
871 BOOL ret = TRUE;
873 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
874 pDecodePara, pvStructInfo, *pcbStructInfo);
876 __TRY
878 struct AsnDecodeSequenceItem items[] = {
879 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
880 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
881 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
882 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
883 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
884 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
885 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
886 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
887 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
888 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
891 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
892 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
893 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
894 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
895 pcbStructInfo, NULL, NULL);
897 __EXCEPT_PAGE_FAULT
899 SetLastError(STATUS_ACCESS_VIOLATION);
900 ret = FALSE;
902 __ENDTRY
904 TRACE("Returning %d (%08x)\n", ret, GetLastError());
905 return ret;
908 static BOOL CRYPT_AsnDecodeCertVersion(const BYTE *pbEncoded, DWORD cbEncoded,
909 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
911 BOOL ret;
912 DWORD dataLen;
914 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
916 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
918 ret = CRYPT_AsnDecodeIntInternal(pbEncoded + 1 + lenBytes, dataLen,
919 dwFlags, pvStructInfo, pcbStructInfo, NULL);
920 if (pcbDecoded)
921 *pcbDecoded = 1 + lenBytes + dataLen;
923 return ret;
926 static BOOL CRYPT_AsnDecodeValidity(const BYTE *pbEncoded, DWORD cbEncoded,
927 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
929 BOOL ret;
931 struct AsnDecodeSequenceItem items[] = {
932 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
933 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
934 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
935 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
938 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
939 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
940 pcbDecoded, NULL);
941 return ret;
944 static BOOL CRYPT_AsnDecodeCertExtensionsInternal(const BYTE *pbEncoded,
945 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
946 DWORD *pcbDecoded)
948 BOOL ret = TRUE;
949 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
950 offsetof(CERT_INFO, cExtension), offsetof(CERT_INFO, rgExtension),
951 FINALMEMBERSIZE(CERT_INFO, cExtension),
952 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
953 offsetof(CERT_EXTENSION, pszObjId) };
955 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
956 pvStructInfo, *pcbStructInfo, pcbDecoded);
958 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
959 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
960 return ret;
963 static BOOL CRYPT_AsnDecodeCertExtensions(const BYTE *pbEncoded,
964 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
965 DWORD *pcbDecoded)
967 BOOL ret;
968 DWORD dataLen;
970 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
972 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
974 ret = CRYPT_AsnDecodeCertExtensionsInternal(pbEncoded + 1 + lenBytes,
975 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
976 if (ret && pcbDecoded)
977 *pcbDecoded = 1 + lenBytes + dataLen;
979 return ret;
982 static BOOL CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
983 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
984 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
986 BOOL ret = TRUE;
987 struct AsnDecodeSequenceItem items[] = {
988 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
989 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
990 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
991 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
992 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
993 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
994 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
995 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
996 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
997 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
998 Issuer.pbData) },
999 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
1000 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
1001 FALSE, 0 },
1002 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
1003 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
1004 Subject.pbData) },
1005 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
1006 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
1007 FALSE, TRUE, offsetof(CERT_INFO,
1008 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
1009 { ASN_CONTEXT | 1, offsetof(CERT_INFO, IssuerUniqueId),
1010 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
1011 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
1012 { ASN_CONTEXT | 2, offsetof(CERT_INFO, SubjectUniqueId),
1013 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
1014 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
1015 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
1016 CRYPT_AsnDecodeCertExtensions, FINALMEMBERSIZE(CERT_INFO, cExtension),
1017 TRUE, TRUE, offsetof(CERT_INFO, rgExtension), 0 },
1020 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1021 pDecodePara, pvStructInfo, *pcbStructInfo);
1023 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1024 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
1025 NULL, NULL);
1026 if (ret && pvStructInfo)
1028 CERT_INFO *info;
1030 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1031 info = *(CERT_INFO **)pvStructInfo;
1032 else
1033 info = pvStructInfo;
1034 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
1035 !info->Subject.cbData)
1037 SetLastError(CRYPT_E_ASN1_CORRUPT);
1038 /* Don't need to deallocate, because it should have failed on the
1039 * first pass (and no memory was allocated.)
1041 ret = FALSE;
1045 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1046 return ret;
1049 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
1050 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1051 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1053 BOOL ret = FALSE;
1055 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1056 pDecodePara, pvStructInfo, *pcbStructInfo);
1058 __TRY
1060 DWORD size = 0;
1062 /* Unless told not to, first try to decode it as a signed cert. */
1063 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1065 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
1067 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1068 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1069 &signedCert, &size);
1070 if (ret)
1072 size = 0;
1073 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1074 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
1075 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
1076 pvStructInfo, pcbStructInfo);
1077 LocalFree(signedCert);
1080 /* Failing that, try it as an unsigned cert */
1081 if (!ret)
1083 size = 0;
1084 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1085 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
1086 pDecodePara, pvStructInfo, pcbStructInfo);
1089 __EXCEPT_PAGE_FAULT
1091 SetLastError(STATUS_ACCESS_VIOLATION);
1093 __ENDTRY
1095 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1096 return ret;
1099 static BOOL CRYPT_AsnDecodeCRLEntryExtensions(const BYTE *pbEncoded,
1100 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1101 DWORD *pcbDecoded)
1103 BOOL ret = TRUE;
1104 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1105 offsetof(CRL_ENTRY, cExtension), offsetof(CRL_ENTRY, rgExtension),
1106 FINALMEMBERSIZE(CRL_ENTRY, cExtension),
1107 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1108 offsetof(CERT_EXTENSION, pszObjId) };
1110 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1111 pvStructInfo, *pcbStructInfo, pcbDecoded);
1113 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1114 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1115 return ret;
1118 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
1119 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1121 BOOL ret;
1122 struct AsnDecodeSequenceItem items[] = {
1123 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
1124 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
1125 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
1126 { 0, offsetof(CRL_ENTRY, RevocationDate),
1127 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
1128 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
1129 CRYPT_AsnDecodeCRLEntryExtensions,
1130 FINALMEMBERSIZE(CRL_ENTRY, cExtension), TRUE, TRUE,
1131 offsetof(CRL_ENTRY, rgExtension), 0 },
1133 PCRL_ENTRY entry = pvStructInfo;
1135 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
1136 *pcbStructInfo);
1138 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1139 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, pcbDecoded,
1140 entry ? entry->SerialNumber.pbData : NULL);
1141 if (ret && entry && !entry->SerialNumber.cbData)
1143 WARN("empty CRL entry serial number\n");
1144 SetLastError(CRYPT_E_ASN1_CORRUPT);
1145 ret = FALSE;
1147 return ret;
1150 /* Warning: assumes pvStructInfo points to the cCRLEntry member of a CRL_INFO
1151 * whose rgCRLEntry member has been set prior to calling.
1153 static BOOL CRYPT_AsnDecodeCRLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
1154 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1156 BOOL ret;
1157 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1158 offsetof(CRL_INFO, cCRLEntry), offsetof(CRL_INFO, rgCRLEntry),
1159 MEMBERSIZE(CRL_INFO, cCRLEntry, cExtension),
1160 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
1161 offsetof(CRL_ENTRY, SerialNumber.pbData) };
1163 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1164 pvStructInfo, *pcbStructInfo, pcbDecoded);
1166 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1167 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1168 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1169 return ret;
1172 static BOOL CRYPT_AsnDecodeCRLExtensionsInternal(const BYTE *pbEncoded,
1173 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1174 DWORD *pcbDecoded)
1176 BOOL ret = TRUE;
1177 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1178 offsetof(CRL_INFO, cExtension), offsetof(CRL_INFO, rgExtension),
1179 FINALMEMBERSIZE(CRL_INFO, cExtension),
1180 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1181 offsetof(CERT_EXTENSION, pszObjId) };
1183 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
1184 pvStructInfo, *pcbStructInfo, pcbDecoded);
1186 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1187 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1188 return ret;
1191 static BOOL CRYPT_AsnDecodeCRLExtensions(const BYTE *pbEncoded,
1192 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1193 DWORD *pcbDecoded)
1195 BOOL ret;
1196 DWORD dataLen;
1198 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1200 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1202 ret = CRYPT_AsnDecodeCRLExtensionsInternal(pbEncoded + 1 + lenBytes,
1203 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
1204 if (ret && pcbDecoded)
1205 *pcbDecoded = 1 + lenBytes + dataLen;
1207 return ret;
1210 static BOOL CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1211 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1212 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1214 struct AsnDecodeSequenceItem items[] = {
1215 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1216 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1217 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1218 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1219 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1220 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1221 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1222 Issuer.pbData) },
1223 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1224 sizeof(FILETIME), FALSE, FALSE, 0 },
1225 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1226 sizeof(FILETIME), TRUE, FALSE, 0 },
1227 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1228 CRYPT_AsnDecodeCRLEntries, MEMBERSIZE(CRL_INFO, cCRLEntry, cExtension),
1229 TRUE, TRUE, offsetof(CRL_INFO, rgCRLEntry), 0 },
1230 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1231 CRYPT_AsnDecodeCRLExtensions, FINALMEMBERSIZE(CRL_INFO, cExtension),
1232 TRUE, TRUE, offsetof(CRL_INFO, rgExtension), 0 },
1234 BOOL ret = TRUE;
1236 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1237 pDecodePara, pvStructInfo, *pcbStructInfo);
1239 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1240 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
1241 NULL, NULL);
1243 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1244 return ret;
1247 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1248 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1249 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1251 BOOL ret = FALSE;
1253 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1254 pDecodePara, pvStructInfo, *pcbStructInfo);
1256 __TRY
1258 DWORD size = 0;
1260 /* Unless told not to, first try to decode it as a signed crl. */
1261 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1263 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1265 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1266 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1267 &signedCrl, &size);
1268 if (ret)
1270 size = 0;
1271 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1272 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1273 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1274 pvStructInfo, pcbStructInfo);
1275 LocalFree(signedCrl);
1278 /* Failing that, try it as an unsigned crl */
1279 if (!ret)
1281 size = 0;
1282 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1283 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1284 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1287 __EXCEPT_PAGE_FAULT
1289 SetLastError(STATUS_ACCESS_VIOLATION);
1291 __ENDTRY
1293 TRACE("Returning %d (%08x)\n", ret, GetLastError());
1294 return ret;
1297 static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded,
1298 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1300 BOOL ret = TRUE;
1301 DWORD dataLen;
1303 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1304 pvStructInfo, *pcbStructInfo);
1306 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1308 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1309 DWORD bytesNeeded = sizeof(LPSTR);
1311 if (dataLen)
1313 /* The largest possible string for the first two components
1314 * is 2.175 (= 2 * 40 + 175 = 255), so this is big enough.
1316 char firstTwo[6];
1317 const BYTE *ptr;
1319 snprintf(firstTwo, sizeof(firstTwo), "%d.%d",
1320 pbEncoded[1 + lenBytes] / 40,
1321 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1322 * 40);
1323 bytesNeeded += strlen(firstTwo) + 1;
1324 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1325 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1327 /* large enough for ".4000000" */
1328 char str[9];
1329 int val = 0;
1331 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1332 (*ptr & 0x80))
1334 val <<= 7;
1335 val |= *ptr & 0x7f;
1336 ptr++;
1338 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1339 (*ptr & 0x80))
1341 SetLastError(CRYPT_E_ASN1_CORRUPT);
1342 ret = FALSE;
1344 else
1346 val <<= 7;
1347 val |= *ptr++;
1348 snprintf(str, sizeof(str), ".%d", val);
1349 bytesNeeded += strlen(str);
1353 if (pcbDecoded)
1354 *pcbDecoded = 1 + lenBytes + dataLen;
1355 if (!pvStructInfo)
1356 *pcbStructInfo = bytesNeeded;
1357 else if (*pcbStructInfo < bytesNeeded)
1359 *pcbStructInfo = bytesNeeded;
1360 SetLastError(ERROR_MORE_DATA);
1361 ret = FALSE;
1363 else
1365 if (dataLen)
1367 const BYTE *ptr;
1368 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1370 *pszObjId = 0;
1371 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1372 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1373 40) * 40);
1374 pszObjId += strlen(pszObjId);
1375 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1376 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1378 int val = 0;
1380 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1381 (*ptr & 0x80))
1383 val <<= 7;
1384 val |= *ptr & 0x7f;
1385 ptr++;
1387 val <<= 7;
1388 val |= *ptr++;
1389 sprintf(pszObjId, ".%d", val);
1390 pszObjId += strlen(pszObjId);
1393 else
1394 *(LPSTR *)pvStructInfo = NULL;
1395 *pcbStructInfo = bytesNeeded;
1398 return ret;
1401 static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded,
1402 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1404 BOOL ret;
1406 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1407 pvStructInfo, *pcbStructInfo);
1409 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1410 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1411 pvStructInfo, pcbStructInfo, pcbDecoded);
1412 else
1414 SetLastError(CRYPT_E_ASN1_BADTAG);
1415 ret = FALSE;
1417 return ret;
1420 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
1421 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1423 struct AsnDecodeSequenceItem items[] = {
1424 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1425 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1426 offsetof(CERT_EXTENSION, pszObjId), 0 },
1427 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1428 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1429 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1430 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1431 offsetof(CERT_EXTENSION, Value.pbData) },
1433 BOOL ret = TRUE;
1434 PCERT_EXTENSION ext = pvStructInfo;
1436 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, ext,
1437 *pcbStructInfo);
1439 if (ext)
1440 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1441 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1442 pbEncoded, cbEncoded, dwFlags, NULL, ext, pcbStructInfo,
1443 pcbDecoded, ext ? ext->pszObjId : NULL);
1444 if (ext)
1445 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1446 debugstr_a(ext->pszObjId));
1447 TRACE("returning %d (%08x)\n", ret, GetLastError());
1448 return ret;
1451 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1452 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1453 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1455 BOOL ret = TRUE;
1457 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1458 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
1460 __TRY
1462 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1463 offsetof(CERT_EXTENSIONS, cExtension),
1464 offsetof(CERT_EXTENSIONS, rgExtension),
1465 sizeof(CERT_EXTENSIONS),
1466 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1467 offsetof(CERT_EXTENSION, pszObjId) };
1469 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1470 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1472 __EXCEPT_PAGE_FAULT
1474 SetLastError(STATUS_ACCESS_VIOLATION);
1475 ret = FALSE;
1477 __ENDTRY
1478 return ret;
1481 /* Warning: this assumes the address of value->Value.pbData is already set, in
1482 * order to avoid overwriting memory. (In some cases, it may change it, if it
1483 * doesn't copy anything to memory.) Be sure to set it correctly!
1485 static BOOL CRYPT_AsnDecodeNameValueInternal(const BYTE *pbEncoded,
1486 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1487 DWORD *pcbDecoded)
1489 BOOL ret = TRUE;
1490 DWORD dataLen;
1491 CERT_NAME_VALUE *value = pvStructInfo;
1493 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1495 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1496 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1498 switch (pbEncoded[0])
1500 case ASN_OCTETSTRING:
1501 valueType = CERT_RDN_OCTET_STRING;
1502 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1503 bytesNeeded += dataLen;
1504 break;
1505 case ASN_NUMERICSTRING:
1506 valueType = CERT_RDN_NUMERIC_STRING;
1507 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1508 bytesNeeded += dataLen;
1509 break;
1510 case ASN_PRINTABLESTRING:
1511 valueType = CERT_RDN_PRINTABLE_STRING;
1512 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1513 bytesNeeded += dataLen;
1514 break;
1515 case ASN_IA5STRING:
1516 valueType = CERT_RDN_IA5_STRING;
1517 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1518 bytesNeeded += dataLen;
1519 break;
1520 case ASN_T61STRING:
1521 valueType = CERT_RDN_T61_STRING;
1522 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1523 bytesNeeded += dataLen;
1524 break;
1525 case ASN_VIDEOTEXSTRING:
1526 valueType = CERT_RDN_VIDEOTEX_STRING;
1527 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1528 bytesNeeded += dataLen;
1529 break;
1530 case ASN_GRAPHICSTRING:
1531 valueType = CERT_RDN_GRAPHIC_STRING;
1532 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1533 bytesNeeded += dataLen;
1534 break;
1535 case ASN_VISIBLESTRING:
1536 valueType = CERT_RDN_VISIBLE_STRING;
1537 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1538 bytesNeeded += dataLen;
1539 break;
1540 case ASN_GENERALSTRING:
1541 valueType = CERT_RDN_GENERAL_STRING;
1542 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1543 bytesNeeded += dataLen;
1544 break;
1545 case ASN_UNIVERSALSTRING:
1546 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1547 SetLastError(CRYPT_E_ASN1_BADTAG);
1548 return FALSE;
1549 case ASN_BMPSTRING:
1550 valueType = CERT_RDN_BMP_STRING;
1551 bytesNeeded += dataLen;
1552 break;
1553 case ASN_UTF8STRING:
1554 valueType = CERT_RDN_UTF8_STRING;
1555 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1556 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
1557 break;
1558 default:
1559 SetLastError(CRYPT_E_ASN1_BADTAG);
1560 return FALSE;
1563 if (pcbDecoded)
1564 *pcbDecoded = 1 + lenBytes + dataLen;
1565 if (!value)
1566 *pcbStructInfo = bytesNeeded;
1567 else if (*pcbStructInfo < bytesNeeded)
1569 *pcbStructInfo = bytesNeeded;
1570 SetLastError(ERROR_MORE_DATA);
1571 ret = FALSE;
1573 else
1575 *pcbStructInfo = bytesNeeded;
1576 value->dwValueType = valueType;
1577 if (dataLen)
1579 DWORD i;
1581 assert(value->Value.pbData);
1582 switch (pbEncoded[0])
1584 case ASN_OCTETSTRING:
1585 case ASN_NUMERICSTRING:
1586 case ASN_PRINTABLESTRING:
1587 case ASN_IA5STRING:
1588 case ASN_T61STRING:
1589 case ASN_VIDEOTEXSTRING:
1590 case ASN_GRAPHICSTRING:
1591 case ASN_VISIBLESTRING:
1592 case ASN_GENERALSTRING:
1593 value->Value.cbData = dataLen;
1594 if (dataLen)
1596 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1597 memcpy(value->Value.pbData,
1598 pbEncoded + 1 + lenBytes, dataLen);
1599 else
1600 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1601 lenBytes;
1603 break;
1604 case ASN_BMPSTRING:
1606 LPWSTR str = (LPWSTR)value->Value.pbData;
1608 value->Value.cbData = dataLen;
1609 for (i = 0; i < dataLen / 2; i++)
1610 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1611 pbEncoded[1 + lenBytes + 2 * i + 1];
1612 break;
1614 case ASN_UTF8STRING:
1616 LPWSTR str = (LPWSTR)value->Value.pbData;
1618 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1619 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1620 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1621 break;
1625 else
1627 value->Value.cbData = 0;
1628 value->Value.pbData = NULL;
1632 return ret;
1635 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1636 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1637 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1639 BOOL ret = TRUE;
1641 __TRY
1643 ret = CRYPT_AsnDecodeNameValueInternal(pbEncoded, cbEncoded,
1644 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1645 if (ret && pvStructInfo)
1647 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1648 pcbStructInfo, *pcbStructInfo);
1649 if (ret)
1651 CERT_NAME_VALUE *value;
1653 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1654 pvStructInfo = *(BYTE **)pvStructInfo;
1655 value = pvStructInfo;
1656 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1657 ret = CRYPT_AsnDecodeNameValueInternal( pbEncoded, cbEncoded,
1658 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1659 pcbStructInfo, NULL);
1660 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
1661 CRYPT_FreeSpace(pDecodePara, value);
1665 __EXCEPT_PAGE_FAULT
1667 SetLastError(STATUS_ACCESS_VIOLATION);
1668 ret = FALSE;
1670 __ENDTRY
1671 return ret;
1674 static BOOL CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE *pbEncoded,
1675 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1676 DWORD *pcbDecoded)
1678 BOOL ret = TRUE;
1679 DWORD dataLen;
1680 CERT_NAME_VALUE *value = pvStructInfo;
1682 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1684 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1685 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1687 switch (pbEncoded[0])
1689 case ASN_NUMERICSTRING:
1690 valueType = CERT_RDN_NUMERIC_STRING;
1691 if (dataLen)
1692 bytesNeeded += (dataLen + 1) * 2;
1693 break;
1694 case ASN_PRINTABLESTRING:
1695 valueType = CERT_RDN_PRINTABLE_STRING;
1696 if (dataLen)
1697 bytesNeeded += (dataLen + 1) * 2;
1698 break;
1699 case ASN_IA5STRING:
1700 valueType = CERT_RDN_IA5_STRING;
1701 if (dataLen)
1702 bytesNeeded += (dataLen + 1) * 2;
1703 break;
1704 case ASN_T61STRING:
1705 valueType = CERT_RDN_T61_STRING;
1706 if (dataLen)
1707 bytesNeeded += (dataLen + 1) * 2;
1708 break;
1709 case ASN_VIDEOTEXSTRING:
1710 valueType = CERT_RDN_VIDEOTEX_STRING;
1711 if (dataLen)
1712 bytesNeeded += (dataLen + 1) * 2;
1713 break;
1714 case ASN_GRAPHICSTRING:
1715 valueType = CERT_RDN_GRAPHIC_STRING;
1716 if (dataLen)
1717 bytesNeeded += (dataLen + 1) * 2;
1718 break;
1719 case ASN_VISIBLESTRING:
1720 valueType = CERT_RDN_VISIBLE_STRING;
1721 if (dataLen)
1722 bytesNeeded += (dataLen + 1) * 2;
1723 break;
1724 case ASN_GENERALSTRING:
1725 valueType = CERT_RDN_GENERAL_STRING;
1726 if (dataLen)
1727 bytesNeeded += (dataLen + 1) * 2;
1728 break;
1729 case ASN_UNIVERSALSTRING:
1730 valueType = CERT_RDN_UNIVERSAL_STRING;
1731 if (dataLen)
1732 bytesNeeded += dataLen / 2 + sizeof(WCHAR);
1733 break;
1734 case ASN_BMPSTRING:
1735 valueType = CERT_RDN_BMP_STRING;
1736 if (dataLen)
1737 bytesNeeded += dataLen + sizeof(WCHAR);
1738 break;
1739 case ASN_UTF8STRING:
1740 valueType = CERT_RDN_UTF8_STRING;
1741 if (dataLen)
1742 bytesNeeded += (MultiByteToWideChar(CP_UTF8, 0,
1743 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) + 1) * 2;
1744 break;
1745 default:
1746 SetLastError(CRYPT_E_ASN1_BADTAG);
1747 return FALSE;
1750 if (pcbDecoded)
1751 *pcbDecoded = 1 + lenBytes + dataLen;
1752 if (!value)
1753 *pcbStructInfo = bytesNeeded;
1754 else if (*pcbStructInfo < bytesNeeded)
1756 *pcbStructInfo = bytesNeeded;
1757 SetLastError(ERROR_MORE_DATA);
1758 ret = FALSE;
1760 else
1762 *pcbStructInfo = bytesNeeded;
1763 value->dwValueType = valueType;
1764 if (dataLen)
1766 DWORD i;
1767 LPWSTR str = (LPWSTR)value->Value.pbData;
1769 assert(value->Value.pbData);
1770 switch (pbEncoded[0])
1772 case ASN_NUMERICSTRING:
1773 case ASN_PRINTABLESTRING:
1774 case ASN_IA5STRING:
1775 case ASN_T61STRING:
1776 case ASN_VIDEOTEXSTRING:
1777 case ASN_GRAPHICSTRING:
1778 case ASN_VISIBLESTRING:
1779 case ASN_GENERALSTRING:
1780 value->Value.cbData = dataLen * 2;
1781 for (i = 0; i < dataLen; i++)
1782 str[i] = pbEncoded[1 + lenBytes + i];
1783 str[i] = 0;
1784 break;
1785 case ASN_UNIVERSALSTRING:
1786 value->Value.cbData = dataLen / 2;
1787 for (i = 0; i < dataLen / 4; i++)
1788 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1789 | pbEncoded[1 + lenBytes + 2 * i + 3];
1790 str[i] = 0;
1791 break;
1792 case ASN_BMPSTRING:
1793 value->Value.cbData = dataLen;
1794 for (i = 0; i < dataLen / 2; i++)
1795 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1796 pbEncoded[1 + lenBytes + 2 * i + 1];
1797 str[i] = 0;
1798 break;
1799 case ASN_UTF8STRING:
1800 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1801 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1802 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * sizeof(WCHAR);
1803 *(WCHAR *)(value->Value.pbData + value->Value.cbData) = 0;
1804 value->Value.cbData += sizeof(WCHAR);
1805 break;
1808 else
1810 value->Value.cbData = 0;
1811 value->Value.pbData = NULL;
1815 return ret;
1818 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1819 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1820 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1822 BOOL ret = TRUE;
1824 __TRY
1826 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded, cbEncoded,
1827 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1828 if (ret && pvStructInfo)
1830 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1831 pcbStructInfo, *pcbStructInfo);
1832 if (ret)
1834 CERT_NAME_VALUE *value;
1836 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1837 pvStructInfo = *(BYTE **)pvStructInfo;
1838 value = pvStructInfo;
1839 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1840 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded,
1841 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1842 pcbStructInfo, NULL);
1843 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
1844 CRYPT_FreeSpace(pDecodePara, value);
1848 __EXCEPT_PAGE_FAULT
1850 SetLastError(STATUS_ACCESS_VIOLATION);
1851 ret = FALSE;
1853 __ENDTRY
1854 return ret;
1857 static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
1858 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1860 BOOL ret;
1861 struct AsnDecodeSequenceItem items[] = {
1862 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1863 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1864 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1865 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1866 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1867 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1869 CERT_RDN_ATTR *attr = pvStructInfo;
1871 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1872 pvStructInfo, *pcbStructInfo);
1874 if (attr)
1875 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1876 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1877 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1878 attr ? attr->pszObjId : NULL);
1879 if (attr)
1881 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1882 debugstr_a(attr->pszObjId));
1883 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1885 TRACE("returning %d (%08x)\n", ret, GetLastError());
1886 return ret;
1889 static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1890 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1892 BOOL ret = TRUE;
1893 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1894 offsetof(CERT_RDN, cRDNAttr), offsetof(CERT_RDN, rgRDNAttr),
1895 sizeof(CERT_RDN),
1896 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1897 offsetof(CERT_RDN_ATTR, pszObjId) };
1899 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1900 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1901 return ret;
1904 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1905 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1906 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1908 BOOL ret = TRUE;
1910 __TRY
1912 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1913 offsetof(CERT_NAME_INFO, cRDN), offsetof(CERT_NAME_INFO, rgRDN),
1914 sizeof(CERT_NAME_INFO),
1915 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1916 offsetof(CERT_RDN, rgRDNAttr) };
1917 DWORD bytesNeeded;
1919 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1920 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded,
1921 NULL);
1922 if (ret)
1924 if (!pvStructInfo)
1925 *pcbStructInfo = bytesNeeded;
1926 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1927 pvStructInfo, pcbStructInfo, bytesNeeded)))
1929 CERT_NAME_INFO *info;
1931 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1932 pvStructInfo = *(BYTE **)pvStructInfo;
1933 info = pvStructInfo;
1934 info->rgRDN = (CERT_RDN *)((BYTE *)pvStructInfo +
1935 sizeof(CERT_NAME_INFO));
1936 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1937 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1938 &bytesNeeded, NULL);
1939 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
1940 CRYPT_FreeSpace(pDecodePara, info);
1944 __EXCEPT_PAGE_FAULT
1946 SetLastError(STATUS_ACCESS_VIOLATION);
1947 ret = FALSE;
1949 __ENDTRY
1950 return ret;
1953 static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
1954 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1955 DWORD *pcbDecoded)
1957 BOOL ret;
1958 struct AsnDecodeSequenceItem items[] = {
1959 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1960 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1961 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1962 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1963 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1964 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1966 CERT_RDN_ATTR *attr = pvStructInfo;
1968 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
1969 pvStructInfo, *pcbStructInfo);
1971 if (attr)
1972 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1973 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
1974 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1975 attr ? attr->pszObjId : NULL);
1976 if (attr)
1978 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1979 debugstr_a(attr->pszObjId));
1980 TRACE("attr->dwValueType is %d\n", attr->dwValueType);
1982 TRACE("returning %d (%08x)\n", ret, GetLastError());
1983 return ret;
1986 static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1987 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1989 BOOL ret = TRUE;
1990 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1991 offsetof(CERT_RDN, cRDNAttr), offsetof(CERT_RDN, rgRDNAttr),
1992 sizeof(CERT_RDN),
1993 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1994 offsetof(CERT_RDN_ATTR, pszObjId) };
1996 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1997 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1998 return ret;
2001 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
2002 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2003 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2005 BOOL ret = TRUE;
2007 __TRY
2009 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2010 offsetof(CERT_NAME_INFO, cRDN), offsetof(CERT_NAME_INFO, rgRDN),
2011 sizeof(CERT_NAME_INFO),
2012 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
2013 offsetof(CERT_RDN, rgRDNAttr) };
2014 DWORD bytesNeeded;
2016 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2017 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded,
2018 NULL);
2019 if (ret)
2021 if (!pvStructInfo)
2022 *pcbStructInfo = bytesNeeded;
2023 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2024 pvStructInfo, pcbStructInfo, bytesNeeded)))
2026 CERT_NAME_INFO *info;
2028 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2029 pvStructInfo = *(BYTE **)pvStructInfo;
2030 info = pvStructInfo;
2031 info->rgRDN = (CERT_RDN *)((BYTE *)pvStructInfo +
2032 sizeof(CERT_NAME_INFO));
2033 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2034 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2035 &bytesNeeded, NULL);
2036 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
2037 CRYPT_FreeSpace(pDecodePara, info);
2041 __EXCEPT_PAGE_FAULT
2043 SetLastError(STATUS_ACCESS_VIOLATION);
2044 ret = FALSE;
2046 __ENDTRY
2047 return ret;
2050 static BOOL CRYPT_FindEncodedLen(const BYTE *pbEncoded, DWORD cbEncoded,
2051 DWORD *pcbDecoded)
2053 BOOL ret = TRUE, done = FALSE;
2054 DWORD indefiniteNestingLevels = 0, decoded = 0;
2056 TRACE("(%p, %d)\n", pbEncoded, cbEncoded);
2058 do {
2059 DWORD dataLen;
2061 if (!cbEncoded)
2062 done = TRUE;
2063 else if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded,
2064 &dataLen)))
2066 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2068 if (dataLen == CMSG_INDEFINITE_LENGTH)
2070 indefiniteNestingLevels++;
2071 pbEncoded += 1 + lenBytes;
2072 cbEncoded -= 1 + lenBytes;
2073 decoded += 1 + lenBytes;
2074 TRACE("indefiniteNestingLevels = %d\n",
2075 indefiniteNestingLevels);
2077 else
2079 if (pbEncoded[0] == 0 && pbEncoded[1] == 0 &&
2080 indefiniteNestingLevels)
2082 indefiniteNestingLevels--;
2083 TRACE("indefiniteNestingLevels = %d\n",
2084 indefiniteNestingLevels);
2086 pbEncoded += 1 + lenBytes + dataLen;
2087 cbEncoded -= 1 + lenBytes + dataLen;
2088 decoded += 1 + lenBytes + dataLen;
2089 if (!indefiniteNestingLevels)
2090 done = TRUE;
2093 } while (ret && !done);
2094 /* If we haven't found all 0 TLVs, we haven't found the end */
2095 if (ret && indefiniteNestingLevels)
2097 SetLastError(CRYPT_E_ASN1_EOD);
2098 ret = FALSE;
2100 if (ret)
2101 *pcbDecoded = decoded;
2102 TRACE("returning %d (%d)\n", ret, ret ? *pcbDecoded : 0);
2103 return ret;
2106 static BOOL CRYPT_AsnDecodeCopyBytes(const BYTE *pbEncoded,
2107 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2108 DWORD *pcbDecoded)
2110 BOOL ret = TRUE;
2111 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB), encodedLen = 0;
2113 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2114 pvStructInfo, *pcbStructInfo);
2116 if ((ret = CRYPT_FindEncodedLen(pbEncoded, cbEncoded, &encodedLen)))
2118 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
2119 bytesNeeded += encodedLen;
2120 if (!pvStructInfo)
2121 *pcbStructInfo = bytesNeeded;
2122 else if (*pcbStructInfo < bytesNeeded)
2124 SetLastError(ERROR_MORE_DATA);
2125 *pcbStructInfo = bytesNeeded;
2126 ret = FALSE;
2128 else
2130 PCRYPT_OBJID_BLOB blob = pvStructInfo;
2132 *pcbStructInfo = bytesNeeded;
2133 blob->cbData = encodedLen;
2134 if (encodedLen)
2136 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2137 blob->pbData = (LPBYTE)pbEncoded;
2138 else
2140 assert(blob->pbData);
2141 memcpy(blob->pbData, pbEncoded, blob->cbData);
2144 else
2145 blob->pbData = NULL;
2147 if (pcbDecoded)
2148 *pcbDecoded = encodedLen;
2150 return ret;
2153 static BOOL CRYPT_AsnDecodeCTLUsage(const BYTE *pbEncoded, DWORD cbEncoded,
2154 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2156 BOOL ret;
2157 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2158 offsetof(CTL_USAGE, cUsageIdentifier),
2159 offsetof(CTL_USAGE, rgpszUsageIdentifier),
2160 sizeof(CTL_USAGE),
2161 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
2163 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2164 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2165 return ret;
2168 static BOOL CRYPT_AsnDecodeCTLEntryAttributes(const BYTE *pbEncoded,
2169 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2170 DWORD *pcbDecoded)
2172 struct AsnArrayDescriptor arrayDesc = { 0,
2173 offsetof(CTL_ENTRY, cAttribute), offsetof(CTL_ENTRY, rgAttribute),
2174 FINALMEMBERSIZE(CTL_ENTRY, cAttribute),
2175 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2176 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2177 BOOL ret;
2179 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2180 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2181 return ret;
2184 static BOOL CRYPT_AsnDecodeCTLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2185 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2187 struct AsnDecodeSequenceItem items[] = {
2188 { ASN_OCTETSTRING, offsetof(CTL_ENTRY, SubjectIdentifier),
2189 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE,
2190 offsetof(CTL_ENTRY, SubjectIdentifier.pbData), 0 },
2191 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CTL_ENTRY, cAttribute),
2192 CRYPT_AsnDecodeCTLEntryAttributes,
2193 FINALMEMBERSIZE(CTL_ENTRY, cAttribute), FALSE, TRUE,
2194 offsetof(CTL_ENTRY, rgAttribute), 0 },
2196 BOOL ret = TRUE;
2197 CTL_ENTRY *entry = pvStructInfo;
2199 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags, entry,
2200 *pcbStructInfo);
2202 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2203 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo,
2204 pcbDecoded, entry ? entry->SubjectIdentifier.pbData : NULL);
2205 return ret;
2208 static BOOL CRYPT_AsnDecodeCTLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
2209 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2211 BOOL ret;
2212 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2213 offsetof(CTL_INFO, cCTLEntry), offsetof(CTL_INFO, rgCTLEntry),
2214 FINALMEMBERSIZE(CTL_INFO, cExtension),
2215 CRYPT_AsnDecodeCTLEntry, sizeof(CTL_ENTRY), TRUE,
2216 offsetof(CTL_ENTRY, SubjectIdentifier.pbData) };
2218 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2219 pvStructInfo, *pcbStructInfo, pcbDecoded);
2221 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2222 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2223 return ret;
2226 static BOOL CRYPT_AsnDecodeCTLExtensionsInternal(const BYTE *pbEncoded,
2227 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2228 DWORD *pcbDecoded)
2230 BOOL ret = TRUE;
2231 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2232 offsetof(CTL_INFO, cExtension), offsetof(CTL_INFO, rgExtension),
2233 FINALMEMBERSIZE(CTL_INFO, cExtension),
2234 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
2235 offsetof(CERT_EXTENSION, pszObjId) };
2237 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2238 pvStructInfo, *pcbStructInfo, pcbDecoded);
2240 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2241 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2242 return ret;
2245 static BOOL CRYPT_AsnDecodeCTLExtensions(const BYTE *pbEncoded,
2246 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2247 DWORD *pcbDecoded)
2249 BOOL ret;
2250 DWORD dataLen;
2252 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2254 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2256 ret = CRYPT_AsnDecodeCTLExtensionsInternal(pbEncoded + 1 + lenBytes,
2257 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
2258 if (ret && pcbDecoded)
2259 *pcbDecoded = 1 + lenBytes + dataLen;
2261 return ret;
2264 static BOOL WINAPI CRYPT_AsnDecodeCTL(DWORD dwCertEncodingType,
2265 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2266 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2268 BOOL ret = FALSE;
2270 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2271 pDecodePara, pvStructInfo, *pcbStructInfo);
2273 __TRY
2275 struct AsnDecodeSequenceItem items[] = {
2276 { ASN_INTEGER, offsetof(CTL_INFO, dwVersion),
2277 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
2278 { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectUsage),
2279 CRYPT_AsnDecodeCTLUsage, sizeof(CTL_USAGE), FALSE, TRUE,
2280 offsetof(CTL_INFO, SubjectUsage.rgpszUsageIdentifier), 0 },
2281 { ASN_OCTETSTRING, offsetof(CTL_INFO, ListIdentifier),
2282 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), TRUE,
2283 TRUE, offsetof(CTL_INFO, ListIdentifier.pbData), 0 },
2284 { ASN_INTEGER, offsetof(CTL_INFO, SequenceNumber),
2285 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2286 TRUE, TRUE, offsetof(CTL_INFO, SequenceNumber.pbData), 0 },
2287 { 0, offsetof(CTL_INFO, ThisUpdate),
2288 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE,
2289 0 },
2290 { 0, offsetof(CTL_INFO, NextUpdate),
2291 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), TRUE, FALSE,
2292 0 },
2293 { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectAlgorithm),
2294 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2295 FALSE, TRUE, offsetof(CTL_INFO, SubjectAlgorithm.pszObjId), 0 },
2296 { ASN_SEQUENCEOF, offsetof(CTL_INFO, cCTLEntry),
2297 CRYPT_AsnDecodeCTLEntries,
2298 MEMBERSIZE(CTL_INFO, cCTLEntry, cExtension),
2299 TRUE, TRUE, offsetof(CTL_INFO, rgCTLEntry), 0 },
2300 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CTL_INFO, cExtension),
2301 CRYPT_AsnDecodeCTLExtensions, FINALMEMBERSIZE(CTL_INFO, cExtension),
2302 TRUE, TRUE, offsetof(CTL_INFO, rgExtension), 0 },
2305 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2306 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2307 pcbStructInfo, NULL, NULL);
2309 __EXCEPT_PAGE_FAULT
2311 SetLastError(STATUS_ACCESS_VIOLATION);
2313 __ENDTRY
2314 return ret;
2317 static BOOL CRYPT_AsnDecodeSMIMECapability(const BYTE *pbEncoded,
2318 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2319 DWORD *pcbDecoded)
2321 BOOL ret;
2322 struct AsnDecodeSequenceItem items[] = {
2323 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_SMIME_CAPABILITY, pszObjId),
2324 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2325 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId), 0 },
2326 { 0, offsetof(CRYPT_SMIME_CAPABILITY, Parameters),
2327 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2328 offsetof(CRYPT_SMIME_CAPABILITY, Parameters.pbData), 0 },
2330 PCRYPT_SMIME_CAPABILITY capability = pvStructInfo;
2332 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2333 pvStructInfo, *pcbStructInfo);
2335 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2336 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2337 pcbDecoded, capability ? capability->pszObjId : NULL);
2338 TRACE("returning %d\n", ret);
2339 return ret;
2342 static BOOL WINAPI CRYPT_AsnDecodeSMIMECapabilities(DWORD dwCertEncodingType,
2343 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2344 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2346 BOOL ret = FALSE;
2348 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2349 pDecodePara, pvStructInfo, *pcbStructInfo);
2351 __TRY
2353 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2354 offsetof(CRYPT_SMIME_CAPABILITIES, cCapability),
2355 offsetof(CRYPT_SMIME_CAPABILITIES, rgCapability),
2356 sizeof(CRYPT_SMIME_CAPABILITIES),
2357 CRYPT_AsnDecodeSMIMECapability, sizeof(CRYPT_SMIME_CAPABILITY), TRUE,
2358 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId) };
2360 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2361 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2363 __EXCEPT_PAGE_FAULT
2365 SetLastError(STATUS_ACCESS_VIOLATION);
2367 __ENDTRY
2368 TRACE("returning %d\n", ret);
2369 return ret;
2372 static BOOL CRYPT_AsnDecodeIA5String(const BYTE *pbEncoded,
2373 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2374 DWORD *pcbDecoded)
2376 BOOL ret = TRUE;
2377 DWORD dataLen;
2378 LPSTR *pStr = pvStructInfo;
2380 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2382 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2383 DWORD bytesNeeded = sizeof(LPSTR) + sizeof(char);
2385 if (pbEncoded[0] != ASN_IA5STRING)
2387 SetLastError(CRYPT_E_ASN1_CORRUPT);
2388 ret = FALSE;
2390 else
2392 bytesNeeded += dataLen;
2393 if (pcbDecoded)
2394 *pcbDecoded = 1 + lenBytes + dataLen;
2395 if (!pvStructInfo)
2396 *pcbStructInfo = bytesNeeded;
2397 else if (*pcbStructInfo < bytesNeeded)
2399 *pcbStructInfo = bytesNeeded;
2400 SetLastError(ERROR_MORE_DATA);
2401 ret = FALSE;
2403 else
2405 *pcbStructInfo = bytesNeeded;
2406 if (dataLen)
2408 LPSTR str = *pStr;
2410 assert(str);
2411 memcpy(str, pbEncoded + 1 + lenBytes, dataLen);
2412 str[dataLen] = 0;
2414 else
2415 *pStr = NULL;
2419 return ret;
2422 static BOOL CRYPT_AsnDecodeNoticeNumbers(const BYTE *pbEncoded,
2423 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2424 DWORD *pcbDecoded)
2426 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2427 offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers),
2428 offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, rgNoticeNumbers),
2429 FINALMEMBERSIZE(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers),
2430 CRYPT_AsnDecodeIntInternal, sizeof(int), FALSE, 0 };
2431 BOOL ret;
2433 TRACE("(%p, %d, %08x, %p, %d)\n", pbEncoded, cbEncoded, dwFlags,
2434 pvStructInfo, pvStructInfo ? *pcbDecoded : 0);
2436 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2437 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2438 TRACE("returning %d\n", ret);
2439 return ret;
2442 static BOOL CRYPT_AsnDecodeNoticeReference(const BYTE *pbEncoded,
2443 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2444 DWORD *pcbDecoded)
2446 BOOL ret;
2447 struct AsnDecodeSequenceItem items[] = {
2448 { ASN_IA5STRING, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2449 pszOrganization), CRYPT_AsnDecodeIA5String, sizeof(LPSTR), FALSE, TRUE,
2450 offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, pszOrganization), 0 },
2451 { ASN_SEQUENCEOF, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2452 cNoticeNumbers), CRYPT_AsnDecodeNoticeNumbers,
2453 FINALMEMBERSIZE(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers),
2454 FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2455 rgNoticeNumbers), 0 },
2457 DWORD bytesNeeded;
2459 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2460 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
2462 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2463 pbEncoded, cbEncoded, dwFlags, NULL, NULL, &bytesNeeded, pcbDecoded,
2464 NULL);
2465 if (ret)
2467 /* The caller is expecting a pointer to a
2468 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE to be decoded, whereas
2469 * CRYPT_AsnDecodeSequence is decoding a
2470 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE. Increment the bytes
2471 * needed, and decode again if the requisite space is available.
2473 bytesNeeded += sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE);
2474 if (!pvStructInfo)
2475 *pcbStructInfo = bytesNeeded;
2476 else if (*pcbStructInfo < bytesNeeded)
2478 *pcbStructInfo = bytesNeeded;
2479 SetLastError(ERROR_MORE_DATA);
2480 ret = FALSE;
2482 else
2484 PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE noticeRef;
2486 *pcbStructInfo = bytesNeeded;
2487 /* The pointer (pvStructInfo) passed in points to the first dynamic
2488 * pointer, so use it as the pointer to the
2489 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, and create the
2490 * appropriate offset for the first dynamic pointer within the
2491 * notice reference by pointing to the first memory location past
2492 * the CERT_POLICY_QUALIFIER_NOTICE_REFERENCE.
2494 noticeRef =
2495 *(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE *)pvStructInfo;
2496 noticeRef->pszOrganization = (LPSTR)((LPBYTE)noticeRef +
2497 sizeof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE));
2498 ret = CRYPT_AsnDecodeSequence(items,
2499 sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
2500 NULL, noticeRef, &bytesNeeded, pcbDecoded,
2501 noticeRef->pszOrganization);
2504 TRACE("returning %d\n", ret);
2505 return ret;
2508 static BOOL CRYPT_AsnDecodeUnicodeString(const BYTE *pbEncoded,
2509 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2510 DWORD *pcbDecoded)
2512 BOOL ret = TRUE;
2513 DWORD dataLen;
2515 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2517 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2518 DWORD bytesNeeded = sizeof(LPWSTR);
2520 switch (pbEncoded[0])
2522 case ASN_NUMERICSTRING:
2523 if (dataLen)
2524 bytesNeeded += (dataLen + 1) * 2;
2525 break;
2526 case ASN_PRINTABLESTRING:
2527 if (dataLen)
2528 bytesNeeded += (dataLen + 1) * 2;
2529 break;
2530 case ASN_IA5STRING:
2531 if (dataLen)
2532 bytesNeeded += (dataLen + 1) * 2;
2533 break;
2534 case ASN_T61STRING:
2535 if (dataLen)
2536 bytesNeeded += (dataLen + 1) * 2;
2537 break;
2538 case ASN_VIDEOTEXSTRING:
2539 if (dataLen)
2540 bytesNeeded += (dataLen + 1) * 2;
2541 break;
2542 case ASN_GRAPHICSTRING:
2543 if (dataLen)
2544 bytesNeeded += (dataLen + 1) * 2;
2545 break;
2546 case ASN_VISIBLESTRING:
2547 if (dataLen)
2548 bytesNeeded += (dataLen + 1) * 2;
2549 break;
2550 case ASN_GENERALSTRING:
2551 if (dataLen)
2552 bytesNeeded += (dataLen + 1) * 2;
2553 break;
2554 case ASN_UNIVERSALSTRING:
2555 if (dataLen)
2556 bytesNeeded += dataLen / 2 + sizeof(WCHAR);
2557 break;
2558 case ASN_BMPSTRING:
2559 if (dataLen)
2560 bytesNeeded += dataLen + sizeof(WCHAR);
2561 break;
2562 case ASN_UTF8STRING:
2563 if (dataLen)
2564 bytesNeeded += (MultiByteToWideChar(CP_UTF8, 0,
2565 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) + 1) * 2;
2566 break;
2567 default:
2568 SetLastError(CRYPT_E_ASN1_BADTAG);
2569 return FALSE;
2572 if (pcbDecoded)
2573 *pcbDecoded = 1 + lenBytes + dataLen;
2574 if (!pvStructInfo)
2575 *pcbStructInfo = bytesNeeded;
2576 else if (*pcbStructInfo < bytesNeeded)
2578 *pcbStructInfo = bytesNeeded;
2579 SetLastError(ERROR_MORE_DATA);
2580 ret = FALSE;
2582 else
2584 LPWSTR *pStr = pvStructInfo;
2586 *pcbStructInfo = bytesNeeded;
2587 if (dataLen)
2589 DWORD i;
2590 LPWSTR str = *(LPWSTR *)pStr;
2592 assert(str);
2593 switch (pbEncoded[0])
2595 case ASN_NUMERICSTRING:
2596 case ASN_PRINTABLESTRING:
2597 case ASN_IA5STRING:
2598 case ASN_T61STRING:
2599 case ASN_VIDEOTEXSTRING:
2600 case ASN_GRAPHICSTRING:
2601 case ASN_VISIBLESTRING:
2602 case ASN_GENERALSTRING:
2603 for (i = 0; i < dataLen; i++)
2604 str[i] = pbEncoded[1 + lenBytes + i];
2605 str[i] = 0;
2606 break;
2607 case ASN_UNIVERSALSTRING:
2608 for (i = 0; i < dataLen / 4; i++)
2609 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
2610 | pbEncoded[1 + lenBytes + 2 * i + 3];
2611 str[i] = 0;
2612 break;
2613 case ASN_BMPSTRING:
2614 for (i = 0; i < dataLen / 2; i++)
2615 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
2616 pbEncoded[1 + lenBytes + 2 * i + 1];
2617 str[i] = 0;
2618 break;
2619 case ASN_UTF8STRING:
2621 int len = MultiByteToWideChar(CP_UTF8, 0,
2622 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
2623 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
2624 str[len] = 0;
2625 break;
2629 else
2630 *pStr = NULL;
2633 return ret;
2636 static BOOL CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(
2637 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
2638 DWORD *pcbStructInfo, DWORD *pcbDecoded)
2640 BOOL ret;
2641 struct AsnDecodeSequenceItem items[] = {
2642 { ASN_SEQUENCE, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE,
2643 pNoticeReference), CRYPT_AsnDecodeNoticeReference,
2644 sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE), TRUE, TRUE,
2645 offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pNoticeReference), 0 },
2646 { 0, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pszDisplayText),
2647 CRYPT_AsnDecodeUnicodeString, sizeof(LPWSTR), TRUE, TRUE,
2648 offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pszDisplayText), 0 },
2650 PCERT_POLICY_QUALIFIER_USER_NOTICE notice = pvStructInfo;
2652 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2653 pvStructInfo, *pcbStructInfo);
2655 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2656 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2657 pcbDecoded, notice ? notice->pNoticeReference : NULL);
2658 TRACE("returning %d\n", ret);
2659 return ret;
2662 static BOOL WINAPI CRYPT_AsnDecodePolicyQualifierUserNotice(
2663 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2664 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2665 void *pvStructInfo, DWORD *pcbStructInfo)
2667 BOOL ret = FALSE;
2669 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2670 pDecodePara, pvStructInfo, *pcbStructInfo);
2672 __TRY
2674 DWORD bytesNeeded;
2676 ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(pbEncoded,
2677 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2678 NULL);
2679 if (ret)
2681 if (!pvStructInfo)
2682 *pcbStructInfo = bytesNeeded;
2683 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2684 pvStructInfo, pcbStructInfo, bytesNeeded)))
2686 PCERT_POLICY_QUALIFIER_USER_NOTICE notice;
2688 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2689 pvStructInfo = *(BYTE **)pvStructInfo;
2690 notice = pvStructInfo;
2691 notice->pNoticeReference =
2692 (PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE)
2693 ((BYTE *)pvStructInfo +
2694 sizeof(CERT_POLICY_QUALIFIER_USER_NOTICE));
2695 ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(
2696 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
2697 pvStructInfo, &bytesNeeded, NULL);
2698 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
2699 CRYPT_FreeSpace(pDecodePara, notice);
2703 __EXCEPT_PAGE_FAULT
2705 SetLastError(STATUS_ACCESS_VIOLATION);
2707 __ENDTRY
2708 TRACE("returning %d\n", ret);
2709 return ret;
2712 static BOOL CRYPT_AsnDecodePKCSAttributeValue(const BYTE *pbEncoded,
2713 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2714 DWORD *pcbDecoded)
2716 BOOL ret;
2717 struct AsnArrayDescriptor arrayDesc = { 0,
2718 offsetof(CRYPT_ATTRIBUTE, cValue), offsetof(CRYPT_ATTRIBUTE, rgValue),
2719 FINALMEMBERSIZE(CRYPT_ATTRIBUTE, cValue),
2720 CRYPT_AsnDecodeCopyBytes,
2721 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
2723 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2724 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
2726 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2727 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2728 return ret;
2731 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
2732 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2733 DWORD *pcbDecoded)
2735 BOOL ret;
2736 struct AsnDecodeSequenceItem items[] = {
2737 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
2738 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2739 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
2740 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
2741 CRYPT_AsnDecodePKCSAttributeValue,
2742 FINALMEMBERSIZE(CRYPT_ATTRIBUTE, cValue), FALSE,
2743 TRUE, offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
2745 PCRYPT_ATTRIBUTE attr = pvStructInfo;
2747 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2748 pvStructInfo, *pcbStructInfo);
2750 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2751 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2752 pcbDecoded, attr ? attr->pszObjId : NULL);
2753 TRACE("returning %d\n", ret);
2754 return ret;
2757 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
2758 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2759 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2761 BOOL ret = FALSE;
2763 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2764 pDecodePara, pvStructInfo, *pcbStructInfo);
2766 __TRY
2768 DWORD bytesNeeded;
2770 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2771 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
2772 if (ret)
2774 if (!pvStructInfo)
2775 *pcbStructInfo = bytesNeeded;
2776 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2777 pvStructInfo, pcbStructInfo, bytesNeeded)))
2779 PCRYPT_ATTRIBUTE attr;
2781 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2782 pvStructInfo = *(BYTE **)pvStructInfo;
2783 attr = pvStructInfo;
2784 attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
2785 sizeof(CRYPT_ATTRIBUTE));
2786 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2787 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
2788 NULL);
2789 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
2790 CRYPT_FreeSpace(pDecodePara, attr);
2794 __EXCEPT_PAGE_FAULT
2796 SetLastError(STATUS_ACCESS_VIOLATION);
2798 __ENDTRY
2799 TRACE("returning %d\n", ret);
2800 return ret;
2803 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
2804 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2805 DWORD *pcbDecoded)
2807 struct AsnArrayDescriptor arrayDesc = { 0,
2808 offsetof(CRYPT_ATTRIBUTES, cAttr), offsetof(CRYPT_ATTRIBUTES, rgAttr),
2809 sizeof(CRYPT_ATTRIBUTES),
2810 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2811 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2812 BOOL ret;
2814 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2815 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2816 return ret;
2819 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
2820 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2821 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2823 BOOL ret = FALSE;
2825 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2826 pDecodePara, pvStructInfo, *pcbStructInfo);
2828 __TRY
2830 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
2831 offsetof(CRYPT_ATTRIBUTES, cAttr), offsetof(CRYPT_ATTRIBUTES, rgAttr),
2832 sizeof(CRYPT_ATTRIBUTES),
2833 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE),
2834 TRUE, offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2836 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2837 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2839 __EXCEPT_PAGE_FAULT
2841 SetLastError(STATUS_ACCESS_VIOLATION);
2843 __ENDTRY
2844 TRACE("returning %d\n", ret);
2845 return ret;
2848 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
2849 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2851 CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
2852 BOOL ret = TRUE;
2853 struct AsnDecodeSequenceItem items[] = {
2854 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
2855 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2856 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
2857 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
2858 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2859 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
2862 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
2863 pvStructInfo, *pcbStructInfo, pcbDecoded);
2865 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2866 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2867 pcbDecoded, algo ? algo->pszObjId : NULL);
2868 if (ret && pvStructInfo)
2870 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
2871 debugstr_a(algo->pszObjId));
2873 return ret;
2876 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
2877 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2878 DWORD *pcbDecoded)
2880 BOOL ret = TRUE;
2881 struct AsnDecodeSequenceItem items[] = {
2882 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
2883 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2884 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
2885 Algorithm.pszObjId) },
2886 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
2887 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2888 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
2890 PCERT_PUBLIC_KEY_INFO info = pvStructInfo;
2892 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
2893 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2894 pcbDecoded, info ? info->Algorithm.Parameters.pbData : NULL);
2895 return ret;
2898 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2899 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2900 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2902 BOOL ret = TRUE;
2904 __TRY
2906 DWORD bytesNeeded;
2908 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2909 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2911 if (!pvStructInfo)
2912 *pcbStructInfo = bytesNeeded;
2913 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2914 pvStructInfo, pcbStructInfo, bytesNeeded)))
2916 PCERT_PUBLIC_KEY_INFO info;
2918 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2919 pvStructInfo = *(BYTE **)pvStructInfo;
2920 info = pvStructInfo;
2921 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2922 sizeof(CERT_PUBLIC_KEY_INFO);
2923 ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2924 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2925 &bytesNeeded, NULL);
2926 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
2927 CRYPT_FreeSpace(pDecodePara, info);
2931 __EXCEPT_PAGE_FAULT
2933 SetLastError(STATUS_ACCESS_VIOLATION);
2934 ret = FALSE;
2936 __ENDTRY
2937 return ret;
2940 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
2941 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2943 BOOL ret;
2945 if (cbEncoded < 3)
2947 SetLastError(CRYPT_E_ASN1_CORRUPT);
2948 return FALSE;
2950 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2952 SetLastError(CRYPT_E_ASN1_CORRUPT);
2953 return FALSE;
2955 if (pbEncoded[1] > 1)
2957 SetLastError(CRYPT_E_ASN1_CORRUPT);
2958 return FALSE;
2960 if (pcbDecoded)
2961 *pcbDecoded = 3;
2962 if (!pvStructInfo)
2964 *pcbStructInfo = sizeof(BOOL);
2965 ret = TRUE;
2967 else if (*pcbStructInfo < sizeof(BOOL))
2969 *pcbStructInfo = sizeof(BOOL);
2970 SetLastError(ERROR_MORE_DATA);
2971 ret = FALSE;
2973 else
2975 *pcbStructInfo = sizeof(BOOL);
2976 *(BOOL *)pvStructInfo = pbEncoded[2] ? TRUE : FALSE;
2977 ret = TRUE;
2979 TRACE("returning %d (%08x)\n", ret, GetLastError());
2980 return ret;
2983 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2984 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2986 PCERT_ALT_NAME_ENTRY entry = pvStructInfo;
2987 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2988 BOOL ret;
2990 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
2991 pvStructInfo, *pcbStructInfo);
2993 if (cbEncoded < 2)
2995 SetLastError(CRYPT_E_ASN1_CORRUPT);
2996 return FALSE;
2998 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2999 if (1 + lenBytes > cbEncoded)
3001 SetLastError(CRYPT_E_ASN1_CORRUPT);
3002 return FALSE;
3004 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3006 switch (pbEncoded[0] & ASN_TYPE_MASK)
3008 case 1: /* rfc822Name */
3009 case 2: /* dNSName */
3010 case 6: /* uniformResourceIdentifier */
3011 if (memchr(pbEncoded + 1 + lenBytes, 0, dataLen))
3013 SetLastError(CRYPT_E_ASN1_RULE);
3014 ret = FALSE;
3016 else
3017 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
3018 break;
3019 case 4: /* directoryName */
3020 case 7: /* iPAddress */
3021 bytesNeeded += dataLen;
3022 break;
3023 case 8: /* registeredID */
3024 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
3025 &dataLen, NULL);
3026 if (ret)
3028 /* FIXME: ugly, shouldn't need to know internals of OID decode
3029 * function to use it.
3031 bytesNeeded += dataLen - sizeof(LPSTR);
3033 break;
3034 case 0: /* otherName */
3035 FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
3036 SetLastError(CRYPT_E_ASN1_BADTAG);
3037 ret = FALSE;
3038 break;
3039 case 3: /* x400Address, unimplemented */
3040 case 5: /* ediPartyName, unimplemented */
3041 TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
3042 SetLastError(CRYPT_E_ASN1_BADTAG);
3043 ret = FALSE;
3044 break;
3045 default:
3046 TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
3047 SetLastError(CRYPT_E_ASN1_CORRUPT);
3048 ret = FALSE;
3050 if (ret)
3052 if (pcbDecoded)
3053 *pcbDecoded = 1 + lenBytes + dataLen;
3054 if (!entry)
3055 *pcbStructInfo = bytesNeeded;
3056 else if (*pcbStructInfo < bytesNeeded)
3058 *pcbStructInfo = bytesNeeded;
3059 SetLastError(ERROR_MORE_DATA);
3060 ret = FALSE;
3062 else
3064 *pcbStructInfo = bytesNeeded;
3065 /* MS used values one greater than the asn1 ones.. sigh */
3066 entry->dwAltNameChoice = (pbEncoded[0] & ASN_TYPE_MASK) + 1;
3067 switch (pbEncoded[0] & ASN_TYPE_MASK)
3069 case 1: /* rfc822Name */
3070 case 2: /* dNSName */
3071 case 6: /* uniformResourceIdentifier */
3073 DWORD i;
3075 for (i = 0; i < dataLen; i++)
3076 entry->u.pwszURL[i] =
3077 (WCHAR)pbEncoded[1 + lenBytes + i];
3078 entry->u.pwszURL[i] = 0;
3079 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
3080 debugstr_w(entry->u.pwszURL));
3081 break;
3083 case 4: /* directoryName */
3084 /* The data are memory-equivalent with the IPAddress case,
3085 * fall-through
3087 case 7: /* iPAddress */
3088 /* The next data pointer is in the pwszURL spot, that is,
3089 * the first 4 bytes. Need to move it to the next spot.
3091 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
3092 entry->u.IPAddress.cbData = dataLen;
3093 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
3094 dataLen);
3095 break;
3096 case 8: /* registeredID */
3097 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
3098 &entry->u.pszRegisteredID, &dataLen, NULL);
3099 break;
3104 return ret;
3107 static BOOL CRYPT_AsnDecodeAltNameInternal(const BYTE *pbEncoded,
3108 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3109 DWORD *pcbDecoded)
3111 BOOL ret;
3112 struct AsnArrayDescriptor arrayDesc = { 0,
3113 offsetof(CERT_ALT_NAME_INFO, cAltEntry),
3114 offsetof(CERT_ALT_NAME_INFO, rgAltEntry),
3115 sizeof(CERT_ALT_NAME_INFO),
3116 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3117 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3119 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3120 pvStructInfo, *pcbStructInfo, pcbDecoded);
3122 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3123 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
3124 return ret;
3127 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
3128 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3129 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3131 BOOL ret;
3133 __TRY
3135 struct AsnDecodeSequenceItem items[] = {
3136 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
3137 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB),
3138 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
3139 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
3140 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
3141 CRYPT_AsnDecodeOctetsInternal, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
3142 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
3143 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
3144 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
3145 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
3146 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
3149 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3150 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3151 pcbStructInfo, NULL, NULL);
3153 __EXCEPT_PAGE_FAULT
3155 SetLastError(STATUS_ACCESS_VIOLATION);
3156 ret = FALSE;
3158 __ENDTRY
3159 return ret;
3162 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
3163 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3164 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3166 BOOL ret;
3168 __TRY
3170 struct AsnDecodeSequenceItem items[] = {
3171 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
3172 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB),
3173 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
3174 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
3175 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
3176 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
3177 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3178 AuthorityCertIssuer.rgAltEntry), 0 },
3179 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3180 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
3181 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
3182 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3183 AuthorityCertSerialNumber.pbData), 0 },
3186 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3187 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3188 pcbStructInfo, NULL, NULL);
3190 __EXCEPT_PAGE_FAULT
3192 SetLastError(STATUS_ACCESS_VIOLATION);
3193 ret = FALSE;
3195 __ENDTRY
3196 return ret;
3199 static BOOL CRYPT_AsnDecodeAccessDescription(const BYTE *pbEncoded,
3200 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3201 DWORD *pcbDecoded)
3203 struct AsnDecodeSequenceItem items[] = {
3204 { 0, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod),
3205 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
3206 offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod), 0 },
3207 { 0, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation),
3208 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), FALSE,
3209 TRUE, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation.u.pwszURL), 0 },
3211 CERT_ACCESS_DESCRIPTION *descr = pvStructInfo;
3213 return CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3214 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3215 pcbDecoded, descr ? descr->pszAccessMethod : NULL);
3218 static BOOL WINAPI CRYPT_AsnDecodeAuthorityInfoAccess(DWORD dwCertEncodingType,
3219 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3220 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3222 BOOL ret;
3224 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3225 pDecodePara, pvStructInfo, *pcbStructInfo);
3227 __TRY
3229 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3230 offsetof(CERT_AUTHORITY_INFO_ACCESS, cAccDescr),
3231 offsetof(CERT_AUTHORITY_INFO_ACCESS, rgAccDescr),
3232 sizeof(CERT_AUTHORITY_INFO_ACCESS),
3233 CRYPT_AsnDecodeAccessDescription, sizeof(CERT_ACCESS_DESCRIPTION),
3234 TRUE, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod) };
3236 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3237 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3239 __EXCEPT_PAGE_FAULT
3241 SetLastError(STATUS_ACCESS_VIOLATION);
3242 ret = FALSE;
3244 __ENDTRY
3245 return ret;
3248 static BOOL CRYPT_AsnDecodePKCSContent(const BYTE *pbEncoded, DWORD cbEncoded,
3249 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3251 BOOL ret;
3252 DWORD dataLen;
3254 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3255 pvStructInfo, *pcbStructInfo, pcbDecoded);
3257 /* The caller has already checked the tag, no need to check it again.
3258 * Check the outer length is valid:
3260 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
3262 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3263 DWORD innerLen;
3265 pbEncoded += 1 + lenBytes;
3266 cbEncoded -= 1 + lenBytes;
3267 if (dataLen == CMSG_INDEFINITE_LENGTH)
3268 cbEncoded -= 2; /* space for 0 TLV */
3269 /* Check the inner length is valid: */
3270 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &innerLen)))
3272 DWORD decodedLen;
3274 ret = CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags,
3275 pvStructInfo, pcbStructInfo, &decodedLen);
3276 if (dataLen == CMSG_INDEFINITE_LENGTH)
3278 if (*(pbEncoded + decodedLen) != 0 ||
3279 *(pbEncoded + decodedLen + 1) != 0)
3281 TRACE("expected 0 TLV, got {%02x,%02x}\n",
3282 *(pbEncoded + decodedLen),
3283 *(pbEncoded + decodedLen + 1));
3284 SetLastError(CRYPT_E_ASN1_CORRUPT);
3285 ret = FALSE;
3287 else
3288 decodedLen += 2;
3290 if (ret && pcbDecoded)
3292 *pcbDecoded = 1 + lenBytes + decodedLen;
3293 TRACE("decoded %d bytes\n", *pcbDecoded);
3297 return ret;
3300 static BOOL CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE *pbEncoded,
3301 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3302 DWORD *pcbDecoded)
3304 CRYPT_CONTENT_INFO *info = pvStructInfo;
3305 struct AsnDecodeSequenceItem items[] = {
3306 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
3307 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
3308 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
3309 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
3310 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
3311 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
3312 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
3314 BOOL ret;
3316 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3317 pvStructInfo, *pcbStructInfo, pcbDecoded);
3319 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3320 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3321 pcbDecoded, info ? info->pszObjId : NULL);
3322 return ret;
3325 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
3326 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3327 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3329 BOOL ret = FALSE;
3331 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3332 pDecodePara, pvStructInfo, *pcbStructInfo);
3334 __TRY
3336 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, cbEncoded,
3337 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
3338 if (ret && pvStructInfo)
3340 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
3341 pcbStructInfo, *pcbStructInfo);
3342 if (ret)
3344 CRYPT_CONTENT_INFO *info;
3346 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3347 pvStructInfo = *(BYTE **)pvStructInfo;
3348 info = pvStructInfo;
3349 info->pszObjId = (LPSTR)((BYTE *)info +
3350 sizeof(CRYPT_CONTENT_INFO));
3351 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded,
3352 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3353 pcbStructInfo, NULL);
3354 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
3355 CRYPT_FreeSpace(pDecodePara, info);
3359 __EXCEPT_PAGE_FAULT
3361 SetLastError(STATUS_ACCESS_VIOLATION);
3363 __ENDTRY
3364 return ret;
3367 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
3368 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3369 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
3371 BOOL ret;
3372 struct AsnDecodeSequenceItem items[] = {
3373 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version),
3374 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3375 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
3376 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3377 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
3378 0 },
3379 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
3380 CRYPT_AsnDecodePKCSContentInfoInternal,
3381 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
3382 ContentInfo.pszObjId), 0 },
3383 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
3384 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
3385 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
3388 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3389 pbEncoded, cbEncoded, dwFlags, pDecodePara, digestedData, pcbDigestedData,
3390 NULL, NULL);
3391 return ret;
3394 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
3395 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3396 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3398 BOOL ret = TRUE;
3400 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3401 pDecodePara, pvStructInfo, *pcbStructInfo);
3403 __TRY
3405 DWORD bytesNeeded;
3407 if ((ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
3408 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3410 if (!pvStructInfo)
3411 *pcbStructInfo = bytesNeeded;
3412 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3413 pvStructInfo, pcbStructInfo, bytesNeeded)))
3415 CERT_ALT_NAME_INFO *name;
3417 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3418 pvStructInfo = *(BYTE **)pvStructInfo;
3419 name = pvStructInfo;
3420 name->rgAltEntry = (PCERT_ALT_NAME_ENTRY)
3421 ((BYTE *)pvStructInfo + sizeof(CERT_ALT_NAME_INFO));
3422 ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
3423 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3424 &bytesNeeded, NULL);
3425 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
3426 CRYPT_FreeSpace(pDecodePara, name);
3430 __EXCEPT_PAGE_FAULT
3432 SetLastError(STATUS_ACCESS_VIOLATION);
3433 ret = FALSE;
3435 __ENDTRY
3436 return ret;
3439 struct PATH_LEN_CONSTRAINT
3441 BOOL fPathLenConstraint;
3442 DWORD dwPathLenConstraint;
3445 static BOOL CRYPT_AsnDecodePathLenConstraint(const BYTE *pbEncoded,
3446 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3447 DWORD *pcbDecoded)
3449 BOOL ret = TRUE;
3450 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT), size;
3452 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3453 pvStructInfo, *pcbStructInfo, pcbDecoded);
3455 if (!pvStructInfo)
3457 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, NULL,
3458 &size, pcbDecoded);
3459 *pcbStructInfo = bytesNeeded;
3461 else if (*pcbStructInfo < bytesNeeded)
3463 SetLastError(ERROR_MORE_DATA);
3464 *pcbStructInfo = bytesNeeded;
3465 ret = FALSE;
3467 else
3469 struct PATH_LEN_CONSTRAINT *constraint = pvStructInfo;
3471 *pcbStructInfo = bytesNeeded;
3472 size = sizeof(constraint->dwPathLenConstraint);
3473 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
3474 &constraint->dwPathLenConstraint, &size, pcbDecoded);
3475 if (ret)
3476 constraint->fPathLenConstraint = TRUE;
3477 TRACE("got an int, dwPathLenConstraint is %d\n",
3478 constraint->dwPathLenConstraint);
3480 TRACE("returning %d (%08x)\n", ret, GetLastError());
3481 return ret;
3484 static BOOL CRYPT_AsnDecodeSubtreeConstraints(const BYTE *pbEncoded,
3485 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3486 DWORD *pcbDecoded)
3488 BOOL ret;
3489 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3490 offsetof(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint),
3491 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint),
3492 FINALMEMBERSIZE(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint),
3493 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
3494 offsetof(CERT_NAME_BLOB, pbData) };
3496 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3497 pvStructInfo, *pcbStructInfo, pcbDecoded);
3499 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3500 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
3501 TRACE("Returning %d (%08x)\n", ret, GetLastError());
3502 return ret;
3505 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
3506 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3507 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3509 BOOL ret;
3511 __TRY
3513 struct AsnDecodeSequenceItem items[] = {
3514 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
3515 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
3516 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
3517 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3518 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3519 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3520 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3521 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
3522 FINALMEMBERSIZE(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint),
3523 TRUE, TRUE,
3524 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
3527 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3528 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3529 pcbStructInfo, NULL, NULL);
3531 __EXCEPT_PAGE_FAULT
3533 SetLastError(STATUS_ACCESS_VIOLATION);
3534 ret = FALSE;
3536 __ENDTRY
3537 return ret;
3540 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
3541 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3542 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3544 BOOL ret;
3546 __TRY
3548 struct AsnDecodeSequenceItem items[] = {
3549 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
3550 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
3551 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
3552 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3553 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3556 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3557 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3558 pcbStructInfo, NULL, NULL);
3560 __EXCEPT_PAGE_FAULT
3562 SetLastError(STATUS_ACCESS_VIOLATION);
3563 ret = FALSE;
3565 __ENDTRY
3566 return ret;
3569 static BOOL CRYPT_AsnDecodePolicyQualifier(const BYTE *pbEncoded,
3570 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3571 DWORD *pcbDecoded)
3573 struct AsnDecodeSequenceItem items[] = {
3574 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_QUALIFIER_INFO,
3575 pszPolicyQualifierId), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
3576 FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId),
3577 0 },
3578 { 0, offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier),
3579 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
3580 offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier.pbData), 0 },
3582 BOOL ret;
3583 CERT_POLICY_QUALIFIER_INFO *qualifier = pvStructInfo;
3585 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3586 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3588 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3589 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3590 pcbDecoded, qualifier ? qualifier->pszPolicyQualifierId : NULL);
3591 return ret;
3594 static BOOL CRYPT_AsnDecodePolicyQualifiers(const BYTE *pbEncoded,
3595 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3596 DWORD *pcbDecoded)
3598 BOOL ret;
3599 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3600 offsetof(CERT_POLICY_INFO, cPolicyQualifier),
3601 offsetof(CERT_POLICY_INFO, rgPolicyQualifier),
3602 FINALMEMBERSIZE(CERT_POLICY_INFO, cPolicyQualifier),
3603 CRYPT_AsnDecodePolicyQualifier, sizeof(CERT_POLICY_QUALIFIER_INFO), TRUE,
3604 offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId) };
3606 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3607 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3609 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3610 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
3611 TRACE("Returning %d (%08x)\n", ret, GetLastError());
3612 return ret;
3615 static BOOL CRYPT_AsnDecodeCertPolicy(const BYTE *pbEncoded, DWORD cbEncoded,
3616 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3618 struct AsnDecodeSequenceItem items[] = {
3619 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_INFO, pszPolicyIdentifier),
3620 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
3621 offsetof(CERT_POLICY_INFO, pszPolicyIdentifier), 0 },
3622 { ASN_SEQUENCEOF, offsetof(CERT_POLICY_INFO, cPolicyQualifier),
3623 CRYPT_AsnDecodePolicyQualifiers,
3624 FINALMEMBERSIZE(CERT_POLICY_INFO, cPolicyQualifier), TRUE,
3625 TRUE, offsetof(CERT_POLICY_INFO, rgPolicyQualifier), 0 },
3627 CERT_POLICY_INFO *info = pvStructInfo;
3628 BOOL ret;
3630 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3631 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3633 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3634 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3635 pcbDecoded, info ? info->pszPolicyIdentifier : NULL);
3636 return ret;
3639 static BOOL WINAPI CRYPT_AsnDecodeCertPolicies(DWORD dwCertEncodingType,
3640 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3641 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3643 BOOL ret = FALSE;
3645 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3646 pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3648 __TRY
3650 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3651 offsetof(CERT_POLICIES_INFO, cPolicyInfo),
3652 offsetof(CERT_POLICIES_INFO, rgPolicyInfo),
3653 sizeof(CERT_POLICIES_INFO),
3654 CRYPT_AsnDecodeCertPolicy, sizeof(CERT_POLICY_INFO), TRUE,
3655 offsetof(CERT_POLICY_INFO, pszPolicyIdentifier) };
3657 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3658 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3660 __EXCEPT_PAGE_FAULT
3662 SetLastError(STATUS_ACCESS_VIOLATION);
3664 __ENDTRY
3665 return ret;
3668 static BOOL CRYPT_AsnDecodeCertPolicyMapping(const BYTE *pbEncoded,
3669 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3670 DWORD *pcbDecoded)
3672 struct AsnDecodeSequenceItem items[] = {
3673 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_MAPPING,
3674 pszIssuerDomainPolicy), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
3675 FALSE, TRUE, offsetof(CERT_POLICY_MAPPING, pszIssuerDomainPolicy), 0 },
3676 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_MAPPING,
3677 pszSubjectDomainPolicy), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
3678 FALSE, TRUE, offsetof(CERT_POLICY_MAPPING, pszSubjectDomainPolicy), 0 },
3680 CERT_POLICY_MAPPING *mapping = pvStructInfo;
3681 BOOL ret;
3683 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3684 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3686 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3687 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3688 pcbDecoded, mapping ? mapping->pszIssuerDomainPolicy : NULL);
3689 return ret;
3692 static BOOL WINAPI CRYPT_AsnDecodeCertPolicyMappings(DWORD dwCertEncodingType,
3693 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3694 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3696 BOOL ret = FALSE;
3698 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3699 pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3701 __TRY
3703 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3704 offsetof(CERT_POLICY_MAPPINGS_INFO, cPolicyMapping),
3705 offsetof(CERT_POLICY_MAPPINGS_INFO, rgPolicyMapping),
3706 sizeof(CERT_POLICY_MAPPING),
3707 CRYPT_AsnDecodeCertPolicyMapping, sizeof(CERT_POLICY_MAPPING), TRUE,
3708 offsetof(CERT_POLICY_MAPPING, pszIssuerDomainPolicy) };
3710 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3711 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3713 __EXCEPT_PAGE_FAULT
3715 SetLastError(STATUS_ACCESS_VIOLATION);
3717 __ENDTRY
3718 return ret;
3721 static BOOL CRYPT_AsnDecodeRequireExplicit(const BYTE *pbEncoded,
3722 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3723 DWORD *pcbDecoded)
3725 BOOL ret;
3726 DWORD skip, size = sizeof(skip);
3728 if (!cbEncoded)
3730 SetLastError(CRYPT_E_ASN1_EOD);
3731 return FALSE;
3733 if (pbEncoded[0] != (ASN_CONTEXT | 0))
3735 SetLastError(CRYPT_E_ASN1_BADTAG);
3736 return FALSE;
3738 if ((ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
3739 &skip, &size, pcbDecoded)))
3741 DWORD bytesNeeded = MEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO,
3742 fRequireExplicitPolicy, fInhibitPolicyMapping);
3744 if (!pvStructInfo)
3745 *pcbStructInfo = bytesNeeded;
3746 else if (*pcbStructInfo < bytesNeeded)
3748 *pcbStructInfo = bytesNeeded;
3749 SetLastError(ERROR_MORE_DATA);
3750 ret = FALSE;
3752 else
3754 CERT_POLICY_CONSTRAINTS_INFO *info = CONTAINING_RECORD(pvStructInfo,
3755 CERT_POLICY_CONSTRAINTS_INFO, fRequireExplicitPolicy);
3757 *pcbStructInfo = bytesNeeded;
3758 /* The BOOL is implicit: if the integer is present, then it's
3759 * TRUE.
3761 info->fRequireExplicitPolicy = TRUE;
3762 info->dwRequireExplicitPolicySkipCerts = skip;
3765 return ret;
3768 static BOOL CRYPT_AsnDecodeInhibitMapping(const BYTE *pbEncoded,
3769 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3770 DWORD *pcbDecoded)
3772 BOOL ret;
3773 DWORD skip, size = sizeof(skip);
3775 if (!cbEncoded)
3777 SetLastError(CRYPT_E_ASN1_EOD);
3778 return FALSE;
3780 if (pbEncoded[0] != (ASN_CONTEXT | 1))
3782 SetLastError(CRYPT_E_ASN1_BADTAG);
3783 return FALSE;
3785 if ((ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
3786 &skip, &size, pcbDecoded)))
3788 DWORD bytesNeeded = FINALMEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO,
3789 fInhibitPolicyMapping);
3791 if (!pvStructInfo)
3792 *pcbStructInfo = bytesNeeded;
3793 else if (*pcbStructInfo < bytesNeeded)
3795 *pcbStructInfo = bytesNeeded;
3796 SetLastError(ERROR_MORE_DATA);
3797 ret = FALSE;
3799 else
3801 CERT_POLICY_CONSTRAINTS_INFO *info = CONTAINING_RECORD(pvStructInfo,
3802 CERT_POLICY_CONSTRAINTS_INFO, fInhibitPolicyMapping);
3804 *pcbStructInfo = bytesNeeded;
3805 /* The BOOL is implicit: if the integer is present, then it's
3806 * TRUE.
3808 info->fInhibitPolicyMapping = TRUE;
3809 info->dwInhibitPolicyMappingSkipCerts = skip;
3812 return ret;
3815 static BOOL WINAPI CRYPT_AsnDecodeCertPolicyConstraints(
3816 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
3817 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3818 void *pvStructInfo, DWORD *pcbStructInfo)
3820 BOOL ret = FALSE;
3822 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3823 pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3825 __TRY
3827 struct AsnDecodeSequenceItem items[] = {
3828 { ASN_CONTEXT | 0,
3829 offsetof(CERT_POLICY_CONSTRAINTS_INFO, fRequireExplicitPolicy),
3830 CRYPT_AsnDecodeRequireExplicit,
3831 MEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO, fRequireExplicitPolicy,
3832 fInhibitPolicyMapping), TRUE, FALSE, 0, 0 },
3833 { ASN_CONTEXT | 1,
3834 offsetof(CERT_POLICY_CONSTRAINTS_INFO, fInhibitPolicyMapping),
3835 CRYPT_AsnDecodeInhibitMapping,
3836 FINALMEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO, fInhibitPolicyMapping),
3837 TRUE, FALSE, 0, 0 },
3840 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3841 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3842 pcbStructInfo, NULL, NULL);
3844 __EXCEPT_PAGE_FAULT
3846 SetLastError(STATUS_ACCESS_VIOLATION);
3848 __ENDTRY
3849 return ret;
3852 #define RSA1_MAGIC 0x31415352
3854 struct DECODED_RSA_PUB_KEY
3856 DWORD pubexp;
3857 CRYPT_INTEGER_BLOB modulus;
3860 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
3861 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3862 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3864 BOOL ret;
3866 __TRY
3868 struct AsnDecodeSequenceItem items[] = {
3869 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
3870 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3871 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
3872 0 },
3873 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
3874 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3876 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
3877 DWORD size = 0;
3879 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
3880 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
3881 &size, NULL, NULL);
3882 if (ret)
3884 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
3885 decodedKey->modulus.cbData;
3887 if (!pvStructInfo)
3889 *pcbStructInfo = bytesNeeded;
3890 ret = TRUE;
3892 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3893 pvStructInfo, pcbStructInfo, bytesNeeded)))
3895 BLOBHEADER *hdr;
3896 RSAPUBKEY *rsaPubKey;
3898 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3899 pvStructInfo = *(BYTE **)pvStructInfo;
3900 hdr = pvStructInfo;
3901 hdr->bType = PUBLICKEYBLOB;
3902 hdr->bVersion = CUR_BLOB_VERSION;
3903 hdr->reserved = 0;
3904 hdr->aiKeyAlg = CALG_RSA_KEYX;
3905 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
3906 sizeof(BLOBHEADER));
3907 rsaPubKey->magic = RSA1_MAGIC;
3908 rsaPubKey->pubexp = decodedKey->pubexp;
3909 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
3910 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
3911 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
3912 decodedKey->modulus.cbData);
3914 LocalFree(decodedKey);
3917 __EXCEPT_PAGE_FAULT
3919 SetLastError(STATUS_ACCESS_VIOLATION);
3920 ret = FALSE;
3922 __ENDTRY
3923 return ret;
3926 static BOOL CRYPT_AsnDecodeOctetsInternal(const BYTE *pbEncoded,
3927 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3928 DWORD *pcbDecoded)
3930 BOOL ret;
3931 DWORD bytesNeeded, dataLen;
3933 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
3934 pvStructInfo, *pcbStructInfo, pcbDecoded);
3936 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3938 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3940 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3941 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
3942 else
3943 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
3944 if (pcbDecoded)
3945 *pcbDecoded = 1 + lenBytes + dataLen;
3946 if (!pvStructInfo)
3947 *pcbStructInfo = bytesNeeded;
3948 else if (*pcbStructInfo < bytesNeeded)
3950 SetLastError(ERROR_MORE_DATA);
3951 *pcbStructInfo = bytesNeeded;
3952 ret = FALSE;
3954 else
3956 CRYPT_DATA_BLOB *blob;
3958 *pcbStructInfo = bytesNeeded;
3959 blob = pvStructInfo;
3960 blob->cbData = dataLen;
3961 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
3962 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
3963 else
3965 assert(blob->pbData);
3966 if (blob->cbData)
3967 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
3968 blob->cbData);
3972 return ret;
3975 static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
3976 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3977 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3979 BOOL ret;
3981 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
3982 pDecodePara, pvStructInfo, *pcbStructInfo);
3984 __TRY
3986 DWORD bytesNeeded;
3988 if (!cbEncoded)
3990 SetLastError(CRYPT_E_ASN1_CORRUPT);
3991 ret = FALSE;
3993 else if (pbEncoded[0] != ASN_OCTETSTRING)
3995 SetLastError(CRYPT_E_ASN1_BADTAG);
3996 ret = FALSE;
3998 else if ((ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
3999 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4001 if (!pvStructInfo)
4002 *pcbStructInfo = bytesNeeded;
4003 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4004 pvStructInfo, pcbStructInfo, bytesNeeded)))
4006 CRYPT_DATA_BLOB *blob;
4008 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4009 pvStructInfo = *(BYTE **)pvStructInfo;
4010 blob = pvStructInfo;
4011 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
4012 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded,
4013 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4014 &bytesNeeded, NULL);
4015 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4016 CRYPT_FreeSpace(pDecodePara, blob);
4020 __EXCEPT_PAGE_FAULT
4022 SetLastError(STATUS_ACCESS_VIOLATION);
4023 ret = FALSE;
4025 __ENDTRY
4026 return ret;
4029 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
4030 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4032 BOOL ret;
4033 DWORD bytesNeeded, dataLen;
4034 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4036 TRACE("(%p, %d, 0x%08x, %p, %d, %p)\n", pbEncoded, cbEncoded, dwFlags,
4037 pvStructInfo, *pcbStructInfo, pcbDecoded);
4039 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4041 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4042 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
4043 else
4044 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
4045 if (pcbDecoded)
4046 *pcbDecoded = 1 + lenBytes + dataLen;
4047 if (!pvStructInfo)
4048 *pcbStructInfo = bytesNeeded;
4049 else if (*pcbStructInfo < bytesNeeded)
4051 *pcbStructInfo = bytesNeeded;
4052 SetLastError(ERROR_MORE_DATA);
4053 ret = FALSE;
4055 else
4057 CRYPT_BIT_BLOB *blob;
4059 *pcbStructInfo = bytesNeeded;
4060 blob = pvStructInfo;
4061 blob->cbData = dataLen - 1;
4062 blob->cUnusedBits = *(pbEncoded + 1 + lenBytes);
4063 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4065 blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes;
4067 else
4069 assert(blob->pbData);
4070 if (blob->cbData)
4072 BYTE mask = 0xff << blob->cUnusedBits;
4074 memcpy(blob->pbData, pbEncoded + 2 + lenBytes,
4075 blob->cbData);
4076 blob->pbData[blob->cbData - 1] &= mask;
4081 return ret;
4084 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
4085 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4086 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4088 BOOL ret;
4090 TRACE("(%p, %d, 0x%08x, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
4091 pDecodePara, pvStructInfo, pcbStructInfo);
4093 __TRY
4095 DWORD bytesNeeded;
4097 if (!cbEncoded)
4099 SetLastError(CRYPT_E_ASN1_CORRUPT);
4100 ret = FALSE;
4102 else if (pbEncoded[0] != ASN_BITSTRING)
4104 SetLastError(CRYPT_E_ASN1_BADTAG);
4105 ret = FALSE;
4107 else if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
4108 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4110 if (!pvStructInfo)
4111 *pcbStructInfo = bytesNeeded;
4112 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4113 pvStructInfo, pcbStructInfo, bytesNeeded)))
4115 CRYPT_BIT_BLOB *blob;
4117 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4118 pvStructInfo = *(BYTE **)pvStructInfo;
4119 blob = pvStructInfo;
4120 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
4121 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
4122 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4123 &bytesNeeded, NULL);
4124 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4125 CRYPT_FreeSpace(pDecodePara, blob);
4129 __EXCEPT_PAGE_FAULT
4131 SetLastError(STATUS_ACCESS_VIOLATION);
4132 ret = FALSE;
4134 __ENDTRY
4135 TRACE("returning %d (%08x)\n", ret, GetLastError());
4136 return ret;
4139 /* Ignores tag. Only allows integers 4 bytes or smaller in size. */
4140 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
4141 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4143 BOOL ret;
4144 DWORD dataLen;
4146 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4148 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4150 if (pcbDecoded)
4151 *pcbDecoded = 1 + lenBytes + dataLen;
4152 if (dataLen > sizeof(int))
4154 SetLastError(CRYPT_E_ASN1_LARGE);
4155 ret = FALSE;
4157 else if (!pvStructInfo)
4158 *pcbStructInfo = sizeof(int);
4159 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int))))
4161 int val, i;
4163 if (dataLen && pbEncoded[1 + lenBytes] & 0x80)
4165 /* initialize to a negative value to sign-extend */
4166 val = -1;
4168 else
4169 val = 0;
4170 for (i = 0; i < dataLen; i++)
4172 val <<= 8;
4173 val |= pbEncoded[1 + lenBytes + i];
4175 memcpy(pvStructInfo, &val, sizeof(int));
4178 return ret;
4181 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
4182 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4183 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4185 BOOL ret;
4187 __TRY
4189 DWORD bytesNeeded;
4191 if (!cbEncoded)
4193 SetLastError(CRYPT_E_ASN1_EOD);
4194 ret = FALSE;
4196 else if (pbEncoded[0] != ASN_INTEGER)
4198 SetLastError(CRYPT_E_ASN1_BADTAG);
4199 ret = FALSE;
4201 else
4202 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
4203 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4204 if (ret)
4206 if (!pvStructInfo)
4207 *pcbStructInfo = bytesNeeded;
4208 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4209 pvStructInfo, pcbStructInfo, bytesNeeded)))
4211 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4212 pvStructInfo = *(BYTE **)pvStructInfo;
4213 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
4214 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4215 &bytesNeeded, NULL);
4216 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4217 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
4221 __EXCEPT_PAGE_FAULT
4223 SetLastError(STATUS_ACCESS_VIOLATION);
4224 ret = FALSE;
4226 __ENDTRY
4227 return ret;
4230 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
4231 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4232 DWORD *pcbDecoded)
4234 BOOL ret;
4235 DWORD bytesNeeded, dataLen;
4237 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4239 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4241 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
4242 if (pcbDecoded)
4243 *pcbDecoded = 1 + lenBytes + dataLen;
4244 if (!pvStructInfo)
4245 *pcbStructInfo = bytesNeeded;
4246 else if (*pcbStructInfo < bytesNeeded)
4248 *pcbStructInfo = bytesNeeded;
4249 SetLastError(ERROR_MORE_DATA);
4250 ret = FALSE;
4252 else
4254 CRYPT_INTEGER_BLOB *blob = pvStructInfo;
4256 *pcbStructInfo = bytesNeeded;
4257 blob->cbData = dataLen;
4258 assert(blob->pbData);
4259 if (blob->cbData)
4261 DWORD i;
4263 for (i = 0; i < blob->cbData; i++)
4265 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
4266 dataLen - i - 1);
4271 return ret;
4274 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
4275 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4276 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4278 BOOL ret;
4280 __TRY
4282 DWORD bytesNeeded;
4284 if (pbEncoded[0] != ASN_INTEGER)
4286 SetLastError(CRYPT_E_ASN1_BADTAG);
4287 ret = FALSE;
4289 else
4290 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
4291 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4292 if (ret)
4294 if (!pvStructInfo)
4295 *pcbStructInfo = bytesNeeded;
4296 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4297 pvStructInfo, pcbStructInfo, bytesNeeded)))
4299 CRYPT_INTEGER_BLOB *blob;
4301 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4302 pvStructInfo = *(BYTE **)pvStructInfo;
4303 blob = pvStructInfo;
4304 blob->pbData = (BYTE *)pvStructInfo +
4305 sizeof(CRYPT_INTEGER_BLOB);
4306 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
4307 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
4308 &bytesNeeded, NULL);
4309 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4310 CRYPT_FreeSpace(pDecodePara, blob);
4314 __EXCEPT_PAGE_FAULT
4316 SetLastError(STATUS_ACCESS_VIOLATION);
4317 ret = FALSE;
4319 __ENDTRY
4320 return ret;
4323 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
4324 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4325 DWORD *pcbDecoded)
4327 BOOL ret;
4329 if (pbEncoded[0] == ASN_INTEGER)
4331 DWORD bytesNeeded, dataLen;
4333 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4335 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4337 if (pcbDecoded)
4338 *pcbDecoded = 1 + lenBytes + dataLen;
4339 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
4340 if (!pvStructInfo)
4341 *pcbStructInfo = bytesNeeded;
4342 else if (*pcbStructInfo < bytesNeeded)
4344 *pcbStructInfo = bytesNeeded;
4345 SetLastError(ERROR_MORE_DATA);
4346 ret = FALSE;
4348 else
4350 CRYPT_INTEGER_BLOB *blob = pvStructInfo;
4352 *pcbStructInfo = bytesNeeded;
4353 blob->cbData = dataLen;
4354 assert(blob->pbData);
4355 /* remove leading zero byte if it exists */
4356 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
4358 blob->cbData--;
4359 blob->pbData++;
4361 if (blob->cbData)
4363 DWORD i;
4365 for (i = 0; i < blob->cbData; i++)
4367 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
4368 dataLen - i - 1);
4374 else
4376 SetLastError(CRYPT_E_ASN1_BADTAG);
4377 ret = FALSE;
4379 return ret;
4382 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
4383 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4384 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4386 BOOL ret;
4388 __TRY
4390 DWORD bytesNeeded;
4392 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded,
4393 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4395 if (!pvStructInfo)
4396 *pcbStructInfo = bytesNeeded;
4397 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4398 pvStructInfo, pcbStructInfo, bytesNeeded)))
4400 CRYPT_INTEGER_BLOB *blob;
4402 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4403 pvStructInfo = *(BYTE **)pvStructInfo;
4404 blob = pvStructInfo;
4405 blob->pbData = (BYTE *)pvStructInfo +
4406 sizeof(CRYPT_INTEGER_BLOB);
4407 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded,
4408 cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
4409 &bytesNeeded, NULL);
4410 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4411 CRYPT_FreeSpace(pDecodePara, blob);
4415 __EXCEPT_PAGE_FAULT
4417 SetLastError(STATUS_ACCESS_VIOLATION);
4418 ret = FALSE;
4420 __ENDTRY
4421 return ret;
4424 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
4425 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4426 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4428 BOOL ret;
4430 if (!pvStructInfo)
4432 *pcbStructInfo = sizeof(int);
4433 return TRUE;
4435 __TRY
4437 if (pbEncoded[0] == ASN_ENUMERATED)
4439 unsigned int val = 0, i;
4441 if (cbEncoded <= 1)
4443 SetLastError(CRYPT_E_ASN1_EOD);
4444 ret = FALSE;
4446 else if (pbEncoded[1] == 0)
4448 SetLastError(CRYPT_E_ASN1_CORRUPT);
4449 ret = FALSE;
4451 else
4453 /* A little strange looking, but we have to accept a sign byte:
4454 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
4455 * assuming a small length is okay here, it has to be in short
4456 * form.
4458 if (pbEncoded[1] > sizeof(unsigned int) + 1)
4460 SetLastError(CRYPT_E_ASN1_LARGE);
4461 return FALSE;
4463 for (i = 0; i < pbEncoded[1]; i++)
4465 val <<= 8;
4466 val |= pbEncoded[2 + i];
4468 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4469 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
4471 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4472 pvStructInfo = *(BYTE **)pvStructInfo;
4473 memcpy(pvStructInfo, &val, sizeof(unsigned int));
4477 else
4479 SetLastError(CRYPT_E_ASN1_BADTAG);
4480 ret = FALSE;
4483 __EXCEPT_PAGE_FAULT
4485 SetLastError(STATUS_ACCESS_VIOLATION);
4486 ret = FALSE;
4488 __ENDTRY
4489 return ret;
4492 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
4493 * if it fails.
4495 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
4496 do { \
4497 BYTE i; \
4499 (word) = 0; \
4500 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
4502 if (!isdigit(*(pbEncoded))) \
4504 SetLastError(CRYPT_E_ASN1_CORRUPT); \
4505 ret = FALSE; \
4507 else \
4509 (word) *= 10; \
4510 (word) += *(pbEncoded)++ - '0'; \
4513 } while (0)
4515 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
4516 SYSTEMTIME *sysTime)
4518 BOOL ret = TRUE;
4520 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
4522 WORD hours, minutes = 0;
4523 BYTE sign = *pbEncoded++;
4525 len--;
4526 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
4527 if (ret && hours >= 24)
4529 SetLastError(CRYPT_E_ASN1_CORRUPT);
4530 ret = FALSE;
4532 else if (len >= 2)
4534 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
4535 if (ret && minutes >= 60)
4537 SetLastError(CRYPT_E_ASN1_CORRUPT);
4538 ret = FALSE;
4541 if (ret)
4543 if (sign == '+')
4545 sysTime->wHour += hours;
4546 sysTime->wMinute += minutes;
4548 else
4550 if (hours > sysTime->wHour)
4552 sysTime->wDay--;
4553 sysTime->wHour = 24 - (hours - sysTime->wHour);
4555 else
4556 sysTime->wHour -= hours;
4557 if (minutes > sysTime->wMinute)
4559 sysTime->wHour--;
4560 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
4562 else
4563 sysTime->wMinute -= minutes;
4567 return ret;
4570 #define MIN_ENCODED_TIME_LENGTH 10
4572 static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
4573 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4574 DWORD *pcbDecoded)
4576 BOOL ret = FALSE;
4578 if (pbEncoded[0] == ASN_UTCTIME)
4580 if (cbEncoded <= 1)
4581 SetLastError(CRYPT_E_ASN1_EOD);
4582 else if (pbEncoded[1] > 0x7f)
4584 /* long-form date strings really can't be valid */
4585 SetLastError(CRYPT_E_ASN1_CORRUPT);
4587 else
4589 SYSTEMTIME sysTime = { 0 };
4590 BYTE len = pbEncoded[1];
4592 if (len < MIN_ENCODED_TIME_LENGTH)
4593 SetLastError(CRYPT_E_ASN1_CORRUPT);
4594 else
4596 ret = TRUE;
4597 if (pcbDecoded)
4598 *pcbDecoded = 2 + len;
4599 pbEncoded += 2;
4600 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
4601 if (sysTime.wYear >= 50)
4602 sysTime.wYear += 1900;
4603 else
4604 sysTime.wYear += 2000;
4605 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
4606 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
4607 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
4608 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
4609 if (ret && len > 0)
4611 if (len >= 2 && isdigit(*pbEncoded) &&
4612 isdigit(*(pbEncoded + 1)))
4613 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4614 sysTime.wSecond);
4615 else if (isdigit(*pbEncoded))
4616 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
4617 sysTime.wSecond);
4618 if (ret)
4619 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
4620 &sysTime);
4622 if (ret)
4624 if (!pvStructInfo)
4625 *pcbStructInfo = sizeof(FILETIME);
4626 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
4627 sizeof(FILETIME))))
4628 ret = SystemTimeToFileTime(&sysTime, pvStructInfo);
4633 else
4634 SetLastError(CRYPT_E_ASN1_BADTAG);
4635 return ret;
4638 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
4639 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4640 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4642 BOOL ret = FALSE;
4644 __TRY
4646 DWORD bytesNeeded;
4648 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
4649 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4650 if (ret)
4652 if (!pvStructInfo)
4653 *pcbStructInfo = bytesNeeded;
4654 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
4655 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
4657 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4658 pvStructInfo = *(BYTE **)pvStructInfo;
4659 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
4660 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4661 &bytesNeeded, NULL);
4662 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4663 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
4667 __EXCEPT_PAGE_FAULT
4669 SetLastError(STATUS_ACCESS_VIOLATION);
4671 __ENDTRY
4672 return ret;
4675 static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
4676 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4677 DWORD *pcbDecoded)
4679 BOOL ret = FALSE;
4681 if (pbEncoded[0] == ASN_GENERALTIME)
4683 if (cbEncoded <= 1)
4684 SetLastError(CRYPT_E_ASN1_EOD);
4685 else if (pbEncoded[1] > 0x7f)
4687 /* long-form date strings really can't be valid */
4688 SetLastError(CRYPT_E_ASN1_CORRUPT);
4690 else
4692 BYTE len = pbEncoded[1];
4694 if (len < MIN_ENCODED_TIME_LENGTH)
4695 SetLastError(CRYPT_E_ASN1_CORRUPT);
4696 else
4698 SYSTEMTIME sysTime = { 0 };
4700 ret = TRUE;
4701 if (pcbDecoded)
4702 *pcbDecoded = 2 + len;
4703 pbEncoded += 2;
4704 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
4705 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
4706 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
4707 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
4708 if (ret && len > 0)
4710 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4711 sysTime.wMinute);
4712 if (ret && len > 0)
4713 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4714 sysTime.wSecond);
4715 if (ret && len > 0 && (*pbEncoded == '.' ||
4716 *pbEncoded == ','))
4718 BYTE digits;
4720 pbEncoded++;
4721 len--;
4722 /* workaround macro weirdness */
4723 digits = min(len, 3);
4724 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
4725 sysTime.wMilliseconds);
4727 if (ret)
4728 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
4729 &sysTime);
4731 if (ret)
4733 if (!pvStructInfo)
4734 *pcbStructInfo = sizeof(FILETIME);
4735 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
4736 sizeof(FILETIME))))
4737 ret = SystemTimeToFileTime(&sysTime, pvStructInfo);
4742 else
4743 SetLastError(CRYPT_E_ASN1_BADTAG);
4744 return ret;
4747 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
4748 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4749 DWORD *pcbDecoded)
4751 BOOL ret;
4752 InternalDecodeFunc decode = NULL;
4754 if (pbEncoded[0] == ASN_UTCTIME)
4755 decode = CRYPT_AsnDecodeUtcTimeInternal;
4756 else if (pbEncoded[0] == ASN_GENERALTIME)
4757 decode = CRYPT_AsnDecodeGeneralizedTime;
4758 if (decode)
4759 ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
4760 pcbStructInfo, pcbDecoded);
4761 else
4763 SetLastError(CRYPT_E_ASN1_BADTAG);
4764 ret = FALSE;
4766 return ret;
4769 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
4770 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4771 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4773 BOOL ret;
4775 __TRY
4777 DWORD bytesNeeded;
4779 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
4780 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4781 if (ret)
4783 if (!pvStructInfo)
4784 *pcbStructInfo = bytesNeeded;
4785 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4786 pvStructInfo, pcbStructInfo, bytesNeeded)))
4788 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4789 pvStructInfo = *(BYTE **)pvStructInfo;
4790 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
4791 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4792 &bytesNeeded, NULL);
4793 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4794 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
4798 __EXCEPT_PAGE_FAULT
4800 SetLastError(STATUS_ACCESS_VIOLATION);
4801 ret = FALSE;
4803 __ENDTRY
4804 return ret;
4807 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
4808 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4809 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4811 BOOL ret = TRUE;
4813 __TRY
4815 if (pbEncoded[0] == ASN_SEQUENCEOF)
4817 DWORD bytesNeeded, dataLen, remainingLen, cValue;
4819 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4821 BYTE lenBytes;
4822 const BYTE *ptr;
4824 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4825 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
4826 cValue = 0;
4827 ptr = pbEncoded + 1 + lenBytes;
4828 remainingLen = dataLen;
4829 while (ret && remainingLen)
4831 DWORD nextLen;
4833 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
4834 if (ret)
4836 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
4838 remainingLen -= 1 + nextLenBytes + nextLen;
4839 ptr += 1 + nextLenBytes + nextLen;
4840 bytesNeeded += sizeof(CRYPT_DER_BLOB);
4841 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
4842 bytesNeeded += 1 + nextLenBytes + nextLen;
4843 cValue++;
4846 if (ret)
4848 CRYPT_SEQUENCE_OF_ANY *seq;
4849 BYTE *nextPtr;
4850 DWORD i;
4852 if (!pvStructInfo)
4853 *pcbStructInfo = bytesNeeded;
4854 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4855 pvStructInfo, pcbStructInfo, bytesNeeded)))
4857 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4858 pvStructInfo = *(BYTE **)pvStructInfo;
4859 seq = pvStructInfo;
4860 seq->cValue = cValue;
4861 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
4862 sizeof(*seq));
4863 nextPtr = (BYTE *)seq->rgValue +
4864 cValue * sizeof(CRYPT_DER_BLOB);
4865 ptr = pbEncoded + 1 + lenBytes;
4866 remainingLen = dataLen;
4867 i = 0;
4868 while (ret && remainingLen)
4870 DWORD nextLen;
4872 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
4873 if (ret)
4875 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
4877 seq->rgValue[i].cbData = 1 + nextLenBytes +
4878 nextLen;
4879 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4880 seq->rgValue[i].pbData = (BYTE *)ptr;
4881 else
4883 seq->rgValue[i].pbData = nextPtr;
4884 memcpy(nextPtr, ptr, 1 + nextLenBytes +
4885 nextLen);
4886 nextPtr += 1 + nextLenBytes + nextLen;
4888 remainingLen -= 1 + nextLenBytes + nextLen;
4889 ptr += 1 + nextLenBytes + nextLen;
4890 i++;
4893 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4894 CRYPT_FreeSpace(pDecodePara, seq);
4899 else
4901 SetLastError(CRYPT_E_ASN1_BADTAG);
4902 ret = FALSE;
4905 __EXCEPT_PAGE_FAULT
4907 SetLastError(STATUS_ACCESS_VIOLATION);
4908 ret = FALSE;
4910 __ENDTRY
4911 return ret;
4914 static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded,
4915 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4916 DWORD *pcbDecoded)
4918 BOOL ret;
4920 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
4922 DWORD bytesNeeded, dataLen;
4924 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4926 struct AsnArrayDescriptor arrayDesc = {
4927 ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
4928 offsetof(CRL_DIST_POINT_NAME, u.FullName.cAltEntry),
4929 offsetof(CRL_DIST_POINT_NAME, u.FullName.rgAltEntry),
4930 FINALMEMBERSIZE(CRL_DIST_POINT_NAME, u),
4931 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
4932 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
4933 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4934 DWORD nameLen;
4936 if (dataLen)
4938 ret = CRYPT_AsnDecodeArray(&arrayDesc,
4939 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
4940 dwFlags, NULL, NULL, &nameLen, NULL);
4941 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen -
4942 FINALMEMBERSIZE(CRL_DIST_POINT_NAME, u);
4944 else
4945 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
4946 if (pcbDecoded)
4947 *pcbDecoded = 1 + lenBytes + dataLen;
4948 if (!pvStructInfo)
4949 *pcbStructInfo = bytesNeeded;
4950 else if (*pcbStructInfo < bytesNeeded)
4952 *pcbStructInfo = bytesNeeded;
4953 SetLastError(ERROR_MORE_DATA);
4954 ret = FALSE;
4956 else
4958 CRL_DIST_POINT_NAME *name = pvStructInfo;
4960 *pcbStructInfo = bytesNeeded;
4961 if (dataLen)
4963 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
4964 ret = CRYPT_AsnDecodeArray(&arrayDesc,
4965 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
4966 dwFlags, NULL, &name->u.FullName.cAltEntry, &nameLen,
4967 NULL);
4969 else
4970 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
4974 else
4976 SetLastError(CRYPT_E_ASN1_BADTAG);
4977 ret = FALSE;
4979 return ret;
4982 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
4983 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4985 struct AsnDecodeSequenceItem items[] = {
4986 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
4987 DistPointName), CRYPT_AsnDecodeDistPointName,
4988 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
4989 DistPointName.u.FullName.rgAltEntry), 0 },
4990 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
4991 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
4992 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
4993 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
4994 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
4995 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
4997 CRL_DIST_POINT *point = pvStructInfo;
4998 BOOL ret;
5000 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5001 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5002 pcbDecoded, point ? point->DistPointName.u.FullName.rgAltEntry : NULL);
5003 return ret;
5006 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
5007 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5008 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5010 BOOL ret;
5012 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5013 pDecodePara, pvStructInfo, *pcbStructInfo);
5015 __TRY
5017 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
5018 offsetof(CRL_DIST_POINTS_INFO, cDistPoint),
5019 offsetof(CRL_DIST_POINTS_INFO, rgDistPoint),
5020 sizeof(CRL_DIST_POINTS_INFO),
5021 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
5022 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
5024 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5025 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
5027 __EXCEPT_PAGE_FAULT
5029 SetLastError(STATUS_ACCESS_VIOLATION);
5030 ret = FALSE;
5032 __ENDTRY
5033 return ret;
5036 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
5037 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5038 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5040 BOOL ret;
5042 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5043 pDecodePara, pvStructInfo, *pcbStructInfo);
5045 __TRY
5047 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
5048 offsetof(CERT_ENHKEY_USAGE, cUsageIdentifier),
5049 offsetof(CERT_ENHKEY_USAGE, rgpszUsageIdentifier),
5050 sizeof(CERT_ENHKEY_USAGE),
5051 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
5053 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5054 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
5056 __EXCEPT_PAGE_FAULT
5058 SetLastError(STATUS_ACCESS_VIOLATION);
5059 ret = FALSE;
5061 __ENDTRY
5062 return ret;
5065 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
5066 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5067 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5069 BOOL ret;
5071 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5072 pDecodePara, pvStructInfo, *pcbStructInfo);
5074 __TRY
5076 struct AsnDecodeSequenceItem items[] = {
5077 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
5078 DistPointName), CRYPT_AsnDecodeDistPointName,
5079 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
5080 offsetof(CRL_ISSUING_DIST_POINT,
5081 DistPointName.u.FullName.rgAltEntry), 0 },
5082 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
5083 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
5084 FALSE, 0 },
5085 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
5086 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
5087 FALSE, 0 },
5088 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
5089 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
5090 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
5091 OnlySomeReasonFlags.pbData), 0 },
5092 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
5093 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
5096 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5097 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
5098 pcbStructInfo, NULL, NULL);
5100 __EXCEPT_PAGE_FAULT
5102 SetLastError(STATUS_ACCESS_VIOLATION);
5103 ret = FALSE;
5105 __ENDTRY
5106 return ret;
5109 static BOOL CRYPT_AsnDecodeMaximum(const BYTE *pbEncoded,
5110 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5111 DWORD *pcbDecoded)
5113 BOOL ret;
5114 DWORD max, size = sizeof(max);
5116 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5117 pvStructInfo, *pcbStructInfo, pcbDecoded);
5119 if (!cbEncoded)
5121 SetLastError(CRYPT_E_ASN1_EOD);
5122 return FALSE;
5124 if (pbEncoded[0] != (ASN_CONTEXT | 1))
5126 SetLastError(CRYPT_E_ASN1_BADTAG);
5127 return FALSE;
5129 if ((ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
5130 &max, &size, pcbDecoded)))
5132 DWORD bytesNeeded = FINALMEMBERSIZE(CERT_GENERAL_SUBTREE, fMaximum);
5134 if (!pvStructInfo)
5135 *pcbStructInfo = bytesNeeded;
5136 else if (*pcbStructInfo < bytesNeeded)
5138 *pcbStructInfo = bytesNeeded;
5139 SetLastError(ERROR_MORE_DATA);
5140 ret = FALSE;
5142 else
5144 CERT_GENERAL_SUBTREE *subtree = CONTAINING_RECORD(pvStructInfo,
5145 CERT_GENERAL_SUBTREE, fMaximum);
5147 *pcbStructInfo = bytesNeeded;
5148 /* The BOOL is implicit: if the integer is present, then it's
5149 * TRUE.
5151 subtree->fMaximum = TRUE;
5152 subtree->dwMaximum = max;
5155 TRACE("returning %d\n", ret);
5156 return ret;
5159 static BOOL CRYPT_AsnDecodeSubtree(const BYTE *pbEncoded,
5160 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5161 DWORD *pcbDecoded)
5163 BOOL ret;
5164 struct AsnDecodeSequenceItem items[] = {
5165 { 0, offsetof(CERT_GENERAL_SUBTREE, Base),
5166 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE, TRUE,
5167 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL), 0 },
5168 { ASN_CONTEXT | 0, offsetof(CERT_GENERAL_SUBTREE, dwMinimum),
5169 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
5170 { ASN_CONTEXT | 1, offsetof(CERT_GENERAL_SUBTREE, fMaximum),
5171 CRYPT_AsnDecodeMaximum, FINALMEMBERSIZE(CERT_GENERAL_SUBTREE, fMaximum),
5172 TRUE, FALSE, 0, 0 },
5174 CERT_GENERAL_SUBTREE *subtree = pvStructInfo;
5176 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5177 pvStructInfo, *pcbStructInfo, pcbDecoded);
5179 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5180 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5181 pcbDecoded, subtree ? subtree->Base.u.pwszURL : NULL);
5182 if (pcbDecoded)
5184 TRACE("%d\n", *pcbDecoded);
5185 if (*pcbDecoded < cbEncoded)
5186 TRACE("%02x %02x\n", *(pbEncoded + *pcbDecoded),
5187 *(pbEncoded + *pcbDecoded + 1));
5189 TRACE("returning %d\n", ret);
5190 return ret;
5193 static BOOL CRYPT_AsnDecodePermittedSubtree(const BYTE *pbEncoded,
5194 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5195 DWORD *pcbDecoded)
5197 BOOL ret = TRUE;
5198 struct AsnArrayDescriptor arrayDesc = { 0,
5199 offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
5200 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree),
5201 MEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree,
5202 cExcludedSubtree),
5203 CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
5204 offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
5206 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5207 pvStructInfo, *pcbStructInfo, pcbDecoded);
5209 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5210 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5211 return ret;
5214 static BOOL CRYPT_AsnDecodeExcludedSubtree(const BYTE *pbEncoded,
5215 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5216 DWORD *pcbDecoded)
5218 BOOL ret = TRUE;
5219 struct AsnArrayDescriptor arrayDesc = { 0,
5220 offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5221 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree),
5222 FINALMEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5223 CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
5224 offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
5226 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5227 pvStructInfo, *pcbStructInfo, pcbDecoded);
5229 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5230 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5231 return ret;
5234 static BOOL WINAPI CRYPT_AsnDecodeNameConstraints(DWORD dwCertEncodingType,
5235 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5236 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5238 BOOL ret = FALSE;
5240 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5241 pDecodePara, pvStructInfo, *pcbStructInfo);
5243 __TRY
5245 struct AsnDecodeSequenceItem items[] = {
5246 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
5247 offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
5248 CRYPT_AsnDecodePermittedSubtree,
5249 MEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree,
5250 cExcludedSubtree), TRUE, TRUE,
5251 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree), 0 },
5252 { ASN_CONTEXT | ASN_CONSTRUCTOR | 1,
5253 offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5254 CRYPT_AsnDecodeExcludedSubtree,
5255 FINALMEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5256 TRUE, TRUE,
5257 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree), 0 },
5260 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5261 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
5262 pcbStructInfo, NULL, NULL);
5264 __EXCEPT_PAGE_FAULT
5266 SetLastError(STATUS_ACCESS_VIOLATION);
5268 __ENDTRY
5269 return ret;
5272 static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded,
5273 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5274 DWORD *pcbDecoded)
5276 BOOL ret;
5277 struct AsnDecodeSequenceItem items[] = {
5278 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
5279 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
5280 Issuer.pbData) },
5281 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
5282 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
5283 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
5285 CERT_ISSUER_SERIAL_NUMBER *issuerSerial = pvStructInfo;
5287 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5288 pvStructInfo, *pcbStructInfo, pcbDecoded);
5290 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5291 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5292 pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL);
5293 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
5295 SetLastError(CRYPT_E_ASN1_CORRUPT);
5296 ret = FALSE;
5298 TRACE("returning %d\n", ret);
5299 return ret;
5302 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
5303 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5304 DWORD *pcbDecoded)
5306 CMSG_SIGNER_INFO *info = pvStructInfo;
5307 struct AsnDecodeSequenceItem items[] = {
5308 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
5309 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5310 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
5311 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
5312 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
5313 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
5314 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5315 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
5316 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5317 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
5318 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5319 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
5320 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
5321 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5322 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
5323 HashEncryptionAlgorithm.pszObjId), 0 },
5324 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
5325 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
5326 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
5327 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5328 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
5329 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5330 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
5332 BOOL ret;
5334 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5335 pvStructInfo, *pcbStructInfo);
5337 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5338 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5339 pcbDecoded, info ? info->Issuer.pbData : NULL);
5340 return ret;
5343 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
5344 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5345 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5347 BOOL ret = FALSE;
5349 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5350 pDecodePara, pvStructInfo, *pcbStructInfo);
5352 __TRY
5354 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
5355 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
5356 if (ret && pvStructInfo)
5358 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
5359 pcbStructInfo, *pcbStructInfo);
5360 if (ret)
5362 CMSG_SIGNER_INFO *info;
5364 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5365 pvStructInfo = *(BYTE **)pvStructInfo;
5366 info = pvStructInfo;
5367 info->Issuer.pbData = ((BYTE *)info +
5368 sizeof(CMSG_SIGNER_INFO));
5369 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
5370 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5371 pcbStructInfo, NULL);
5372 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5373 CRYPT_FreeSpace(pDecodePara, info);
5377 __EXCEPT_PAGE_FAULT
5379 SetLastError(STATUS_ACCESS_VIOLATION);
5381 __ENDTRY
5382 TRACE("returning %d\n", ret);
5383 return ret;
5386 static BOOL CRYPT_AsnDecodeCMSCertEncoded(const BYTE *pbEncoded,
5387 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5388 DWORD *pcbDecoded)
5390 BOOL ret;
5391 struct AsnArrayDescriptor arrayDesc = { 0,
5392 offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
5393 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded),
5394 MEMBERSIZE(CRYPT_SIGNED_INFO, cCertEncoded, cCrlEncoded),
5395 CRYPT_AsnDecodeCopyBytes,
5396 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
5398 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5399 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
5401 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5402 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5403 return ret;
5406 static BOOL CRYPT_AsnDecodeCMSCrlEncoded(const BYTE *pbEncoded,
5407 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5408 DWORD *pcbDecoded)
5410 BOOL ret;
5411 struct AsnArrayDescriptor arrayDesc = { 0,
5412 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded),
5413 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded),
5414 MEMBERSIZE(CRYPT_SIGNED_INFO, cCrlEncoded, content),
5415 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_DER_BLOB),
5416 TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
5418 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5419 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
5421 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5422 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5423 return ret;
5426 static BOOL CRYPT_AsnDecodeCMSSignerId(const BYTE *pbEncoded,
5427 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5428 DWORD *pcbDecoded)
5430 CERT_ID *id = pvStructInfo;
5431 BOOL ret = FALSE;
5433 if (*pbEncoded == ASN_SEQUENCEOF)
5435 ret = CRYPT_AsnDecodeIssuerSerialNumber(pbEncoded, cbEncoded, dwFlags,
5436 id ? &id->u.IssuerSerialNumber : NULL, pcbStructInfo, pcbDecoded);
5437 if (ret)
5439 if (id)
5440 id->dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
5441 if (*pcbStructInfo > sizeof(CERT_ISSUER_SERIAL_NUMBER))
5442 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
5443 sizeof(CERT_ISSUER_SERIAL_NUMBER);
5444 else
5445 *pcbStructInfo = sizeof(CERT_ID);
5448 else if (*pbEncoded == (ASN_CONTEXT | 0))
5450 ret = CRYPT_AsnDecodeOctetsInternal(pbEncoded, cbEncoded, dwFlags,
5451 id ? &id->u.KeyId : NULL, pcbStructInfo, pcbDecoded);
5452 if (ret)
5454 if (id)
5455 id->dwIdChoice = CERT_ID_KEY_IDENTIFIER;
5456 if (*pcbStructInfo > sizeof(CRYPT_DATA_BLOB))
5457 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
5458 sizeof(CRYPT_DATA_BLOB);
5459 else
5460 *pcbStructInfo = sizeof(CERT_ID);
5463 else
5464 SetLastError(CRYPT_E_ASN1_BADTAG);
5465 return ret;
5468 static BOOL CRYPT_AsnDecodeCMSSignerInfoInternal(const BYTE *pbEncoded,
5469 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5470 DWORD *pcbDecoded)
5472 CMSG_CMS_SIGNER_INFO *info = pvStructInfo;
5473 struct AsnDecodeSequenceItem items[] = {
5474 { ASN_INTEGER, offsetof(CMSG_CMS_SIGNER_INFO, dwVersion),
5475 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5476 { 0, offsetof(CMSG_CMS_SIGNER_INFO, SignerId),
5477 CRYPT_AsnDecodeCMSSignerId, sizeof(CERT_ID), FALSE, TRUE,
5478 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData), 0 },
5479 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm),
5480 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5481 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
5482 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5483 offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs),
5484 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5485 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
5486 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashEncryptionAlgorithm),
5487 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5488 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO,
5489 HashEncryptionAlgorithm.pszObjId), 0 },
5490 { ASN_OCTETSTRING, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash),
5491 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DER_BLOB),
5492 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash.pbData), 0 },
5493 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5494 offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs),
5495 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5496 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
5498 BOOL ret;
5500 TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5501 pvStructInfo, *pcbStructInfo);
5503 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5504 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5505 pcbDecoded, info ? info->SignerId.u.KeyId.pbData : NULL);
5506 return ret;
5509 static BOOL WINAPI CRYPT_AsnDecodeCMSSignerInfo(DWORD dwCertEncodingType,
5510 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5511 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5513 BOOL ret = FALSE;
5515 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5516 pDecodePara, pvStructInfo, *pcbStructInfo);
5518 __TRY
5520 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded, cbEncoded,
5521 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
5522 if (ret && pvStructInfo)
5524 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
5525 pcbStructInfo, *pcbStructInfo);
5526 if (ret)
5528 CMSG_CMS_SIGNER_INFO *info;
5530 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5531 pvStructInfo = *(BYTE **)pvStructInfo;
5532 info = pvStructInfo;
5533 info->SignerId.u.KeyId.pbData = ((BYTE *)info +
5534 sizeof(CMSG_CMS_SIGNER_INFO));
5535 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded,
5536 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5537 pcbStructInfo, NULL);
5538 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5539 CRYPT_FreeSpace(pDecodePara, info);
5543 __EXCEPT_PAGE_FAULT
5545 SetLastError(STATUS_ACCESS_VIOLATION);
5547 __ENDTRY
5548 TRACE("returning %d\n", ret);
5549 return ret;
5552 static BOOL CRYPT_DecodeSignerArray(const BYTE *pbEncoded, DWORD cbEncoded,
5553 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5555 BOOL ret;
5556 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
5557 offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
5558 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo),
5559 FINALMEMBERSIZE(CRYPT_SIGNED_INFO, cSignerInfo),
5560 CRYPT_AsnDecodeCMSSignerInfoInternal, sizeof(CMSG_CMS_SIGNER_INFO), TRUE,
5561 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData) };
5563 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5564 pvStructInfo, *pcbStructInfo, pcbDecoded);
5566 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5567 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5568 return ret;
5571 BOOL CRYPT_AsnDecodeCMSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
5572 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
5573 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
5575 BOOL ret = FALSE;
5576 struct AsnDecodeSequenceItem items[] = {
5577 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version),
5578 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5579 /* Placeholder for the hash algorithms - redundant with those in the
5580 * signers, so just ignore them.
5582 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
5583 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
5584 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
5585 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
5586 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5587 offsetof(CRYPT_SIGNED_INFO, cCertEncoded), CRYPT_AsnDecodeCMSCertEncoded,
5588 MEMBERSIZE(CRYPT_SIGNED_INFO, cCertEncoded, cCrlEncoded), TRUE, TRUE,
5589 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
5590 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5591 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_AsnDecodeCMSCrlEncoded,
5592 MEMBERSIZE(CRYPT_SIGNED_INFO, cCrlEncoded, content), TRUE, TRUE,
5593 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
5594 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
5595 CRYPT_DecodeSignerArray,
5596 FINALMEMBERSIZE(CRYPT_SIGNED_INFO, cSignerInfo), TRUE, TRUE,
5597 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
5600 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5601 pDecodePara, signedInfo, *pcbSignedInfo);
5603 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5604 pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo,
5605 NULL, NULL);
5606 TRACE("returning %d\n", ret);
5607 return ret;
5610 static BOOL CRYPT_AsnDecodeRecipientInfo(const BYTE *pbEncoded, DWORD cbEncoded,
5611 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5613 BOOL ret;
5614 CMSG_KEY_TRANS_RECIPIENT_INFO *info = pvStructInfo;
5615 struct AsnDecodeSequenceItem items[] = {
5616 { ASN_INTEGER, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, dwVersion),
5617 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5618 { ASN_SEQUENCEOF, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
5619 RecipientId.u.IssuerSerialNumber), CRYPT_AsnDecodeIssuerSerialNumber,
5620 sizeof(CERT_ISSUER_SERIAL_NUMBER), FALSE, TRUE,
5621 offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
5622 RecipientId.u.IssuerSerialNumber.Issuer.pbData), 0 },
5623 { ASN_SEQUENCEOF, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
5624 KeyEncryptionAlgorithm), CRYPT_AsnDecodeAlgorithmId,
5625 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
5626 offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
5627 KeyEncryptionAlgorithm.pszObjId), 0 },
5628 { ASN_OCTETSTRING, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, EncryptedKey),
5629 CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE,
5630 offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, EncryptedKey.pbData), 0 },
5633 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5634 pvStructInfo, *pcbStructInfo, pcbDecoded);
5636 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5637 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5638 pcbDecoded, info ? info->RecipientId.u.IssuerSerialNumber.Issuer.pbData :
5639 NULL);
5640 if (info)
5641 info->RecipientId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
5642 TRACE("returning %d\n", ret);
5643 return ret;
5646 static BOOL CRYPT_DecodeRecipientInfoArray(const BYTE *pbEncoded,
5647 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5648 DWORD *pcbDecoded)
5650 BOOL ret;
5651 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
5652 offsetof(CRYPT_ENVELOPED_DATA, cRecipientInfo),
5653 offsetof(CRYPT_ENVELOPED_DATA, rgRecipientInfo),
5654 MEMBERSIZE(CRYPT_ENVELOPED_DATA, cRecipientInfo, encryptedContentInfo),
5655 CRYPT_AsnDecodeRecipientInfo, sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO), TRUE,
5656 offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
5657 RecipientId.u.IssuerSerialNumber.Issuer.pbData) };
5659 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5660 pvStructInfo, *pcbStructInfo, pcbDecoded);
5662 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5663 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5664 TRACE("returning %d\n", ret);
5665 return ret;
5668 static BOOL CRYPT_AsnDecodeEncryptedContentInfo(const BYTE *pbEncoded,
5669 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5670 DWORD *pcbDecoded)
5672 BOOL ret;
5673 CRYPT_ENCRYPTED_CONTENT_INFO *info = pvStructInfo;
5674 struct AsnDecodeSequenceItem items[] = {
5675 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
5676 contentType), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
5677 FALSE, TRUE, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
5678 contentType), 0 },
5679 { ASN_SEQUENCEOF, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
5680 contentEncryptionAlgorithm), CRYPT_AsnDecodeAlgorithmId,
5681 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
5682 offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
5683 contentEncryptionAlgorithm.pszObjId), 0 },
5684 { ASN_CONTEXT | 0, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
5685 encryptedContent), CRYPT_AsnDecodeOctetsInternal,
5686 sizeof(CRYPT_DATA_BLOB), TRUE, TRUE,
5687 offsetof(CRYPT_ENCRYPTED_CONTENT_INFO, encryptedContent.pbData) },
5690 TRACE("%p, %d, %08x, %p, %d, %p\n", pbEncoded, cbEncoded, dwFlags,
5691 pvStructInfo, *pcbStructInfo, pcbDecoded);
5693 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5694 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5695 pcbDecoded, info ? info->contentType : NULL);
5696 TRACE("returning %d\n", ret);
5697 return ret;
5700 BOOL CRYPT_AsnDecodePKCSEnvelopedData(const BYTE *pbEncoded, DWORD cbEncoded,
5701 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
5702 CRYPT_ENVELOPED_DATA *envelopedData, DWORD *pcbEnvelopedData)
5704 BOOL ret;
5705 struct AsnDecodeSequenceItem items[] = {
5706 { ASN_INTEGER, offsetof(CRYPT_ENVELOPED_DATA, version),
5707 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5708 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ENVELOPED_DATA,
5709 cRecipientInfo), CRYPT_DecodeRecipientInfoArray,
5710 MEMBERSIZE(CRYPT_ENVELOPED_DATA, cRecipientInfo, encryptedContentInfo),
5711 FALSE, TRUE, offsetof(CRYPT_ENVELOPED_DATA, rgRecipientInfo), 0 },
5712 { ASN_SEQUENCEOF, offsetof(CRYPT_ENVELOPED_DATA, encryptedContentInfo),
5713 CRYPT_AsnDecodeEncryptedContentInfo,
5714 sizeof(CRYPT_ENCRYPTED_CONTENT_INFO), FALSE, TRUE,
5715 offsetof(CRYPT_ENVELOPED_DATA, encryptedContentInfo.contentType), 0 },
5718 TRACE("%p, %d, %08x, %p, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
5719 pDecodePara, envelopedData, *pcbEnvelopedData);
5721 ret = CRYPT_AsnDecodeSequence(items, sizeof(items) / sizeof(items[0]),
5722 pbEncoded, cbEncoded, dwFlags, pDecodePara, envelopedData,
5723 pcbEnvelopedData, NULL, NULL);
5724 TRACE("returning %d\n", ret);
5725 return ret;
5728 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
5729 LPCSTR lpszStructType)
5731 CryptDecodeObjectExFunc decodeFunc = NULL;
5733 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
5734 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
5736 SetLastError(ERROR_FILE_NOT_FOUND);
5737 return NULL;
5739 if (IS_INTOID(lpszStructType))
5741 switch (LOWORD(lpszStructType))
5743 case LOWORD(X509_CERT):
5744 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
5745 break;
5746 case LOWORD(X509_CERT_TO_BE_SIGNED):
5747 decodeFunc = CRYPT_AsnDecodeCert;
5748 break;
5749 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
5750 decodeFunc = CRYPT_AsnDecodeCRL;
5751 break;
5752 case LOWORD(X509_EXTENSIONS):
5753 decodeFunc = CRYPT_AsnDecodeExtensions;
5754 break;
5755 case LOWORD(X509_NAME_VALUE):
5756 decodeFunc = CRYPT_AsnDecodeNameValue;
5757 break;
5758 case LOWORD(X509_NAME):
5759 decodeFunc = CRYPT_AsnDecodeName;
5760 break;
5761 case LOWORD(X509_PUBLIC_KEY_INFO):
5762 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
5763 break;
5764 case LOWORD(X509_AUTHORITY_KEY_ID):
5765 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
5766 break;
5767 case LOWORD(X509_ALTERNATE_NAME):
5768 decodeFunc = CRYPT_AsnDecodeAltName;
5769 break;
5770 case LOWORD(X509_BASIC_CONSTRAINTS):
5771 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
5772 break;
5773 case LOWORD(X509_BASIC_CONSTRAINTS2):
5774 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
5775 break;
5776 case LOWORD(X509_CERT_POLICIES):
5777 decodeFunc = CRYPT_AsnDecodeCertPolicies;
5778 break;
5779 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
5780 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
5781 break;
5782 case LOWORD(X509_UNICODE_NAME):
5783 decodeFunc = CRYPT_AsnDecodeUnicodeName;
5784 break;
5785 case LOWORD(PKCS_ATTRIBUTE):
5786 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
5787 break;
5788 case LOWORD(X509_UNICODE_NAME_VALUE):
5789 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
5790 break;
5791 case LOWORD(X509_OCTET_STRING):
5792 decodeFunc = CRYPT_AsnDecodeOctets;
5793 break;
5794 case LOWORD(X509_BITS):
5795 case LOWORD(X509_KEY_USAGE):
5796 decodeFunc = CRYPT_AsnDecodeBits;
5797 break;
5798 case LOWORD(X509_INTEGER):
5799 decodeFunc = CRYPT_AsnDecodeInt;
5800 break;
5801 case LOWORD(X509_MULTI_BYTE_INTEGER):
5802 decodeFunc = CRYPT_AsnDecodeInteger;
5803 break;
5804 case LOWORD(X509_MULTI_BYTE_UINT):
5805 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
5806 break;
5807 case LOWORD(X509_ENUMERATED):
5808 decodeFunc = CRYPT_AsnDecodeEnumerated;
5809 break;
5810 case LOWORD(X509_CHOICE_OF_TIME):
5811 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
5812 break;
5813 case LOWORD(X509_AUTHORITY_KEY_ID2):
5814 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
5815 break;
5816 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
5817 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
5818 break;
5819 case LOWORD(PKCS_CONTENT_INFO):
5820 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
5821 break;
5822 case LOWORD(X509_SEQUENCE_OF_ANY):
5823 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
5824 break;
5825 case LOWORD(PKCS_UTC_TIME):
5826 decodeFunc = CRYPT_AsnDecodeUtcTime;
5827 break;
5828 case LOWORD(X509_CRL_DIST_POINTS):
5829 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
5830 break;
5831 case LOWORD(X509_ENHANCED_KEY_USAGE):
5832 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
5833 break;
5834 case LOWORD(PKCS_CTL):
5835 decodeFunc = CRYPT_AsnDecodeCTL;
5836 break;
5837 case LOWORD(PKCS_SMIME_CAPABILITIES):
5838 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
5839 break;
5840 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE):
5841 decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
5842 break;
5843 case LOWORD(PKCS_ATTRIBUTES):
5844 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
5845 break;
5846 case LOWORD(X509_ISSUING_DIST_POINT):
5847 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
5848 break;
5849 case LOWORD(X509_NAME_CONSTRAINTS):
5850 decodeFunc = CRYPT_AsnDecodeNameConstraints;
5851 break;
5852 case LOWORD(X509_POLICY_MAPPINGS):
5853 decodeFunc = CRYPT_AsnDecodeCertPolicyMappings;
5854 break;
5855 case LOWORD(X509_POLICY_CONSTRAINTS):
5856 decodeFunc = CRYPT_AsnDecodeCertPolicyConstraints;
5857 break;
5858 case LOWORD(PKCS7_SIGNER_INFO):
5859 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
5860 break;
5861 case LOWORD(CMS_SIGNER_INFO):
5862 decodeFunc = CRYPT_AsnDecodeCMSSignerInfo;
5863 break;
5866 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
5867 decodeFunc = CRYPT_AsnDecodeExtensions;
5868 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
5869 decodeFunc = CRYPT_AsnDecodeUtcTime;
5870 else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
5871 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
5872 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
5873 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
5874 else if (!strcmp(lpszStructType, szOID_LEGACY_POLICY_MAPPINGS))
5875 decodeFunc = CRYPT_AsnDecodeCertPolicyMappings;
5876 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
5877 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
5878 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
5879 decodeFunc = CRYPT_AsnDecodeEnumerated;
5880 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
5881 decodeFunc = CRYPT_AsnDecodeBits;
5882 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
5883 decodeFunc = CRYPT_AsnDecodeOctets;
5884 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
5885 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
5886 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
5887 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
5888 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
5889 decodeFunc = CRYPT_AsnDecodeAltName;
5890 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
5891 decodeFunc = CRYPT_AsnDecodeAltName;
5892 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
5893 decodeFunc = CRYPT_AsnDecodeAltName;
5894 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
5895 decodeFunc = CRYPT_AsnDecodeAltName;
5896 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
5897 decodeFunc = CRYPT_AsnDecodeAltName;
5898 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
5899 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
5900 else if (!strcmp(lpszStructType, szOID_CERT_POLICIES))
5901 decodeFunc = CRYPT_AsnDecodeCertPolicies;
5902 else if (!strcmp(lpszStructType, szOID_POLICY_MAPPINGS))
5903 decodeFunc = CRYPT_AsnDecodeCertPolicyMappings;
5904 else if (!strcmp(lpszStructType, szOID_POLICY_CONSTRAINTS))
5905 decodeFunc = CRYPT_AsnDecodeCertPolicyConstraints;
5906 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
5907 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
5908 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
5909 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
5910 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
5911 decodeFunc = CRYPT_AsnDecodeNameConstraints;
5912 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
5913 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
5914 else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
5915 decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
5916 else if (!strcmp(lpszStructType, szOID_CTL))
5917 decodeFunc = CRYPT_AsnDecodeCTL;
5918 return decodeFunc;
5921 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
5922 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
5924 static HCRYPTOIDFUNCSET set = NULL;
5925 CryptDecodeObjectFunc decodeFunc = NULL;
5927 if (!set)
5928 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
5929 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
5930 (void **)&decodeFunc, hFunc);
5931 return decodeFunc;
5934 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
5935 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
5937 static HCRYPTOIDFUNCSET set = NULL;
5938 CryptDecodeObjectExFunc decodeFunc = NULL;
5940 if (!set)
5941 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
5942 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
5943 (void **)&decodeFunc, hFunc);
5944 return decodeFunc;
5947 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
5948 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
5949 DWORD *pcbStructInfo)
5951 BOOL ret = FALSE;
5952 CryptDecodeObjectFunc pCryptDecodeObject = NULL;
5953 CryptDecodeObjectExFunc pCryptDecodeObjectEx = NULL;
5954 HCRYPTOIDFUNCADDR hFunc = NULL;
5956 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p)\n", dwCertEncodingType,
5957 debugstr_a(lpszStructType), pbEncoded, cbEncoded, dwFlags,
5958 pvStructInfo, pcbStructInfo);
5960 if (!pvStructInfo && !pcbStructInfo)
5962 SetLastError(ERROR_INVALID_PARAMETER);
5963 return FALSE;
5965 if (cbEncoded > MAX_ENCODED_LEN)
5967 SetLastError(CRYPT_E_ASN1_LARGE);
5968 return FALSE;
5971 if (!(pCryptDecodeObjectEx = CRYPT_GetBuiltinDecoder(dwCertEncodingType,
5972 lpszStructType)))
5974 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
5975 debugstr_a(lpszStructType));
5976 pCryptDecodeObject = CRYPT_LoadDecoderFunc(dwCertEncodingType,
5977 lpszStructType, &hFunc);
5978 if (!pCryptDecodeObject)
5979 pCryptDecodeObjectEx = CRYPT_LoadDecoderExFunc(dwCertEncodingType,
5980 lpszStructType, &hFunc);
5982 if (pCryptDecodeObject)
5983 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
5984 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
5985 else if (pCryptDecodeObjectEx)
5986 ret = pCryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
5987 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
5988 pvStructInfo, pcbStructInfo);
5989 if (hFunc)
5990 CryptFreeOIDFunctionAddress(hFunc, 0);
5991 TRACE_(crypt)("returning %d\n", ret);
5992 return ret;
5995 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
5996 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5997 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5999 BOOL ret = FALSE;
6000 CryptDecodeObjectExFunc decodeFunc;
6001 HCRYPTOIDFUNCADDR hFunc = NULL;
6003 TRACE_(crypt)("(0x%08x, %s, %p, %d, 0x%08x, %p, %p, %p)\n",
6004 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
6005 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
6007 if (!pvStructInfo && !pcbStructInfo)
6009 SetLastError(ERROR_INVALID_PARAMETER);
6010 return FALSE;
6012 if (cbEncoded > MAX_ENCODED_LEN)
6014 SetLastError(CRYPT_E_ASN1_LARGE);
6015 return FALSE;
6018 SetLastError(NOERROR);
6019 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
6021 if (!pvStructInfo)
6023 SetLastError(ERROR_INVALID_PARAMETER);
6024 return FALSE;
6026 *(BYTE **)pvStructInfo = NULL;
6028 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
6029 if (!decodeFunc)
6031 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
6032 debugstr_a(lpszStructType));
6033 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
6034 &hFunc);
6036 if (decodeFunc)
6037 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
6038 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
6039 else
6041 CryptDecodeObjectFunc pCryptDecodeObject =
6042 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
6044 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
6045 * directly, as that could cause an infinite loop.
6047 if (pCryptDecodeObject)
6049 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
6051 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
6052 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
6053 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
6054 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
6056 ret = pCryptDecodeObject(dwCertEncodingType,
6057 lpszStructType, pbEncoded, cbEncoded, dwFlags,
6058 *(BYTE **)pvStructInfo, pcbStructInfo);
6059 if (!ret)
6060 CRYPT_FreeSpace(pDecodePara, *(BYTE **)pvStructInfo);
6063 else
6064 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
6065 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
6068 if (hFunc)
6069 CryptFreeOIDFunctionAddress(hFunc, 0);
6070 TRACE_(crypt)("returning %d\n", ret);
6071 return ret;
6074 BOOL WINAPI PFXIsPFXBlob(CRYPT_DATA_BLOB *pPFX)
6076 BOOL ret;
6078 TRACE_(crypt)("(%p)\n", pPFX);
6080 /* A PFX blob is an asn.1-encoded sequence, consisting of at least a
6081 * version integer of length 1 (3 encoded byes) and at least one other
6082 * datum (two encoded bytes), plus at least two bytes for the outer
6083 * sequence. Thus, even an empty PFX blob is at least 7 bytes in length.
6085 if (pPFX->cbData < 7)
6086 ret = FALSE;
6087 else if (pPFX->pbData[0] == ASN_SEQUENCE)
6089 DWORD len;
6091 if ((ret = CRYPT_GetLengthIndefinite(pPFX->pbData, pPFX->cbData, &len)))
6093 BYTE lenLen = GET_LEN_BYTES(pPFX->pbData[1]);
6095 /* Need at least three bytes for the integer version */
6096 if (pPFX->cbData < 1 + lenLen + 3)
6097 ret = FALSE;
6098 else if (pPFX->pbData[1 + lenLen] != ASN_INTEGER || /* Tag */
6099 pPFX->pbData[1 + lenLen + 1] != 1 || /* Definite length */
6100 pPFX->pbData[1 + lenLen + 2] != 3) /* PFX version */
6101 ret = FALSE;
6104 else
6105 ret = FALSE;
6106 return ret;
6109 HCERTSTORE WINAPI PFXImportCertStore(CRYPT_DATA_BLOB *pPFX, LPCWSTR szPassword,
6110 DWORD dwFlags)
6112 FIXME_(crypt)("(%p, %p, %08x): stub\n", pPFX, szPassword, dwFlags);
6113 return NULL;
6116 BOOL WINAPI PFXVerifyPassword(CRYPT_DATA_BLOB *pPFX, LPCWSTR szPassword,
6117 DWORD dwFlags)
6119 FIXME_(crypt)("(%p, %p, %08x): stub\n", pPFX, szPassword, dwFlags);
6120 return FALSE;