wow32: Use spec file imports.
[wine.git] / dlls / crypt32 / decode.c
blob946114dcb4dfd59cdf17f481f9f41be3293388e0
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 <assert.h>
34 #include <stdarg.h>
35 #include <stdio.h>
36 #include <stdlib.h>
38 #define NONAMELESSUNION
40 #include "windef.h"
41 #include "winbase.h"
42 #include "wincrypt.h"
43 #include "winnls.h"
44 #include "snmp.h"
45 #include "wine/debug.h"
46 #include "wine/exception.h"
47 #include "crypt32_private.h"
49 /* This is a bit arbitrary, but to set some limit: */
50 #define MAX_ENCODED_LEN 0x04000000
52 #define ASN_FLAGS_MASK 0xe0
53 #define ASN_TYPE_MASK 0x1f
55 WINE_DEFAULT_DEBUG_CHANNEL(cryptasn);
56 WINE_DECLARE_DEBUG_CHANNEL(crypt);
58 void CRYPT_CopyReversed(BYTE *dst, const BYTE *src, size_t len)
60 DWORD i;
61 for (i = 0; i < len; i++) {
62 dst[len - i - 1] = src[i];
66 typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
67 DWORD, DWORD, void *, DWORD *);
68 typedef BOOL (WINAPI *CryptDecodeObjectExFunc)(DWORD, LPCSTR, const BYTE *,
69 DWORD, DWORD, PCRYPT_DECODE_PARA, void *, DWORD *);
71 /* Internal decoders don't do memory allocation or exception handling, and
72 * they report how many bytes they decoded.
74 typedef BOOL (*InternalDecodeFunc)(const BYTE *pbEncoded, DWORD cbEncoded,
75 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
77 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
78 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
79 DWORD *pcbDecoded);
80 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
81 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
82 DWORD *pcbDecoded);
83 /* Assumes pvStructInfo is a CERT_EXTENSION whose pszObjId is set ahead of time.
85 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
86 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
87 /* Assumes algo->Parameters.pbData is set ahead of time. */
88 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
89 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
90 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
91 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
92 /* Assumes the CRYPT_DATA_BLOB's pbData member has been initialized */
93 static BOOL CRYPT_AsnDecodeOctets(const BYTE *pbEncoded,
94 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
95 DWORD *pcbDecoded);
96 /* Doesn't check the tag, assumes the caller does so */
97 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
98 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
99 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
100 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded);
101 /* Like CRYPT_AsnDecodeInteger, but assumes the CRYPT_INTEGER_BLOB's pbData
102 * member has been initialized, doesn't do exception handling, and doesn't do
103 * memory allocation. Also doesn't check tag, assumes the caller has checked
104 * it.
106 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
107 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
108 DWORD *pcbDecoded);
109 /* Like CRYPT_AsnDecodeInteger, but unsigned. */
110 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
111 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
112 DWORD *pcbDecoded);
113 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
114 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
115 DWORD *pcbDecoded);
117 /* Gets the number of length bytes from the given (leading) length byte */
118 #define GET_LEN_BYTES(b) ((b) <= 0x80 ? 1 : 1 + ((b) & 0x7f))
120 /* Helper function to get the encoded length of the data starting at pbEncoded,
121 * where pbEncoded[0] is the tag. If the data are too short to contain a
122 * length or if the length is too large for cbEncoded, sets an appropriate
123 * error code and returns FALSE. If the encoded length is unknown due to
124 * indefinite length encoding, *len is set to CMSG_INDEFINITE_LENGTH.
126 static BOOL CRYPT_GetLengthIndefinite(const BYTE *pbEncoded, DWORD cbEncoded,
127 DWORD *len)
129 BOOL ret;
131 if (cbEncoded <= 1)
133 SetLastError(CRYPT_E_ASN1_CORRUPT);
134 ret = FALSE;
136 else if (pbEncoded[1] <= 0x7f)
138 if (pbEncoded[1] + 1 > cbEncoded)
140 SetLastError(CRYPT_E_ASN1_EOD);
141 ret = FALSE;
143 else
145 *len = pbEncoded[1];
146 ret = TRUE;
149 else if (pbEncoded[1] == 0x80)
151 *len = CMSG_INDEFINITE_LENGTH;
152 ret = TRUE;
154 else
156 BYTE lenLen = GET_LEN_BYTES(pbEncoded[1]);
158 if (lenLen > sizeof(DWORD) + 1)
160 SetLastError(CRYPT_E_ASN1_LARGE);
161 ret = FALSE;
163 else if (lenLen + 2 > cbEncoded)
165 SetLastError(CRYPT_E_ASN1_CORRUPT);
166 ret = FALSE;
168 else
170 DWORD out = 0;
172 pbEncoded += 2;
173 while (--lenLen)
175 out <<= 8;
176 out |= *pbEncoded++;
178 if (out + lenLen + 1 > cbEncoded)
180 SetLastError(CRYPT_E_ASN1_EOD);
181 ret = FALSE;
183 else
185 *len = out;
186 ret = TRUE;
190 return ret;
193 /* Like CRYPT_GetLengthIndefinite, but disallows indefinite-length encoding. */
194 static BOOL CRYPT_GetLen(const BYTE *pbEncoded, DWORD cbEncoded, DWORD *len)
196 BOOL ret;
198 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, len)) &&
199 *len == CMSG_INDEFINITE_LENGTH)
201 SetLastError(CRYPT_E_ASN1_CORRUPT);
202 ret = FALSE;
204 return ret;
207 /* Helper function to check *pcbStructInfo, set it to the required size, and
208 * optionally to allocate memory. Assumes pvStructInfo is not NULL.
209 * If CRYPT_DECODE_ALLOC_FLAG is set in dwFlags, *pvStructInfo will be set to a
210 * pointer to the newly allocated memory.
212 static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
213 const CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
214 DWORD bytesNeeded)
216 BOOL ret = TRUE;
218 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
220 if (pDecodePara && pDecodePara->pfnAlloc)
221 *(BYTE **)pvStructInfo = pDecodePara->pfnAlloc(bytesNeeded);
222 else
223 *(BYTE **)pvStructInfo = LocalAlloc(LPTR, bytesNeeded);
224 if (!*(BYTE **)pvStructInfo)
225 ret = FALSE;
226 else
227 *pcbStructInfo = bytesNeeded;
229 else if (*pcbStructInfo < bytesNeeded)
231 *pcbStructInfo = bytesNeeded;
232 SetLastError(ERROR_MORE_DATA);
233 ret = FALSE;
235 else
236 *pcbStructInfo = bytesNeeded;
237 return ret;
240 static void CRYPT_FreeSpace(const CRYPT_DECODE_PARA *pDecodePara, LPVOID pv)
242 if (pDecodePara && pDecodePara->pfnFree)
243 pDecodePara->pfnFree(pv);
244 else
245 LocalFree(pv);
248 /* Helper function to check *pcbStructInfo and set it to the required size.
249 * Assumes pvStructInfo is not NULL.
251 static BOOL CRYPT_DecodeCheckSpace(DWORD *pcbStructInfo, DWORD bytesNeeded)
253 BOOL ret;
255 if (*pcbStructInfo < bytesNeeded)
257 *pcbStructInfo = bytesNeeded;
258 SetLastError(ERROR_MORE_DATA);
259 ret = FALSE;
261 else
263 *pcbStructInfo = bytesNeeded;
264 ret = TRUE;
266 return ret;
269 /* tag:
270 * The expected tag of the item. If tag is 0, decodeFunc is called
271 * regardless of the tag value seen.
272 * offset:
273 * A sequence is decoded into a struct. The offset member is the
274 * offset of this item within that struct.
275 * decodeFunc:
276 * The decoder function to use. If this is NULL, then the member isn't
277 * decoded, but minSize space is reserved for it.
278 * minSize:
279 * The minimum amount of space occupied after decoding. You must set this.
280 * optional:
281 * If true, and the tag doesn't match the expected tag for this item,
282 * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
283 * filled with 0 for this member.
284 * hasPointer, pointerOffset:
285 * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
286 * the offset within the struct of the data pointer (or to the
287 * first data pointer, if more than one exist).
288 * size:
289 * Used by CRYPT_AsnDecodeSequence, not for your use.
291 struct AsnDecodeSequenceItem
293 BYTE tag;
294 DWORD offset;
295 InternalDecodeFunc decodeFunc;
296 DWORD minSize;
297 BOOL optional;
298 BOOL hasPointer;
299 DWORD pointerOffset;
300 DWORD size;
303 #define FINALMEMBERSIZE(s, member) (sizeof(s) - offsetof(s, member))
304 #define MEMBERSIZE(s, member, nextmember) \
305 (offsetof(s, nextmember) - offsetof(s, member))
307 /* Decodes the items in a sequence, where the items are described in items,
308 * the encoded data are in pbEncoded with length cbEncoded. Decodes into
309 * pvStructInfo. nextData is a pointer to the memory location at which the
310 * first decoded item with a dynamic pointer should point.
311 * Upon decoding, *cbDecoded is the total number of bytes decoded.
312 * Each item decoder is never called with CRYPT_DECODE_ALLOC_FLAG set.
314 static BOOL CRYPT_AsnDecodeSequenceItems(struct AsnDecodeSequenceItem items[],
315 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
316 void *pvStructInfo, BYTE *nextData, DWORD *cbDecoded)
318 BOOL ret;
319 DWORD i, decoded = 0;
320 const BYTE *ptr = pbEncoded;
322 TRACE("%p, %ld, %p, %ld, %08lx, %p, %p, %p\n", items, cItem, pbEncoded,
323 cbEncoded, dwFlags, pvStructInfo, nextData, cbDecoded);
325 for (i = 0, ret = TRUE; ret && i < cItem; i++)
327 if (cbEncoded - (ptr - pbEncoded) != 0)
329 DWORD itemLen;
331 if ((ret = CRYPT_GetLengthIndefinite(ptr,
332 cbEncoded - (ptr - pbEncoded), &itemLen)))
334 BYTE itemLenBytes = GET_LEN_BYTES(ptr[1]);
336 if (ptr[0] == items[i].tag || !items[i].tag)
338 DWORD itemEncodedLen;
340 if (itemLen == CMSG_INDEFINITE_LENGTH)
341 itemEncodedLen = cbEncoded - (ptr - pbEncoded);
342 else
343 itemEncodedLen = 1 + itemLenBytes + itemLen;
344 if (nextData && pvStructInfo && items[i].hasPointer)
346 TRACE("Setting next pointer to %p\n",
347 nextData);
348 *(BYTE **)((BYTE *)pvStructInfo +
349 items[i].pointerOffset) = nextData;
351 if (items[i].decodeFunc)
353 DWORD itemDecoded;
355 if (pvStructInfo)
356 TRACE("decoding item %ld\n", i);
357 else
358 TRACE("sizing item %ld\n", i);
359 ret = items[i].decodeFunc(ptr, itemEncodedLen,
360 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
361 pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
362 : NULL, &items[i].size, &itemDecoded);
363 if (ret)
365 if (items[i].size < items[i].minSize)
366 items[i].size = items[i].minSize;
367 else if (items[i].size > items[i].minSize)
369 /* Account for alignment padding */
370 items[i].size = ALIGN_DWORD_PTR(items[i].size);
372 TRACE("item %ld size: %ld\n", i, items[i].size);
373 if (nextData && items[i].hasPointer &&
374 items[i].size > items[i].minSize)
375 nextData += items[i].size - items[i].minSize;
376 if (itemDecoded > itemEncodedLen)
378 WARN("decoded length %ld exceeds encoded %ld\n",
379 itemDecoded, itemEncodedLen);
380 SetLastError(CRYPT_E_ASN1_CORRUPT);
381 ret = FALSE;
383 else
385 ptr += itemDecoded;
386 decoded += itemDecoded;
387 TRACE("item %ld: decoded %ld bytes\n", i,
388 itemDecoded);
391 else if (items[i].optional &&
392 GetLastError() == CRYPT_E_ASN1_BADTAG)
394 TRACE("skipping optional item %ld\n", i);
395 items[i].size = items[i].minSize;
396 SetLastError(NOERROR);
397 ret = TRUE;
399 else
400 TRACE("item %ld failed: %08lx\n", i,
401 GetLastError());
403 else if (itemLen == CMSG_INDEFINITE_LENGTH)
405 ERR("can't use indefinite length encoding without a decoder\n");
406 SetLastError(CRYPT_E_ASN1_CORRUPT);
407 ret = FALSE;
409 else
411 TRACE("item %ld: decoded %ld bytes\n", i, itemEncodedLen);
412 ptr += itemEncodedLen;
413 decoded += itemEncodedLen;
414 items[i].size = items[i].minSize;
417 else if (items[i].optional)
419 TRACE("skipping optional item %ld\n", i);
420 items[i].size = items[i].minSize;
422 else
424 TRACE("item %ld: tag %02x doesn't match expected %02x\n",
425 i, ptr[0], items[i].tag);
426 SetLastError(CRYPT_E_ASN1_BADTAG);
427 ret = FALSE;
431 else if (items[i].optional)
433 TRACE("missing optional item %ld, skipping\n", i);
434 items[i].size = items[i].minSize;
436 else
438 TRACE("not enough bytes for item %ld, failing\n", i);
439 SetLastError(CRYPT_E_ASN1_CORRUPT);
440 ret = FALSE;
443 if (cbDecoded)
444 *cbDecoded = decoded;
445 TRACE("returning %d\n", ret);
446 return ret;
449 /* This decodes an arbitrary sequence into a contiguous block of memory
450 * (basically, a struct.) Each element being decoded is described by a struct
451 * AsnDecodeSequenceItem, see above.
452 * startingPointer is an optional pointer to the first place where dynamic
453 * data will be stored. If you know the starting offset, you may pass it
454 * here. Otherwise, pass NULL, and one will be inferred from the items.
456 static BOOL CRYPT_AsnDecodeSequence(struct AsnDecodeSequenceItem items[],
457 DWORD cItem, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
458 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
459 DWORD *pcbDecoded, void *startingPointer)
461 BOOL ret;
463 TRACE("%p, %ld, %p, %ld, %08lx, %p, %p, %ld, %p\n", items, cItem, pbEncoded,
464 cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
465 startingPointer);
467 if (!cbEncoded)
469 SetLastError(CRYPT_E_ASN1_EOD);
470 return FALSE;
472 if (pbEncoded[0] == ASN_SEQUENCE)
474 DWORD dataLen;
476 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
478 DWORD lenBytes = GET_LEN_BYTES(pbEncoded[1]), cbDecoded;
479 const BYTE *ptr = pbEncoded + 1 + lenBytes;
480 BOOL indefinite = FALSE;
482 cbEncoded -= 1 + lenBytes;
483 if (dataLen == CMSG_INDEFINITE_LENGTH)
485 dataLen = cbEncoded;
486 indefinite = TRUE;
487 lenBytes += 2;
489 else if (cbEncoded < dataLen)
491 TRACE("dataLen %ld exceeds cbEncoded %ld, failing\n", dataLen,
492 cbEncoded);
493 SetLastError(CRYPT_E_ASN1_CORRUPT);
494 ret = FALSE;
496 if (ret)
498 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
499 ptr, dataLen, dwFlags, NULL, NULL, &cbDecoded);
500 if (ret && dataLen == CMSG_INDEFINITE_LENGTH)
502 if (cbDecoded > cbEncoded - 2)
504 /* Not enough space for 0 TLV */
505 SetLastError(CRYPT_E_ASN1_CORRUPT);
506 ret = FALSE;
508 else if (*(ptr + cbDecoded) != 0 ||
509 *(ptr + cbDecoded + 1) != 0)
511 TRACE("expected 0 TLV\n");
512 SetLastError(CRYPT_E_ASN1_CORRUPT);
513 ret = FALSE;
515 else
516 cbDecoded += 2;
519 if (ret && !indefinite && cbDecoded != dataLen)
521 TRACE("expected %ld decoded, got %ld, failing\n", dataLen,
522 cbDecoded);
523 SetLastError(CRYPT_E_ASN1_CORRUPT);
524 ret = FALSE;
526 if (ret)
528 DWORD i, bytesNeeded = 0, structSize = 0;
530 for (i = 0; i < cItem; i++)
532 if (items[i].size > items[i].minSize)
533 bytesNeeded += items[i].size - items[i].minSize;
534 structSize = max( structSize, items[i].offset + items[i].minSize );
536 bytesNeeded += structSize;
537 if (pcbDecoded)
538 *pcbDecoded = 1 + lenBytes + cbDecoded;
539 if (!pvStructInfo)
540 *pcbStructInfo = bytesNeeded;
541 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
542 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
544 BYTE *nextData;
546 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
547 pvStructInfo = *(BYTE **)pvStructInfo;
548 if (startingPointer)
549 nextData = startingPointer;
550 else
551 nextData = (BYTE *)pvStructInfo + structSize;
552 memset(pvStructInfo, 0, structSize);
553 ret = CRYPT_AsnDecodeSequenceItems(items, cItem,
554 ptr, dataLen, dwFlags, pvStructInfo, nextData,
555 &cbDecoded);
556 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
557 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
562 else
564 SetLastError(CRYPT_E_ASN1_BADTAG);
565 ret = FALSE;
567 TRACE("returning %d (%08lx)\n", ret, GetLastError());
568 return ret;
571 /* tag:
572 * The expected tag of the entire encoded array (usually a variant
573 * of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
574 * regardless of the tag seen.
575 * countOffset:
576 * The offset within the outer structure at which the count exists.
577 * For example, a structure such as CRYPT_ATTRIBUTES has countOffset == 0,
578 * while CRYPT_ATTRIBUTE has countOffset ==
579 * offsetof(CRYPT_ATTRIBUTE, cValue).
580 * arrayOffset:
581 * The offset within the outer structure at which the array pointer exists.
582 * For example, CRYPT_ATTRIBUTES has arrayOffset ==
583 * offsetof(CRYPT_ATTRIBUTES, rgAttr).
584 * minArraySize:
585 * The minimum size of the decoded array. On WIN32, this is always 8:
586 * sizeof(DWORD) + sizeof(void *). On WIN64, it can be larger due to
587 * alignment.
588 * decodeFunc:
589 * used to decode each item in the array
590 * itemSize:
591 * is the minimum size of each decoded item
592 * hasPointer:
593 * indicates whether each item has a dynamic pointer
594 * pointerOffset:
595 * indicates the offset within itemSize at which the pointer exists
597 struct AsnArrayDescriptor
599 BYTE tag;
600 DWORD countOffset;
601 DWORD arrayOffset;
602 DWORD minArraySize;
603 InternalDecodeFunc decodeFunc;
604 DWORD itemSize;
605 BOOL hasPointer;
606 DWORD pointerOffset;
609 struct AsnArrayItemSize
611 DWORD encodedLen;
612 DWORD size;
615 /* Decodes an array of like types into a structure described by a struct
616 * AsnArrayDescriptor.
618 static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
619 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
620 const CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo,
621 DWORD *pcbDecoded)
623 BOOL ret = TRUE;
625 TRACE("%p, %p, %ld, %p, %ld\n", arrayDesc, pbEncoded,
626 cbEncoded, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
628 if (!cbEncoded)
630 SetLastError(CRYPT_E_ASN1_EOD);
631 ret = FALSE;
633 else if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
635 DWORD dataLen;
637 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
639 DWORD bytesNeeded = arrayDesc->minArraySize, cItems = 0, capacity = 0, decoded;
640 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
641 /* There can be arbitrarily many items, but there is often only one.
643 struct AsnArrayItemSize itemSize = { 0 }, *itemSizes = &itemSize;
645 decoded = 1 + lenBytes;
646 if (dataLen)
648 const BYTE *ptr;
649 BOOL doneDecoding = FALSE;
651 for (ptr = pbEncoded + 1 + lenBytes; ret && !doneDecoding; )
653 if (dataLen == CMSG_INDEFINITE_LENGTH)
655 if (ptr[0] == 0)
657 doneDecoding = TRUE;
658 if (ptr[1] != 0)
660 SetLastError(CRYPT_E_ASN1_CORRUPT);
661 ret = FALSE;
663 else
664 decoded += 2;
667 else if (ptr - pbEncoded - 1 - lenBytes >= dataLen)
668 doneDecoding = TRUE;
669 if (!doneDecoding)
671 DWORD itemEncoded, itemDataLen, itemDecoded, size = 0;
673 /* Each item decoded may not tolerate extraneous bytes,
674 * so get the length of the next element if known.
676 if ((ret = CRYPT_GetLengthIndefinite(ptr,
677 cbEncoded - (ptr - pbEncoded), &itemDataLen)))
679 if (itemDataLen == CMSG_INDEFINITE_LENGTH)
680 itemEncoded = cbEncoded - (ptr - pbEncoded);
681 else
682 itemEncoded = 1 + GET_LEN_BYTES(ptr[1]) +
683 itemDataLen;
685 if (ret)
686 ret = arrayDesc->decodeFunc(ptr, itemEncoded,
687 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &size,
688 &itemDecoded);
689 if (ret)
691 /* Ignore an item that failed to decode but the decoder doesn't want to fail the whole process */
692 if (!size)
694 ptr += itemEncoded;
695 continue;
698 if (++cItems <= 1)
699 itemSizes = &itemSize;
700 else if (itemSizes == &itemSize)
702 capacity = 1024;
703 itemSizes = CryptMemAlloc(capacity * sizeof(struct AsnArrayItemSize));
704 if (itemSizes) *itemSizes = itemSize;
706 else if (cItems > capacity)
708 capacity = capacity * 3 / 2;
709 itemSizes = CryptMemRealloc(itemSizes, capacity * sizeof(struct AsnArrayItemSize));
711 if (itemSizes)
713 decoded += itemDecoded;
714 itemSizes[cItems - 1].encodedLen = itemEncoded;
715 itemSizes[cItems - 1].size = size;
716 bytesNeeded += size;
717 ptr += itemEncoded;
719 else
720 ret = FALSE;
725 if (ret)
727 if (pcbDecoded)
728 *pcbDecoded = decoded;
729 if (!pvStructInfo)
730 *pcbStructInfo = bytesNeeded;
731 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
732 pvStructInfo, pcbStructInfo, bytesNeeded)))
734 DWORD i, *pcItems;
735 BYTE *nextData;
736 const BYTE *ptr;
737 void *rgItems;
739 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
740 pvStructInfo = *(void **)pvStructInfo;
741 pcItems = pvStructInfo;
742 *pcItems = cItems;
743 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
745 rgItems = (BYTE *)pvStructInfo +
746 arrayDesc->minArraySize;
747 *(void **)((BYTE *)pcItems -
748 arrayDesc->countOffset + arrayDesc->arrayOffset) =
749 rgItems;
751 else
752 rgItems = *(void **)((BYTE *)pcItems -
753 arrayDesc->countOffset + arrayDesc->arrayOffset);
754 nextData = (BYTE *)rgItems + cItems * arrayDesc->itemSize;
755 for (i = 0, ptr = pbEncoded + 1 + lenBytes; ret &&
756 i < cItems && ptr - pbEncoded - 1 - lenBytes <
757 dataLen; i++)
759 DWORD itemDecoded;
761 if (arrayDesc->hasPointer)
762 *(BYTE **)((BYTE *)rgItems + i * arrayDesc->itemSize
763 + arrayDesc->pointerOffset) = nextData;
764 ret = arrayDesc->decodeFunc(ptr,
765 itemSizes[i].encodedLen,
766 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
767 (BYTE *)rgItems + i * arrayDesc->itemSize,
768 &itemSizes[i].size, &itemDecoded);
769 if (ret)
771 nextData += itemSizes[i].size - arrayDesc->itemSize;
772 ptr += itemDecoded;
775 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
776 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
779 if (itemSizes != &itemSize)
780 CryptMemFree(itemSizes);
783 else
785 SetLastError(CRYPT_E_ASN1_BADTAG);
786 ret = FALSE;
788 return ret;
791 /* Decodes a DER-encoded BLOB into a CRYPT_DER_BLOB struct pointed to by
792 * pvStructInfo. The BLOB must be non-empty, otherwise the last error is set
793 * to CRYPT_E_ASN1_CORRUPT.
794 * Warning: assumes the CRYPT_DER_BLOB pointed to by pvStructInfo has pbData
795 * set!
797 static BOOL CRYPT_AsnDecodeDerBlob(const BYTE *pbEncoded, DWORD cbEncoded,
798 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
800 BOOL ret;
801 DWORD dataLen;
803 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
805 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
806 DWORD bytesNeeded = sizeof(CRYPT_DER_BLOB);
808 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
809 bytesNeeded += 1 + lenBytes + dataLen;
811 if (pcbDecoded)
812 *pcbDecoded = 1 + lenBytes + dataLen;
813 if (!pvStructInfo)
814 *pcbStructInfo = bytesNeeded;
815 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, bytesNeeded)))
817 CRYPT_DER_BLOB *blob;
819 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
820 pvStructInfo = *(BYTE **)pvStructInfo;
821 blob = pvStructInfo;
822 blob->cbData = 1 + lenBytes + dataLen;
823 if (blob->cbData)
825 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
826 blob->pbData = (BYTE *)pbEncoded;
827 else
829 assert(blob->pbData);
830 memcpy(blob->pbData, pbEncoded, blob->cbData);
833 else
835 SetLastError(CRYPT_E_ASN1_CORRUPT);
836 ret = FALSE;
840 return ret;
843 /* Like CRYPT_AsnDecodeBitsInternal, but swaps the bytes */
844 static BOOL CRYPT_AsnDecodeBitsSwapBytes(const BYTE *pbEncoded,
845 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
846 DWORD *pcbDecoded)
848 BOOL ret;
850 TRACE("(%p, %ld, 0x%08lx, %p, %ld, %p)\n", pbEncoded, cbEncoded, dwFlags,
851 pvStructInfo, *pcbStructInfo, pcbDecoded);
853 /* Can't use the CRYPT_DECODE_NOCOPY_FLAG, because we modify the bytes in-
854 * place.
856 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
857 dwFlags & ~CRYPT_DECODE_NOCOPY_FLAG, pvStructInfo, pcbStructInfo,
858 pcbDecoded);
859 if (ret && pvStructInfo)
861 CRYPT_BIT_BLOB *blob = pvStructInfo;
863 if (blob->cbData)
865 DWORD i;
866 BYTE temp;
868 for (i = 0; i < blob->cbData / 2; i++)
870 temp = blob->pbData[i];
871 blob->pbData[i] = blob->pbData[blob->cbData - i - 1];
872 blob->pbData[blob->cbData - i - 1] = temp;
876 TRACE("returning %d (%08lx)\n", ret, GetLastError());
877 return ret;
880 static BOOL WINAPI CRYPT_AsnDecodeCertSignedContent(DWORD dwCertEncodingType,
881 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
882 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
884 BOOL ret = TRUE;
886 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
887 pDecodePara, pvStructInfo, *pcbStructInfo);
889 __TRY
891 struct AsnDecodeSequenceItem items[] = {
892 { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
893 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
894 offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
895 { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
896 SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
897 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
898 offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
899 { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
900 CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
901 offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
904 if (dwFlags & CRYPT_DECODE_NO_SIGNATURE_BYTE_REVERSAL_FLAG)
905 items[2].decodeFunc = CRYPT_AsnDecodeBitsInternal;
906 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
907 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
908 pcbStructInfo, NULL, NULL);
910 __EXCEPT_PAGE_FAULT
912 SetLastError(STATUS_ACCESS_VIOLATION);
913 ret = FALSE;
915 __ENDTRY
917 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
918 return ret;
921 static BOOL CRYPT_AsnDecodeCertVersion(const BYTE *pbEncoded, DWORD cbEncoded,
922 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
924 BOOL ret;
925 DWORD dataLen;
927 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
929 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
931 ret = CRYPT_AsnDecodeIntInternal(pbEncoded + 1 + lenBytes, dataLen,
932 dwFlags, pvStructInfo, pcbStructInfo, NULL);
933 if (pcbDecoded)
934 *pcbDecoded = 1 + lenBytes + dataLen;
936 return ret;
939 static BOOL CRYPT_AsnDecodeValidity(const BYTE *pbEncoded, DWORD cbEncoded,
940 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
942 BOOL ret;
944 struct AsnDecodeSequenceItem items[] = {
945 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
946 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
947 { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
948 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
951 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
952 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
953 pcbDecoded, NULL);
954 return ret;
957 static BOOL CRYPT_AsnDecodeCertExtensionsInternal(const BYTE *pbEncoded,
958 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
959 DWORD *pcbDecoded)
961 BOOL ret = TRUE;
962 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
963 offsetof(CERT_INFO, cExtension), offsetof(CERT_INFO, rgExtension),
964 FINALMEMBERSIZE(CERT_INFO, cExtension),
965 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
966 offsetof(CERT_EXTENSION, pszObjId) };
968 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
969 pvStructInfo, *pcbStructInfo, pcbDecoded);
971 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
972 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
973 return ret;
976 static BOOL CRYPT_AsnDecodeCertExtensions(const BYTE *pbEncoded,
977 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
978 DWORD *pcbDecoded)
980 BOOL ret;
981 DWORD dataLen;
983 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
985 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
987 ret = CRYPT_AsnDecodeCertExtensionsInternal(pbEncoded + 1 + lenBytes,
988 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
989 if (ret && pcbDecoded)
990 *pcbDecoded = 1 + lenBytes + dataLen;
992 return ret;
995 static BOOL CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
996 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
997 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
999 BOOL ret = TRUE;
1000 struct AsnDecodeSequenceItem items[] = {
1001 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
1002 CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1003 { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
1004 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
1005 TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
1006 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
1007 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1008 FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
1009 { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1010 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
1011 Issuer.pbData) },
1012 { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
1013 CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
1014 FALSE, 0 },
1015 { 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
1016 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
1017 Subject.pbData) },
1018 { ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
1019 CRYPT_AsnDecodePubKeyInfoInternal, sizeof(CERT_PUBLIC_KEY_INFO),
1020 FALSE, TRUE, offsetof(CERT_INFO,
1021 SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
1022 { ASN_CONTEXT | 1, offsetof(CERT_INFO, IssuerUniqueId),
1023 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
1024 offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
1025 { ASN_CONTEXT | 2, offsetof(CERT_INFO, SubjectUniqueId),
1026 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
1027 offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
1028 { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
1029 CRYPT_AsnDecodeCertExtensions, FINALMEMBERSIZE(CERT_INFO, cExtension),
1030 TRUE, TRUE, offsetof(CERT_INFO, rgExtension), 0 },
1033 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1034 pDecodePara, pvStructInfo, *pcbStructInfo);
1036 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
1037 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo,
1038 NULL, NULL);
1039 if (ret && pvStructInfo)
1041 CERT_INFO *info;
1043 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1044 info = *(CERT_INFO **)pvStructInfo;
1045 else
1046 info = pvStructInfo;
1047 if (!info->SerialNumber.cbData || !info->Issuer.cbData ||
1048 !info->Subject.cbData)
1050 SetLastError(CRYPT_E_ASN1_CORRUPT);
1051 /* Don't need to deallocate, because it should have failed on the
1052 * first pass (and no memory was allocated.)
1054 ret = FALSE;
1058 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
1059 return ret;
1062 static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
1063 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1064 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1066 BOOL ret = FALSE;
1068 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1069 pDecodePara, pvStructInfo, *pcbStructInfo);
1071 __TRY
1073 DWORD size = 0;
1075 /* Unless told not to, first try to decode it as a signed cert. */
1076 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1078 PCERT_SIGNED_CONTENT_INFO signedCert = NULL;
1080 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1081 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1082 &signedCert, &size);
1083 if (ret)
1085 size = 0;
1086 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1087 X509_CERT_TO_BE_SIGNED, signedCert->ToBeSigned.pbData,
1088 signedCert->ToBeSigned.cbData, dwFlags, pDecodePara,
1089 pvStructInfo, pcbStructInfo);
1090 LocalFree(signedCert);
1093 /* Failing that, try it as an unsigned cert */
1094 if (!ret)
1096 size = 0;
1097 ret = CRYPT_AsnDecodeCertInfo(dwCertEncodingType,
1098 X509_CERT_TO_BE_SIGNED, pbEncoded, cbEncoded, dwFlags,
1099 pDecodePara, pvStructInfo, pcbStructInfo);
1102 __EXCEPT_PAGE_FAULT
1104 SetLastError(STATUS_ACCESS_VIOLATION);
1106 __ENDTRY
1108 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
1109 return ret;
1112 static BOOL CRYPT_AsnDecodeCRLEntryExtensions(const BYTE *pbEncoded,
1113 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1114 DWORD *pcbDecoded)
1116 BOOL ret = TRUE;
1117 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1118 offsetof(CRL_ENTRY, cExtension), offsetof(CRL_ENTRY, rgExtension),
1119 FINALMEMBERSIZE(CRL_ENTRY, cExtension),
1120 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1121 offsetof(CERT_EXTENSION, pszObjId) };
1123 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
1124 pvStructInfo, *pcbStructInfo, pcbDecoded);
1126 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1127 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1128 return ret;
1131 static BOOL CRYPT_AsnDecodeCRLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
1132 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1134 BOOL ret;
1135 struct AsnDecodeSequenceItem items[] = {
1136 { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
1137 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
1138 offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
1139 { 0, offsetof(CRL_ENTRY, RevocationDate),
1140 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE, 0 },
1141 { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
1142 CRYPT_AsnDecodeCRLEntryExtensions,
1143 FINALMEMBERSIZE(CRL_ENTRY, cExtension), TRUE, TRUE,
1144 offsetof(CRL_ENTRY, rgExtension), 0 },
1146 PCRL_ENTRY entry = pvStructInfo;
1148 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, entry,
1149 *pcbStructInfo);
1151 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
1152 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo, pcbDecoded,
1153 entry ? entry->SerialNumber.pbData : NULL);
1154 if (ret && entry && !entry->SerialNumber.cbData)
1156 WARN("empty CRL entry serial number\n");
1157 SetLastError(CRYPT_E_ASN1_CORRUPT);
1158 ret = FALSE;
1160 return ret;
1163 /* Warning: assumes pvStructInfo points to the cCRLEntry member of a CRL_INFO
1164 * whose rgCRLEntry member has been set prior to calling.
1166 static BOOL CRYPT_AsnDecodeCRLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
1167 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1169 BOOL ret;
1170 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1171 offsetof(CRL_INFO, cCRLEntry), offsetof(CRL_INFO, rgCRLEntry),
1172 MEMBERSIZE(CRL_INFO, cCRLEntry, cExtension),
1173 CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
1174 offsetof(CRL_ENTRY, SerialNumber.pbData) };
1176 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
1177 pvStructInfo, *pcbStructInfo, pcbDecoded);
1179 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1180 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1181 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
1182 return ret;
1185 static BOOL CRYPT_AsnDecodeCRLExtensionsInternal(const BYTE *pbEncoded,
1186 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1187 DWORD *pcbDecoded)
1189 BOOL ret = TRUE;
1190 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1191 offsetof(CRL_INFO, cExtension), offsetof(CRL_INFO, rgExtension),
1192 FINALMEMBERSIZE(CRL_INFO, cExtension),
1193 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1194 offsetof(CERT_EXTENSION, pszObjId) };
1196 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
1197 pvStructInfo, *pcbStructInfo, pcbDecoded);
1199 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1200 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1201 return ret;
1204 static BOOL CRYPT_AsnDecodeCRLExtensions(const BYTE *pbEncoded,
1205 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1206 DWORD *pcbDecoded)
1208 BOOL ret;
1209 DWORD dataLen;
1211 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1213 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1215 ret = CRYPT_AsnDecodeCRLExtensionsInternal(pbEncoded + 1 + lenBytes,
1216 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
1217 if (ret && pcbDecoded)
1218 *pcbDecoded = 1 + lenBytes + dataLen;
1220 return ret;
1223 static BOOL CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
1224 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1225 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1227 struct AsnDecodeSequenceItem items[] = {
1228 { ASN_INTEGER, offsetof(CRL_INFO, dwVersion),
1229 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
1230 { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
1231 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
1232 FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
1233 { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
1234 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
1235 Issuer.pbData) },
1236 { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1237 sizeof(FILETIME), FALSE, FALSE, 0 },
1238 { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTimeInternal,
1239 sizeof(FILETIME), TRUE, FALSE, 0 },
1240 { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
1241 CRYPT_AsnDecodeCRLEntries, MEMBERSIZE(CRL_INFO, cCRLEntry, cExtension),
1242 TRUE, TRUE, offsetof(CRL_INFO, rgCRLEntry), 0 },
1243 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_INFO, cExtension),
1244 CRYPT_AsnDecodeCRLExtensions, FINALMEMBERSIZE(CRL_INFO, cExtension),
1245 TRUE, TRUE, offsetof(CRL_INFO, rgExtension), 0 },
1247 BOOL ret = TRUE;
1249 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1250 pDecodePara, pvStructInfo, *pcbStructInfo);
1252 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags,
1253 pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
1255 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
1256 return ret;
1259 static BOOL WINAPI CRYPT_AsnDecodeCRL(DWORD dwCertEncodingType,
1260 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1261 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1263 BOOL ret = FALSE;
1265 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1266 pDecodePara, pvStructInfo, *pcbStructInfo);
1268 __TRY
1270 DWORD size = 0;
1272 /* Unless told not to, first try to decode it as a signed crl. */
1273 if (!(dwFlags & CRYPT_DECODE_TO_BE_SIGNED_FLAG))
1275 PCERT_SIGNED_CONTENT_INFO signedCrl = NULL;
1277 ret = CRYPT_AsnDecodeCertSignedContent(dwCertEncodingType,
1278 X509_CERT, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL,
1279 &signedCrl, &size);
1280 if (ret)
1282 size = 0;
1283 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1284 X509_CERT_CRL_TO_BE_SIGNED, signedCrl->ToBeSigned.pbData,
1285 signedCrl->ToBeSigned.cbData, dwFlags, pDecodePara,
1286 pvStructInfo, pcbStructInfo);
1287 LocalFree(signedCrl);
1290 /* Failing that, try it as an unsigned crl */
1291 if (!ret)
1293 size = 0;
1294 ret = CRYPT_AsnDecodeCRLInfo(dwCertEncodingType,
1295 X509_CERT_CRL_TO_BE_SIGNED, pbEncoded, cbEncoded,
1296 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
1299 __EXCEPT_PAGE_FAULT
1301 SetLastError(STATUS_ACCESS_VIOLATION);
1303 __ENDTRY
1305 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
1306 return ret;
1309 static BOOL CRYPT_AsnDecodeOidIgnoreTag(const BYTE *pbEncoded, DWORD cbEncoded,
1310 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1312 BOOL ret = TRUE;
1313 DWORD dataLen;
1315 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1316 pvStructInfo, *pcbStructInfo);
1318 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1320 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1321 DWORD bytesNeeded = sizeof(LPSTR);
1323 if (dataLen)
1325 const BYTE *ptr;
1326 char str[32];
1328 snprintf(str, sizeof(str), "%d.%d",
1329 pbEncoded[1 + lenBytes] / 40,
1330 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] / 40)
1331 * 40);
1332 bytesNeeded += strlen(str) + 1;
1333 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1334 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1336 int val = 0;
1338 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1339 (*ptr & 0x80))
1341 val <<= 7;
1342 val |= *ptr & 0x7f;
1343 ptr++;
1345 if (ptr - pbEncoded - 1 - lenBytes >= dataLen ||
1346 (*ptr & 0x80))
1348 SetLastError(CRYPT_E_ASN1_CORRUPT);
1349 ret = FALSE;
1351 else
1353 val <<= 7;
1354 val |= *ptr++;
1355 snprintf(str, sizeof(str), ".%d", val);
1356 bytesNeeded += strlen(str);
1360 if (pcbDecoded)
1361 *pcbDecoded = 1 + lenBytes + dataLen;
1362 if (!pvStructInfo)
1363 *pcbStructInfo = bytesNeeded;
1364 else if (*pcbStructInfo < bytesNeeded)
1366 *pcbStructInfo = bytesNeeded;
1367 SetLastError(ERROR_MORE_DATA);
1368 ret = FALSE;
1370 else
1372 if (dataLen)
1374 const BYTE *ptr;
1375 LPSTR pszObjId = *(LPSTR *)pvStructInfo;
1377 *pszObjId = 0;
1378 sprintf(pszObjId, "%d.%d", pbEncoded[1 + lenBytes] / 40,
1379 pbEncoded[1 + lenBytes] - (pbEncoded[1 + lenBytes] /
1380 40) * 40);
1381 pszObjId += strlen(pszObjId);
1382 for (ptr = pbEncoded + 2 + lenBytes; ret &&
1383 ptr - pbEncoded - 1 - lenBytes < dataLen; )
1385 int val = 0;
1387 while (ptr - pbEncoded - 1 - lenBytes < dataLen &&
1388 (*ptr & 0x80))
1390 val <<= 7;
1391 val |= *ptr & 0x7f;
1392 ptr++;
1394 val <<= 7;
1395 val |= *ptr++;
1396 sprintf(pszObjId, ".%d", val);
1397 pszObjId += strlen(pszObjId);
1400 else
1401 *(LPSTR *)pvStructInfo = NULL;
1402 *pcbStructInfo = bytesNeeded;
1405 return ret;
1408 static BOOL CRYPT_AsnDecodeOidInternal(const BYTE *pbEncoded, DWORD cbEncoded,
1409 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1411 BOOL ret;
1413 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1414 pvStructInfo, *pcbStructInfo);
1416 if (pbEncoded[0] == ASN_OBJECTIDENTIFIER)
1417 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, dwFlags,
1418 pvStructInfo, pcbStructInfo, pcbDecoded);
1419 else
1421 SetLastError(CRYPT_E_ASN1_BADTAG);
1422 ret = FALSE;
1424 return ret;
1427 static BOOL CRYPT_AsnDecodeExtension(const BYTE *pbEncoded, DWORD cbEncoded,
1428 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1430 struct AsnDecodeSequenceItem items[] = {
1431 { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
1432 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1433 offsetof(CERT_EXTENSION, pszObjId), 0 },
1434 { ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
1435 sizeof(BOOL), TRUE, FALSE, 0, 0 },
1436 { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
1437 CRYPT_AsnDecodeOctets, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
1438 offsetof(CERT_EXTENSION, Value.pbData) },
1440 BOOL ret = TRUE;
1441 PCERT_EXTENSION ext = pvStructInfo;
1443 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, ext,
1444 *pcbStructInfo);
1446 if (ext)
1447 TRACE("ext->pszObjId is %p\n", ext->pszObjId);
1448 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
1449 pbEncoded, cbEncoded, dwFlags, NULL, ext, pcbStructInfo,
1450 pcbDecoded, ext ? ext->pszObjId : NULL);
1451 if (ext)
1452 TRACE("ext->pszObjId is %p (%s)\n", ext->pszObjId,
1453 debugstr_a(ext->pszObjId));
1454 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1455 return ret;
1458 static BOOL WINAPI CRYPT_AsnDecodeExtensions(DWORD dwCertEncodingType,
1459 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1460 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1462 BOOL ret = TRUE;
1464 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1465 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
1467 __TRY
1469 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1470 offsetof(CERT_EXTENSIONS, cExtension),
1471 offsetof(CERT_EXTENSIONS, rgExtension),
1472 sizeof(CERT_EXTENSIONS),
1473 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
1474 offsetof(CERT_EXTENSION, pszObjId) };
1475 CERT_EXTENSIONS *exts = pvStructInfo;
1477 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
1478 exts->rgExtension = (CERT_EXTENSION *)(exts + 1);
1479 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1480 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
1482 __EXCEPT_PAGE_FAULT
1484 SetLastError(STATUS_ACCESS_VIOLATION);
1485 ret = FALSE;
1487 __ENDTRY
1488 return ret;
1491 /* Warning: this assumes the address of value->Value.pbData is already set, in
1492 * order to avoid overwriting memory. (In some cases, it may change it, if it
1493 * doesn't copy anything to memory.) Be sure to set it correctly!
1495 static BOOL CRYPT_AsnDecodeNameValueInternal(const BYTE *pbEncoded,
1496 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1497 DWORD *pcbDecoded)
1499 BOOL ret = TRUE;
1500 DWORD dataLen;
1501 CERT_NAME_VALUE *value = pvStructInfo;
1503 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1505 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1506 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1508 switch (pbEncoded[0])
1510 case ASN_OCTETSTRING:
1511 valueType = CERT_RDN_OCTET_STRING;
1512 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1513 bytesNeeded += dataLen;
1514 break;
1515 case ASN_NUMERICSTRING:
1516 valueType = CERT_RDN_NUMERIC_STRING;
1517 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1518 bytesNeeded += dataLen;
1519 break;
1520 case ASN_PRINTABLESTRING:
1521 valueType = CERT_RDN_PRINTABLE_STRING;
1522 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1523 bytesNeeded += dataLen;
1524 break;
1525 case ASN_IA5STRING:
1526 valueType = CERT_RDN_IA5_STRING;
1527 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1528 bytesNeeded += dataLen;
1529 break;
1530 case ASN_T61STRING:
1531 valueType = CERT_RDN_T61_STRING;
1532 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1533 bytesNeeded += dataLen;
1534 break;
1535 case ASN_VIDEOTEXSTRING:
1536 valueType = CERT_RDN_VIDEOTEX_STRING;
1537 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1538 bytesNeeded += dataLen;
1539 break;
1540 case ASN_GRAPHICSTRING:
1541 valueType = CERT_RDN_GRAPHIC_STRING;
1542 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1543 bytesNeeded += dataLen;
1544 break;
1545 case ASN_VISIBLESTRING:
1546 valueType = CERT_RDN_VISIBLE_STRING;
1547 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1548 bytesNeeded += dataLen;
1549 break;
1550 case ASN_GENERALSTRING:
1551 valueType = CERT_RDN_GENERAL_STRING;
1552 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1553 bytesNeeded += dataLen;
1554 break;
1555 case ASN_UNIVERSALSTRING:
1556 FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
1557 SetLastError(CRYPT_E_ASN1_BADTAG);
1558 return FALSE;
1559 case ASN_BMPSTRING:
1560 valueType = CERT_RDN_BMP_STRING;
1561 bytesNeeded += dataLen;
1562 break;
1563 case ASN_UTF8STRING:
1564 valueType = CERT_RDN_UTF8_STRING;
1565 bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
1566 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * sizeof(WCHAR);
1567 break;
1568 default:
1569 SetLastError(CRYPT_E_ASN1_BADTAG);
1570 return FALSE;
1573 if (pcbDecoded)
1574 *pcbDecoded = 1 + lenBytes + dataLen;
1575 if (!value)
1576 *pcbStructInfo = bytesNeeded;
1577 else if (*pcbStructInfo < bytesNeeded)
1579 *pcbStructInfo = bytesNeeded;
1580 SetLastError(ERROR_MORE_DATA);
1581 ret = FALSE;
1583 else
1585 *pcbStructInfo = bytesNeeded;
1586 value->dwValueType = valueType;
1587 if (dataLen)
1589 DWORD i;
1591 assert(value->Value.pbData);
1592 switch (pbEncoded[0])
1594 case ASN_OCTETSTRING:
1595 case ASN_NUMERICSTRING:
1596 case ASN_PRINTABLESTRING:
1597 case ASN_IA5STRING:
1598 case ASN_T61STRING:
1599 case ASN_VIDEOTEXSTRING:
1600 case ASN_GRAPHICSTRING:
1601 case ASN_VISIBLESTRING:
1602 case ASN_GENERALSTRING:
1603 value->Value.cbData = dataLen;
1604 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
1605 memcpy(value->Value.pbData,
1606 pbEncoded + 1 + lenBytes, dataLen);
1607 else
1608 value->Value.pbData = (LPBYTE)pbEncoded + 1 +
1609 lenBytes;
1610 break;
1611 case ASN_BMPSTRING:
1613 LPWSTR str = (LPWSTR)value->Value.pbData;
1615 value->Value.cbData = dataLen;
1616 for (i = 0; i < dataLen / 2; i++)
1617 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1618 pbEncoded[1 + lenBytes + 2 * i + 1];
1619 break;
1621 case ASN_UTF8STRING:
1623 LPWSTR str = (LPWSTR)value->Value.pbData;
1625 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1626 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1627 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
1628 break;
1632 else
1634 value->Value.cbData = 0;
1635 value->Value.pbData = NULL;
1639 return ret;
1642 static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
1643 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1644 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1646 BOOL ret = TRUE;
1648 __TRY
1650 ret = CRYPT_AsnDecodeNameValueInternal(pbEncoded, cbEncoded,
1651 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1652 if (ret && pvStructInfo)
1654 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1655 pcbStructInfo, *pcbStructInfo);
1656 if (ret)
1658 CERT_NAME_VALUE *value;
1660 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1661 pvStructInfo = *(BYTE **)pvStructInfo;
1662 value = pvStructInfo;
1663 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1664 ret = CRYPT_AsnDecodeNameValueInternal( pbEncoded, cbEncoded,
1665 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1666 pcbStructInfo, NULL);
1667 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
1668 CRYPT_FreeSpace(pDecodePara, value);
1672 __EXCEPT_PAGE_FAULT
1674 SetLastError(STATUS_ACCESS_VIOLATION);
1675 ret = FALSE;
1677 __ENDTRY
1678 return ret;
1681 static BOOL CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE *pbEncoded,
1682 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1683 DWORD *pcbDecoded)
1685 BOOL ret = TRUE;
1686 DWORD dataLen;
1687 CERT_NAME_VALUE *value = pvStructInfo;
1689 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
1691 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
1692 DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
1694 switch (pbEncoded[0])
1696 case ASN_NUMERICSTRING:
1697 valueType = CERT_RDN_NUMERIC_STRING;
1698 if (dataLen)
1699 bytesNeeded += (dataLen + 1) * 2;
1700 break;
1701 case ASN_PRINTABLESTRING:
1702 valueType = CERT_RDN_PRINTABLE_STRING;
1703 if (dataLen)
1704 bytesNeeded += (dataLen + 1) * 2;
1705 break;
1706 case ASN_IA5STRING:
1707 valueType = CERT_RDN_IA5_STRING;
1708 if (dataLen)
1709 bytesNeeded += (dataLen + 1) * 2;
1710 break;
1711 case ASN_T61STRING:
1712 valueType = CERT_RDN_T61_STRING;
1713 if (dataLen)
1714 bytesNeeded += (dataLen + 1) * 2;
1715 break;
1716 case ASN_VIDEOTEXSTRING:
1717 valueType = CERT_RDN_VIDEOTEX_STRING;
1718 if (dataLen)
1719 bytesNeeded += (dataLen + 1) * 2;
1720 break;
1721 case ASN_GRAPHICSTRING:
1722 valueType = CERT_RDN_GRAPHIC_STRING;
1723 if (dataLen)
1724 bytesNeeded += (dataLen + 1) * 2;
1725 break;
1726 case ASN_VISIBLESTRING:
1727 valueType = CERT_RDN_VISIBLE_STRING;
1728 if (dataLen)
1729 bytesNeeded += (dataLen + 1) * 2;
1730 break;
1731 case ASN_GENERALSTRING:
1732 valueType = CERT_RDN_GENERAL_STRING;
1733 if (dataLen)
1734 bytesNeeded += (dataLen + 1) * 2;
1735 break;
1736 case ASN_UNIVERSALSTRING:
1737 valueType = CERT_RDN_UNIVERSAL_STRING;
1738 if (dataLen)
1739 bytesNeeded += dataLen / 2 + sizeof(WCHAR);
1740 break;
1741 case ASN_BMPSTRING:
1742 valueType = CERT_RDN_BMP_STRING;
1743 if (dataLen)
1744 bytesNeeded += dataLen + sizeof(WCHAR);
1745 break;
1746 case ASN_UTF8STRING:
1747 valueType = CERT_RDN_UTF8_STRING;
1748 if (dataLen)
1749 bytesNeeded += (MultiByteToWideChar(CP_UTF8, 0,
1750 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) + 1) * 2;
1751 break;
1752 default:
1753 SetLastError(CRYPT_E_ASN1_BADTAG);
1754 return FALSE;
1757 if (pcbDecoded)
1758 *pcbDecoded = 1 + lenBytes + dataLen;
1759 if (!value)
1760 *pcbStructInfo = bytesNeeded;
1761 else if (*pcbStructInfo < bytesNeeded)
1763 *pcbStructInfo = bytesNeeded;
1764 SetLastError(ERROR_MORE_DATA);
1765 ret = FALSE;
1767 else
1769 *pcbStructInfo = bytesNeeded;
1770 value->dwValueType = valueType;
1771 if (dataLen)
1773 DWORD i;
1774 LPWSTR str = (LPWSTR)value->Value.pbData;
1776 assert(value->Value.pbData);
1777 switch (pbEncoded[0])
1779 case ASN_NUMERICSTRING:
1780 case ASN_PRINTABLESTRING:
1781 case ASN_IA5STRING:
1782 case ASN_T61STRING:
1783 case ASN_VIDEOTEXSTRING:
1784 case ASN_GRAPHICSTRING:
1785 case ASN_VISIBLESTRING:
1786 case ASN_GENERALSTRING:
1787 value->Value.cbData = dataLen * 2;
1788 for (i = 0; i < dataLen; i++)
1789 str[i] = pbEncoded[1 + lenBytes + i];
1790 str[i] = 0;
1791 break;
1792 case ASN_UNIVERSALSTRING:
1793 value->Value.cbData = dataLen / 2;
1794 for (i = 0; i < dataLen / 4; i++)
1795 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
1796 | pbEncoded[1 + lenBytes + 2 * i + 3];
1797 str[i] = 0;
1798 break;
1799 case ASN_BMPSTRING:
1800 value->Value.cbData = dataLen;
1801 for (i = 0; i < dataLen / 2; i++)
1802 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
1803 pbEncoded[1 + lenBytes + 2 * i + 1];
1804 str[i] = 0;
1805 break;
1806 case ASN_UTF8STRING:
1807 value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
1808 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
1809 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * sizeof(WCHAR);
1810 *(WCHAR *)(value->Value.pbData + value->Value.cbData) = 0;
1811 value->Value.cbData += sizeof(WCHAR);
1812 break;
1815 else
1817 value->Value.cbData = 0;
1818 value->Value.pbData = NULL;
1822 return ret;
1825 static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
1826 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1827 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1829 BOOL ret = TRUE;
1831 __TRY
1833 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded, cbEncoded,
1834 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
1835 if (ret && pvStructInfo)
1837 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
1838 pcbStructInfo, *pcbStructInfo);
1839 if (ret)
1841 CERT_NAME_VALUE *value;
1843 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1844 pvStructInfo = *(BYTE **)pvStructInfo;
1845 value = pvStructInfo;
1846 value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
1847 ret = CRYPT_AsnDecodeUnicodeNameValueInternal(pbEncoded,
1848 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
1849 pcbStructInfo, NULL);
1850 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
1851 CRYPT_FreeSpace(pDecodePara, value);
1855 __EXCEPT_PAGE_FAULT
1857 SetLastError(STATUS_ACCESS_VIOLATION);
1858 ret = FALSE;
1860 __ENDTRY
1861 return ret;
1864 static BOOL CRYPT_AsnDecodeRdnAttr(const BYTE *pbEncoded, DWORD cbEncoded,
1865 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1867 BOOL ret;
1868 struct AsnDecodeSequenceItem items[] = {
1869 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1870 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1871 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1872 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1873 CRYPT_AsnDecodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1874 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1876 CERT_RDN_ATTR *attr = pvStructInfo;
1878 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1879 pvStructInfo, *pcbStructInfo);
1881 if (attr)
1882 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1883 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
1884 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1885 attr ? attr->pszObjId : NULL);
1886 if (attr)
1888 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1889 debugstr_a(attr->pszObjId));
1890 TRACE("attr->dwValueType is %ld\n", attr->dwValueType);
1892 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1893 return ret;
1896 static BOOL CRYPT_AsnDecodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1897 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1899 BOOL ret = TRUE;
1900 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1901 offsetof(CERT_RDN, cRDNAttr), offsetof(CERT_RDN, rgRDNAttr),
1902 sizeof(CERT_RDN),
1903 CRYPT_AsnDecodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
1904 offsetof(CERT_RDN_ATTR, pszObjId) };
1906 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
1907 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
1908 return ret;
1911 static BOOL WINAPI CRYPT_AsnDecodeName(DWORD dwCertEncodingType,
1912 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
1913 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
1915 BOOL ret = TRUE;
1917 __TRY
1919 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
1920 offsetof(CERT_NAME_INFO, cRDN), offsetof(CERT_NAME_INFO, rgRDN),
1921 sizeof(CERT_NAME_INFO),
1922 CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
1923 offsetof(CERT_RDN, rgRDNAttr) };
1924 DWORD bytesNeeded = 0;
1926 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1927 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded,
1928 NULL);
1929 if (ret)
1931 if (!pvStructInfo)
1932 *pcbStructInfo = bytesNeeded;
1933 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
1934 pvStructInfo, pcbStructInfo, bytesNeeded)))
1936 CERT_NAME_INFO *info;
1938 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
1939 pvStructInfo = *(BYTE **)pvStructInfo;
1940 info = pvStructInfo;
1941 info->rgRDN = (CERT_RDN *)((BYTE *)pvStructInfo +
1942 sizeof(CERT_NAME_INFO));
1943 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
1944 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
1945 &bytesNeeded, NULL);
1946 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
1947 CRYPT_FreeSpace(pDecodePara, info);
1951 __EXCEPT_PAGE_FAULT
1953 SetLastError(STATUS_ACCESS_VIOLATION);
1954 ret = FALSE;
1956 __ENDTRY
1957 return ret;
1960 static BOOL CRYPT_AsnDecodeUnicodeRdnAttr(const BYTE *pbEncoded,
1961 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
1962 DWORD *pcbDecoded)
1964 BOOL ret;
1965 struct AsnDecodeSequenceItem items[] = {
1966 { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
1967 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
1968 offsetof(CERT_RDN_ATTR, pszObjId), 0 },
1969 { 0, offsetof(CERT_RDN_ATTR, dwValueType),
1970 CRYPT_AsnDecodeUnicodeNameValueInternal, sizeof(CERT_NAME_VALUE),
1971 FALSE, TRUE, offsetof(CERT_RDN_ATTR, Value.pbData), 0 },
1973 CERT_RDN_ATTR *attr = pvStructInfo;
1975 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
1976 pvStructInfo, *pcbStructInfo);
1978 if (attr)
1979 TRACE("attr->pszObjId is %p\n", attr->pszObjId);
1980 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
1981 pbEncoded, cbEncoded, dwFlags, NULL, attr, pcbStructInfo, pcbDecoded,
1982 attr ? attr->pszObjId : NULL);
1983 if (attr)
1985 TRACE("attr->pszObjId is %p (%s)\n", attr->pszObjId,
1986 debugstr_a(attr->pszObjId));
1987 TRACE("attr->dwValueType is %ld\n", attr->dwValueType);
1989 TRACE("returning %d (%08lx)\n", ret, GetLastError());
1990 return ret;
1993 static BOOL CRYPT_AsnDecodeUnicodeRdn(const BYTE *pbEncoded, DWORD cbEncoded,
1994 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
1996 BOOL ret = TRUE;
1997 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
1998 offsetof(CERT_RDN, cRDNAttr), offsetof(CERT_RDN, rgRDNAttr),
1999 sizeof(CERT_RDN),
2000 CRYPT_AsnDecodeUnicodeRdnAttr, sizeof(CERT_RDN_ATTR), TRUE,
2001 offsetof(CERT_RDN_ATTR, pszObjId) };
2003 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2004 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2005 return ret;
2008 static BOOL WINAPI CRYPT_AsnDecodeUnicodeName(DWORD dwCertEncodingType,
2009 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2010 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2012 BOOL ret = TRUE;
2014 __TRY
2016 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2017 offsetof(CERT_NAME_INFO, cRDN), offsetof(CERT_NAME_INFO, rgRDN),
2018 sizeof(CERT_NAME_INFO),
2019 CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
2020 offsetof(CERT_RDN, rgRDNAttr) };
2021 DWORD bytesNeeded = 0;
2023 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2024 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded,
2025 NULL);
2026 if (ret)
2028 if (!pvStructInfo)
2029 *pcbStructInfo = bytesNeeded;
2030 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2031 pvStructInfo, pcbStructInfo, bytesNeeded)))
2033 CERT_NAME_INFO *info;
2035 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2036 pvStructInfo = *(BYTE **)pvStructInfo;
2037 info = pvStructInfo;
2038 info->rgRDN = (CERT_RDN *)((BYTE *)pvStructInfo +
2039 sizeof(CERT_NAME_INFO));
2040 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2041 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
2042 &bytesNeeded, NULL);
2043 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
2044 CRYPT_FreeSpace(pDecodePara, info);
2048 __EXCEPT_PAGE_FAULT
2050 SetLastError(STATUS_ACCESS_VIOLATION);
2051 ret = FALSE;
2053 __ENDTRY
2054 return ret;
2057 static BOOL CRYPT_FindEncodedLen(const BYTE *pbEncoded, DWORD cbEncoded,
2058 DWORD *pcbDecoded)
2060 BOOL ret = TRUE, done = FALSE;
2061 DWORD indefiniteNestingLevels = 0, decoded = 0;
2063 TRACE("(%p, %ld)\n", pbEncoded, cbEncoded);
2065 do {
2066 DWORD dataLen;
2068 if (!cbEncoded)
2069 done = TRUE;
2070 else if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded,
2071 &dataLen)))
2073 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2075 if (dataLen == CMSG_INDEFINITE_LENGTH)
2077 indefiniteNestingLevels++;
2078 pbEncoded += 1 + lenBytes;
2079 cbEncoded -= 1 + lenBytes;
2080 decoded += 1 + lenBytes;
2081 TRACE("indefiniteNestingLevels = %ld\n",
2082 indefiniteNestingLevels);
2084 else
2086 if (pbEncoded[0] == 0 && pbEncoded[1] == 0 &&
2087 indefiniteNestingLevels)
2089 indefiniteNestingLevels--;
2090 TRACE("indefiniteNestingLevels = %ld\n",
2091 indefiniteNestingLevels);
2093 pbEncoded += 1 + lenBytes + dataLen;
2094 cbEncoded -= 1 + lenBytes + dataLen;
2095 decoded += 1 + lenBytes + dataLen;
2096 if (!indefiniteNestingLevels)
2097 done = TRUE;
2100 } while (ret && !done);
2101 /* If we haven't found all 0 TLVs, we haven't found the end */
2102 if (ret && indefiniteNestingLevels)
2104 SetLastError(CRYPT_E_ASN1_EOD);
2105 ret = FALSE;
2107 if (ret)
2108 *pcbDecoded = decoded;
2109 TRACE("returning %d (%ld)\n", ret, ret ? *pcbDecoded : 0);
2110 return ret;
2113 static BOOL CRYPT_AsnDecodeCopyBytes(const BYTE *pbEncoded,
2114 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2115 DWORD *pcbDecoded)
2117 BOOL ret = TRUE;
2118 DWORD bytesNeeded = sizeof(CRYPT_OBJID_BLOB), encodedLen = 0;
2120 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2121 pvStructInfo, *pcbStructInfo);
2123 if ((ret = CRYPT_FindEncodedLen(pbEncoded, cbEncoded, &encodedLen)))
2125 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
2126 bytesNeeded += encodedLen;
2127 if (!pvStructInfo)
2128 *pcbStructInfo = bytesNeeded;
2129 else if (*pcbStructInfo < bytesNeeded)
2131 SetLastError(ERROR_MORE_DATA);
2132 *pcbStructInfo = bytesNeeded;
2133 ret = FALSE;
2135 else
2137 PCRYPT_OBJID_BLOB blob = pvStructInfo;
2139 *pcbStructInfo = bytesNeeded;
2140 blob->cbData = encodedLen;
2141 if (encodedLen)
2143 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
2144 blob->pbData = (LPBYTE)pbEncoded;
2145 else
2147 assert(blob->pbData);
2148 memcpy(blob->pbData, pbEncoded, blob->cbData);
2151 else
2152 blob->pbData = NULL;
2154 if (pcbDecoded)
2155 *pcbDecoded = encodedLen;
2157 return ret;
2160 static BOOL CRYPT_AsnDecodeCTLUsage(const BYTE *pbEncoded, DWORD cbEncoded,
2161 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2163 BOOL ret;
2164 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2165 offsetof(CTL_USAGE, cUsageIdentifier),
2166 offsetof(CTL_USAGE, rgpszUsageIdentifier),
2167 sizeof(CTL_USAGE),
2168 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
2170 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2171 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2172 return ret;
2175 static BOOL CRYPT_AsnDecodeCTLEntryAttributes(const BYTE *pbEncoded,
2176 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2177 DWORD *pcbDecoded)
2179 struct AsnArrayDescriptor arrayDesc = { 0,
2180 offsetof(CTL_ENTRY, cAttribute), offsetof(CTL_ENTRY, rgAttribute),
2181 FINALMEMBERSIZE(CTL_ENTRY, cAttribute),
2182 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2183 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2184 BOOL ret;
2186 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2187 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2188 return ret;
2191 static BOOL CRYPT_AsnDecodeCTLEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2192 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2194 struct AsnDecodeSequenceItem items[] = {
2195 { ASN_OCTETSTRING, offsetof(CTL_ENTRY, SubjectIdentifier),
2196 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE,
2197 offsetof(CTL_ENTRY, SubjectIdentifier.pbData), 0 },
2198 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CTL_ENTRY, cAttribute),
2199 CRYPT_AsnDecodeCTLEntryAttributes,
2200 FINALMEMBERSIZE(CTL_ENTRY, cAttribute), FALSE, TRUE,
2201 offsetof(CTL_ENTRY, rgAttribute), 0 },
2203 BOOL ret = TRUE;
2204 CTL_ENTRY *entry = pvStructInfo;
2206 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, entry,
2207 *pcbStructInfo);
2209 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2210 pbEncoded, cbEncoded, dwFlags, NULL, entry, pcbStructInfo,
2211 pcbDecoded, entry ? entry->SubjectIdentifier.pbData : NULL);
2212 return ret;
2215 static BOOL CRYPT_AsnDecodeCTLEntries(const BYTE *pbEncoded, DWORD cbEncoded,
2216 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2218 BOOL ret;
2219 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2220 offsetof(CTL_INFO, cCTLEntry), offsetof(CTL_INFO, rgCTLEntry),
2221 FINALMEMBERSIZE(CTL_INFO, cExtension),
2222 CRYPT_AsnDecodeCTLEntry, sizeof(CTL_ENTRY), TRUE,
2223 offsetof(CTL_ENTRY, SubjectIdentifier.pbData) };
2225 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
2226 pvStructInfo, *pcbStructInfo, pcbDecoded);
2228 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2229 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2230 return ret;
2233 static BOOL CRYPT_AsnDecodeCTLExtensionsInternal(const BYTE *pbEncoded,
2234 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2235 DWORD *pcbDecoded)
2237 BOOL ret = TRUE;
2238 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2239 offsetof(CTL_INFO, cExtension), offsetof(CTL_INFO, rgExtension),
2240 FINALMEMBERSIZE(CTL_INFO, cExtension),
2241 CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
2242 offsetof(CERT_EXTENSION, pszObjId) };
2244 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
2245 pvStructInfo, *pcbStructInfo, pcbDecoded);
2247 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2248 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2249 return ret;
2252 static BOOL CRYPT_AsnDecodeCTLExtensions(const BYTE *pbEncoded,
2253 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2254 DWORD *pcbDecoded)
2256 BOOL ret;
2257 DWORD dataLen;
2259 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2261 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2263 ret = CRYPT_AsnDecodeCTLExtensionsInternal(pbEncoded + 1 + lenBytes,
2264 dataLen, dwFlags, pvStructInfo, pcbStructInfo, NULL);
2265 if (ret && pcbDecoded)
2266 *pcbDecoded = 1 + lenBytes + dataLen;
2268 return ret;
2271 static BOOL WINAPI CRYPT_AsnDecodeCTL(DWORD dwCertEncodingType,
2272 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2273 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2275 BOOL ret = FALSE;
2277 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2278 pDecodePara, pvStructInfo, *pcbStructInfo);
2280 __TRY
2282 struct AsnDecodeSequenceItem items[] = {
2283 { ASN_INTEGER, offsetof(CTL_INFO, dwVersion),
2284 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
2285 { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectUsage),
2286 CRYPT_AsnDecodeCTLUsage, sizeof(CTL_USAGE), FALSE, TRUE,
2287 offsetof(CTL_INFO, SubjectUsage.rgpszUsageIdentifier), 0 },
2288 { ASN_OCTETSTRING, offsetof(CTL_INFO, ListIdentifier),
2289 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB), TRUE,
2290 TRUE, offsetof(CTL_INFO, ListIdentifier.pbData), 0 },
2291 { ASN_INTEGER, offsetof(CTL_INFO, SequenceNumber),
2292 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
2293 TRUE, TRUE, offsetof(CTL_INFO, SequenceNumber.pbData), 0 },
2294 { 0, offsetof(CTL_INFO, ThisUpdate),
2295 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), FALSE, FALSE,
2296 0 },
2297 { 0, offsetof(CTL_INFO, NextUpdate),
2298 CRYPT_AsnDecodeChoiceOfTimeInternal, sizeof(FILETIME), TRUE, FALSE,
2299 0 },
2300 { ASN_SEQUENCEOF, offsetof(CTL_INFO, SubjectAlgorithm),
2301 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2302 FALSE, TRUE, offsetof(CTL_INFO, SubjectAlgorithm.pszObjId), 0 },
2303 { ASN_SEQUENCEOF, offsetof(CTL_INFO, cCTLEntry),
2304 CRYPT_AsnDecodeCTLEntries,
2305 MEMBERSIZE(CTL_INFO, cCTLEntry, cExtension),
2306 TRUE, TRUE, offsetof(CTL_INFO, rgCTLEntry), 0 },
2307 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CTL_INFO, cExtension),
2308 CRYPT_AsnDecodeCTLExtensions, FINALMEMBERSIZE(CTL_INFO, cExtension),
2309 TRUE, TRUE, offsetof(CTL_INFO, rgExtension), 0 },
2312 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2313 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
2314 pcbStructInfo, NULL, NULL);
2316 __EXCEPT_PAGE_FAULT
2318 SetLastError(STATUS_ACCESS_VIOLATION);
2320 __ENDTRY
2321 return ret;
2324 static BOOL CRYPT_AsnDecodeSMIMECapability(const BYTE *pbEncoded,
2325 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2326 DWORD *pcbDecoded)
2328 BOOL ret;
2329 struct AsnDecodeSequenceItem items[] = {
2330 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_SMIME_CAPABILITY, pszObjId),
2331 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2332 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId), 0 },
2333 { 0, offsetof(CRYPT_SMIME_CAPABILITY, Parameters),
2334 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2335 offsetof(CRYPT_SMIME_CAPABILITY, Parameters.pbData), 0 },
2337 PCRYPT_SMIME_CAPABILITY capability = pvStructInfo;
2339 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2340 pvStructInfo, *pcbStructInfo);
2342 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2343 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2344 pcbDecoded, capability ? capability->pszObjId : NULL);
2345 TRACE("returning %d\n", ret);
2346 return ret;
2349 static BOOL WINAPI CRYPT_AsnDecodeSMIMECapabilities(DWORD dwCertEncodingType,
2350 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2351 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2353 BOOL ret = FALSE;
2355 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2356 pDecodePara, pvStructInfo, *pcbStructInfo);
2358 __TRY
2360 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2361 offsetof(CRYPT_SMIME_CAPABILITIES, cCapability),
2362 offsetof(CRYPT_SMIME_CAPABILITIES, rgCapability),
2363 sizeof(CRYPT_SMIME_CAPABILITIES),
2364 CRYPT_AsnDecodeSMIMECapability, sizeof(CRYPT_SMIME_CAPABILITY), TRUE,
2365 offsetof(CRYPT_SMIME_CAPABILITY, pszObjId) };
2366 CRYPT_SMIME_CAPABILITIES *capabilities = pvStructInfo;
2368 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
2369 capabilities->rgCapability = (CRYPT_SMIME_CAPABILITY *)(capabilities + 1);
2370 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2371 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2373 __EXCEPT_PAGE_FAULT
2375 SetLastError(STATUS_ACCESS_VIOLATION);
2377 __ENDTRY
2378 TRACE("returning %d\n", ret);
2379 return ret;
2382 static BOOL CRYPT_AsnDecodeIA5String(const BYTE *pbEncoded,
2383 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2384 DWORD *pcbDecoded)
2386 BOOL ret = TRUE;
2387 DWORD dataLen;
2388 LPSTR *pStr = pvStructInfo;
2390 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2392 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2393 DWORD bytesNeeded = sizeof(LPSTR) + sizeof(char);
2395 if (pbEncoded[0] != ASN_IA5STRING)
2397 SetLastError(CRYPT_E_ASN1_CORRUPT);
2398 ret = FALSE;
2400 else
2402 bytesNeeded += dataLen;
2403 if (pcbDecoded)
2404 *pcbDecoded = 1 + lenBytes + dataLen;
2405 if (!pvStructInfo)
2406 *pcbStructInfo = bytesNeeded;
2407 else if (*pcbStructInfo < bytesNeeded)
2409 *pcbStructInfo = bytesNeeded;
2410 SetLastError(ERROR_MORE_DATA);
2411 ret = FALSE;
2413 else
2415 *pcbStructInfo = bytesNeeded;
2416 if (dataLen)
2418 LPSTR str = *pStr;
2420 assert(str);
2421 memcpy(str, pbEncoded + 1 + lenBytes, dataLen);
2422 str[dataLen] = 0;
2424 else
2425 *pStr = NULL;
2429 return ret;
2432 static BOOL CRYPT_AsnDecodeNoticeNumbers(const BYTE *pbEncoded,
2433 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2434 DWORD *pcbDecoded)
2436 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
2437 offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers),
2438 offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, rgNoticeNumbers),
2439 FINALMEMBERSIZE(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers),
2440 CRYPT_AsnDecodeIntInternal, sizeof(int), FALSE, 0 };
2441 BOOL ret;
2443 TRACE("(%p, %ld, %08lx, %p, %ld)\n", pbEncoded, cbEncoded, dwFlags,
2444 pvStructInfo, pvStructInfo ? *pcbDecoded : 0);
2446 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2447 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2448 TRACE("returning %d\n", ret);
2449 return ret;
2452 static BOOL CRYPT_AsnDecodeNoticeReference(const BYTE *pbEncoded,
2453 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2454 DWORD *pcbDecoded)
2456 BOOL ret;
2457 struct AsnDecodeSequenceItem items[] = {
2458 { ASN_IA5STRING, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2459 pszOrganization), CRYPT_AsnDecodeIA5String, sizeof(LPSTR), FALSE, TRUE,
2460 offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, pszOrganization), 0 },
2461 { ASN_SEQUENCEOF, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2462 cNoticeNumbers), CRYPT_AsnDecodeNoticeNumbers,
2463 FINALMEMBERSIZE(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, cNoticeNumbers),
2464 FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE,
2465 rgNoticeNumbers), 0 },
2467 DWORD bytesNeeded = 0;
2469 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2470 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
2472 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2473 pbEncoded, cbEncoded, dwFlags, NULL, NULL, &bytesNeeded, pcbDecoded,
2474 NULL);
2475 if (ret)
2477 /* The caller is expecting a pointer to a
2478 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE to be decoded, whereas
2479 * CRYPT_AsnDecodeSequence is decoding a
2480 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE. Increment the bytes
2481 * needed, and decode again if the requisite space is available.
2483 bytesNeeded += sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE);
2484 if (!pvStructInfo)
2485 *pcbStructInfo = bytesNeeded;
2486 else if (*pcbStructInfo < bytesNeeded)
2488 *pcbStructInfo = bytesNeeded;
2489 SetLastError(ERROR_MORE_DATA);
2490 ret = FALSE;
2492 else
2494 PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE noticeRef;
2496 *pcbStructInfo = bytesNeeded;
2497 /* The pointer (pvStructInfo) passed in points to the first dynamic
2498 * pointer, so use it as the pointer to the
2499 * CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, and create the
2500 * appropriate offset for the first dynamic pointer within the
2501 * notice reference by pointing to the first memory location past
2502 * the CERT_POLICY_QUALIFIER_NOTICE_REFERENCE.
2504 noticeRef =
2505 *(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE *)pvStructInfo;
2506 noticeRef->pszOrganization = (LPSTR)((LPBYTE)noticeRef +
2507 sizeof(CERT_POLICY_QUALIFIER_NOTICE_REFERENCE));
2508 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items), pbEncoded, cbEncoded, dwFlags,
2509 NULL, noticeRef, &bytesNeeded, pcbDecoded, noticeRef->pszOrganization);
2512 TRACE("returning %d\n", ret);
2513 return ret;
2516 static BOOL CRYPT_AsnDecodeUnicodeString(const BYTE *pbEncoded,
2517 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2518 DWORD *pcbDecoded)
2520 BOOL ret = TRUE;
2521 DWORD dataLen;
2523 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
2525 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
2526 DWORD bytesNeeded = sizeof(LPWSTR);
2528 switch (pbEncoded[0])
2530 case ASN_NUMERICSTRING:
2531 if (dataLen)
2532 bytesNeeded += (dataLen + 1) * 2;
2533 break;
2534 case ASN_PRINTABLESTRING:
2535 if (dataLen)
2536 bytesNeeded += (dataLen + 1) * 2;
2537 break;
2538 case ASN_IA5STRING:
2539 if (dataLen)
2540 bytesNeeded += (dataLen + 1) * 2;
2541 break;
2542 case ASN_T61STRING:
2543 if (dataLen)
2544 bytesNeeded += (dataLen + 1) * 2;
2545 break;
2546 case ASN_VIDEOTEXSTRING:
2547 if (dataLen)
2548 bytesNeeded += (dataLen + 1) * 2;
2549 break;
2550 case ASN_GRAPHICSTRING:
2551 if (dataLen)
2552 bytesNeeded += (dataLen + 1) * 2;
2553 break;
2554 case ASN_VISIBLESTRING:
2555 if (dataLen)
2556 bytesNeeded += (dataLen + 1) * 2;
2557 break;
2558 case ASN_GENERALSTRING:
2559 if (dataLen)
2560 bytesNeeded += (dataLen + 1) * 2;
2561 break;
2562 case ASN_UNIVERSALSTRING:
2563 if (dataLen)
2564 bytesNeeded += dataLen / 2 + sizeof(WCHAR);
2565 break;
2566 case ASN_BMPSTRING:
2567 if (dataLen)
2568 bytesNeeded += dataLen + sizeof(WCHAR);
2569 break;
2570 case ASN_UTF8STRING:
2571 if (dataLen)
2572 bytesNeeded += (MultiByteToWideChar(CP_UTF8, 0,
2573 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) + 1) * 2;
2574 break;
2575 default:
2576 SetLastError(CRYPT_E_ASN1_BADTAG);
2577 return FALSE;
2580 if (pcbDecoded)
2581 *pcbDecoded = 1 + lenBytes + dataLen;
2582 if (!pvStructInfo)
2583 *pcbStructInfo = bytesNeeded;
2584 else if (*pcbStructInfo < bytesNeeded)
2586 *pcbStructInfo = bytesNeeded;
2587 SetLastError(ERROR_MORE_DATA);
2588 ret = FALSE;
2590 else
2592 LPWSTR *pStr = pvStructInfo;
2594 *pcbStructInfo = bytesNeeded;
2595 if (dataLen)
2597 DWORD i;
2598 LPWSTR str = *pStr;
2600 assert(str);
2601 switch (pbEncoded[0])
2603 case ASN_NUMERICSTRING:
2604 case ASN_PRINTABLESTRING:
2605 case ASN_IA5STRING:
2606 case ASN_T61STRING:
2607 case ASN_VIDEOTEXSTRING:
2608 case ASN_GRAPHICSTRING:
2609 case ASN_VISIBLESTRING:
2610 case ASN_GENERALSTRING:
2611 for (i = 0; i < dataLen; i++)
2612 str[i] = pbEncoded[1 + lenBytes + i];
2613 str[i] = 0;
2614 break;
2615 case ASN_UNIVERSALSTRING:
2616 for (i = 0; i < dataLen / 4; i++)
2617 str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
2618 | pbEncoded[1 + lenBytes + 2 * i + 3];
2619 str[i] = 0;
2620 break;
2621 case ASN_BMPSTRING:
2622 for (i = 0; i < dataLen / 2; i++)
2623 str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
2624 pbEncoded[1 + lenBytes + 2 * i + 1];
2625 str[i] = 0;
2626 break;
2627 case ASN_UTF8STRING:
2629 int len = MultiByteToWideChar(CP_UTF8, 0,
2630 (LPCSTR)pbEncoded + 1 + lenBytes, dataLen,
2631 str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
2632 str[len] = 0;
2633 break;
2637 else
2638 *pStr = NULL;
2641 return ret;
2644 static BOOL CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(
2645 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
2646 DWORD *pcbStructInfo, DWORD *pcbDecoded)
2648 BOOL ret;
2649 struct AsnDecodeSequenceItem items[] = {
2650 { ASN_SEQUENCE, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE,
2651 pNoticeReference), CRYPT_AsnDecodeNoticeReference,
2652 sizeof(PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE), TRUE, TRUE,
2653 offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pNoticeReference), 0 },
2654 { 0, offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pszDisplayText),
2655 CRYPT_AsnDecodeUnicodeString, sizeof(LPWSTR), TRUE, TRUE,
2656 offsetof(CERT_POLICY_QUALIFIER_USER_NOTICE, pszDisplayText), 0 },
2658 PCERT_POLICY_QUALIFIER_USER_NOTICE notice = pvStructInfo;
2660 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2661 pvStructInfo, *pcbStructInfo);
2663 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2664 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2665 pcbDecoded, notice ? notice->pNoticeReference : NULL);
2666 TRACE("returning %d\n", ret);
2667 return ret;
2670 static BOOL WINAPI CRYPT_AsnDecodePolicyQualifierUserNotice(
2671 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
2672 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
2673 void *pvStructInfo, DWORD *pcbStructInfo)
2675 BOOL ret = FALSE;
2677 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2678 pDecodePara, pvStructInfo, *pcbStructInfo);
2680 __TRY
2682 DWORD bytesNeeded = 0;
2684 ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(pbEncoded,
2685 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
2686 NULL);
2687 if (ret)
2689 if (!pvStructInfo)
2690 *pcbStructInfo = bytesNeeded;
2691 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2692 pvStructInfo, pcbStructInfo, bytesNeeded)))
2694 PCERT_POLICY_QUALIFIER_USER_NOTICE notice;
2696 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2697 pvStructInfo = *(BYTE **)pvStructInfo;
2698 notice = pvStructInfo;
2699 notice->pNoticeReference =
2700 (PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE)
2701 ((BYTE *)pvStructInfo +
2702 sizeof(CERT_POLICY_QUALIFIER_USER_NOTICE));
2703 ret = CRYPT_AsnDecodePolicyQualifierUserNoticeInternal(
2704 pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
2705 pvStructInfo, &bytesNeeded, NULL);
2706 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
2707 CRYPT_FreeSpace(pDecodePara, notice);
2711 __EXCEPT_PAGE_FAULT
2713 SetLastError(STATUS_ACCESS_VIOLATION);
2715 __ENDTRY
2716 TRACE("returning %d\n", ret);
2717 return ret;
2720 static BOOL CRYPT_AsnDecodePKCSAttributeValue(const BYTE *pbEncoded,
2721 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2722 DWORD *pcbDecoded)
2724 BOOL ret;
2725 struct AsnArrayDescriptor arrayDesc = { 0,
2726 offsetof(CRYPT_ATTRIBUTE, cValue), offsetof(CRYPT_ATTRIBUTE, rgValue),
2727 FINALMEMBERSIZE(CRYPT_ATTRIBUTE, cValue),
2728 CRYPT_AsnDecodeCopyBytes,
2729 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
2731 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
2732 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
2734 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2735 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2736 return ret;
2739 static BOOL CRYPT_AsnDecodePKCSAttributeInternal(const BYTE *pbEncoded,
2740 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2741 DWORD *pcbDecoded)
2743 BOOL ret;
2744 struct AsnDecodeSequenceItem items[] = {
2745 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ATTRIBUTE, pszObjId),
2746 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2747 offsetof(CRYPT_ATTRIBUTE, pszObjId), 0 },
2748 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ATTRIBUTE, cValue),
2749 CRYPT_AsnDecodePKCSAttributeValue,
2750 FINALMEMBERSIZE(CRYPT_ATTRIBUTE, cValue), FALSE,
2751 TRUE, offsetof(CRYPT_ATTRIBUTE, rgValue), 0 },
2753 PCRYPT_ATTRIBUTE attr = pvStructInfo;
2755 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2756 pvStructInfo, *pcbStructInfo);
2758 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2759 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2760 pcbDecoded, attr ? attr->pszObjId : NULL);
2761 TRACE("returning %d\n", ret);
2762 return ret;
2765 static BOOL WINAPI CRYPT_AsnDecodePKCSAttribute(DWORD dwCertEncodingType,
2766 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2767 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2769 BOOL ret = FALSE;
2771 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2772 pDecodePara, pvStructInfo, *pcbStructInfo);
2774 __TRY
2776 DWORD bytesNeeded = 0;
2778 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2779 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
2780 if (ret)
2782 if (!pvStructInfo)
2783 *pcbStructInfo = bytesNeeded;
2784 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2785 pvStructInfo, pcbStructInfo, bytesNeeded)))
2787 PCRYPT_ATTRIBUTE attr;
2789 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2790 pvStructInfo = *(BYTE **)pvStructInfo;
2791 attr = pvStructInfo;
2792 attr->pszObjId = (LPSTR)((BYTE *)pvStructInfo +
2793 sizeof(CRYPT_ATTRIBUTE));
2794 ret = CRYPT_AsnDecodePKCSAttributeInternal(pbEncoded, cbEncoded,
2795 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo, &bytesNeeded,
2796 NULL);
2797 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
2798 CRYPT_FreeSpace(pDecodePara, attr);
2802 __EXCEPT_PAGE_FAULT
2804 SetLastError(STATUS_ACCESS_VIOLATION);
2806 __ENDTRY
2807 TRACE("returning %d\n", ret);
2808 return ret;
2811 static BOOL CRYPT_AsnDecodePKCSAttributesInternal(const BYTE *pbEncoded,
2812 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2813 DWORD *pcbDecoded)
2815 struct AsnArrayDescriptor arrayDesc = { 0,
2816 offsetof(CRYPT_ATTRIBUTES, cAttr), offsetof(CRYPT_ATTRIBUTES, rgAttr),
2817 sizeof(CRYPT_ATTRIBUTES),
2818 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE), TRUE,
2819 offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2820 BOOL ret;
2822 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
2823 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
2824 return ret;
2827 static BOOL WINAPI CRYPT_AsnDecodePKCSAttributes(DWORD dwCertEncodingType,
2828 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2829 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2831 BOOL ret = FALSE;
2833 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
2834 pDecodePara, pvStructInfo, *pcbStructInfo);
2836 __TRY
2838 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
2839 offsetof(CRYPT_ATTRIBUTES, cAttr), offsetof(CRYPT_ATTRIBUTES, rgAttr),
2840 sizeof(CRYPT_ATTRIBUTES),
2841 CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE),
2842 TRUE, offsetof(CRYPT_ATTRIBUTE, pszObjId) };
2843 CRYPT_ATTRIBUTES *attrs = pvStructInfo;
2845 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
2846 attrs->rgAttr = (CRYPT_ATTRIBUTE *)(attrs + 1);
2847 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
2848 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
2850 __EXCEPT_PAGE_FAULT
2852 SetLastError(STATUS_ACCESS_VIOLATION);
2854 __ENDTRY
2855 TRACE("returning %d\n", ret);
2856 return ret;
2859 static BOOL CRYPT_AsnDecodeAlgorithmId(const BYTE *pbEncoded, DWORD cbEncoded,
2860 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2862 CRYPT_ALGORITHM_IDENTIFIER *algo = pvStructInfo;
2863 BOOL ret = TRUE;
2864 struct AsnDecodeSequenceItem items[] = {
2865 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
2866 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
2867 offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
2868 { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
2869 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
2870 offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
2873 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
2874 pvStructInfo, *pcbStructInfo, pcbDecoded);
2876 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2877 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2878 pcbDecoded, algo ? algo->pszObjId : NULL);
2879 if (ret && pvStructInfo)
2881 TRACE("pszObjId is %p (%s)\n", algo->pszObjId,
2882 debugstr_a(algo->pszObjId));
2884 return ret;
2887 static BOOL CRYPT_AsnDecodePubKeyInfoInternal(const BYTE *pbEncoded,
2888 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
2889 DWORD *pcbDecoded)
2891 BOOL ret = TRUE;
2892 struct AsnDecodeSequenceItem items[] = {
2893 { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
2894 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
2895 FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
2896 Algorithm.pszObjId) },
2897 { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
2898 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
2899 offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
2901 PCERT_PUBLIC_KEY_INFO info = pvStructInfo;
2903 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
2904 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
2905 pcbDecoded, info ? info->Algorithm.Parameters.pbData : NULL);
2906 return ret;
2909 static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
2910 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
2911 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
2913 BOOL ret = TRUE;
2915 __TRY
2917 DWORD bytesNeeded = 0;
2919 if ((ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2920 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
2922 if (!pvStructInfo)
2923 *pcbStructInfo = bytesNeeded;
2924 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
2925 pvStructInfo, pcbStructInfo, bytesNeeded)))
2927 PCERT_PUBLIC_KEY_INFO info;
2929 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
2930 pvStructInfo = *(BYTE **)pvStructInfo;
2931 info = pvStructInfo;
2932 info->Algorithm.Parameters.pbData = (BYTE *)pvStructInfo +
2933 sizeof(CERT_PUBLIC_KEY_INFO);
2934 ret = CRYPT_AsnDecodePubKeyInfoInternal(pbEncoded, cbEncoded,
2935 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
2936 &bytesNeeded, NULL);
2937 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
2938 CRYPT_FreeSpace(pDecodePara, info);
2942 __EXCEPT_PAGE_FAULT
2944 SetLastError(STATUS_ACCESS_VIOLATION);
2945 ret = FALSE;
2947 __ENDTRY
2948 return ret;
2951 static BOOL CRYPT_AsnDecodeBool(const BYTE *pbEncoded, DWORD cbEncoded,
2952 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2954 BOOL ret;
2956 if (cbEncoded < 3)
2958 SetLastError(CRYPT_E_ASN1_CORRUPT);
2959 return FALSE;
2961 if (GET_LEN_BYTES(pbEncoded[1]) > 1)
2963 SetLastError(CRYPT_E_ASN1_CORRUPT);
2964 return FALSE;
2966 if (pbEncoded[1] > 1)
2968 SetLastError(CRYPT_E_ASN1_CORRUPT);
2969 return FALSE;
2971 if (pcbDecoded)
2972 *pcbDecoded = 3;
2973 if (!pvStructInfo)
2975 *pcbStructInfo = sizeof(BOOL);
2976 ret = TRUE;
2978 else if (*pcbStructInfo < sizeof(BOOL))
2980 *pcbStructInfo = sizeof(BOOL);
2981 SetLastError(ERROR_MORE_DATA);
2982 ret = FALSE;
2984 else
2986 *pcbStructInfo = sizeof(BOOL);
2987 *(BOOL *)pvStructInfo = pbEncoded[2] != 0;
2988 ret = TRUE;
2990 TRACE("returning %d (%08lx)\n", ret, GetLastError());
2991 return ret;
2994 static BOOL CRYPT_AsnDecodeAltNameEntry(const BYTE *pbEncoded, DWORD cbEncoded,
2995 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
2997 PCERT_ALT_NAME_ENTRY entry = pvStructInfo;
2998 DWORD dataLen, lenBytes, bytesNeeded = sizeof(CERT_ALT_NAME_ENTRY);
2999 BOOL ret;
3001 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3002 pvStructInfo, *pcbStructInfo);
3004 if (cbEncoded < 2)
3006 SetLastError(CRYPT_E_ASN1_CORRUPT);
3007 return FALSE;
3009 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3010 if (1 + lenBytes > cbEncoded)
3012 SetLastError(CRYPT_E_ASN1_CORRUPT);
3013 return FALSE;
3015 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
3017 switch (pbEncoded[0] & ASN_TYPE_MASK)
3019 case 1: /* rfc822Name */
3020 case 2: /* dNSName */
3021 case 6: /* uniformResourceIdentifier */
3022 if (memchr(pbEncoded + 1 + lenBytes, 0, dataLen))
3024 SetLastError(CRYPT_E_ASN1_RULE);
3025 ret = FALSE;
3027 else
3028 bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
3029 break;
3030 case 4: /* directoryName */
3031 case 7: /* iPAddress */
3032 bytesNeeded += dataLen;
3033 break;
3034 case 8: /* registeredID */
3035 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0, NULL,
3036 &dataLen, NULL);
3037 if (ret)
3039 /* FIXME: ugly, shouldn't need to know internals of OID decode
3040 * function to use it.
3042 bytesNeeded += dataLen - sizeof(LPSTR);
3044 break;
3045 case 0: /* otherName */
3046 FIXME("%d: stub\n", pbEncoded[0] & ASN_TYPE_MASK);
3047 SetLastError(CRYPT_E_ASN1_BADTAG);
3048 ret = FALSE;
3049 break;
3050 case 3: /* x400Address, unimplemented */
3051 case 5: /* ediPartyName, unimplemented */
3052 TRACE("type %d unimplemented\n", pbEncoded[0] & ASN_TYPE_MASK);
3053 SetLastError(CRYPT_E_ASN1_BADTAG);
3054 ret = FALSE;
3055 break;
3056 default:
3057 TRACE("type %d bad\n", pbEncoded[0] & ASN_TYPE_MASK);
3058 SetLastError(CRYPT_E_ASN1_CORRUPT);
3059 ret = FALSE;
3061 if (ret)
3063 if (pcbDecoded)
3064 *pcbDecoded = 1 + lenBytes + dataLen;
3065 if (!entry)
3066 *pcbStructInfo = bytesNeeded;
3067 else if (*pcbStructInfo < bytesNeeded)
3069 *pcbStructInfo = bytesNeeded;
3070 SetLastError(ERROR_MORE_DATA);
3071 ret = FALSE;
3073 else
3075 *pcbStructInfo = bytesNeeded;
3076 /* MS used values one greater than the asn1 ones.. sigh */
3077 entry->dwAltNameChoice = (pbEncoded[0] & ASN_TYPE_MASK) + 1;
3078 switch (pbEncoded[0] & ASN_TYPE_MASK)
3080 case 1: /* rfc822Name */
3081 case 2: /* dNSName */
3082 case 6: /* uniformResourceIdentifier */
3084 DWORD i;
3086 for (i = 0; i < dataLen; i++)
3087 entry->u.pwszURL[i] =
3088 (WCHAR)pbEncoded[1 + lenBytes + i];
3089 entry->u.pwszURL[i] = 0;
3090 TRACE("URL is %p (%s)\n", entry->u.pwszURL,
3091 debugstr_w(entry->u.pwszURL));
3092 break;
3094 case 4: /* directoryName */
3095 /* The data are memory-equivalent with the IPAddress case,
3096 * fall-through
3098 case 7: /* iPAddress */
3099 /* The next data pointer is in the pwszURL spot, that is,
3100 * the first 4 bytes. Need to move it to the next spot.
3102 entry->u.IPAddress.pbData = (LPBYTE)entry->u.pwszURL;
3103 entry->u.IPAddress.cbData = dataLen;
3104 memcpy(entry->u.IPAddress.pbData, pbEncoded + 1 + lenBytes,
3105 dataLen);
3106 break;
3107 case 8: /* registeredID */
3108 ret = CRYPT_AsnDecodeOidIgnoreTag(pbEncoded, cbEncoded, 0,
3109 &entry->u.pszRegisteredID, &dataLen, NULL);
3110 break;
3115 return ret;
3118 static BOOL CRYPT_AsnDecodeAltNameInternal(const BYTE *pbEncoded,
3119 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3120 DWORD *pcbDecoded)
3122 BOOL ret;
3123 struct AsnArrayDescriptor arrayDesc = { 0,
3124 offsetof(CERT_ALT_NAME_INFO, cAltEntry),
3125 offsetof(CERT_ALT_NAME_INFO, rgAltEntry),
3126 sizeof(CERT_ALT_NAME_INFO),
3127 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
3128 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
3130 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
3131 pvStructInfo, *pcbStructInfo, pcbDecoded);
3133 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
3134 NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
3135 return ret;
3138 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
3139 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3140 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3142 BOOL ret;
3144 __TRY
3146 struct AsnDecodeSequenceItem items[] = {
3147 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId),
3148 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB),
3149 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID_INFO, KeyId.pbData), 0 },
3150 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
3151 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer),
3152 CRYPT_AsnDecodeOctets, sizeof(CERT_NAME_BLOB), TRUE, TRUE,
3153 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertIssuer.pbData), 0 },
3154 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID_INFO,
3155 CertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
3156 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
3157 offsetof(CERT_AUTHORITY_KEY_ID_INFO, CertSerialNumber.pbData), 0 },
3160 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3161 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3162 pcbStructInfo, NULL, NULL);
3164 __EXCEPT_PAGE_FAULT
3166 SetLastError(STATUS_ACCESS_VIOLATION);
3167 ret = FALSE;
3169 __ENDTRY
3170 return ret;
3173 static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(DWORD dwCertEncodingType,
3174 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3175 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3177 BOOL ret;
3179 __TRY
3181 struct AsnDecodeSequenceItem items[] = {
3182 { ASN_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
3183 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB),
3184 TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
3185 { ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
3186 offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
3187 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
3188 TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3189 AuthorityCertIssuer.rgAltEntry), 0 },
3190 { ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3191 AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
3192 sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
3193 offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
3194 AuthorityCertSerialNumber.pbData), 0 },
3197 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3198 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3199 pcbStructInfo, NULL, NULL);
3201 __EXCEPT_PAGE_FAULT
3203 SetLastError(STATUS_ACCESS_VIOLATION);
3204 ret = FALSE;
3206 __ENDTRY
3207 return ret;
3210 static BOOL CRYPT_AsnDecodeAccessDescription(const BYTE *pbEncoded,
3211 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3212 DWORD *pcbDecoded)
3214 struct AsnDecodeSequenceItem items[] = {
3215 { 0, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod),
3216 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
3217 offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod), 0 },
3218 { 0, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation),
3219 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), FALSE,
3220 TRUE, offsetof(CERT_ACCESS_DESCRIPTION, AccessLocation.u.pwszURL), 0 },
3222 CERT_ACCESS_DESCRIPTION *descr = pvStructInfo;
3224 return CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3225 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3226 pcbDecoded, descr ? descr->pszAccessMethod : NULL);
3229 static BOOL WINAPI CRYPT_AsnDecodeAuthorityInfoAccess(DWORD dwCertEncodingType,
3230 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3231 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3233 BOOL ret;
3235 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3236 pDecodePara, pvStructInfo, *pcbStructInfo);
3238 __TRY
3240 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3241 offsetof(CERT_AUTHORITY_INFO_ACCESS, cAccDescr),
3242 offsetof(CERT_AUTHORITY_INFO_ACCESS, rgAccDescr),
3243 sizeof(CERT_AUTHORITY_INFO_ACCESS),
3244 CRYPT_AsnDecodeAccessDescription, sizeof(CERT_ACCESS_DESCRIPTION),
3245 TRUE, offsetof(CERT_ACCESS_DESCRIPTION, pszAccessMethod) };
3246 CERT_AUTHORITY_INFO_ACCESS *info = pvStructInfo;
3248 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
3249 info->rgAccDescr = (CERT_ACCESS_DESCRIPTION *)(info + 1);
3250 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3251 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3253 __EXCEPT_PAGE_FAULT
3255 SetLastError(STATUS_ACCESS_VIOLATION);
3256 ret = FALSE;
3258 __ENDTRY
3259 return ret;
3262 static BOOL CRYPT_AsnDecodePKCSContent(const BYTE *pbEncoded, DWORD cbEncoded,
3263 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3265 BOOL ret;
3266 DWORD dataLen;
3268 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
3269 pvStructInfo, *pcbStructInfo, pcbDecoded);
3271 /* The caller has already checked the tag, no need to check it again.
3272 * Check the outer length is valid:
3274 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &dataLen)))
3276 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
3277 DWORD innerLen;
3279 pbEncoded += 1 + lenBytes;
3280 cbEncoded -= 1 + lenBytes;
3281 if (dataLen == CMSG_INDEFINITE_LENGTH)
3282 cbEncoded -= 2; /* space for 0 TLV */
3283 /* Check the inner length is valid: */
3284 if ((ret = CRYPT_GetLengthIndefinite(pbEncoded, cbEncoded, &innerLen)))
3286 DWORD decodedLen;
3288 ret = CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags,
3289 pvStructInfo, pcbStructInfo, &decodedLen);
3290 if (dataLen == CMSG_INDEFINITE_LENGTH)
3292 if (*(pbEncoded + decodedLen) != 0 ||
3293 *(pbEncoded + decodedLen + 1) != 0)
3295 TRACE("expected 0 TLV, got {%02x,%02x}\n",
3296 *(pbEncoded + decodedLen),
3297 *(pbEncoded + decodedLen + 1));
3298 SetLastError(CRYPT_E_ASN1_CORRUPT);
3299 ret = FALSE;
3301 else
3302 decodedLen += 2;
3304 if (ret && pcbDecoded)
3306 *pcbDecoded = 1 + lenBytes + decodedLen;
3307 TRACE("decoded %ld bytes\n", *pcbDecoded);
3311 return ret;
3314 static BOOL CRYPT_AsnDecodePKCSContentInfoInternal(const BYTE *pbEncoded,
3315 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3316 DWORD *pcbDecoded)
3318 CRYPT_CONTENT_INFO *info = pvStructInfo;
3319 struct AsnDecodeSequenceItem items[] = {
3320 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_CONTENT_INFO, pszObjId),
3321 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
3322 offsetof(CRYPT_CONTENT_INFO, pszObjId), 0 },
3323 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
3324 offsetof(CRYPT_CONTENT_INFO, Content), CRYPT_AsnDecodePKCSContent,
3325 sizeof(CRYPT_DER_BLOB), TRUE, TRUE,
3326 offsetof(CRYPT_CONTENT_INFO, Content.pbData), 0 },
3328 BOOL ret;
3330 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
3331 pvStructInfo, *pcbStructInfo, pcbDecoded);
3333 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3334 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3335 pcbDecoded, info ? info->pszObjId : NULL);
3336 return ret;
3339 static BOOL WINAPI CRYPT_AsnDecodePKCSContentInfo(DWORD dwCertEncodingType,
3340 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3341 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3343 BOOL ret = FALSE;
3345 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3346 pDecodePara, pvStructInfo, *pcbStructInfo);
3348 __TRY
3350 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded, cbEncoded,
3351 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
3352 if (ret && pvStructInfo)
3354 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
3355 pcbStructInfo, *pcbStructInfo);
3356 if (ret)
3358 CRYPT_CONTENT_INFO *info;
3360 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3361 pvStructInfo = *(BYTE **)pvStructInfo;
3362 info = pvStructInfo;
3363 info->pszObjId = (LPSTR)((BYTE *)info +
3364 sizeof(CRYPT_CONTENT_INFO));
3365 ret = CRYPT_AsnDecodePKCSContentInfoInternal(pbEncoded,
3366 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3367 pcbStructInfo, NULL);
3368 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
3369 CRYPT_FreeSpace(pDecodePara, info);
3373 __EXCEPT_PAGE_FAULT
3375 SetLastError(STATUS_ACCESS_VIOLATION);
3377 __ENDTRY
3378 return ret;
3381 BOOL CRYPT_AsnDecodePKCSDigestedData(const BYTE *pbEncoded, DWORD cbEncoded,
3382 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3383 CRYPT_DIGESTED_DATA *digestedData, DWORD *pcbDigestedData)
3385 BOOL ret;
3386 struct AsnDecodeSequenceItem items[] = {
3387 { ASN_INTEGER, offsetof(CRYPT_DIGESTED_DATA, version),
3388 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3389 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm),
3390 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
3391 FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA, DigestAlgorithm.pszObjId),
3392 0 },
3393 { ASN_SEQUENCEOF, offsetof(CRYPT_DIGESTED_DATA, ContentInfo),
3394 CRYPT_AsnDecodePKCSContentInfoInternal,
3395 sizeof(CRYPT_CONTENT_INFO), FALSE, TRUE, offsetof(CRYPT_DIGESTED_DATA,
3396 ContentInfo.pszObjId), 0 },
3397 { ASN_OCTETSTRING, offsetof(CRYPT_DIGESTED_DATA, hash),
3398 CRYPT_AsnDecodeOctets, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
3399 offsetof(CRYPT_DIGESTED_DATA, hash.pbData), 0 },
3402 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3403 pbEncoded, cbEncoded, dwFlags, pDecodePara, digestedData, pcbDigestedData,
3404 NULL, NULL);
3405 return ret;
3408 static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType,
3409 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3410 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3412 BOOL ret = TRUE;
3414 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3415 pDecodePara, pvStructInfo, *pcbStructInfo);
3417 __TRY
3419 DWORD bytesNeeded = 0;
3421 if ((ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
3422 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
3424 if (!pvStructInfo)
3425 *pcbStructInfo = bytesNeeded;
3426 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3427 pvStructInfo, pcbStructInfo, bytesNeeded)))
3429 CERT_ALT_NAME_INFO *name;
3431 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3432 pvStructInfo = *(BYTE **)pvStructInfo;
3433 name = pvStructInfo;
3434 name->rgAltEntry = (PCERT_ALT_NAME_ENTRY)
3435 ((BYTE *)pvStructInfo + sizeof(CERT_ALT_NAME_INFO));
3436 ret = CRYPT_AsnDecodeAltNameInternal(pbEncoded, cbEncoded,
3437 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
3438 &bytesNeeded, NULL);
3439 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
3440 CRYPT_FreeSpace(pDecodePara, name);
3444 __EXCEPT_PAGE_FAULT
3446 SetLastError(STATUS_ACCESS_VIOLATION);
3447 ret = FALSE;
3449 __ENDTRY
3450 return ret;
3453 struct PATH_LEN_CONSTRAINT
3455 BOOL fPathLenConstraint;
3456 DWORD dwPathLenConstraint;
3459 static BOOL CRYPT_AsnDecodePathLenConstraint(const BYTE *pbEncoded,
3460 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3461 DWORD *pcbDecoded)
3463 BOOL ret = TRUE;
3464 DWORD bytesNeeded = sizeof(struct PATH_LEN_CONSTRAINT), size;
3466 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
3467 pvStructInfo, *pcbStructInfo, pcbDecoded);
3469 if (!pvStructInfo)
3471 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, NULL,
3472 &size, pcbDecoded);
3473 *pcbStructInfo = bytesNeeded;
3475 else if (*pcbStructInfo < bytesNeeded)
3477 SetLastError(ERROR_MORE_DATA);
3478 *pcbStructInfo = bytesNeeded;
3479 ret = FALSE;
3481 else
3483 struct PATH_LEN_CONSTRAINT *constraint = pvStructInfo;
3485 *pcbStructInfo = bytesNeeded;
3486 size = sizeof(constraint->dwPathLenConstraint);
3487 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
3488 &constraint->dwPathLenConstraint, &size, pcbDecoded);
3489 if (ret)
3490 constraint->fPathLenConstraint = TRUE;
3491 TRACE("got an int, dwPathLenConstraint is %ld\n",
3492 constraint->dwPathLenConstraint);
3494 TRACE("returning %d (%08lx)\n", ret, GetLastError());
3495 return ret;
3498 static BOOL CRYPT_AsnDecodeSubtreeConstraints(const BYTE *pbEncoded,
3499 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3500 DWORD *pcbDecoded)
3502 BOOL ret;
3503 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3504 offsetof(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint),
3505 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint),
3506 FINALMEMBERSIZE(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint),
3507 CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
3508 offsetof(CERT_NAME_BLOB, pbData) };
3510 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
3511 pvStructInfo, *pcbStructInfo, pcbDecoded);
3513 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3514 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
3515 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
3516 return ret;
3519 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
3520 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3521 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3523 BOOL ret;
3525 __TRY
3527 struct AsnDecodeSequenceItem items[] = {
3528 { ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
3529 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
3530 offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
3531 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3532 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3533 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3534 { ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
3535 cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
3536 FINALMEMBERSIZE(CERT_BASIC_CONSTRAINTS_INFO, cSubtreesConstraint),
3537 TRUE, TRUE,
3538 offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
3541 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3542 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3543 pcbStructInfo, NULL, NULL);
3545 __EXCEPT_PAGE_FAULT
3547 SetLastError(STATUS_ACCESS_VIOLATION);
3548 ret = FALSE;
3550 __ENDTRY
3551 return ret;
3554 static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
3555 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3556 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3558 BOOL ret;
3560 __TRY
3562 struct AsnDecodeSequenceItem items[] = {
3563 { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
3564 CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
3565 { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
3566 fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
3567 sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
3570 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3571 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3572 pcbStructInfo, NULL, NULL);
3574 __EXCEPT_PAGE_FAULT
3576 SetLastError(STATUS_ACCESS_VIOLATION);
3577 ret = FALSE;
3579 __ENDTRY
3580 return ret;
3583 static BOOL CRYPT_AsnDecodePolicyQualifier(const BYTE *pbEncoded,
3584 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3585 DWORD *pcbDecoded)
3587 struct AsnDecodeSequenceItem items[] = {
3588 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_QUALIFIER_INFO,
3589 pszPolicyQualifierId), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
3590 FALSE, TRUE, offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId),
3591 0 },
3592 { 0, offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier),
3593 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
3594 offsetof(CERT_POLICY_QUALIFIER_INFO, Qualifier.pbData), 0 },
3596 BOOL ret;
3597 CERT_POLICY_QUALIFIER_INFO *qualifier = pvStructInfo;
3599 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3600 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3602 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3603 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3604 pcbDecoded, qualifier ? qualifier->pszPolicyQualifierId : NULL);
3605 return ret;
3608 static BOOL CRYPT_AsnDecodePolicyQualifiers(const BYTE *pbEncoded,
3609 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3610 DWORD *pcbDecoded)
3612 BOOL ret;
3613 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3614 offsetof(CERT_POLICY_INFO, cPolicyQualifier),
3615 offsetof(CERT_POLICY_INFO, rgPolicyQualifier),
3616 FINALMEMBERSIZE(CERT_POLICY_INFO, cPolicyQualifier),
3617 CRYPT_AsnDecodePolicyQualifier, sizeof(CERT_POLICY_QUALIFIER_INFO), TRUE,
3618 offsetof(CERT_POLICY_QUALIFIER_INFO, pszPolicyQualifierId) };
3620 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3621 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3623 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3624 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
3625 TRACE("Returning %d (%08lx)\n", ret, GetLastError());
3626 return ret;
3629 static BOOL CRYPT_AsnDecodeCertPolicy(const BYTE *pbEncoded, DWORD cbEncoded,
3630 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
3632 struct AsnDecodeSequenceItem items[] = {
3633 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_INFO, pszPolicyIdentifier),
3634 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), FALSE, TRUE,
3635 offsetof(CERT_POLICY_INFO, pszPolicyIdentifier), 0 },
3636 { ASN_SEQUENCEOF, offsetof(CERT_POLICY_INFO, cPolicyQualifier),
3637 CRYPT_AsnDecodePolicyQualifiers,
3638 FINALMEMBERSIZE(CERT_POLICY_INFO, cPolicyQualifier), TRUE,
3639 TRUE, offsetof(CERT_POLICY_INFO, rgPolicyQualifier), 0 },
3641 CERT_POLICY_INFO *info = pvStructInfo;
3642 BOOL ret;
3644 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3645 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3647 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3648 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3649 pcbDecoded, info ? info->pszPolicyIdentifier : NULL);
3650 return ret;
3653 static BOOL WINAPI CRYPT_AsnDecodeCertPolicies(DWORD dwCertEncodingType,
3654 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3655 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3657 BOOL ret = FALSE;
3659 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3660 pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3662 __TRY
3664 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3665 offsetof(CERT_POLICIES_INFO, cPolicyInfo),
3666 offsetof(CERT_POLICIES_INFO, rgPolicyInfo),
3667 sizeof(CERT_POLICIES_INFO),
3668 CRYPT_AsnDecodeCertPolicy, sizeof(CERT_POLICY_INFO), TRUE,
3669 offsetof(CERT_POLICY_INFO, pszPolicyIdentifier) };
3670 CERT_POLICIES_INFO *info = pvStructInfo;
3672 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
3673 info->rgPolicyInfo = (CERT_POLICY_INFO *)(info + 1);
3675 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3676 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3678 __EXCEPT_PAGE_FAULT
3680 SetLastError(STATUS_ACCESS_VIOLATION);
3682 __ENDTRY
3683 return ret;
3686 static BOOL CRYPT_AsnDecodeCertPolicyMapping(const BYTE *pbEncoded,
3687 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3688 DWORD *pcbDecoded)
3690 struct AsnDecodeSequenceItem items[] = {
3691 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_MAPPING,
3692 pszIssuerDomainPolicy), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
3693 FALSE, TRUE, offsetof(CERT_POLICY_MAPPING, pszIssuerDomainPolicy), 0 },
3694 { ASN_OBJECTIDENTIFIER, offsetof(CERT_POLICY_MAPPING,
3695 pszSubjectDomainPolicy), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
3696 FALSE, TRUE, offsetof(CERT_POLICY_MAPPING, pszSubjectDomainPolicy), 0 },
3698 CERT_POLICY_MAPPING *mapping = pvStructInfo;
3699 BOOL ret;
3701 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3702 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3704 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3705 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
3706 pcbDecoded, mapping ? mapping->pszIssuerDomainPolicy : NULL);
3707 return ret;
3710 static BOOL WINAPI CRYPT_AsnDecodeCertPolicyMappings(DWORD dwCertEncodingType,
3711 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3712 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3714 BOOL ret = FALSE;
3716 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3717 pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3719 __TRY
3721 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
3722 offsetof(CERT_POLICY_MAPPINGS_INFO, cPolicyMapping),
3723 offsetof(CERT_POLICY_MAPPINGS_INFO, rgPolicyMapping),
3724 sizeof(CERT_POLICY_MAPPING),
3725 CRYPT_AsnDecodeCertPolicyMapping, sizeof(CERT_POLICY_MAPPING), TRUE,
3726 offsetof(CERT_POLICY_MAPPING, pszIssuerDomainPolicy) };
3727 CERT_POLICY_MAPPINGS_INFO *info = pvStructInfo;
3729 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
3730 info->rgPolicyMapping = (CERT_POLICY_MAPPING *)(info + 1);
3731 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
3732 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
3734 __EXCEPT_PAGE_FAULT
3736 SetLastError(STATUS_ACCESS_VIOLATION);
3738 __ENDTRY
3739 return ret;
3742 static BOOL CRYPT_AsnDecodeRequireExplicit(const BYTE *pbEncoded,
3743 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3744 DWORD *pcbDecoded)
3746 BOOL ret;
3747 DWORD skip, size = sizeof(skip);
3749 if (!cbEncoded)
3751 SetLastError(CRYPT_E_ASN1_EOD);
3752 return FALSE;
3754 if (pbEncoded[0] != (ASN_CONTEXT | 0))
3756 SetLastError(CRYPT_E_ASN1_BADTAG);
3757 return FALSE;
3759 if ((ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
3760 &skip, &size, pcbDecoded)))
3762 DWORD bytesNeeded = MEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO,
3763 fRequireExplicitPolicy, fInhibitPolicyMapping);
3765 if (!pvStructInfo)
3766 *pcbStructInfo = bytesNeeded;
3767 else if (*pcbStructInfo < bytesNeeded)
3769 *pcbStructInfo = bytesNeeded;
3770 SetLastError(ERROR_MORE_DATA);
3771 ret = FALSE;
3773 else
3775 CERT_POLICY_CONSTRAINTS_INFO *info = CONTAINING_RECORD(pvStructInfo,
3776 CERT_POLICY_CONSTRAINTS_INFO, fRequireExplicitPolicy);
3778 *pcbStructInfo = bytesNeeded;
3779 /* The BOOL is implicit: if the integer is present, then it's
3780 * TRUE.
3782 info->fRequireExplicitPolicy = TRUE;
3783 info->dwRequireExplicitPolicySkipCerts = skip;
3786 return ret;
3789 static BOOL CRYPT_AsnDecodeInhibitMapping(const BYTE *pbEncoded,
3790 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
3791 DWORD *pcbDecoded)
3793 BOOL ret;
3794 DWORD skip, size = sizeof(skip);
3796 if (!cbEncoded)
3798 SetLastError(CRYPT_E_ASN1_EOD);
3799 return FALSE;
3801 if (pbEncoded[0] != (ASN_CONTEXT | 1))
3803 SetLastError(CRYPT_E_ASN1_BADTAG);
3804 return FALSE;
3806 if ((ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
3807 &skip, &size, pcbDecoded)))
3809 DWORD bytesNeeded = FINALMEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO,
3810 fInhibitPolicyMapping);
3812 if (!pvStructInfo)
3813 *pcbStructInfo = bytesNeeded;
3814 else if (*pcbStructInfo < bytesNeeded)
3816 *pcbStructInfo = bytesNeeded;
3817 SetLastError(ERROR_MORE_DATA);
3818 ret = FALSE;
3820 else
3822 CERT_POLICY_CONSTRAINTS_INFO *info = CONTAINING_RECORD(pvStructInfo,
3823 CERT_POLICY_CONSTRAINTS_INFO, fInhibitPolicyMapping);
3825 *pcbStructInfo = bytesNeeded;
3826 /* The BOOL is implicit: if the integer is present, then it's
3827 * TRUE.
3829 info->fInhibitPolicyMapping = TRUE;
3830 info->dwInhibitPolicyMappingSkipCerts = skip;
3833 return ret;
3836 static BOOL WINAPI CRYPT_AsnDecodeCertPolicyConstraints(
3837 DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
3838 DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
3839 void *pvStructInfo, DWORD *pcbStructInfo)
3841 BOOL ret = FALSE;
3843 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3844 pDecodePara, pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
3846 __TRY
3848 struct AsnDecodeSequenceItem items[] = {
3849 { ASN_CONTEXT | 0,
3850 offsetof(CERT_POLICY_CONSTRAINTS_INFO, fRequireExplicitPolicy),
3851 CRYPT_AsnDecodeRequireExplicit,
3852 MEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO, fRequireExplicitPolicy,
3853 fInhibitPolicyMapping), TRUE, FALSE, 0, 0 },
3854 { ASN_CONTEXT | 1,
3855 offsetof(CERT_POLICY_CONSTRAINTS_INFO, fInhibitPolicyMapping),
3856 CRYPT_AsnDecodeInhibitMapping,
3857 FINALMEMBERSIZE(CERT_POLICY_CONSTRAINTS_INFO, fInhibitPolicyMapping),
3858 TRUE, FALSE, 0, 0 },
3861 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3862 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
3863 pcbStructInfo, NULL, NULL);
3865 __EXCEPT_PAGE_FAULT
3867 SetLastError(STATUS_ACCESS_VIOLATION);
3869 __ENDTRY
3870 return ret;
3873 #define RSA1_MAGIC 0x31415352
3875 struct DECODED_RSA_PUB_KEY
3877 CRYPT_INTEGER_BLOB pubexp;
3878 CRYPT_INTEGER_BLOB modulus;
3881 /* Helper function to decode an ASN.1 DER encoded RSA public key, writing the decoded
3882 * key into 'decodedKey', and the length into 'size'. The memory
3883 * for 'decodedKey' is allocated with 'CRYPT_DECODE_ALLOC_FLAG'
3885 static BOOL CRYPT_raw_decode_rsa_pub_key(struct DECODED_RSA_PUB_KEY **decodedKey,
3886 DWORD *size, const BYTE *pbEncoded, DWORD cbEncoded)
3888 BOOL ret;
3890 struct AsnDecodeSequenceItem items[] = {
3891 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
3892 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3893 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
3894 0 },
3895 { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
3896 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
3897 FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, pubexp.pbData),
3898 0 },
3901 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3902 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, decodedKey,
3903 size, NULL, NULL);
3905 if (ret && (*decodedKey)->pubexp.cbData > sizeof(DWORD))
3907 WARN("Unexpected exponent length %lu.\n", (*decodedKey)->pubexp.cbData);
3908 LocalFree(*decodedKey);
3909 SetLastError(CRYPT_E_ASN1_LARGE);
3910 ret = FALSE;
3913 return ret;
3916 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey_Bcrypt(DWORD dwCertEncodingType,
3917 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3918 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3920 BOOL ret;
3922 __TRY
3924 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
3925 DWORD size = 0;
3927 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3928 pvStructInfo, *pcbStructInfo);
3930 ret = CRYPT_raw_decode_rsa_pub_key(&decodedKey, &size, pbEncoded, cbEncoded);
3931 if (ret)
3933 /* Header, exponent, and modulus */
3934 DWORD bytesNeeded = sizeof(BCRYPT_RSAKEY_BLOB) + decodedKey->pubexp.cbData +
3935 decodedKey->modulus.cbData;
3937 if (!pvStructInfo)
3939 *pcbStructInfo = bytesNeeded;
3940 ret = TRUE;
3942 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3943 pvStructInfo, pcbStructInfo, bytesNeeded)))
3945 BCRYPT_RSAKEY_BLOB *hdr;
3947 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3948 pvStructInfo = *(BYTE **)pvStructInfo;
3950 hdr = pvStructInfo;
3951 hdr->Magic = BCRYPT_RSAPUBLIC_MAGIC;
3952 hdr->BitLength = decodedKey->modulus.cbData * 8;
3953 hdr->cbPublicExp = decodedKey->pubexp.cbData;
3954 hdr->cbModulus = decodedKey->modulus.cbData;
3955 hdr->cbPrime1 = 0;
3956 hdr->cbPrime2 = 0;
3957 /* CNG_RSA_PUBLIC_KEY_BLOB always stores the exponent and modulus
3958 * in big-endian format, so we need to convert from little-endian
3960 CRYPT_CopyReversed((BYTE *)pvStructInfo + sizeof(BCRYPT_RSAKEY_BLOB),
3961 decodedKey->pubexp.pbData, hdr->cbPublicExp);
3962 CRYPT_CopyReversed((BYTE *)pvStructInfo + sizeof(BCRYPT_RSAKEY_BLOB) +
3963 hdr->cbPublicExp, decodedKey->modulus.pbData,
3964 decodedKey->modulus.cbData);
3966 LocalFree(decodedKey);
3969 __EXCEPT_PAGE_FAULT
3971 SetLastError(STATUS_ACCESS_VIOLATION);
3972 ret = FALSE;
3974 __ENDTRY
3975 return ret;
3979 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
3980 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3981 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3983 BOOL ret;
3985 __TRY
3987 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
3988 DWORD size = 0;
3989 ret = CRYPT_raw_decode_rsa_pub_key(&decodedKey, &size, pbEncoded, cbEncoded);
3990 if (ret)
3992 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
3993 decodedKey->modulus.cbData;
3995 if (!pvStructInfo)
3997 *pcbStructInfo = bytesNeeded;
3999 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4000 pvStructInfo, pcbStructInfo, bytesNeeded)))
4002 BLOBHEADER *hdr;
4003 RSAPUBKEY *rsaPubKey;
4004 unsigned int i;
4006 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4007 pvStructInfo = *(BYTE **)pvStructInfo;
4008 hdr = pvStructInfo;
4009 hdr->bType = PUBLICKEYBLOB;
4010 hdr->bVersion = CUR_BLOB_VERSION;
4011 hdr->reserved = 0;
4012 hdr->aiKeyAlg = CALG_RSA_KEYX;
4013 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
4014 sizeof(BLOBHEADER));
4015 rsaPubKey->magic = RSA1_MAGIC;
4016 rsaPubKey->pubexp = 0;
4017 assert(decodedKey->pubexp.cbData <= sizeof(rsaPubKey->pubexp));
4018 for (i = 0; i < decodedKey->pubexp.cbData; ++i)
4019 rsaPubKey->pubexp |= decodedKey->pubexp.pbData[i] << (i * 8);
4021 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
4022 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
4023 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
4024 decodedKey->modulus.cbData);
4026 LocalFree(decodedKey);
4029 __EXCEPT_PAGE_FAULT
4031 SetLastError(STATUS_ACCESS_VIOLATION);
4032 ret = FALSE;
4034 __ENDTRY
4035 return ret;
4038 #define RSA2_MAGIC 0x32415352
4040 struct DECODED_RSA_PRIV_KEY
4042 DWORD version;
4043 DWORD pubexp;
4044 CRYPT_INTEGER_BLOB modulus;
4045 CRYPT_INTEGER_BLOB privexp;
4046 CRYPT_INTEGER_BLOB prime1;
4047 CRYPT_INTEGER_BLOB prime2;
4048 CRYPT_INTEGER_BLOB exponent1;
4049 CRYPT_INTEGER_BLOB exponent2;
4050 CRYPT_INTEGER_BLOB coefficient;
4053 static BOOL WINAPI CRYPT_AsnDecodeRsaPrivKey(DWORD dwCertEncodingType,
4054 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4055 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4057 BOOL ret;
4058 DWORD halflen;
4060 __TRY
4062 struct AsnDecodeSequenceItem items[] = {
4063 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, version),
4064 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4065 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, modulus),
4066 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
4067 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, modulus.pbData),
4068 0 },
4069 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, pubexp),
4070 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4071 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, privexp),
4072 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
4073 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, privexp.pbData),
4074 0 },
4075 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, prime1),
4076 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
4077 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, prime1.pbData),
4078 0 },
4079 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, prime2),
4080 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
4081 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, prime2.pbData),
4082 0 },
4083 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, exponent1),
4084 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
4085 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, exponent1.pbData),
4086 0 },
4087 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, exponent2),
4088 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
4089 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, exponent2.pbData),
4090 0 },
4091 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, coefficient),
4092 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
4093 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, coefficient.pbData),
4094 0 },
4096 struct DECODED_RSA_PRIV_KEY *decodedKey = NULL;
4097 DWORD size = 0;
4099 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
4100 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
4101 &size, NULL, NULL);
4102 if (ret)
4104 halflen = decodedKey->prime1.cbData;
4105 if (halflen < decodedKey->prime2.cbData)
4106 halflen = decodedKey->prime2.cbData;
4107 if (halflen < decodedKey->exponent1.cbData)
4108 halflen = decodedKey->exponent1.cbData;
4109 if (halflen < decodedKey->exponent2.cbData)
4110 halflen = decodedKey->exponent2.cbData;
4111 if (halflen < decodedKey->coefficient.cbData)
4112 halflen = decodedKey->coefficient.cbData;
4113 if (halflen * 2 < decodedKey->modulus.cbData)
4114 halflen = decodedKey->modulus.cbData / 2 + decodedKey->modulus.cbData % 2;
4115 if (halflen * 2 < decodedKey->privexp.cbData)
4116 halflen = decodedKey->privexp.cbData / 2 + decodedKey->privexp.cbData % 2;
4118 if (ret)
4120 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
4121 (halflen * 9);
4123 if (!pvStructInfo)
4125 *pcbStructInfo = bytesNeeded;
4126 ret = TRUE;
4128 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4129 pvStructInfo, pcbStructInfo, bytesNeeded)))
4131 BLOBHEADER *hdr;
4132 RSAPUBKEY *rsaPubKey;
4133 BYTE *vardata;
4135 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4136 pvStructInfo = *(BYTE **)pvStructInfo;
4138 hdr = pvStructInfo;
4139 hdr->bType = PRIVATEKEYBLOB;
4140 hdr->bVersion = CUR_BLOB_VERSION;
4141 hdr->reserved = 0;
4142 hdr->aiKeyAlg = CALG_RSA_KEYX;
4144 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
4145 sizeof(BLOBHEADER));
4146 rsaPubKey->magic = RSA2_MAGIC;
4147 rsaPubKey->pubexp = decodedKey->pubexp;
4148 rsaPubKey->bitlen = halflen * 16;
4150 vardata = (BYTE*)(rsaPubKey + 1);
4151 memset(vardata, 0, halflen * 9);
4152 memcpy(vardata,
4153 decodedKey->modulus.pbData, decodedKey->modulus.cbData);
4154 memcpy(vardata + halflen * 2,
4155 decodedKey->prime1.pbData, decodedKey->prime1.cbData);
4156 memcpy(vardata + halflen * 3,
4157 decodedKey->prime2.pbData, decodedKey->prime2.cbData);
4158 memcpy(vardata + halflen * 4,
4159 decodedKey->exponent1.pbData, decodedKey->exponent1.cbData);
4160 memcpy(vardata + halflen * 5,
4161 decodedKey->exponent2.pbData, decodedKey->exponent2.cbData);
4162 memcpy(vardata + halflen * 6,
4163 decodedKey->coefficient.pbData, decodedKey->coefficient.cbData);
4164 memcpy(vardata + halflen * 7,
4165 decodedKey->privexp.pbData, decodedKey->privexp.cbData);
4169 LocalFree(decodedKey);
4172 __EXCEPT_PAGE_FAULT
4174 SetLastError(STATUS_ACCESS_VIOLATION);
4175 ret = FALSE;
4177 __ENDTRY
4178 return ret;
4181 static BOOL CRYPT_AsnDecodeOctets(const BYTE *pbEncoded,
4182 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4183 DWORD *pcbDecoded)
4185 BOOL ret;
4186 DWORD bytesNeeded, dataLen;
4188 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
4189 pvStructInfo, *pcbStructInfo, pcbDecoded);
4191 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4193 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4195 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4196 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
4197 else
4198 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
4199 if (pcbDecoded)
4200 *pcbDecoded = 1 + lenBytes + dataLen;
4201 if (!pvStructInfo)
4202 *pcbStructInfo = bytesNeeded;
4203 else if (*pcbStructInfo < bytesNeeded)
4205 SetLastError(ERROR_MORE_DATA);
4206 *pcbStructInfo = bytesNeeded;
4207 ret = FALSE;
4209 else
4211 CRYPT_DATA_BLOB *blob;
4213 *pcbStructInfo = bytesNeeded;
4214 blob = pvStructInfo;
4215 blob->cbData = dataLen;
4216 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4217 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
4218 else
4220 assert(blob->pbData);
4221 if (blob->cbData)
4222 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
4223 blob->cbData);
4227 return ret;
4230 static BOOL CRYPT_AsnDecodeOctetStringInternal(const BYTE *encoded, DWORD encoded_size,
4231 DWORD flags, void *buf, DWORD *buf_size, DWORD *ret_decoded)
4233 DWORD decoded = 0, indefinite_len_depth = 0, len_size, len, bytes_needed;
4234 CRYPT_DATA_BLOB *blob;
4235 const BYTE *string;
4237 while (encoded[0] == (ASN_CONSTRUCTOR | ASN_OCTETSTRING))
4239 if (!CRYPT_GetLengthIndefinite(encoded, encoded_size, &len))
4240 return FALSE;
4242 len_size = GET_LEN_BYTES(encoded[1]);
4243 encoded += 1 + len_size;
4244 encoded_size -= 1 + len_size;
4245 decoded += 1 + len_size;
4247 if (len == CMSG_INDEFINITE_LENGTH)
4249 indefinite_len_depth++;
4250 if (encoded_size < 2)
4252 SetLastError(CRYPT_E_ASN1_EOD);
4253 return FALSE;
4255 encoded_size -= 2;
4256 decoded += 2;
4260 if (encoded[0] != ASN_OCTETSTRING)
4262 WARN("Unexpected tag %02x\n", encoded[0]);
4263 SetLastError(CRYPT_E_ASN1_BADTAG);
4264 return FALSE;
4267 if (!CRYPT_GetLen(encoded, encoded_size, &len))
4268 return FALSE;
4269 len_size = GET_LEN_BYTES(encoded[1]);
4270 decoded += 1 + len_size + len;
4271 encoded_size -= 1 + len_size;
4273 if (len > encoded_size)
4275 SetLastError(CRYPT_E_ASN1_EOD);
4276 return FALSE;
4278 if (ret_decoded)
4279 *ret_decoded = decoded;
4281 encoded += 1 + len_size;
4282 string = encoded;
4283 encoded += len;
4285 while (indefinite_len_depth--)
4287 if (encoded[0] || encoded[1])
4289 TRACE("expected 0 TLV, got %02x %02x\n", encoded[0], encoded[1]);
4290 SetLastError(CRYPT_E_ASN1_CORRUPT);
4291 return FALSE;
4295 bytes_needed = sizeof(*blob);
4296 if (!(flags & CRYPT_DECODE_NOCOPY_FLAG)) bytes_needed += len;
4297 if (!buf)
4299 *buf_size = bytes_needed;
4300 return TRUE;
4302 if (*buf_size < bytes_needed)
4304 SetLastError(ERROR_MORE_DATA);
4305 *buf_size = bytes_needed;
4306 return FALSE;
4309 *buf_size = bytes_needed;
4310 blob = buf;
4311 blob->cbData = len;
4312 if (flags & CRYPT_DECODE_NOCOPY_FLAG)
4313 blob->pbData = (BYTE*)string;
4314 else if (blob->cbData)
4315 memcpy(blob->pbData, string, blob->cbData);
4317 if (ret_decoded)
4318 *ret_decoded = decoded;
4319 return TRUE;
4322 static BOOL WINAPI CRYPT_AsnDecodeOctetString(DWORD dwCertEncodingType,
4323 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4324 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4326 BOOL ret;
4328 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
4329 pDecodePara, pvStructInfo, *pcbStructInfo);
4331 if (!cbEncoded)
4333 SetLastError(CRYPT_E_ASN1_CORRUPT);
4334 return FALSE;
4337 __TRY
4339 DWORD bytesNeeded = 0;
4341 if ((ret = CRYPT_AsnDecodeOctetStringInternal(pbEncoded, cbEncoded,
4342 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4344 if (!pvStructInfo)
4345 *pcbStructInfo = bytesNeeded;
4346 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4347 pvStructInfo, pcbStructInfo, bytesNeeded)))
4349 CRYPT_DATA_BLOB *blob;
4351 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4352 pvStructInfo = *(BYTE **)pvStructInfo;
4353 blob = pvStructInfo;
4354 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
4355 ret = CRYPT_AsnDecodeOctetStringInternal(pbEncoded, cbEncoded,
4356 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4357 &bytesNeeded, NULL);
4358 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4359 CRYPT_FreeSpace(pDecodePara, blob);
4363 __EXCEPT_PAGE_FAULT
4365 SetLastError(STATUS_ACCESS_VIOLATION);
4366 ret = FALSE;
4368 __ENDTRY
4369 return ret;
4372 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
4373 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4375 BOOL ret;
4376 DWORD bytesNeeded, dataLen;
4377 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4379 TRACE("(%p, %ld, 0x%08lx, %p, %ld, %p)\n", pbEncoded, cbEncoded, dwFlags,
4380 pvStructInfo, *pcbStructInfo, pcbDecoded);
4382 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4384 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4385 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
4386 else
4387 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
4388 if (pcbDecoded)
4389 *pcbDecoded = 1 + lenBytes + dataLen;
4390 if (!pvStructInfo)
4391 *pcbStructInfo = bytesNeeded;
4392 else if (*pcbStructInfo < bytesNeeded)
4394 *pcbStructInfo = bytesNeeded;
4395 SetLastError(ERROR_MORE_DATA);
4396 ret = FALSE;
4398 else
4400 CRYPT_BIT_BLOB *blob;
4402 *pcbStructInfo = bytesNeeded;
4403 blob = pvStructInfo;
4404 blob->cbData = dataLen - 1;
4405 blob->cUnusedBits = *(pbEncoded + 1 + lenBytes);
4406 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4408 blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes;
4410 else
4412 assert(blob->pbData);
4413 if (blob->cbData)
4415 BYTE mask = 0xff << blob->cUnusedBits;
4417 memcpy(blob->pbData, pbEncoded + 2 + lenBytes,
4418 blob->cbData);
4419 blob->pbData[blob->cbData - 1] &= mask;
4424 return ret;
4427 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
4428 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4429 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4431 BOOL ret;
4433 TRACE("(%p, %ld, 0x%08lx, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
4434 pDecodePara, pvStructInfo, pcbStructInfo);
4436 __TRY
4438 DWORD bytesNeeded = 0;
4440 if (!cbEncoded)
4442 SetLastError(CRYPT_E_ASN1_CORRUPT);
4443 ret = FALSE;
4445 else if (pbEncoded[0] != ASN_BITSTRING)
4447 SetLastError(CRYPT_E_ASN1_BADTAG);
4448 ret = FALSE;
4450 else if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
4451 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4453 if (!pvStructInfo)
4454 *pcbStructInfo = bytesNeeded;
4455 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4456 pvStructInfo, pcbStructInfo, bytesNeeded)))
4458 CRYPT_BIT_BLOB *blob;
4460 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4461 pvStructInfo = *(BYTE **)pvStructInfo;
4462 blob = pvStructInfo;
4463 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
4464 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
4465 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4466 &bytesNeeded, NULL);
4467 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4468 CRYPT_FreeSpace(pDecodePara, blob);
4472 __EXCEPT_PAGE_FAULT
4474 SetLastError(STATUS_ACCESS_VIOLATION);
4475 ret = FALSE;
4477 __ENDTRY
4478 TRACE("returning %d (%08lx)\n", ret, GetLastError());
4479 return ret;
4482 /* Ignores tag. Only allows integers 4 bytes or smaller in size. */
4483 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
4484 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4486 BOOL ret;
4487 DWORD dataLen;
4489 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4491 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4493 if (pcbDecoded)
4494 *pcbDecoded = 1 + lenBytes + dataLen;
4495 if (dataLen > sizeof(int))
4497 SetLastError(CRYPT_E_ASN1_LARGE);
4498 ret = FALSE;
4500 else if (!pvStructInfo)
4501 *pcbStructInfo = sizeof(int);
4502 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int))))
4504 int val, i;
4506 if (dataLen && pbEncoded[1 + lenBytes] & 0x80)
4508 /* initialize to a negative value to sign-extend */
4509 val = -1;
4511 else
4512 val = 0;
4513 for (i = 0; i < dataLen; i++)
4515 val <<= 8;
4516 val |= pbEncoded[1 + lenBytes + i];
4518 memcpy(pvStructInfo, &val, sizeof(int));
4521 return ret;
4524 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
4525 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4526 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4528 BOOL ret;
4530 __TRY
4532 DWORD bytesNeeded = 0;
4534 if (!cbEncoded)
4536 SetLastError(CRYPT_E_ASN1_EOD);
4537 ret = FALSE;
4539 else if (pbEncoded[0] != ASN_INTEGER)
4541 SetLastError(CRYPT_E_ASN1_BADTAG);
4542 ret = FALSE;
4544 else
4545 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
4546 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4547 if (ret)
4549 if (!pvStructInfo)
4550 *pcbStructInfo = bytesNeeded;
4551 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4552 pvStructInfo, pcbStructInfo, bytesNeeded)))
4554 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4555 pvStructInfo = *(BYTE **)pvStructInfo;
4556 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
4557 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4558 &bytesNeeded, NULL);
4559 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4560 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
4564 __EXCEPT_PAGE_FAULT
4566 SetLastError(STATUS_ACCESS_VIOLATION);
4567 ret = FALSE;
4569 __ENDTRY
4570 return ret;
4573 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
4574 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4575 DWORD *pcbDecoded)
4577 BOOL ret;
4578 DWORD bytesNeeded, dataLen;
4580 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4582 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4584 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
4585 if (pcbDecoded)
4586 *pcbDecoded = 1 + lenBytes + dataLen;
4587 if (!pvStructInfo)
4588 *pcbStructInfo = bytesNeeded;
4589 else if (*pcbStructInfo < bytesNeeded)
4591 *pcbStructInfo = bytesNeeded;
4592 SetLastError(ERROR_MORE_DATA);
4593 ret = FALSE;
4595 else
4597 CRYPT_INTEGER_BLOB *blob = pvStructInfo;
4599 *pcbStructInfo = bytesNeeded;
4600 blob->cbData = dataLen;
4601 assert(blob->pbData);
4602 if (blob->cbData)
4604 DWORD i;
4606 for (i = 0; i < blob->cbData; i++)
4608 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
4609 dataLen - i - 1);
4614 return ret;
4617 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
4618 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4619 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4621 BOOL ret;
4623 __TRY
4625 DWORD bytesNeeded = 0;
4627 if (pbEncoded[0] != ASN_INTEGER)
4629 SetLastError(CRYPT_E_ASN1_BADTAG);
4630 ret = FALSE;
4632 else
4633 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
4634 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4635 if (ret)
4637 if (!pvStructInfo)
4638 *pcbStructInfo = bytesNeeded;
4639 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4640 pvStructInfo, pcbStructInfo, bytesNeeded)))
4642 CRYPT_INTEGER_BLOB *blob;
4644 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4645 pvStructInfo = *(BYTE **)pvStructInfo;
4646 blob = pvStructInfo;
4647 blob->pbData = (BYTE *)pvStructInfo +
4648 sizeof(CRYPT_INTEGER_BLOB);
4649 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
4650 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
4651 &bytesNeeded, NULL);
4652 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4653 CRYPT_FreeSpace(pDecodePara, blob);
4657 __EXCEPT_PAGE_FAULT
4659 SetLastError(STATUS_ACCESS_VIOLATION);
4660 ret = FALSE;
4662 __ENDTRY
4663 return ret;
4666 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
4667 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4668 DWORD *pcbDecoded)
4670 BOOL ret;
4672 if (pbEncoded[0] == ASN_INTEGER)
4674 DWORD bytesNeeded, dataLen;
4676 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4678 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4680 if (pcbDecoded)
4681 *pcbDecoded = 1 + lenBytes + dataLen;
4682 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
4683 if (!pvStructInfo)
4684 *pcbStructInfo = bytesNeeded;
4685 else if (*pcbStructInfo < bytesNeeded)
4687 *pcbStructInfo = bytesNeeded;
4688 SetLastError(ERROR_MORE_DATA);
4689 ret = FALSE;
4691 else
4693 CRYPT_INTEGER_BLOB *blob = pvStructInfo;
4695 *pcbStructInfo = bytesNeeded;
4696 blob->cbData = dataLen;
4697 assert(blob->pbData);
4698 /* remove leading zero byte if it exists */
4699 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
4701 blob->cbData--;
4702 blob->pbData++;
4704 if (blob->cbData)
4706 DWORD i;
4708 for (i = 0; i < blob->cbData; i++)
4710 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
4711 dataLen - i - 1);
4717 else
4719 SetLastError(CRYPT_E_ASN1_BADTAG);
4720 ret = FALSE;
4722 return ret;
4725 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
4726 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4727 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4729 BOOL ret;
4731 __TRY
4733 DWORD bytesNeeded = 0;
4735 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded,
4736 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4738 if (!pvStructInfo)
4739 *pcbStructInfo = bytesNeeded;
4740 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4741 pvStructInfo, pcbStructInfo, bytesNeeded)))
4743 CRYPT_INTEGER_BLOB *blob;
4745 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4746 pvStructInfo = *(BYTE **)pvStructInfo;
4747 blob = pvStructInfo;
4748 blob->pbData = (BYTE *)pvStructInfo +
4749 sizeof(CRYPT_INTEGER_BLOB);
4750 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded,
4751 cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
4752 &bytesNeeded, NULL);
4753 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4754 CRYPT_FreeSpace(pDecodePara, blob);
4758 __EXCEPT_PAGE_FAULT
4760 SetLastError(STATUS_ACCESS_VIOLATION);
4761 ret = FALSE;
4763 __ENDTRY
4764 return ret;
4767 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
4768 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4769 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4771 BOOL ret;
4773 if (!pvStructInfo)
4775 *pcbStructInfo = sizeof(int);
4776 return TRUE;
4778 __TRY
4780 if (pbEncoded[0] == ASN_ENUMERATED)
4782 unsigned int val = 0, i;
4784 if (cbEncoded <= 1)
4786 SetLastError(CRYPT_E_ASN1_EOD);
4787 ret = FALSE;
4789 else if (pbEncoded[1] == 0)
4791 SetLastError(CRYPT_E_ASN1_CORRUPT);
4792 ret = FALSE;
4794 else
4796 /* A little strange looking, but we have to accept a sign byte:
4797 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
4798 * assuming a small length is okay here, it has to be in short
4799 * form.
4801 if (pbEncoded[1] > sizeof(unsigned int) + 1)
4803 SetLastError(CRYPT_E_ASN1_LARGE);
4804 return FALSE;
4806 for (i = 0; i < pbEncoded[1]; i++)
4808 val <<= 8;
4809 val |= pbEncoded[2 + i];
4811 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4812 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
4814 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4815 pvStructInfo = *(BYTE **)pvStructInfo;
4816 memcpy(pvStructInfo, &val, sizeof(unsigned int));
4820 else
4822 SetLastError(CRYPT_E_ASN1_BADTAG);
4823 ret = FALSE;
4826 __EXCEPT_PAGE_FAULT
4828 SetLastError(STATUS_ACCESS_VIOLATION);
4829 ret = FALSE;
4831 __ENDTRY
4832 return ret;
4835 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
4836 * if it fails.
4838 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
4839 do { \
4840 BYTE i; \
4842 (word) = 0; \
4843 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
4845 if (!isdigit(*(pbEncoded))) \
4847 SetLastError(CRYPT_E_ASN1_CORRUPT); \
4848 ret = FALSE; \
4850 else \
4852 (word) *= 10; \
4853 (word) += *(pbEncoded)++ - '0'; \
4856 } while (0)
4858 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
4859 SYSTEMTIME *sysTime)
4861 BOOL ret = TRUE;
4863 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
4865 WORD hours, minutes = 0;
4866 BYTE sign = *pbEncoded++;
4868 len--;
4869 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
4870 if (ret && hours >= 24)
4872 SetLastError(CRYPT_E_ASN1_CORRUPT);
4873 ret = FALSE;
4875 else if (len >= 2)
4877 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
4878 if (ret && minutes >= 60)
4880 SetLastError(CRYPT_E_ASN1_CORRUPT);
4881 ret = FALSE;
4884 if (ret)
4886 if (sign == '+')
4888 sysTime->wHour += hours;
4889 sysTime->wMinute += minutes;
4891 else
4893 if (hours > sysTime->wHour)
4895 sysTime->wDay--;
4896 sysTime->wHour = 24 - (hours - sysTime->wHour);
4898 else
4899 sysTime->wHour -= hours;
4900 if (minutes > sysTime->wMinute)
4902 sysTime->wHour--;
4903 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
4905 else
4906 sysTime->wMinute -= minutes;
4910 return ret;
4913 #define MIN_ENCODED_TIME_LENGTH 10
4915 static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
4916 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4917 DWORD *pcbDecoded)
4919 BOOL ret = FALSE;
4921 if (pbEncoded[0] == ASN_UTCTIME)
4923 if (cbEncoded <= 1)
4924 SetLastError(CRYPT_E_ASN1_EOD);
4925 else if (pbEncoded[1] > 0x7f)
4927 /* long-form date strings really can't be valid */
4928 SetLastError(CRYPT_E_ASN1_CORRUPT);
4930 else
4932 SYSTEMTIME sysTime = { 0 };
4933 BYTE len = pbEncoded[1];
4935 if (len < MIN_ENCODED_TIME_LENGTH)
4936 SetLastError(CRYPT_E_ASN1_CORRUPT);
4937 else
4939 ret = TRUE;
4940 if (pcbDecoded)
4941 *pcbDecoded = 2 + len;
4942 pbEncoded += 2;
4943 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
4944 if (sysTime.wYear >= 50)
4945 sysTime.wYear += 1900;
4946 else
4947 sysTime.wYear += 2000;
4948 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
4949 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
4950 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
4951 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
4952 if (ret && len > 0)
4954 if (len >= 2 && isdigit(*pbEncoded) &&
4955 isdigit(*(pbEncoded + 1)))
4956 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4957 sysTime.wSecond);
4958 else if (isdigit(*pbEncoded))
4959 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
4960 sysTime.wSecond);
4961 if (ret)
4962 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
4963 &sysTime);
4965 if (ret)
4967 if (!pvStructInfo)
4968 *pcbStructInfo = sizeof(FILETIME);
4969 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
4970 sizeof(FILETIME))))
4971 ret = SystemTimeToFileTime(&sysTime, pvStructInfo);
4976 else
4977 SetLastError(CRYPT_E_ASN1_BADTAG);
4978 return ret;
4981 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
4982 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4983 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4985 BOOL ret = FALSE;
4987 __TRY
4989 DWORD bytesNeeded = 0;
4991 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
4992 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4993 if (ret)
4995 if (!pvStructInfo)
4996 *pcbStructInfo = bytesNeeded;
4997 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
4998 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
5000 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5001 pvStructInfo = *(BYTE **)pvStructInfo;
5002 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
5003 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5004 &bytesNeeded, NULL);
5005 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5006 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
5010 __EXCEPT_PAGE_FAULT
5012 SetLastError(STATUS_ACCESS_VIOLATION);
5014 __ENDTRY
5015 return ret;
5018 static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
5019 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5020 DWORD *pcbDecoded)
5022 BOOL ret = FALSE;
5024 if (pbEncoded[0] == ASN_GENERALTIME)
5026 if (cbEncoded <= 1)
5027 SetLastError(CRYPT_E_ASN1_EOD);
5028 else if (pbEncoded[1] > 0x7f)
5030 /* long-form date strings really can't be valid */
5031 SetLastError(CRYPT_E_ASN1_CORRUPT);
5033 else
5035 BYTE len = pbEncoded[1];
5037 if (len < MIN_ENCODED_TIME_LENGTH)
5038 SetLastError(CRYPT_E_ASN1_CORRUPT);
5039 else
5041 SYSTEMTIME sysTime = { 0 };
5043 ret = TRUE;
5044 if (pcbDecoded)
5045 *pcbDecoded = 2 + len;
5046 pbEncoded += 2;
5047 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
5048 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
5049 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
5050 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
5051 if (ret && len > 0)
5053 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
5054 sysTime.wMinute);
5055 if (ret && len > 0)
5056 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
5057 sysTime.wSecond);
5058 if (ret && len > 0 && (*pbEncoded == '.' ||
5059 *pbEncoded == ','))
5061 BYTE digits;
5063 pbEncoded++;
5064 len--;
5065 /* workaround macro weirdness */
5066 digits = min(len, 3);
5067 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
5068 sysTime.wMilliseconds);
5070 if (ret)
5071 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
5072 &sysTime);
5074 if (ret)
5076 if (!pvStructInfo)
5077 *pcbStructInfo = sizeof(FILETIME);
5078 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
5079 sizeof(FILETIME))))
5080 ret = SystemTimeToFileTime(&sysTime, pvStructInfo);
5085 else
5086 SetLastError(CRYPT_E_ASN1_BADTAG);
5087 return ret;
5090 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
5091 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5092 DWORD *pcbDecoded)
5094 BOOL ret;
5095 InternalDecodeFunc decode = NULL;
5097 if (pbEncoded[0] == ASN_UTCTIME)
5098 decode = CRYPT_AsnDecodeUtcTimeInternal;
5099 else if (pbEncoded[0] == ASN_GENERALTIME)
5100 decode = CRYPT_AsnDecodeGeneralizedTime;
5101 if (decode)
5102 ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
5103 pcbStructInfo, pcbDecoded);
5104 else
5106 SetLastError(CRYPT_E_ASN1_BADTAG);
5107 ret = FALSE;
5109 return ret;
5112 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
5113 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5114 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5116 BOOL ret;
5118 __TRY
5120 DWORD bytesNeeded = 0;
5122 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
5123 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
5124 if (ret)
5126 if (!pvStructInfo)
5127 *pcbStructInfo = bytesNeeded;
5128 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
5129 pvStructInfo, pcbStructInfo, bytesNeeded)))
5131 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5132 pvStructInfo = *(BYTE **)pvStructInfo;
5133 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
5134 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5135 &bytesNeeded, NULL);
5136 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5137 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
5141 __EXCEPT_PAGE_FAULT
5143 SetLastError(STATUS_ACCESS_VIOLATION);
5144 ret = FALSE;
5146 __ENDTRY
5147 return ret;
5150 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
5151 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5152 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5154 BOOL ret = TRUE;
5156 __TRY
5158 if (pbEncoded[0] == ASN_SEQUENCEOF)
5160 DWORD bytesNeeded, dataLen, remainingLen, cValue;
5162 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
5164 BYTE lenBytes;
5165 const BYTE *ptr;
5167 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
5168 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
5169 cValue = 0;
5170 ptr = pbEncoded + 1 + lenBytes;
5171 remainingLen = dataLen;
5172 while (ret && remainingLen)
5174 DWORD nextLen;
5176 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
5177 if (ret)
5179 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
5181 remainingLen -= 1 + nextLenBytes + nextLen;
5182 ptr += 1 + nextLenBytes + nextLen;
5183 bytesNeeded += sizeof(CRYPT_DER_BLOB);
5184 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
5185 bytesNeeded += 1 + nextLenBytes + nextLen;
5186 cValue++;
5189 if (ret)
5191 CRYPT_SEQUENCE_OF_ANY *seq;
5192 BYTE *nextPtr;
5193 DWORD i;
5195 if (!pvStructInfo)
5196 *pcbStructInfo = bytesNeeded;
5197 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
5198 pvStructInfo, pcbStructInfo, bytesNeeded)))
5200 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5201 pvStructInfo = *(BYTE **)pvStructInfo;
5202 seq = pvStructInfo;
5203 seq->cValue = cValue;
5204 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
5205 sizeof(*seq));
5206 nextPtr = (BYTE *)seq->rgValue +
5207 cValue * sizeof(CRYPT_DER_BLOB);
5208 ptr = pbEncoded + 1 + lenBytes;
5209 remainingLen = dataLen;
5210 i = 0;
5211 while (ret && remainingLen)
5213 DWORD nextLen;
5215 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
5216 if (ret)
5218 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
5220 seq->rgValue[i].cbData = 1 + nextLenBytes +
5221 nextLen;
5222 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
5223 seq->rgValue[i].pbData = (BYTE *)ptr;
5224 else
5226 seq->rgValue[i].pbData = nextPtr;
5227 memcpy(nextPtr, ptr, 1 + nextLenBytes +
5228 nextLen);
5229 nextPtr += 1 + nextLenBytes + nextLen;
5231 remainingLen -= 1 + nextLenBytes + nextLen;
5232 ptr += 1 + nextLenBytes + nextLen;
5233 i++;
5236 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5237 CRYPT_FreeSpace(pDecodePara, seq);
5242 else
5244 SetLastError(CRYPT_E_ASN1_BADTAG);
5245 ret = FALSE;
5248 __EXCEPT_PAGE_FAULT
5250 SetLastError(STATUS_ACCESS_VIOLATION);
5251 ret = FALSE;
5253 __ENDTRY
5254 return ret;
5257 static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded,
5258 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5259 DWORD *pcbDecoded)
5261 BOOL ret;
5263 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
5265 DWORD bytesNeeded = 0, dataLen;
5267 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
5269 struct AsnArrayDescriptor arrayDesc = {
5270 ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
5271 offsetof(CRL_DIST_POINT_NAME, u.FullName.cAltEntry),
5272 offsetof(CRL_DIST_POINT_NAME, u.FullName.rgAltEntry),
5273 FINALMEMBERSIZE(CRL_DIST_POINT_NAME, u),
5274 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
5275 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
5276 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
5277 DWORD nameLen;
5279 if (dataLen)
5281 ret = CRYPT_AsnDecodeArray(&arrayDesc,
5282 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
5283 dwFlags, NULL, NULL, &nameLen, NULL);
5284 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen -
5285 FINALMEMBERSIZE(CRL_DIST_POINT_NAME, u);
5287 else
5288 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
5289 if (pcbDecoded)
5290 *pcbDecoded = 1 + lenBytes + dataLen;
5291 if (!pvStructInfo)
5292 *pcbStructInfo = bytesNeeded;
5293 else if (*pcbStructInfo < bytesNeeded)
5295 *pcbStructInfo = bytesNeeded;
5296 SetLastError(ERROR_MORE_DATA);
5297 ret = FALSE;
5299 else
5301 CRL_DIST_POINT_NAME *name = pvStructInfo;
5303 *pcbStructInfo = bytesNeeded;
5304 if (dataLen)
5306 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
5307 ret = CRYPT_AsnDecodeArray(&arrayDesc,
5308 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
5309 dwFlags, NULL, &name->u.FullName.cAltEntry, &nameLen,
5310 NULL);
5312 else
5313 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
5317 else
5319 SetLastError(CRYPT_E_ASN1_BADTAG);
5320 ret = FALSE;
5322 return ret;
5325 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
5326 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5328 struct AsnDecodeSequenceItem items[] = {
5329 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
5330 DistPointName), CRYPT_AsnDecodeDistPointName,
5331 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
5332 DistPointName.u.FullName.rgAltEntry), 0 },
5333 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
5334 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
5335 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
5336 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
5337 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
5338 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
5340 CRL_DIST_POINT *point = pvStructInfo;
5341 BOOL ret;
5343 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5344 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5345 pcbDecoded, point ? point->DistPointName.u.FullName.rgAltEntry : NULL);
5346 return ret;
5349 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
5350 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5351 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5353 BOOL ret;
5355 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
5356 pDecodePara, pvStructInfo, *pcbStructInfo);
5358 __TRY
5360 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
5361 offsetof(CRL_DIST_POINTS_INFO, cDistPoint),
5362 offsetof(CRL_DIST_POINTS_INFO, rgDistPoint),
5363 sizeof(CRL_DIST_POINTS_INFO),
5364 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
5365 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
5366 CRL_DIST_POINTS_INFO *info = pvStructInfo;
5368 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5369 info->rgDistPoint = (CRL_DIST_POINT *)(info + 1);
5370 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5371 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
5373 __EXCEPT_PAGE_FAULT
5375 SetLastError(STATUS_ACCESS_VIOLATION);
5376 ret = FALSE;
5378 __ENDTRY
5379 return ret;
5382 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
5383 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5384 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5386 BOOL ret;
5388 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
5389 pDecodePara, pvStructInfo, *pcbStructInfo);
5391 __TRY
5393 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
5394 offsetof(CERT_ENHKEY_USAGE, cUsageIdentifier),
5395 offsetof(CERT_ENHKEY_USAGE, rgpszUsageIdentifier),
5396 sizeof(CERT_ENHKEY_USAGE),
5397 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
5398 CERT_ENHKEY_USAGE *usage = pvStructInfo;
5400 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5401 usage->rgpszUsageIdentifier = (LPSTR *)(usage + 1);
5402 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5403 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
5405 __EXCEPT_PAGE_FAULT
5407 SetLastError(STATUS_ACCESS_VIOLATION);
5408 ret = FALSE;
5410 __ENDTRY
5411 return ret;
5414 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
5415 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5416 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5418 BOOL ret;
5420 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
5421 pDecodePara, pvStructInfo, *pcbStructInfo);
5423 __TRY
5425 struct AsnDecodeSequenceItem items[] = {
5426 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
5427 DistPointName), CRYPT_AsnDecodeDistPointName,
5428 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
5429 offsetof(CRL_ISSUING_DIST_POINT,
5430 DistPointName.u.FullName.rgAltEntry), 0 },
5431 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
5432 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
5433 FALSE, 0 },
5434 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
5435 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
5436 FALSE, 0 },
5437 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
5438 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
5439 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
5440 OnlySomeReasonFlags.pbData), 0 },
5441 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
5442 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
5445 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5446 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
5447 pcbStructInfo, NULL, NULL);
5449 __EXCEPT_PAGE_FAULT
5451 SetLastError(STATUS_ACCESS_VIOLATION);
5452 ret = FALSE;
5454 __ENDTRY
5455 return ret;
5458 static BOOL CRYPT_AsnDecodeMaximum(const BYTE *pbEncoded,
5459 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5460 DWORD *pcbDecoded)
5462 BOOL ret;
5463 DWORD max, size = sizeof(max);
5465 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
5466 pvStructInfo, *pcbStructInfo, pcbDecoded);
5468 if (!cbEncoded)
5470 SetLastError(CRYPT_E_ASN1_EOD);
5471 return FALSE;
5473 if (pbEncoded[0] != (ASN_CONTEXT | 1))
5475 SetLastError(CRYPT_E_ASN1_BADTAG);
5476 return FALSE;
5478 if ((ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
5479 &max, &size, pcbDecoded)))
5481 DWORD bytesNeeded = FINALMEMBERSIZE(CERT_GENERAL_SUBTREE, fMaximum);
5483 if (!pvStructInfo)
5484 *pcbStructInfo = bytesNeeded;
5485 else if (*pcbStructInfo < bytesNeeded)
5487 *pcbStructInfo = bytesNeeded;
5488 SetLastError(ERROR_MORE_DATA);
5489 ret = FALSE;
5491 else
5493 CERT_GENERAL_SUBTREE *subtree = CONTAINING_RECORD(pvStructInfo,
5494 CERT_GENERAL_SUBTREE, fMaximum);
5496 *pcbStructInfo = bytesNeeded;
5497 /* The BOOL is implicit: if the integer is present, then it's
5498 * TRUE.
5500 subtree->fMaximum = TRUE;
5501 subtree->dwMaximum = max;
5504 TRACE("returning %d\n", ret);
5505 return ret;
5508 static BOOL CRYPT_AsnDecodeSubtree(const BYTE *pbEncoded,
5509 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5510 DWORD *pcbDecoded)
5512 BOOL ret;
5513 struct AsnDecodeSequenceItem items[] = {
5514 { 0, offsetof(CERT_GENERAL_SUBTREE, Base),
5515 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE, TRUE,
5516 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL), 0 },
5517 { ASN_CONTEXT | 0, offsetof(CERT_GENERAL_SUBTREE, dwMinimum),
5518 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
5519 { ASN_CONTEXT | 1, offsetof(CERT_GENERAL_SUBTREE, fMaximum),
5520 CRYPT_AsnDecodeMaximum, FINALMEMBERSIZE(CERT_GENERAL_SUBTREE, fMaximum),
5521 TRUE, FALSE, 0, 0 },
5523 CERT_GENERAL_SUBTREE *subtree = pvStructInfo;
5525 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
5526 pvStructInfo, *pcbStructInfo, pcbDecoded);
5528 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5529 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5530 pcbDecoded, subtree ? subtree->Base.u.pwszURL : NULL);
5531 if (pcbDecoded)
5533 TRACE("%ld\n", *pcbDecoded);
5534 if (*pcbDecoded < cbEncoded)
5535 TRACE("%02x %02x\n", *(pbEncoded + *pcbDecoded),
5536 *(pbEncoded + *pcbDecoded + 1));
5538 TRACE("returning %d\n", ret);
5539 return ret;
5542 static BOOL CRYPT_AsnDecodePermittedSubtree(const BYTE *pbEncoded,
5543 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5544 DWORD *pcbDecoded)
5546 BOOL ret = TRUE;
5547 struct AsnArrayDescriptor arrayDesc = { 0,
5548 offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
5549 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree),
5550 MEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree,
5551 cExcludedSubtree),
5552 CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
5553 offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
5555 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
5556 pvStructInfo, *pcbStructInfo, pcbDecoded);
5558 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5559 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5560 return ret;
5563 static BOOL CRYPT_AsnDecodeExcludedSubtree(const BYTE *pbEncoded,
5564 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5565 DWORD *pcbDecoded)
5567 BOOL ret = TRUE;
5568 struct AsnArrayDescriptor arrayDesc = { 0,
5569 offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5570 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree),
5571 FINALMEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5572 CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
5573 offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
5575 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
5576 pvStructInfo, *pcbStructInfo, pcbDecoded);
5578 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5579 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5580 return ret;
5583 static BOOL WINAPI CRYPT_AsnDecodeNameConstraints(DWORD dwCertEncodingType,
5584 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5585 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5587 BOOL ret = FALSE;
5589 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
5590 pDecodePara, pvStructInfo, *pcbStructInfo);
5592 __TRY
5594 struct AsnDecodeSequenceItem items[] = {
5595 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
5596 offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
5597 CRYPT_AsnDecodePermittedSubtree,
5598 MEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree,
5599 cExcludedSubtree), TRUE, TRUE,
5600 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree), 0 },
5601 { ASN_CONTEXT | ASN_CONSTRUCTOR | 1,
5602 offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5603 CRYPT_AsnDecodeExcludedSubtree,
5604 FINALMEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5605 TRUE, TRUE,
5606 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree), 0 },
5609 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5610 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
5611 pcbStructInfo, NULL, NULL);
5613 __EXCEPT_PAGE_FAULT
5615 SetLastError(STATUS_ACCESS_VIOLATION);
5617 __ENDTRY
5618 return ret;
5621 static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded,
5622 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5623 DWORD *pcbDecoded)
5625 BOOL ret;
5626 struct AsnDecodeSequenceItem items[] = {
5627 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
5628 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
5629 Issuer.pbData) },
5630 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
5631 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
5632 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
5634 CERT_ISSUER_SERIAL_NUMBER *issuerSerial = pvStructInfo;
5636 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
5637 pvStructInfo, *pcbStructInfo, pcbDecoded);
5639 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5640 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5641 pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL);
5642 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
5644 SetLastError(CRYPT_E_ASN1_CORRUPT);
5645 ret = FALSE;
5647 TRACE("returning %d\n", ret);
5648 return ret;
5651 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
5652 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5653 DWORD *pcbDecoded)
5655 CMSG_SIGNER_INFO *info = pvStructInfo;
5656 struct AsnDecodeSequenceItem items[] = {
5657 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
5658 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5659 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
5660 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
5661 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
5662 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
5663 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5664 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
5665 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5666 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
5667 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5668 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
5669 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
5670 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5671 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
5672 HashEncryptionAlgorithm.pszObjId), 0 },
5673 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
5674 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB),
5675 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
5676 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5677 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
5678 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5679 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
5681 BOOL ret;
5683 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
5684 pvStructInfo, *pcbStructInfo);
5686 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5687 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5688 pcbDecoded, info ? info->Issuer.pbData : NULL);
5689 return ret;
5692 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
5693 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5694 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5696 BOOL ret = FALSE;
5698 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
5699 pDecodePara, pvStructInfo, *pcbStructInfo);
5701 __TRY
5703 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
5704 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
5705 if (ret && pvStructInfo)
5707 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
5708 pcbStructInfo, *pcbStructInfo);
5709 if (ret)
5711 CMSG_SIGNER_INFO *info;
5713 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5714 pvStructInfo = *(BYTE **)pvStructInfo;
5715 info = pvStructInfo;
5716 info->Issuer.pbData = ((BYTE *)info +
5717 sizeof(CMSG_SIGNER_INFO));
5718 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
5719 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5720 pcbStructInfo, NULL);
5721 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5722 CRYPT_FreeSpace(pDecodePara, info);
5726 __EXCEPT_PAGE_FAULT
5728 SetLastError(STATUS_ACCESS_VIOLATION);
5730 __ENDTRY
5731 TRACE("returning %d\n", ret);
5732 return ret;
5735 static BOOL verify_and_copy_certificate(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5736 void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5738 PCCERT_CONTEXT cert;
5740 cert = CertCreateCertificateContext(X509_ASN_ENCODING, pbEncoded, cbEncoded);
5741 if (!cert)
5743 WARN("CertCreateCertificateContext error %#lx\n", GetLastError());
5744 *pcbStructInfo = 0;
5745 *pcbDecoded = 0;
5746 return TRUE;
5749 CertFreeCertificateContext(cert);
5751 return CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo, pcbDecoded);
5754 static BOOL CRYPT_AsnDecodeCMSCertEncoded(const BYTE *pbEncoded,
5755 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5756 DWORD *pcbDecoded)
5758 BOOL ret;
5759 struct AsnArrayDescriptor arrayDesc = { 0,
5760 offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
5761 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded),
5762 MEMBERSIZE(CRYPT_SIGNED_INFO, cCertEncoded, cCrlEncoded),
5763 verify_and_copy_certificate,
5764 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
5766 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
5767 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
5769 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5770 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5771 return ret;
5774 static BOOL CRYPT_AsnDecodeCMSCrlEncoded(const BYTE *pbEncoded,
5775 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5776 DWORD *pcbDecoded)
5778 BOOL ret;
5779 struct AsnArrayDescriptor arrayDesc = { 0,
5780 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded),
5781 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded),
5782 MEMBERSIZE(CRYPT_SIGNED_INFO, cCrlEncoded, content),
5783 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_DER_BLOB),
5784 TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
5786 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
5787 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
5789 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5790 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5791 return ret;
5794 static BOOL CRYPT_AsnDecodeCMSSignerId(const BYTE *pbEncoded,
5795 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5796 DWORD *pcbDecoded)
5798 CERT_ID *id = pvStructInfo;
5799 BOOL ret = FALSE;
5801 if (*pbEncoded == ASN_SEQUENCEOF)
5803 ret = CRYPT_AsnDecodeIssuerSerialNumber(pbEncoded, cbEncoded, dwFlags,
5804 id ? &id->u.IssuerSerialNumber : NULL, pcbStructInfo, pcbDecoded);
5805 if (ret)
5807 if (id)
5808 id->dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
5809 if (*pcbStructInfo > sizeof(CERT_ISSUER_SERIAL_NUMBER))
5810 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
5811 sizeof(CERT_ISSUER_SERIAL_NUMBER);
5812 else
5813 *pcbStructInfo = sizeof(CERT_ID);
5816 else if (*pbEncoded == (ASN_CONTEXT | 0))
5818 ret = CRYPT_AsnDecodeOctets(pbEncoded, cbEncoded, dwFlags,
5819 id ? &id->u.KeyId : NULL, pcbStructInfo, pcbDecoded);
5820 if (ret)
5822 if (id)
5823 id->dwIdChoice = CERT_ID_KEY_IDENTIFIER;
5824 if (*pcbStructInfo > sizeof(CRYPT_DATA_BLOB))
5825 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
5826 sizeof(CRYPT_DATA_BLOB);
5827 else
5828 *pcbStructInfo = sizeof(CERT_ID);
5831 else
5832 SetLastError(CRYPT_E_ASN1_BADTAG);
5833 return ret;
5836 static BOOL CRYPT_AsnDecodeCMSSignerInfoInternal(const BYTE *pbEncoded,
5837 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5838 DWORD *pcbDecoded)
5840 CMSG_CMS_SIGNER_INFO *info = pvStructInfo;
5841 struct AsnDecodeSequenceItem items[] = {
5842 { ASN_INTEGER, offsetof(CMSG_CMS_SIGNER_INFO, dwVersion),
5843 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5844 { 0, offsetof(CMSG_CMS_SIGNER_INFO, SignerId),
5845 CRYPT_AsnDecodeCMSSignerId, sizeof(CERT_ID), FALSE, TRUE,
5846 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData), 0 },
5847 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm),
5848 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5849 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
5850 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5851 offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs),
5852 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5853 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
5854 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashEncryptionAlgorithm),
5855 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5856 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO,
5857 HashEncryptionAlgorithm.pszObjId), 0 },
5858 { ASN_OCTETSTRING, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash),
5859 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB),
5860 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash.pbData), 0 },
5861 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5862 offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs),
5863 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5864 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
5866 BOOL ret;
5868 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
5869 pvStructInfo, *pcbStructInfo);
5871 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5872 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5873 pcbDecoded, info ? info->SignerId.u.KeyId.pbData : NULL);
5874 return ret;
5877 static BOOL WINAPI CRYPT_AsnDecodeCMSSignerInfo(DWORD dwCertEncodingType,
5878 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5879 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5881 BOOL ret = FALSE;
5883 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
5884 pDecodePara, pvStructInfo, *pcbStructInfo);
5886 __TRY
5888 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded, cbEncoded,
5889 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
5890 if (ret && pvStructInfo)
5892 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
5893 pcbStructInfo, *pcbStructInfo);
5894 if (ret)
5896 CMSG_CMS_SIGNER_INFO *info;
5898 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5899 pvStructInfo = *(BYTE **)pvStructInfo;
5900 info = pvStructInfo;
5901 info->SignerId.u.KeyId.pbData = ((BYTE *)info +
5902 sizeof(CMSG_CMS_SIGNER_INFO));
5903 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded,
5904 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5905 pcbStructInfo, NULL);
5906 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5907 CRYPT_FreeSpace(pDecodePara, info);
5911 __EXCEPT_PAGE_FAULT
5913 SetLastError(STATUS_ACCESS_VIOLATION);
5915 __ENDTRY
5916 TRACE("returning %d\n", ret);
5917 return ret;
5920 static BOOL CRYPT_DecodeSignerArray(const BYTE *pbEncoded, DWORD cbEncoded,
5921 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5923 BOOL ret;
5924 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
5925 offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
5926 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo),
5927 FINALMEMBERSIZE(CRYPT_SIGNED_INFO, cSignerInfo),
5928 CRYPT_AsnDecodeCMSSignerInfoInternal, sizeof(CMSG_CMS_SIGNER_INFO), TRUE,
5929 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData) };
5931 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
5932 pvStructInfo, *pcbStructInfo, pcbDecoded);
5934 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5935 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5936 return ret;
5939 BOOL CRYPT_AsnDecodeCMSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
5940 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
5941 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
5943 BOOL ret = FALSE;
5944 struct AsnDecodeSequenceItem items[] = {
5945 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version),
5946 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5947 /* Placeholder for the hash algorithms - redundant with those in the
5948 * signers, so just ignore them.
5950 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
5951 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
5952 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
5953 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
5954 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5955 offsetof(CRYPT_SIGNED_INFO, cCertEncoded), CRYPT_AsnDecodeCMSCertEncoded,
5956 MEMBERSIZE(CRYPT_SIGNED_INFO, cCertEncoded, cCrlEncoded), TRUE, TRUE,
5957 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
5958 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5959 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_AsnDecodeCMSCrlEncoded,
5960 MEMBERSIZE(CRYPT_SIGNED_INFO, cCrlEncoded, content), TRUE, TRUE,
5961 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
5962 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
5963 CRYPT_DecodeSignerArray,
5964 FINALMEMBERSIZE(CRYPT_SIGNED_INFO, cSignerInfo), TRUE, TRUE,
5965 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
5968 TRACE("%p, %ld, %08lx, %p, %p, %p\n", pbEncoded, cbEncoded, dwFlags,
5969 pDecodePara, signedInfo, pcbSignedInfo);
5971 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5972 pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo,
5973 NULL, NULL);
5974 TRACE("returning %d\n", ret);
5975 return ret;
5978 static BOOL CRYPT_AsnDecodeRecipientInfo(const BYTE *pbEncoded, DWORD cbEncoded,
5979 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5981 BOOL ret;
5982 CMSG_KEY_TRANS_RECIPIENT_INFO *info = pvStructInfo;
5983 struct AsnDecodeSequenceItem items[] = {
5984 { ASN_INTEGER, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, dwVersion),
5985 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5986 { ASN_SEQUENCEOF, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
5987 RecipientId.u.IssuerSerialNumber), CRYPT_AsnDecodeIssuerSerialNumber,
5988 sizeof(CERT_ISSUER_SERIAL_NUMBER), FALSE, TRUE,
5989 offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
5990 RecipientId.u.IssuerSerialNumber.Issuer.pbData), 0 },
5991 { ASN_SEQUENCEOF, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
5992 KeyEncryptionAlgorithm), CRYPT_AsnDecodeAlgorithmId,
5993 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
5994 offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
5995 KeyEncryptionAlgorithm.pszObjId), 0 },
5996 { ASN_OCTETSTRING, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, EncryptedKey),
5997 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE,
5998 offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, EncryptedKey.pbData), 0 },
6001 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
6002 pvStructInfo, *pcbStructInfo, pcbDecoded);
6004 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
6005 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
6006 pcbDecoded, info ? info->RecipientId.u.IssuerSerialNumber.Issuer.pbData :
6007 NULL);
6008 if (info)
6009 info->RecipientId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6010 TRACE("returning %d\n", ret);
6011 return ret;
6014 static BOOL CRYPT_DecodeRecipientInfoArray(const BYTE *pbEncoded,
6015 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6016 DWORD *pcbDecoded)
6018 BOOL ret;
6019 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
6020 offsetof(CRYPT_ENVELOPED_DATA, cRecipientInfo),
6021 offsetof(CRYPT_ENVELOPED_DATA, rgRecipientInfo),
6022 MEMBERSIZE(CRYPT_ENVELOPED_DATA, cRecipientInfo, encryptedContentInfo),
6023 CRYPT_AsnDecodeRecipientInfo, sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO), TRUE,
6024 offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
6025 RecipientId.u.IssuerSerialNumber.Issuer.pbData) };
6027 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
6028 pvStructInfo, *pcbStructInfo, pcbDecoded);
6030 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
6031 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
6032 TRACE("returning %d\n", ret);
6033 return ret;
6036 static BOOL CRYPT_AsnDecodeEncryptedContentInfo(const BYTE *pbEncoded,
6037 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6038 DWORD *pcbDecoded)
6040 BOOL ret;
6041 CRYPT_ENCRYPTED_CONTENT_INFO *info = pvStructInfo;
6042 struct AsnDecodeSequenceItem items[] = {
6043 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
6044 contentType), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
6045 FALSE, TRUE, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
6046 contentType), 0 },
6047 { ASN_SEQUENCEOF, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
6048 contentEncryptionAlgorithm), CRYPT_AsnDecodeAlgorithmId,
6049 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
6050 offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
6051 contentEncryptionAlgorithm.pszObjId), 0 },
6052 { ASN_CONTEXT | 0, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
6053 encryptedContent), CRYPT_AsnDecodeOctets,
6054 sizeof(CRYPT_DATA_BLOB), TRUE, TRUE,
6055 offsetof(CRYPT_ENCRYPTED_CONTENT_INFO, encryptedContent.pbData) },
6058 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
6059 pvStructInfo, *pcbStructInfo, pcbDecoded);
6061 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
6062 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
6063 pcbDecoded, info ? info->contentType : NULL);
6064 TRACE("returning %d\n", ret);
6065 return ret;
6068 BOOL CRYPT_AsnDecodePKCSEnvelopedData(const BYTE *pbEncoded, DWORD cbEncoded,
6069 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
6070 CRYPT_ENVELOPED_DATA *envelopedData, DWORD *pcbEnvelopedData)
6072 BOOL ret;
6073 struct AsnDecodeSequenceItem items[] = {
6074 { ASN_INTEGER, offsetof(CRYPT_ENVELOPED_DATA, version),
6075 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
6076 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ENVELOPED_DATA,
6077 cRecipientInfo), CRYPT_DecodeRecipientInfoArray,
6078 MEMBERSIZE(CRYPT_ENVELOPED_DATA, cRecipientInfo, encryptedContentInfo),
6079 FALSE, TRUE, offsetof(CRYPT_ENVELOPED_DATA, rgRecipientInfo), 0 },
6080 { ASN_SEQUENCEOF, offsetof(CRYPT_ENVELOPED_DATA, encryptedContentInfo),
6081 CRYPT_AsnDecodeEncryptedContentInfo,
6082 sizeof(CRYPT_ENCRYPTED_CONTENT_INFO), FALSE, TRUE,
6083 offsetof(CRYPT_ENVELOPED_DATA, encryptedContentInfo.contentType), 0 },
6086 TRACE("%p, %ld, %08lx, %p, %p, %p\n", pbEncoded, cbEncoded, dwFlags,
6087 pDecodePara, envelopedData, pcbEnvelopedData);
6089 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
6090 pbEncoded, cbEncoded, dwFlags, pDecodePara, envelopedData,
6091 pcbEnvelopedData, NULL, NULL);
6092 TRACE("returning %d\n", ret);
6093 return ret;
6096 static BOOL WINAPI CRYPT_AsnDecodeObjectIdentifier(DWORD dwCertEncodingType,
6097 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
6098 CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
6100 DWORD bytesNeeded = 0;
6101 BOOL ret;
6103 __TRY
6105 ret = CRYPT_AsnDecodeOidInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
6106 NULL, &bytesNeeded, NULL);
6107 if (ret)
6109 if (!pvStructInfo)
6110 *pcbStructInfo = bytesNeeded;
6111 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
6113 LPSTR *info;
6115 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
6116 pvStructInfo = *(BYTE **)pvStructInfo;
6118 info = pvStructInfo;
6119 *info = (void *)((BYTE *)info + sizeof(*info));
6120 ret = CRYPT_AsnDecodeOidInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
6121 pvStructInfo, &bytesNeeded, NULL);
6122 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
6123 CRYPT_FreeSpace(pDecodePara, info);
6127 __EXCEPT_PAGE_FAULT
6129 SetLastError(STATUS_ACCESS_VIOLATION);
6130 ret = FALSE;
6132 __ENDTRY
6133 return ret;
6136 static BOOL WINAPI CRYPT_AsnDecodeEccSignature(DWORD dwCertEncodingType,
6137 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
6138 CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
6140 BOOL ret;
6141 struct AsnDecodeSequenceItem items[] = {
6142 { ASN_INTEGER, offsetof(CERT_ECC_SIGNATURE, r),
6143 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_UINT_BLOB), FALSE,
6144 TRUE, offsetof(CERT_ECC_SIGNATURE, r.pbData), 0 },
6145 { ASN_INTEGER, offsetof(CERT_ECC_SIGNATURE, s),
6146 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_UINT_BLOB), FALSE,
6147 TRUE, offsetof(CERT_ECC_SIGNATURE, s.pbData), 0 },
6150 __TRY
6152 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
6153 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
6154 pcbStructInfo, NULL, NULL);
6156 __EXCEPT_PAGE_FAULT
6158 SetLastError(STATUS_ACCESS_VIOLATION);
6159 ret = FALSE;
6161 __ENDTRY
6162 return ret;
6165 static BOOL CRYPT_AsnDecodeOCSPResponseStatus(const BYTE *pbEncoded,
6166 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6167 DWORD *pcbDecoded)
6169 if (!cbEncoded)
6171 SetLastError(CRYPT_E_ASN1_EOD);
6172 return FALSE;
6174 if (pbEncoded[0] != ASN_ENUMERATED)
6176 SetLastError(CRYPT_E_ASN1_BADTAG);
6177 return FALSE;
6180 return CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
6181 pcbStructInfo, pcbDecoded);
6184 static BOOL CRYPT_AsnDecodeOCSPResponseBytes(const BYTE *pbEncoded,
6185 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6186 DWORD *pcbDecoded)
6188 DWORD dataLen;
6189 BOOL ret;
6191 if (!cbEncoded)
6193 SetLastError(CRYPT_E_ASN1_EOD);
6194 return FALSE;
6196 if (pbEncoded[0] != (ASN_CONTEXT | ASN_CONSTRUCTOR))
6198 SetLastError(CRYPT_E_ASN1_BADTAG);
6199 return FALSE;
6202 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
6204 struct AsnDecodeSequenceItem items[] = {
6205 { ASN_OBJECTIDENTIFIER, 0,
6206 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
6207 0, 0 },
6208 { ASN_OCTETSTRING, sizeof(LPSTR),
6209 CRYPT_AsnDecodeOctets, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
6210 sizeof(LPSTR) + offsetof(CRYPT_OBJID_BLOB, pbData), 0 },
6212 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
6213 DWORD bytesNeeded;
6215 if (dataLen)
6217 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
6218 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes, dwFlags, NULL,
6219 pvStructInfo, pcbStructInfo, &bytesNeeded, NULL);
6220 if (ret) *pcbDecoded = bytesNeeded + lenBytes + 1;
6223 return ret;
6226 static BOOL WINAPI CRYPT_AsnDecodeOCSPResponse(DWORD dwCertEncodingType,
6227 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
6228 CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
6230 BOOL ret;
6231 struct AsnDecodeSequenceItem items[] = {
6232 { ASN_ENUMERATED, offsetof(OCSP_RESPONSE_INFO, dwStatus),
6233 CRYPT_AsnDecodeOCSPResponseStatus, sizeof(DWORD), FALSE, FALSE,
6234 0, 0 },
6235 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(OCSP_RESPONSE_INFO, pszObjId),
6236 CRYPT_AsnDecodeOCSPResponseBytes, sizeof(LPSTR) + sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
6237 offsetof(OCSP_RESPONSE_INFO, pszObjId), 0 },
6240 __TRY
6242 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
6243 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
6244 pcbStructInfo, NULL, NULL);
6246 __EXCEPT_PAGE_FAULT
6248 SetLastError(STATUS_ACCESS_VIOLATION);
6249 ret = FALSE;
6251 __ENDTRY
6252 return ret;
6255 static BOOL CRYPT_AsnDecodeOCSPSignatureInfoCertEncoded(const BYTE *pbEncoded,
6256 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6257 DWORD *pcbDecoded)
6259 BOOL ret;
6260 struct AsnArrayDescriptor arrayDesc = { 0,
6261 offsetof(OCSP_SIGNATURE_INFO, cCertEncoded), offsetof(OCSP_SIGNATURE_INFO, rgCertEncoded),
6262 FINALMEMBERSIZE(OCSP_SIGNATURE_INFO, cCertEncoded), verify_and_copy_certificate,
6263 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
6265 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
6266 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
6267 return ret;
6270 static BOOL WINAPI CRYPT_AsnDecodeOCSPBasicSignedResponse(DWORD dwCertEncodingType,
6271 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
6272 CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
6274 BOOL ret;
6275 struct AsnDecodeSequenceItem items[] = {
6276 { 0, offsetof(OCSP_BASIC_SIGNED_RESPONSE_INFO, ToBeSigned),
6277 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
6278 offsetof(OCSP_BASIC_SIGNED_RESPONSE_INFO, ToBeSigned.pbData), 0 },
6279 { ASN_SEQUENCEOF, offsetof(OCSP_BASIC_SIGNED_RESPONSE_INFO, SignatureInfo.SignatureAlgorithm),
6280 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
6281 offsetof(OCSP_BASIC_SIGNED_RESPONSE_INFO, SignatureInfo.SignatureAlgorithm.pszObjId), 0 },
6282 { ASN_BITSTRING, offsetof(OCSP_BASIC_SIGNED_RESPONSE_INFO, SignatureInfo.Signature),
6283 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
6284 offsetof(OCSP_BASIC_SIGNED_RESPONSE_INFO, SignatureInfo.Signature.pbData) },
6285 { 0, offsetof(OCSP_BASIC_SIGNED_RESPONSE_INFO, SignatureInfo.cCertEncoded),
6286 CRYPT_AsnDecodeOCSPSignatureInfoCertEncoded, FINALMEMBERSIZE(OCSP_SIGNATURE_INFO, cCertEncoded),
6287 TRUE, TRUE, offsetof(OCSP_BASIC_SIGNED_RESPONSE_INFO, SignatureInfo.rgCertEncoded) },
6290 __TRY
6292 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
6293 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
6294 pcbStructInfo, NULL, NULL);
6296 __EXCEPT_PAGE_FAULT
6298 SetLastError(STATUS_ACCESS_VIOLATION);
6299 ret = FALSE;
6301 __ENDTRY
6302 return ret;
6305 static BOOL CRYPT_AsnDecodeOCSPHashAlgorithm(const BYTE *pbEncoded,
6306 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6307 DWORD *pcbDecoded)
6309 DWORD dataLen;
6310 BOOL ret;
6312 if (!cbEncoded)
6314 SetLastError(CRYPT_E_ASN1_EOD);
6315 return FALSE;
6317 if (pbEncoded[0] != ASN_SEQUENCEOF)
6319 SetLastError(CRYPT_E_ASN1_BADTAG);
6320 return FALSE;
6323 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
6325 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
6326 DWORD bytesDecoded;
6327 if (dataLen)
6329 ret = CRYPT_AsnDecodeAlgorithmId(pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes, dwFlags,
6330 pvStructInfo, pcbStructInfo, &bytesDecoded);
6331 if (ret) *pcbDecoded = bytesDecoded + lenBytes + 1;
6334 return ret;
6337 static BOOL CRYPT_AsnDecodeOCSPNextUpdate(const BYTE *pbEncoded,
6338 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6339 DWORD *pcbDecoded)
6341 DWORD dataLen;
6342 BOOL ret;
6344 if (!cbEncoded)
6346 SetLastError(CRYPT_E_ASN1_EOD);
6347 return FALSE;
6349 if (pbEncoded[0] != (ASN_CONTEXT | ASN_CONSTRUCTOR))
6351 SetLastError(CRYPT_E_ASN1_BADTAG);
6352 return FALSE;
6355 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
6357 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
6358 DWORD bytesDecoded;
6359 if (dataLen)
6361 ret = CRYPT_AsnDecodeGeneralizedTime(pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes, dwFlags,
6362 pvStructInfo, pcbStructInfo, &bytesDecoded);
6363 if (ret) *pcbDecoded = bytesDecoded + lenBytes + 1;
6366 return ret;
6369 static BOOL CRYPT_AsnDecodeCertStatus(const BYTE *pbEncoded,
6370 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6371 DWORD *pcbDecoded)
6373 BOOL ret = TRUE;
6374 BYTE tag = pbEncoded[0] & ~3, status = pbEncoded[0] & 3;
6375 DWORD bytesNeeded = FIELD_OFFSET(OCSP_BASIC_RESPONSE_ENTRY, ThisUpdate) -
6376 FIELD_OFFSET(OCSP_BASIC_RESPONSE_ENTRY, dwCertStatus);
6378 if (!cbEncoded)
6380 SetLastError(CRYPT_E_ASN1_EOD);
6381 return FALSE;
6384 switch (status)
6386 case 0:
6387 if (tag != ASN_CONTEXT)
6389 WARN("Unexpected tag %02x\n", tag);
6390 SetLastError(CRYPT_E_ASN1_BADTAG);
6391 return FALSE;
6393 if (cbEncoded < 2 || pbEncoded[1])
6395 SetLastError(CRYPT_E_ASN1_CORRUPT);
6396 return FALSE;
6398 if (!pvStructInfo)
6399 *pcbStructInfo = bytesNeeded;
6400 else if (*pcbStructInfo < bytesNeeded)
6402 *pcbStructInfo = bytesNeeded;
6403 SetLastError(ERROR_MORE_DATA);
6404 return FALSE;
6406 if (pvStructInfo)
6408 *(DWORD *)pvStructInfo = 0;
6409 *(OCSP_BASIC_REVOKED_INFO **)((char *)pvStructInfo
6410 + FIELD_OFFSET(OCSP_BASIC_RESPONSE_ENTRY, u.pRevokedInfo)
6411 - FIELD_OFFSET(OCSP_BASIC_RESPONSE_ENTRY, dwCertStatus)) = NULL;
6413 *pcbStructInfo = bytesNeeded;
6414 *pcbDecoded = 2;
6415 break;
6417 case 1:
6419 DWORD dataLen;
6421 if (tag != (ASN_CONTEXT | ASN_CONSTRUCTOR))
6423 WARN("Unexpected tag %02x\n", tag);
6424 SetLastError(CRYPT_E_ASN1_BADTAG);
6425 return FALSE;
6427 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
6429 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
6430 DWORD bytesDecoded, size;
6431 FILETIME date;
6433 if (dataLen)
6435 size = sizeof(date);
6436 ret = CRYPT_AsnDecodeGeneralizedTime(pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
6437 dwFlags, &date, &size, &bytesDecoded);
6438 if (ret)
6440 OCSP_BASIC_REVOKED_INFO *info;
6442 bytesNeeded += sizeof(*info);
6443 if (!pvStructInfo)
6444 *pcbStructInfo = bytesNeeded;
6445 else if (*pcbStructInfo < bytesNeeded)
6447 *pcbStructInfo = bytesNeeded;
6448 SetLastError(ERROR_MORE_DATA);
6449 return FALSE;
6451 if (pvStructInfo)
6453 *(DWORD *)pvStructInfo = 1;
6454 info = *(OCSP_BASIC_REVOKED_INFO **)((char *)pvStructInfo
6455 + FIELD_OFFSET(OCSP_BASIC_RESPONSE_ENTRY, u.pRevokedInfo)
6456 - FIELD_OFFSET(OCSP_BASIC_RESPONSE_ENTRY, dwCertStatus));
6457 info->RevocationDate = date;
6459 *pcbStructInfo = bytesNeeded;
6460 *pcbDecoded = 1 + lenBytes + bytesDecoded;
6464 break;
6466 default:
6467 FIXME("Unhandled status %u\n", status);
6468 SetLastError(CRYPT_E_ASN1_BADTAG);
6469 return FALSE;
6472 return ret;
6475 static BOOL CRYPT_AsnDecodeOCSPBasicResponseEntry(const BYTE *pbEncoded, DWORD cbEncoded,
6476 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
6478 struct AsnDecodeSequenceItem items[] = {
6479 { ASN_SEQUENCEOF, offsetof(OCSP_BASIC_RESPONSE_ENTRY, CertId.HashAlgorithm.pszObjId),
6480 CRYPT_AsnDecodeOCSPHashAlgorithm, sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
6481 offsetof(OCSP_BASIC_RESPONSE_ENTRY, CertId.HashAlgorithm.pszObjId), 0 },
6482 { ASN_OCTETSTRING, offsetof(OCSP_BASIC_RESPONSE_ENTRY, CertId.IssuerNameHash),
6483 CRYPT_AsnDecodeOctets, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
6484 offsetof(OCSP_BASIC_RESPONSE_ENTRY, CertId.IssuerNameHash.pbData), 0 },
6485 { ASN_OCTETSTRING, offsetof(OCSP_BASIC_RESPONSE_ENTRY, CertId.IssuerKeyHash),
6486 CRYPT_AsnDecodeOctets, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
6487 offsetof(OCSP_BASIC_RESPONSE_ENTRY, CertId.IssuerKeyHash.pbData), 0 },
6488 { ASN_INTEGER, offsetof(OCSP_BASIC_RESPONSE_ENTRY, CertId.SerialNumber),
6489 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
6490 offsetof(OCSP_BASIC_RESPONSE_ENTRY, CertId.SerialNumber.pbData), 0 },
6491 { 0, offsetof(OCSP_BASIC_RESPONSE_ENTRY, dwCertStatus),
6492 CRYPT_AsnDecodeCertStatus, sizeof(DWORD), FALSE, TRUE,
6493 offsetof(OCSP_BASIC_RESPONSE_ENTRY, u.pRevokedInfo), 0 },
6494 { ASN_GENERALTIME, offsetof(OCSP_BASIC_RESPONSE_ENTRY, ThisUpdate),
6495 CRYPT_AsnDecodeGeneralizedTime, sizeof(FILETIME), FALSE, FALSE,
6496 0, 0 },
6497 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(OCSP_BASIC_RESPONSE_ENTRY, NextUpdate),
6498 CRYPT_AsnDecodeOCSPNextUpdate, sizeof(FILETIME), TRUE, FALSE,
6499 0, 0 },
6500 { ASN_CONTEXT | ASN_CONSTRUCTOR /* FIXME */, offsetof(OCSP_BASIC_RESPONSE_ENTRY, cExtension),
6501 CRYPT_AsnDecodeCertExtensions, FINALMEMBERSIZE(OCSP_BASIC_RESPONSE_ENTRY, cExtension),
6502 TRUE, TRUE, offsetof(OCSP_BASIC_RESPONSE_ENTRY, rgExtension), 0 },
6505 return CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
6506 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo,
6507 pcbStructInfo, pcbDecoded, NULL);
6510 static BOOL CRYPT_AsnDecodeOCSPBasicResponseEntriesArray(const BYTE *pbEncoded,
6511 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6512 DWORD *pcbDecoded)
6514 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
6515 offsetof(OCSP_BASIC_RESPONSE_INFO, cResponseEntry), offsetof(OCSP_BASIC_RESPONSE_INFO, rgResponseEntry),
6516 MEMBERSIZE(OCSP_BASIC_RESPONSE_INFO, cResponseEntry, cExtension),
6517 CRYPT_AsnDecodeOCSPBasicResponseEntry, sizeof(OCSP_BASIC_RESPONSE_ENTRY),
6518 FALSE, 0 };
6520 return CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
6521 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
6524 static BOOL CRYPT_AsnDecodeResponderIDByName(const BYTE *pbEncoded,
6525 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6526 DWORD *pcbDecoded)
6528 OCSP_BASIC_RESPONSE_INFO *info = pvStructInfo;
6529 DWORD dataLen, decodedLen, lenBytes, bytesNeeded = sizeof(*info);
6530 BYTE tag = pbEncoded[0] & ~3;
6531 CERT_NAME_BLOB *blob;
6533 if (tag != (ASN_CONTEXT | ASN_CONSTRUCTOR))
6535 WARN("Unexpected tag %02x\n", tag);
6536 SetLastError(CRYPT_E_ASN1_BADTAG);
6537 return FALSE;
6540 if (!CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))
6541 return FALSE;
6542 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
6543 cbEncoded -= 1 + lenBytes;
6545 if (dataLen > cbEncoded)
6547 SetLastError(CRYPT_E_ASN1_EOD);
6548 return FALSE;
6550 pbEncoded += 1 + lenBytes;
6551 decodedLen = 1 + lenBytes + dataLen;
6553 if (pbEncoded[0] != ASN_SEQUENCE)
6555 WARN("Unexpected tag %02x %02x\n", pbEncoded[0], pbEncoded[1]);
6556 SetLastError(CRYPT_E_ASN1_BADTAG);
6557 return FALSE;
6560 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) bytesNeeded += dataLen;
6561 if (pvStructInfo && *pcbStructInfo >= bytesNeeded)
6563 info->dwResponderIdChoice = 1;
6565 blob = &info->u.ByNameResponderId;
6566 blob->cbData = dataLen;
6567 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
6568 blob->pbData = (BYTE *)pbEncoded;
6569 else if (blob->cbData)
6571 blob->pbData = (BYTE *)(info + 1);
6572 memcpy(blob->pbData, pbEncoded, blob->cbData);
6576 if (pcbDecoded)
6577 *pcbDecoded = decodedLen;
6579 if (!pvStructInfo)
6581 *pcbStructInfo = bytesNeeded;
6582 return TRUE;
6585 if (*pcbStructInfo < bytesNeeded)
6587 SetLastError(ERROR_MORE_DATA);
6588 *pcbStructInfo = bytesNeeded;
6589 return FALSE;
6592 *pcbStructInfo = bytesNeeded;
6593 return TRUE;
6596 static BOOL CRYPT_AsnDecodeResponderIDByKey(const BYTE *pbEncoded,
6597 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6598 DWORD *pcbDecoded)
6600 OCSP_BASIC_RESPONSE_INFO *info = pvStructInfo;
6601 DWORD dataLen, decodedLen, lenBytes, bytesNeeded = sizeof(*info), len;
6602 BYTE tag = pbEncoded[0] & ~3;
6603 CRYPT_HASH_BLOB *blob;
6605 if (tag != (ASN_CONTEXT | ASN_CONSTRUCTOR))
6607 WARN("Unexpected tag %02x\n", tag);
6608 SetLastError(CRYPT_E_ASN1_BADTAG);
6609 return FALSE;
6612 if (!CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))
6613 return FALSE;
6614 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
6615 cbEncoded -= 1 + lenBytes;
6616 decodedLen = 1 + lenBytes;
6618 if (dataLen > cbEncoded)
6620 SetLastError(CRYPT_E_ASN1_EOD);
6621 return FALSE;
6623 pbEncoded += 1 + lenBytes;
6624 if (pbEncoded[0] != ASN_OCTETSTRING)
6626 WARN("Unexpected tag %02x\n", pbEncoded[0]);
6627 SetLastError(CRYPT_E_ASN1_BADTAG);
6628 return FALSE;
6631 if (!CRYPT_GetLen(pbEncoded, cbEncoded, &len))
6632 return FALSE;
6633 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
6634 decodedLen += 1 + lenBytes + len;
6635 cbEncoded -= 1 + lenBytes;
6637 if (len > cbEncoded)
6639 SetLastError(CRYPT_E_ASN1_EOD);
6640 return FALSE;
6642 pbEncoded += 1 + lenBytes;
6644 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) bytesNeeded += len;
6645 if (pvStructInfo && *pcbStructInfo >= bytesNeeded)
6647 info->dwResponderIdChoice = 2;
6648 blob = &info->u.ByKeyResponderId;
6649 blob->cbData = len;
6650 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
6651 blob->pbData = (BYTE *)pbEncoded;
6652 else if (blob->cbData)
6654 blob->pbData = (BYTE *)(info + 1);
6655 memcpy(blob->pbData, pbEncoded, blob->cbData);
6659 if (pcbDecoded)
6660 *pcbDecoded = decodedLen;
6662 if (!pvStructInfo)
6664 *pcbStructInfo = bytesNeeded;
6665 return TRUE;
6668 if (*pcbStructInfo < bytesNeeded)
6670 SetLastError(ERROR_MORE_DATA);
6671 *pcbStructInfo = bytesNeeded;
6672 return FALSE;
6675 *pcbStructInfo = bytesNeeded;
6676 return TRUE;
6679 static BOOL CRYPT_AsnDecodeResponderID(const BYTE *pbEncoded,
6680 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6681 DWORD *pcbDecoded)
6683 BYTE choice = pbEncoded[0] & 3;
6685 TRACE("choice %02x\n", choice);
6686 switch (choice)
6688 case 1:
6689 return CRYPT_AsnDecodeResponderIDByName(pbEncoded, cbEncoded, dwFlags,
6690 pvStructInfo, pcbStructInfo, pcbDecoded);
6691 case 2:
6692 return CRYPT_AsnDecodeResponderIDByKey(pbEncoded, cbEncoded, dwFlags,
6693 pvStructInfo, pcbStructInfo, pcbDecoded);
6694 default:
6695 WARN("Unexpected choice %02x\n", choice);
6696 SetLastError(CRYPT_E_ASN1_CORRUPT);
6697 return FALSE;
6701 static BOOL WINAPI CRYPT_AsnDecodeOCSPBasicResponse(DWORD dwCertEncodingType,
6702 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
6703 CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
6705 struct AsnDecodeSequenceItem items[] = {
6706 { 0, 0,
6707 CRYPT_AsnDecodeResponderID, offsetof(OCSP_BASIC_RESPONSE_INFO, ProducedAt), FALSE, TRUE,
6708 offsetof(OCSP_BASIC_RESPONSE_INFO, u.ByNameResponderId.pbData), 0 },
6709 { ASN_GENERALTIME, offsetof(OCSP_BASIC_RESPONSE_INFO, ProducedAt),
6710 CRYPT_AsnDecodeGeneralizedTime, sizeof(FILETIME), FALSE, FALSE,
6711 0, 0 },
6712 { ASN_SEQUENCEOF, offsetof(OCSP_BASIC_RESPONSE_INFO, cResponseEntry),
6713 CRYPT_AsnDecodeOCSPBasicResponseEntriesArray, MEMBERSIZE(OCSP_BASIC_RESPONSE_INFO, cResponseEntry, cExtension),
6714 TRUE, TRUE, offsetof(OCSP_BASIC_RESPONSE_INFO, rgResponseEntry) },
6715 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(OCSP_BASIC_RESPONSE_INFO, cExtension),
6716 CRYPT_AsnDecodeCertExtensions, FINALMEMBERSIZE(OCSP_BASIC_RESPONSE_INFO, cExtension),
6717 TRUE, TRUE, offsetof(OCSP_BASIC_RESPONSE_INFO, rgExtension), 0 },
6719 BOOL ret;
6721 __TRY
6723 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
6724 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
6725 pcbStructInfo, NULL, NULL);
6727 __EXCEPT_PAGE_FAULT
6729 SetLastError(STATUS_ACCESS_VIOLATION);
6730 ret = FALSE;
6732 __ENDTRY
6733 return ret;
6736 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
6737 LPCSTR lpszStructType)
6739 CryptDecodeObjectExFunc decodeFunc = NULL;
6741 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
6742 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
6744 SetLastError(ERROR_FILE_NOT_FOUND);
6745 return NULL;
6747 if (IS_INTOID(lpszStructType))
6749 switch (LOWORD(lpszStructType))
6751 case LOWORD(X509_CERT):
6752 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
6753 break;
6754 case LOWORD(X509_CERT_TO_BE_SIGNED):
6755 decodeFunc = CRYPT_AsnDecodeCert;
6756 break;
6757 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
6758 decodeFunc = CRYPT_AsnDecodeCRL;
6759 break;
6760 case LOWORD(X509_EXTENSIONS):
6761 decodeFunc = CRYPT_AsnDecodeExtensions;
6762 break;
6763 case LOWORD(X509_NAME_VALUE):
6764 decodeFunc = CRYPT_AsnDecodeNameValue;
6765 break;
6766 case LOWORD(X509_NAME):
6767 decodeFunc = CRYPT_AsnDecodeName;
6768 break;
6769 case LOWORD(X509_PUBLIC_KEY_INFO):
6770 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
6771 break;
6772 case LOWORD(X509_AUTHORITY_KEY_ID):
6773 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
6774 break;
6775 case LOWORD(X509_ALTERNATE_NAME):
6776 decodeFunc = CRYPT_AsnDecodeAltName;
6777 break;
6778 case LOWORD(X509_BASIC_CONSTRAINTS):
6779 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
6780 break;
6781 case LOWORD(X509_BASIC_CONSTRAINTS2):
6782 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
6783 break;
6784 case LOWORD(X509_CERT_POLICIES):
6785 decodeFunc = CRYPT_AsnDecodeCertPolicies;
6786 break;
6787 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
6788 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
6789 break;
6790 case LOWORD(PKCS_RSA_PRIVATE_KEY):
6791 decodeFunc = CRYPT_AsnDecodeRsaPrivKey;
6792 break;
6793 case LOWORD(X509_UNICODE_NAME):
6794 decodeFunc = CRYPT_AsnDecodeUnicodeName;
6795 break;
6796 case LOWORD(PKCS_ATTRIBUTE):
6797 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
6798 break;
6799 case LOWORD(X509_UNICODE_NAME_VALUE):
6800 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
6801 break;
6802 case LOWORD(X509_OCTET_STRING):
6803 decodeFunc = CRYPT_AsnDecodeOctetString;
6804 break;
6805 case LOWORD(X509_BITS):
6806 case LOWORD(X509_KEY_USAGE):
6807 decodeFunc = CRYPT_AsnDecodeBits;
6808 break;
6809 case LOWORD(X509_INTEGER):
6810 decodeFunc = CRYPT_AsnDecodeInt;
6811 break;
6812 case LOWORD(X509_MULTI_BYTE_INTEGER):
6813 decodeFunc = CRYPT_AsnDecodeInteger;
6814 break;
6815 case LOWORD(X509_MULTI_BYTE_UINT):
6816 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
6817 break;
6818 case LOWORD(X509_ENUMERATED):
6819 decodeFunc = CRYPT_AsnDecodeEnumerated;
6820 break;
6821 case LOWORD(X509_CHOICE_OF_TIME):
6822 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
6823 break;
6824 case LOWORD(X509_AUTHORITY_KEY_ID2):
6825 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
6826 break;
6827 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
6828 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
6829 break;
6830 case LOWORD(PKCS_CONTENT_INFO):
6831 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
6832 break;
6833 case LOWORD(X509_SEQUENCE_OF_ANY):
6834 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
6835 break;
6836 case LOWORD(PKCS_UTC_TIME):
6837 decodeFunc = CRYPT_AsnDecodeUtcTime;
6838 break;
6839 case LOWORD(X509_CRL_DIST_POINTS):
6840 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
6841 break;
6842 case LOWORD(X509_ENHANCED_KEY_USAGE):
6843 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
6844 break;
6845 case LOWORD(PKCS_CTL):
6846 decodeFunc = CRYPT_AsnDecodeCTL;
6847 break;
6848 case LOWORD(PKCS_SMIME_CAPABILITIES):
6849 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
6850 break;
6851 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE):
6852 decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
6853 break;
6854 case LOWORD(PKCS_ATTRIBUTES):
6855 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
6856 break;
6857 case LOWORD(X509_ISSUING_DIST_POINT):
6858 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
6859 break;
6860 case LOWORD(X509_NAME_CONSTRAINTS):
6861 decodeFunc = CRYPT_AsnDecodeNameConstraints;
6862 break;
6863 case LOWORD(X509_POLICY_MAPPINGS):
6864 decodeFunc = CRYPT_AsnDecodeCertPolicyMappings;
6865 break;
6866 case LOWORD(X509_POLICY_CONSTRAINTS):
6867 decodeFunc = CRYPT_AsnDecodeCertPolicyConstraints;
6868 break;
6869 case LOWORD(PKCS7_SIGNER_INFO):
6870 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
6871 break;
6872 case LOWORD(CMS_SIGNER_INFO):
6873 decodeFunc = CRYPT_AsnDecodeCMSSignerInfo;
6874 break;
6875 case LOWORD(X509_OBJECT_IDENTIFIER):
6876 decodeFunc = CRYPT_AsnDecodeObjectIdentifier;
6877 break;
6878 case LOWORD(X509_ECC_SIGNATURE):
6879 decodeFunc = CRYPT_AsnDecodeEccSignature;
6880 break;
6881 case LOWORD(CNG_RSA_PUBLIC_KEY_BLOB):
6882 decodeFunc = CRYPT_AsnDecodeRsaPubKey_Bcrypt;
6883 break;
6884 case LOWORD(OCSP_RESPONSE):
6885 decodeFunc = CRYPT_AsnDecodeOCSPResponse;
6886 break;
6887 case LOWORD(OCSP_BASIC_SIGNED_RESPONSE):
6888 decodeFunc = CRYPT_AsnDecodeOCSPBasicSignedResponse;
6889 break;
6890 case LOWORD(OCSP_BASIC_RESPONSE):
6891 decodeFunc = CRYPT_AsnDecodeOCSPBasicResponse;
6892 break;
6893 default:
6894 break;
6897 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
6898 decodeFunc = CRYPT_AsnDecodeExtensions;
6899 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
6900 decodeFunc = CRYPT_AsnDecodeUtcTime;
6901 else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
6902 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
6903 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
6904 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
6905 else if (!strcmp(lpszStructType, szOID_LEGACY_POLICY_MAPPINGS))
6906 decodeFunc = CRYPT_AsnDecodeCertPolicyMappings;
6907 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
6908 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
6909 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
6910 decodeFunc = CRYPT_AsnDecodeEnumerated;
6911 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
6912 decodeFunc = CRYPT_AsnDecodeBits;
6913 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
6914 decodeFunc = CRYPT_AsnDecodeOctetString;
6915 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
6916 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
6917 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
6918 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
6919 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
6920 decodeFunc = CRYPT_AsnDecodeAltName;
6921 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
6922 decodeFunc = CRYPT_AsnDecodeAltName;
6923 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
6924 decodeFunc = CRYPT_AsnDecodeAltName;
6925 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
6926 decodeFunc = CRYPT_AsnDecodeAltName;
6927 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
6928 decodeFunc = CRYPT_AsnDecodeAltName;
6929 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
6930 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
6931 else if (!strcmp(lpszStructType, szOID_CERT_POLICIES))
6932 decodeFunc = CRYPT_AsnDecodeCertPolicies;
6933 else if (!strcmp(lpszStructType, szOID_POLICY_MAPPINGS))
6934 decodeFunc = CRYPT_AsnDecodeCertPolicyMappings;
6935 else if (!strcmp(lpszStructType, szOID_POLICY_CONSTRAINTS))
6936 decodeFunc = CRYPT_AsnDecodeCertPolicyConstraints;
6937 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
6938 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
6939 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
6940 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
6941 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
6942 decodeFunc = CRYPT_AsnDecodeNameConstraints;
6943 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
6944 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
6945 else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
6946 decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
6947 else if (!strcmp(lpszStructType, szOID_CTL))
6948 decodeFunc = CRYPT_AsnDecodeCTL;
6949 else if (!strcmp(lpszStructType, szOID_ECC_PUBLIC_KEY))
6950 decodeFunc = CRYPT_AsnDecodeObjectIdentifier;
6951 return decodeFunc;
6954 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
6955 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
6957 static HCRYPTOIDFUNCSET set = NULL;
6958 CryptDecodeObjectFunc decodeFunc = NULL;
6960 if (!set)
6961 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
6962 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
6963 (void **)&decodeFunc, hFunc);
6964 return decodeFunc;
6967 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
6968 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
6970 static HCRYPTOIDFUNCSET set = NULL;
6971 CryptDecodeObjectExFunc decodeFunc = NULL;
6973 if (!set)
6974 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
6975 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
6976 (void **)&decodeFunc, hFunc);
6977 return decodeFunc;
6980 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
6981 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
6982 DWORD *pcbStructInfo)
6984 return CryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
6985 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo);
6988 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
6989 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
6990 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
6992 BOOL ret = FALSE;
6993 CryptDecodeObjectExFunc decodeFunc;
6994 HCRYPTOIDFUNCADDR hFunc = NULL;
6996 TRACE_(crypt)("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p, %p)\n",
6997 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
6998 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
7000 if (!pvStructInfo && !pcbStructInfo)
7002 SetLastError(ERROR_INVALID_PARAMETER);
7003 return FALSE;
7005 if (cbEncoded > MAX_ENCODED_LEN)
7007 FIXME_(crypt)("Returning CRYPT_E_ASN1_LARGE, cbEncoded %lu.\n", cbEncoded);
7008 SetLastError(CRYPT_E_ASN1_LARGE);
7009 return FALSE;
7012 SetLastError(NOERROR);
7013 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
7015 if (!pvStructInfo)
7017 SetLastError(ERROR_INVALID_PARAMETER);
7018 return FALSE;
7020 *(BYTE **)pvStructInfo = NULL;
7022 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
7023 if (!decodeFunc)
7025 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
7026 debugstr_a(lpszStructType));
7027 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
7028 &hFunc);
7029 if (!decodeFunc)
7031 if (IS_INTOID(lpszStructType))
7032 FIXME("Unimplemented decoder for lpszStructType OID %d\n", LOWORD(lpszStructType));
7033 else
7034 FIXME("Unsupported decoder for lpszStructType %s\n", lpszStructType);
7037 if (decodeFunc)
7038 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
7039 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
7040 else
7042 CryptDecodeObjectFunc pCryptDecodeObject =
7043 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
7045 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
7046 * directly, as that could cause an infinite loop.
7048 if (pCryptDecodeObject)
7050 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
7052 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
7053 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
7054 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
7055 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
7057 ret = pCryptDecodeObject(dwCertEncodingType,
7058 lpszStructType, pbEncoded, cbEncoded, dwFlags,
7059 *(BYTE **)pvStructInfo, pcbStructInfo);
7060 if (!ret)
7061 CRYPT_FreeSpace(pDecodePara, *(BYTE **)pvStructInfo);
7064 else
7065 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
7066 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
7069 if (hFunc)
7070 CryptFreeOIDFunctionAddress(hFunc, 0);
7071 TRACE_(crypt)("returning %d\n", ret);
7072 return ret;
7075 BOOL WINAPI PFXIsPFXBlob(CRYPT_DATA_BLOB *pPFX)
7077 BOOL ret;
7079 TRACE_(crypt)("(%p)\n", pPFX);
7081 /* A PFX blob is an asn.1-encoded sequence, consisting of at least a
7082 * version integer of length 1 (3 encoded byes) and at least one other
7083 * datum (two encoded bytes), plus at least two bytes for the outer
7084 * sequence. Thus, even an empty PFX blob is at least 7 bytes in length.
7086 if (pPFX->cbData < 7)
7087 ret = FALSE;
7088 else if (pPFX->pbData[0] == ASN_SEQUENCE)
7090 DWORD len;
7092 if ((ret = CRYPT_GetLengthIndefinite(pPFX->pbData, pPFX->cbData, &len)))
7094 BYTE lenLen = GET_LEN_BYTES(pPFX->pbData[1]);
7096 /* Need at least three bytes for the integer version */
7097 if (pPFX->cbData < 1 + lenLen + 3)
7098 ret = FALSE;
7099 else if (pPFX->pbData[1 + lenLen] != ASN_INTEGER || /* Tag */
7100 pPFX->pbData[1 + lenLen + 1] != 1 || /* Definite length */
7101 pPFX->pbData[1 + lenLen + 2] != 3) /* PFX version */
7102 ret = FALSE;
7105 else
7106 ret = FALSE;
7107 return ret;