crypt32: Add partial support for decoding OCSP_BASIC_RESPONSE_INFO structures.
[wine.git] / dlls / crypt32 / decode.c
blob762d1b54661615202b3d6712793630dad86cfeaf
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 DWORD 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_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
3899 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
3900 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, decodedKey,
3901 size, NULL, NULL);
3902 return ret;
3905 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey_Bcrypt(DWORD dwCertEncodingType,
3906 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3907 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3909 BOOL ret;
3911 __TRY
3913 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
3914 DWORD size = 0;
3916 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
3917 pvStructInfo, *pcbStructInfo);
3919 ret = CRYPT_raw_decode_rsa_pub_key(&decodedKey, &size, pbEncoded, cbEncoded);
3920 if (ret)
3922 /* Header, exponent, and modulus */
3923 DWORD bytesNeeded = sizeof(BCRYPT_RSAKEY_BLOB) + sizeof(DWORD) +
3924 decodedKey->modulus.cbData;
3926 if (!pvStructInfo)
3928 *pcbStructInfo = bytesNeeded;
3929 ret = TRUE;
3931 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3932 pvStructInfo, pcbStructInfo, bytesNeeded)))
3934 BCRYPT_RSAKEY_BLOB *hdr;
3936 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3937 pvStructInfo = *(BYTE **)pvStructInfo;
3939 hdr = pvStructInfo;
3940 hdr->Magic = BCRYPT_RSAPUBLIC_MAGIC;
3941 hdr->BitLength = decodedKey->modulus.cbData * 8;
3942 hdr->cbPublicExp = sizeof(DWORD);
3943 hdr->cbModulus = decodedKey->modulus.cbData;
3944 hdr->cbPrime1 = 0;
3945 hdr->cbPrime2 = 0;
3946 /* CNG_RSA_PUBLIC_KEY_BLOB always stores the exponent and modulus
3947 * in big-endian format, so we need to convert from little-endian
3949 CRYPT_CopyReversed((BYTE *)pvStructInfo + sizeof(BCRYPT_RSAKEY_BLOB),
3950 (BYTE *)&decodedKey->pubexp, sizeof(DWORD));
3951 CRYPT_CopyReversed((BYTE *)pvStructInfo + sizeof(BCRYPT_RSAKEY_BLOB) +
3952 sizeof(DWORD), decodedKey->modulus.pbData,
3953 decodedKey->modulus.cbData);
3955 LocalFree(decodedKey);
3958 __EXCEPT_PAGE_FAULT
3960 SetLastError(STATUS_ACCESS_VIOLATION);
3961 ret = FALSE;
3963 __ENDTRY
3964 return ret;
3968 static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
3969 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
3970 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
3972 BOOL ret;
3974 __TRY
3976 struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
3977 DWORD size = 0;
3978 ret = CRYPT_raw_decode_rsa_pub_key(&decodedKey, &size, pbEncoded, cbEncoded);
3979 if (ret)
3981 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
3982 decodedKey->modulus.cbData;
3984 if (!pvStructInfo)
3986 *pcbStructInfo = bytesNeeded;
3987 ret = TRUE;
3989 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
3990 pvStructInfo, pcbStructInfo, bytesNeeded)))
3992 BLOBHEADER *hdr;
3993 RSAPUBKEY *rsaPubKey;
3995 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
3996 pvStructInfo = *(BYTE **)pvStructInfo;
3997 hdr = pvStructInfo;
3998 hdr->bType = PUBLICKEYBLOB;
3999 hdr->bVersion = CUR_BLOB_VERSION;
4000 hdr->reserved = 0;
4001 hdr->aiKeyAlg = CALG_RSA_KEYX;
4002 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
4003 sizeof(BLOBHEADER));
4004 rsaPubKey->magic = RSA1_MAGIC;
4005 rsaPubKey->pubexp = decodedKey->pubexp;
4006 rsaPubKey->bitlen = decodedKey->modulus.cbData * 8;
4007 memcpy((BYTE *)pvStructInfo + sizeof(BLOBHEADER) +
4008 sizeof(RSAPUBKEY), decodedKey->modulus.pbData,
4009 decodedKey->modulus.cbData);
4011 LocalFree(decodedKey);
4014 __EXCEPT_PAGE_FAULT
4016 SetLastError(STATUS_ACCESS_VIOLATION);
4017 ret = FALSE;
4019 __ENDTRY
4020 return ret;
4023 #define RSA2_MAGIC 0x32415352
4025 struct DECODED_RSA_PRIV_KEY
4027 DWORD version;
4028 DWORD pubexp;
4029 CRYPT_INTEGER_BLOB modulus;
4030 CRYPT_INTEGER_BLOB privexp;
4031 CRYPT_INTEGER_BLOB prime1;
4032 CRYPT_INTEGER_BLOB prime2;
4033 CRYPT_INTEGER_BLOB exponent1;
4034 CRYPT_INTEGER_BLOB exponent2;
4035 CRYPT_INTEGER_BLOB coefficient;
4038 static BOOL WINAPI CRYPT_AsnDecodeRsaPrivKey(DWORD dwCertEncodingType,
4039 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4040 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4042 BOOL ret;
4043 DWORD halflen;
4045 __TRY
4047 struct AsnDecodeSequenceItem items[] = {
4048 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, version),
4049 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4050 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, modulus),
4051 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
4052 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, modulus.pbData),
4053 0 },
4054 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, pubexp),
4055 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
4056 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, privexp),
4057 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
4058 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, privexp.pbData),
4059 0 },
4060 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, prime1),
4061 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
4062 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, prime1.pbData),
4063 0 },
4064 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, prime2),
4065 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
4066 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, prime2.pbData),
4067 0 },
4068 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, exponent1),
4069 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
4070 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, exponent1.pbData),
4071 0 },
4072 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, exponent2),
4073 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
4074 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, exponent2.pbData),
4075 0 },
4076 { ASN_INTEGER, offsetof(struct DECODED_RSA_PRIV_KEY, coefficient),
4077 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
4078 FALSE, TRUE, offsetof(struct DECODED_RSA_PRIV_KEY, coefficient.pbData),
4079 0 },
4081 struct DECODED_RSA_PRIV_KEY *decodedKey = NULL;
4082 DWORD size = 0;
4084 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
4085 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &decodedKey,
4086 &size, NULL, NULL);
4087 if (ret)
4089 halflen = decodedKey->prime1.cbData;
4090 if (halflen < decodedKey->prime2.cbData)
4091 halflen = decodedKey->prime2.cbData;
4092 if (halflen < decodedKey->exponent1.cbData)
4093 halflen = decodedKey->exponent1.cbData;
4094 if (halflen < decodedKey->exponent2.cbData)
4095 halflen = decodedKey->exponent2.cbData;
4096 if (halflen < decodedKey->coefficient.cbData)
4097 halflen = decodedKey->coefficient.cbData;
4098 if (halflen * 2 < decodedKey->modulus.cbData)
4099 halflen = decodedKey->modulus.cbData / 2 + decodedKey->modulus.cbData % 2;
4100 if (halflen * 2 < decodedKey->privexp.cbData)
4101 halflen = decodedKey->privexp.cbData / 2 + decodedKey->privexp.cbData % 2;
4103 if (ret)
4105 DWORD bytesNeeded = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
4106 (halflen * 9);
4108 if (!pvStructInfo)
4110 *pcbStructInfo = bytesNeeded;
4111 ret = TRUE;
4113 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4114 pvStructInfo, pcbStructInfo, bytesNeeded)))
4116 BLOBHEADER *hdr;
4117 RSAPUBKEY *rsaPubKey;
4118 BYTE *vardata;
4120 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4121 pvStructInfo = *(BYTE **)pvStructInfo;
4123 hdr = pvStructInfo;
4124 hdr->bType = PRIVATEKEYBLOB;
4125 hdr->bVersion = CUR_BLOB_VERSION;
4126 hdr->reserved = 0;
4127 hdr->aiKeyAlg = CALG_RSA_KEYX;
4129 rsaPubKey = (RSAPUBKEY *)((BYTE *)pvStructInfo +
4130 sizeof(BLOBHEADER));
4131 rsaPubKey->magic = RSA2_MAGIC;
4132 rsaPubKey->pubexp = decodedKey->pubexp;
4133 rsaPubKey->bitlen = halflen * 16;
4135 vardata = (BYTE*)(rsaPubKey + 1);
4136 memset(vardata, 0, halflen * 9);
4137 memcpy(vardata,
4138 decodedKey->modulus.pbData, decodedKey->modulus.cbData);
4139 memcpy(vardata + halflen * 2,
4140 decodedKey->prime1.pbData, decodedKey->prime1.cbData);
4141 memcpy(vardata + halflen * 3,
4142 decodedKey->prime2.pbData, decodedKey->prime2.cbData);
4143 memcpy(vardata + halflen * 4,
4144 decodedKey->exponent1.pbData, decodedKey->exponent1.cbData);
4145 memcpy(vardata + halflen * 5,
4146 decodedKey->exponent2.pbData, decodedKey->exponent2.cbData);
4147 memcpy(vardata + halflen * 6,
4148 decodedKey->coefficient.pbData, decodedKey->coefficient.cbData);
4149 memcpy(vardata + halflen * 7,
4150 decodedKey->privexp.pbData, decodedKey->privexp.cbData);
4154 LocalFree(decodedKey);
4157 __EXCEPT_PAGE_FAULT
4159 SetLastError(STATUS_ACCESS_VIOLATION);
4160 ret = FALSE;
4162 __ENDTRY
4163 return ret;
4166 static BOOL CRYPT_AsnDecodeOctets(const BYTE *pbEncoded,
4167 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4168 DWORD *pcbDecoded)
4170 BOOL ret;
4171 DWORD bytesNeeded, dataLen;
4173 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
4174 pvStructInfo, *pcbStructInfo, pcbDecoded);
4176 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4178 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4180 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4181 bytesNeeded = sizeof(CRYPT_DATA_BLOB);
4182 else
4183 bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
4184 if (pcbDecoded)
4185 *pcbDecoded = 1 + lenBytes + dataLen;
4186 if (!pvStructInfo)
4187 *pcbStructInfo = bytesNeeded;
4188 else if (*pcbStructInfo < bytesNeeded)
4190 SetLastError(ERROR_MORE_DATA);
4191 *pcbStructInfo = bytesNeeded;
4192 ret = FALSE;
4194 else
4196 CRYPT_DATA_BLOB *blob;
4198 *pcbStructInfo = bytesNeeded;
4199 blob = pvStructInfo;
4200 blob->cbData = dataLen;
4201 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4202 blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
4203 else
4205 assert(blob->pbData);
4206 if (blob->cbData)
4207 memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
4208 blob->cbData);
4212 return ret;
4215 static BOOL CRYPT_AsnDecodeOctetStringInternal(const BYTE *encoded, DWORD encoded_size,
4216 DWORD flags, void *buf, DWORD *buf_size, DWORD *ret_decoded)
4218 DWORD decoded = 0, indefinite_len_depth = 0, len_size, len, bytes_needed;
4219 CRYPT_DATA_BLOB *blob;
4220 const BYTE *string;
4222 while (encoded[0] == (ASN_CONSTRUCTOR | ASN_OCTETSTRING))
4224 if (!CRYPT_GetLengthIndefinite(encoded, encoded_size, &len))
4225 return FALSE;
4227 len_size = GET_LEN_BYTES(encoded[1]);
4228 encoded += 1 + len_size;
4229 encoded_size -= 1 + len_size;
4230 decoded += 1 + len_size;
4232 if (len == CMSG_INDEFINITE_LENGTH)
4234 indefinite_len_depth++;
4235 if (encoded_size < 2)
4237 SetLastError(CRYPT_E_ASN1_EOD);
4238 return FALSE;
4240 encoded_size -= 2;
4241 decoded += 2;
4245 if (encoded[0] != ASN_OCTETSTRING)
4247 WARN("Unexpected tag %02x\n", encoded[0]);
4248 SetLastError(CRYPT_E_ASN1_BADTAG);
4249 return FALSE;
4252 if (!CRYPT_GetLen(encoded, encoded_size, &len))
4253 return FALSE;
4254 len_size = GET_LEN_BYTES(encoded[1]);
4255 decoded += 1 + len_size + len;
4256 encoded_size -= 1 + len_size;
4258 if (len > encoded_size)
4260 SetLastError(CRYPT_E_ASN1_EOD);
4261 return FALSE;
4263 if (ret_decoded)
4264 *ret_decoded = decoded;
4266 encoded += 1 + len_size;
4267 string = encoded;
4268 encoded += len;
4270 while (indefinite_len_depth--)
4272 if (encoded[0] || encoded[1])
4274 TRACE("expected 0 TLV, got %02x %02x\n", encoded[0], encoded[1]);
4275 SetLastError(CRYPT_E_ASN1_CORRUPT);
4276 return FALSE;
4280 bytes_needed = sizeof(*blob);
4281 if (!(flags & CRYPT_DECODE_NOCOPY_FLAG)) bytes_needed += len;
4282 if (!buf)
4284 *buf_size = bytes_needed;
4285 return TRUE;
4287 if (*buf_size < bytes_needed)
4289 SetLastError(ERROR_MORE_DATA);
4290 *buf_size = bytes_needed;
4291 return FALSE;
4294 *buf_size = bytes_needed;
4295 blob = buf;
4296 blob->cbData = len;
4297 if (flags & CRYPT_DECODE_NOCOPY_FLAG)
4298 blob->pbData = (BYTE*)string;
4299 else if (blob->cbData)
4300 memcpy(blob->pbData, string, blob->cbData);
4302 if (ret_decoded)
4303 *ret_decoded = decoded;
4304 return TRUE;
4307 static BOOL WINAPI CRYPT_AsnDecodeOctetString(DWORD dwCertEncodingType,
4308 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4309 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4311 BOOL ret;
4313 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
4314 pDecodePara, pvStructInfo, *pcbStructInfo);
4316 if (!cbEncoded)
4318 SetLastError(CRYPT_E_ASN1_CORRUPT);
4319 return FALSE;
4322 __TRY
4324 DWORD bytesNeeded = 0;
4326 if ((ret = CRYPT_AsnDecodeOctetStringInternal(pbEncoded, cbEncoded,
4327 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4329 if (!pvStructInfo)
4330 *pcbStructInfo = bytesNeeded;
4331 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4332 pvStructInfo, pcbStructInfo, bytesNeeded)))
4334 CRYPT_DATA_BLOB *blob;
4336 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4337 pvStructInfo = *(BYTE **)pvStructInfo;
4338 blob = pvStructInfo;
4339 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_DATA_BLOB);
4340 ret = CRYPT_AsnDecodeOctetStringInternal(pbEncoded, cbEncoded,
4341 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4342 &bytesNeeded, NULL);
4343 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4344 CRYPT_FreeSpace(pDecodePara, blob);
4348 __EXCEPT_PAGE_FAULT
4350 SetLastError(STATUS_ACCESS_VIOLATION);
4351 ret = FALSE;
4353 __ENDTRY
4354 return ret;
4357 static BOOL CRYPT_AsnDecodeBitsInternal(const BYTE *pbEncoded, DWORD cbEncoded,
4358 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4360 BOOL ret;
4361 DWORD bytesNeeded, dataLen;
4362 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4364 TRACE("(%p, %ld, 0x%08lx, %p, %ld, %p)\n", pbEncoded, cbEncoded, dwFlags,
4365 pvStructInfo, *pcbStructInfo, pcbDecoded);
4367 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4369 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4370 bytesNeeded = sizeof(CRYPT_BIT_BLOB);
4371 else
4372 bytesNeeded = dataLen - 1 + sizeof(CRYPT_BIT_BLOB);
4373 if (pcbDecoded)
4374 *pcbDecoded = 1 + lenBytes + dataLen;
4375 if (!pvStructInfo)
4376 *pcbStructInfo = bytesNeeded;
4377 else if (*pcbStructInfo < bytesNeeded)
4379 *pcbStructInfo = bytesNeeded;
4380 SetLastError(ERROR_MORE_DATA);
4381 ret = FALSE;
4383 else
4385 CRYPT_BIT_BLOB *blob;
4387 *pcbStructInfo = bytesNeeded;
4388 blob = pvStructInfo;
4389 blob->cbData = dataLen - 1;
4390 blob->cUnusedBits = *(pbEncoded + 1 + lenBytes);
4391 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
4393 blob->pbData = (BYTE *)pbEncoded + 2 + lenBytes;
4395 else
4397 assert(blob->pbData);
4398 if (blob->cbData)
4400 BYTE mask = 0xff << blob->cUnusedBits;
4402 memcpy(blob->pbData, pbEncoded + 2 + lenBytes,
4403 blob->cbData);
4404 blob->pbData[blob->cbData - 1] &= mask;
4409 return ret;
4412 static BOOL WINAPI CRYPT_AsnDecodeBits(DWORD dwCertEncodingType,
4413 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4414 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4416 BOOL ret;
4418 TRACE("(%p, %ld, 0x%08lx, %p, %p, %p)\n", pbEncoded, cbEncoded, dwFlags,
4419 pDecodePara, pvStructInfo, pcbStructInfo);
4421 __TRY
4423 DWORD bytesNeeded = 0;
4425 if (!cbEncoded)
4427 SetLastError(CRYPT_E_ASN1_CORRUPT);
4428 ret = FALSE;
4430 else if (pbEncoded[0] != ASN_BITSTRING)
4432 SetLastError(CRYPT_E_ASN1_BADTAG);
4433 ret = FALSE;
4435 else if ((ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
4436 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4438 if (!pvStructInfo)
4439 *pcbStructInfo = bytesNeeded;
4440 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4441 pvStructInfo, pcbStructInfo, bytesNeeded)))
4443 CRYPT_BIT_BLOB *blob;
4445 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4446 pvStructInfo = *(BYTE **)pvStructInfo;
4447 blob = pvStructInfo;
4448 blob->pbData = (BYTE *)pvStructInfo + sizeof(CRYPT_BIT_BLOB);
4449 ret = CRYPT_AsnDecodeBitsInternal(pbEncoded, cbEncoded,
4450 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4451 &bytesNeeded, NULL);
4452 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4453 CRYPT_FreeSpace(pDecodePara, blob);
4457 __EXCEPT_PAGE_FAULT
4459 SetLastError(STATUS_ACCESS_VIOLATION);
4460 ret = FALSE;
4462 __ENDTRY
4463 TRACE("returning %d (%08lx)\n", ret, GetLastError());
4464 return ret;
4467 /* Ignores tag. Only allows integers 4 bytes or smaller in size. */
4468 static BOOL CRYPT_AsnDecodeIntInternal(const BYTE *pbEncoded, DWORD cbEncoded,
4469 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
4471 BOOL ret;
4472 DWORD dataLen;
4474 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4476 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4478 if (pcbDecoded)
4479 *pcbDecoded = 1 + lenBytes + dataLen;
4480 if (dataLen > sizeof(int))
4482 SetLastError(CRYPT_E_ASN1_LARGE);
4483 ret = FALSE;
4485 else if (!pvStructInfo)
4486 *pcbStructInfo = sizeof(int);
4487 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo, sizeof(int))))
4489 int val, i;
4491 if (dataLen && pbEncoded[1 + lenBytes] & 0x80)
4493 /* initialize to a negative value to sign-extend */
4494 val = -1;
4496 else
4497 val = 0;
4498 for (i = 0; i < dataLen; i++)
4500 val <<= 8;
4501 val |= pbEncoded[1 + lenBytes + i];
4503 memcpy(pvStructInfo, &val, sizeof(int));
4506 return ret;
4509 static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
4510 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4511 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4513 BOOL ret;
4515 __TRY
4517 DWORD bytesNeeded = 0;
4519 if (!cbEncoded)
4521 SetLastError(CRYPT_E_ASN1_EOD);
4522 ret = FALSE;
4524 else if (pbEncoded[0] != ASN_INTEGER)
4526 SetLastError(CRYPT_E_ASN1_BADTAG);
4527 ret = FALSE;
4529 else
4530 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
4531 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4532 if (ret)
4534 if (!pvStructInfo)
4535 *pcbStructInfo = bytesNeeded;
4536 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4537 pvStructInfo, pcbStructInfo, bytesNeeded)))
4539 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4540 pvStructInfo = *(BYTE **)pvStructInfo;
4541 ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded,
4542 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4543 &bytesNeeded, NULL);
4544 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4545 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
4549 __EXCEPT_PAGE_FAULT
4551 SetLastError(STATUS_ACCESS_VIOLATION);
4552 ret = FALSE;
4554 __ENDTRY
4555 return ret;
4558 static BOOL CRYPT_AsnDecodeIntegerInternal(const BYTE *pbEncoded,
4559 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4560 DWORD *pcbDecoded)
4562 BOOL ret;
4563 DWORD bytesNeeded, dataLen;
4565 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4567 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4569 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
4570 if (pcbDecoded)
4571 *pcbDecoded = 1 + lenBytes + dataLen;
4572 if (!pvStructInfo)
4573 *pcbStructInfo = bytesNeeded;
4574 else if (*pcbStructInfo < bytesNeeded)
4576 *pcbStructInfo = bytesNeeded;
4577 SetLastError(ERROR_MORE_DATA);
4578 ret = FALSE;
4580 else
4582 CRYPT_INTEGER_BLOB *blob = pvStructInfo;
4584 *pcbStructInfo = bytesNeeded;
4585 blob->cbData = dataLen;
4586 assert(blob->pbData);
4587 if (blob->cbData)
4589 DWORD i;
4591 for (i = 0; i < blob->cbData; i++)
4593 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
4594 dataLen - i - 1);
4599 return ret;
4602 static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
4603 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4604 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4606 BOOL ret;
4608 __TRY
4610 DWORD bytesNeeded = 0;
4612 if (pbEncoded[0] != ASN_INTEGER)
4614 SetLastError(CRYPT_E_ASN1_BADTAG);
4615 ret = FALSE;
4617 else
4618 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
4619 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4620 if (ret)
4622 if (!pvStructInfo)
4623 *pcbStructInfo = bytesNeeded;
4624 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4625 pvStructInfo, pcbStructInfo, bytesNeeded)))
4627 CRYPT_INTEGER_BLOB *blob;
4629 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4630 pvStructInfo = *(BYTE **)pvStructInfo;
4631 blob = pvStructInfo;
4632 blob->pbData = (BYTE *)pvStructInfo +
4633 sizeof(CRYPT_INTEGER_BLOB);
4634 ret = CRYPT_AsnDecodeIntegerInternal(pbEncoded, cbEncoded,
4635 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
4636 &bytesNeeded, NULL);
4637 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4638 CRYPT_FreeSpace(pDecodePara, blob);
4642 __EXCEPT_PAGE_FAULT
4644 SetLastError(STATUS_ACCESS_VIOLATION);
4645 ret = FALSE;
4647 __ENDTRY
4648 return ret;
4651 static BOOL CRYPT_AsnDecodeUnsignedIntegerInternal(const BYTE *pbEncoded,
4652 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4653 DWORD *pcbDecoded)
4655 BOOL ret;
4657 if (pbEncoded[0] == ASN_INTEGER)
4659 DWORD bytesNeeded, dataLen;
4661 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
4663 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
4665 if (pcbDecoded)
4666 *pcbDecoded = 1 + lenBytes + dataLen;
4667 bytesNeeded = dataLen + sizeof(CRYPT_INTEGER_BLOB);
4668 if (!pvStructInfo)
4669 *pcbStructInfo = bytesNeeded;
4670 else if (*pcbStructInfo < bytesNeeded)
4672 *pcbStructInfo = bytesNeeded;
4673 SetLastError(ERROR_MORE_DATA);
4674 ret = FALSE;
4676 else
4678 CRYPT_INTEGER_BLOB *blob = pvStructInfo;
4680 *pcbStructInfo = bytesNeeded;
4681 blob->cbData = dataLen;
4682 assert(blob->pbData);
4683 /* remove leading zero byte if it exists */
4684 if (blob->cbData && *(pbEncoded + 1 + lenBytes) == 0)
4686 blob->cbData--;
4687 blob->pbData++;
4689 if (blob->cbData)
4691 DWORD i;
4693 for (i = 0; i < blob->cbData; i++)
4695 blob->pbData[i] = *(pbEncoded + 1 + lenBytes +
4696 dataLen - i - 1);
4702 else
4704 SetLastError(CRYPT_E_ASN1_BADTAG);
4705 ret = FALSE;
4707 return ret;
4710 static BOOL WINAPI CRYPT_AsnDecodeUnsignedInteger(DWORD dwCertEncodingType,
4711 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4712 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4714 BOOL ret;
4716 __TRY
4718 DWORD bytesNeeded = 0;
4720 if ((ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded, cbEncoded,
4721 dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL)))
4723 if (!pvStructInfo)
4724 *pcbStructInfo = bytesNeeded;
4725 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4726 pvStructInfo, pcbStructInfo, bytesNeeded)))
4728 CRYPT_INTEGER_BLOB *blob;
4730 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4731 pvStructInfo = *(BYTE **)pvStructInfo;
4732 blob = pvStructInfo;
4733 blob->pbData = (BYTE *)pvStructInfo +
4734 sizeof(CRYPT_INTEGER_BLOB);
4735 ret = CRYPT_AsnDecodeUnsignedIntegerInternal(pbEncoded,
4736 cbEncoded, dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, pvStructInfo,
4737 &bytesNeeded, NULL);
4738 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4739 CRYPT_FreeSpace(pDecodePara, blob);
4743 __EXCEPT_PAGE_FAULT
4745 SetLastError(STATUS_ACCESS_VIOLATION);
4746 ret = FALSE;
4748 __ENDTRY
4749 return ret;
4752 static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
4753 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4754 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4756 BOOL ret;
4758 if (!pvStructInfo)
4760 *pcbStructInfo = sizeof(int);
4761 return TRUE;
4763 __TRY
4765 if (pbEncoded[0] == ASN_ENUMERATED)
4767 unsigned int val = 0, i;
4769 if (cbEncoded <= 1)
4771 SetLastError(CRYPT_E_ASN1_EOD);
4772 ret = FALSE;
4774 else if (pbEncoded[1] == 0)
4776 SetLastError(CRYPT_E_ASN1_CORRUPT);
4777 ret = FALSE;
4779 else
4781 /* A little strange looking, but we have to accept a sign byte:
4782 * 0xffffffff gets encoded as 0a 05 00 ff ff ff ff. Also,
4783 * assuming a small length is okay here, it has to be in short
4784 * form.
4786 if (pbEncoded[1] > sizeof(unsigned int) + 1)
4788 SetLastError(CRYPT_E_ASN1_LARGE);
4789 return FALSE;
4791 for (i = 0; i < pbEncoded[1]; i++)
4793 val <<= 8;
4794 val |= pbEncoded[2 + i];
4796 if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
4797 pvStructInfo, pcbStructInfo, sizeof(unsigned int))))
4799 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4800 pvStructInfo = *(BYTE **)pvStructInfo;
4801 memcpy(pvStructInfo, &val, sizeof(unsigned int));
4805 else
4807 SetLastError(CRYPT_E_ASN1_BADTAG);
4808 ret = FALSE;
4811 __EXCEPT_PAGE_FAULT
4813 SetLastError(STATUS_ACCESS_VIOLATION);
4814 ret = FALSE;
4816 __ENDTRY
4817 return ret;
4820 /* Modifies word, pbEncoded, and len, and magically sets a value ret to FALSE
4821 * if it fails.
4823 #define CRYPT_TIME_GET_DIGITS(pbEncoded, len, numDigits, word) \
4824 do { \
4825 BYTE i; \
4827 (word) = 0; \
4828 for (i = 0; (len) > 0 && i < (numDigits); i++, (len)--) \
4830 if (!isdigit(*(pbEncoded))) \
4832 SetLastError(CRYPT_E_ASN1_CORRUPT); \
4833 ret = FALSE; \
4835 else \
4837 (word) *= 10; \
4838 (word) += *(pbEncoded)++ - '0'; \
4841 } while (0)
4843 static BOOL CRYPT_AsnDecodeTimeZone(const BYTE *pbEncoded, DWORD len,
4844 SYSTEMTIME *sysTime)
4846 BOOL ret = TRUE;
4848 if (len >= 3 && (*pbEncoded == '+' || *pbEncoded == '-'))
4850 WORD hours, minutes = 0;
4851 BYTE sign = *pbEncoded++;
4853 len--;
4854 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, hours);
4855 if (ret && hours >= 24)
4857 SetLastError(CRYPT_E_ASN1_CORRUPT);
4858 ret = FALSE;
4860 else if (len >= 2)
4862 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, minutes);
4863 if (ret && minutes >= 60)
4865 SetLastError(CRYPT_E_ASN1_CORRUPT);
4866 ret = FALSE;
4869 if (ret)
4871 if (sign == '+')
4873 sysTime->wHour += hours;
4874 sysTime->wMinute += minutes;
4876 else
4878 if (hours > sysTime->wHour)
4880 sysTime->wDay--;
4881 sysTime->wHour = 24 - (hours - sysTime->wHour);
4883 else
4884 sysTime->wHour -= hours;
4885 if (minutes > sysTime->wMinute)
4887 sysTime->wHour--;
4888 sysTime->wMinute = 60 - (minutes - sysTime->wMinute);
4890 else
4891 sysTime->wMinute -= minutes;
4895 return ret;
4898 #define MIN_ENCODED_TIME_LENGTH 10
4900 static BOOL CRYPT_AsnDecodeUtcTimeInternal(const BYTE *pbEncoded,
4901 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
4902 DWORD *pcbDecoded)
4904 BOOL ret = FALSE;
4906 if (pbEncoded[0] == ASN_UTCTIME)
4908 if (cbEncoded <= 1)
4909 SetLastError(CRYPT_E_ASN1_EOD);
4910 else if (pbEncoded[1] > 0x7f)
4912 /* long-form date strings really can't be valid */
4913 SetLastError(CRYPT_E_ASN1_CORRUPT);
4915 else
4917 SYSTEMTIME sysTime = { 0 };
4918 BYTE len = pbEncoded[1];
4920 if (len < MIN_ENCODED_TIME_LENGTH)
4921 SetLastError(CRYPT_E_ASN1_CORRUPT);
4922 else
4924 ret = TRUE;
4925 if (pcbDecoded)
4926 *pcbDecoded = 2 + len;
4927 pbEncoded += 2;
4928 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wYear);
4929 if (sysTime.wYear >= 50)
4930 sysTime.wYear += 1900;
4931 else
4932 sysTime.wYear += 2000;
4933 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
4934 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
4935 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
4936 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMinute);
4937 if (ret && len > 0)
4939 if (len >= 2 && isdigit(*pbEncoded) &&
4940 isdigit(*(pbEncoded + 1)))
4941 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
4942 sysTime.wSecond);
4943 else if (isdigit(*pbEncoded))
4944 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 1,
4945 sysTime.wSecond);
4946 if (ret)
4947 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
4948 &sysTime);
4950 if (ret)
4952 if (!pvStructInfo)
4953 *pcbStructInfo = sizeof(FILETIME);
4954 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
4955 sizeof(FILETIME))))
4956 ret = SystemTimeToFileTime(&sysTime, pvStructInfo);
4961 else
4962 SetLastError(CRYPT_E_ASN1_BADTAG);
4963 return ret;
4966 static BOOL WINAPI CRYPT_AsnDecodeUtcTime(DWORD dwCertEncodingType,
4967 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
4968 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
4970 BOOL ret = FALSE;
4972 __TRY
4974 DWORD bytesNeeded = 0;
4976 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
4977 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
4978 if (ret)
4980 if (!pvStructInfo)
4981 *pcbStructInfo = bytesNeeded;
4982 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
4983 pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
4985 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
4986 pvStructInfo = *(BYTE **)pvStructInfo;
4987 ret = CRYPT_AsnDecodeUtcTimeInternal(pbEncoded, cbEncoded,
4988 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
4989 &bytesNeeded, NULL);
4990 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
4991 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
4995 __EXCEPT_PAGE_FAULT
4997 SetLastError(STATUS_ACCESS_VIOLATION);
4999 __ENDTRY
5000 return ret;
5003 static BOOL CRYPT_AsnDecodeGeneralizedTime(const BYTE *pbEncoded,
5004 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5005 DWORD *pcbDecoded)
5007 BOOL ret = FALSE;
5009 if (pbEncoded[0] == ASN_GENERALTIME)
5011 if (cbEncoded <= 1)
5012 SetLastError(CRYPT_E_ASN1_EOD);
5013 else if (pbEncoded[1] > 0x7f)
5015 /* long-form date strings really can't be valid */
5016 SetLastError(CRYPT_E_ASN1_CORRUPT);
5018 else
5020 BYTE len = pbEncoded[1];
5022 if (len < MIN_ENCODED_TIME_LENGTH)
5023 SetLastError(CRYPT_E_ASN1_CORRUPT);
5024 else
5026 SYSTEMTIME sysTime = { 0 };
5028 ret = TRUE;
5029 if (pcbDecoded)
5030 *pcbDecoded = 2 + len;
5031 pbEncoded += 2;
5032 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 4, sysTime.wYear);
5033 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wMonth);
5034 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wDay);
5035 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2, sysTime.wHour);
5036 if (ret && len > 0)
5038 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
5039 sysTime.wMinute);
5040 if (ret && len > 0)
5041 CRYPT_TIME_GET_DIGITS(pbEncoded, len, 2,
5042 sysTime.wSecond);
5043 if (ret && len > 0 && (*pbEncoded == '.' ||
5044 *pbEncoded == ','))
5046 BYTE digits;
5048 pbEncoded++;
5049 len--;
5050 /* workaround macro weirdness */
5051 digits = min(len, 3);
5052 CRYPT_TIME_GET_DIGITS(pbEncoded, len, digits,
5053 sysTime.wMilliseconds);
5055 if (ret)
5056 ret = CRYPT_AsnDecodeTimeZone(pbEncoded, len,
5057 &sysTime);
5059 if (ret)
5061 if (!pvStructInfo)
5062 *pcbStructInfo = sizeof(FILETIME);
5063 else if ((ret = CRYPT_DecodeCheckSpace(pcbStructInfo,
5064 sizeof(FILETIME))))
5065 ret = SystemTimeToFileTime(&sysTime, pvStructInfo);
5070 else
5071 SetLastError(CRYPT_E_ASN1_BADTAG);
5072 return ret;
5075 static BOOL CRYPT_AsnDecodeChoiceOfTimeInternal(const BYTE *pbEncoded,
5076 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5077 DWORD *pcbDecoded)
5079 BOOL ret;
5080 InternalDecodeFunc decode = NULL;
5082 if (pbEncoded[0] == ASN_UTCTIME)
5083 decode = CRYPT_AsnDecodeUtcTimeInternal;
5084 else if (pbEncoded[0] == ASN_GENERALTIME)
5085 decode = CRYPT_AsnDecodeGeneralizedTime;
5086 if (decode)
5087 ret = decode(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
5088 pcbStructInfo, pcbDecoded);
5089 else
5091 SetLastError(CRYPT_E_ASN1_BADTAG);
5092 ret = FALSE;
5094 return ret;
5097 static BOOL WINAPI CRYPT_AsnDecodeChoiceOfTime(DWORD dwCertEncodingType,
5098 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5099 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5101 BOOL ret;
5103 __TRY
5105 DWORD bytesNeeded = 0;
5107 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
5108 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded, NULL);
5109 if (ret)
5111 if (!pvStructInfo)
5112 *pcbStructInfo = bytesNeeded;
5113 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
5114 pvStructInfo, pcbStructInfo, bytesNeeded)))
5116 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5117 pvStructInfo = *(BYTE **)pvStructInfo;
5118 ret = CRYPT_AsnDecodeChoiceOfTimeInternal(pbEncoded, cbEncoded,
5119 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5120 &bytesNeeded, NULL);
5121 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5122 CRYPT_FreeSpace(pDecodePara, pvStructInfo);
5126 __EXCEPT_PAGE_FAULT
5128 SetLastError(STATUS_ACCESS_VIOLATION);
5129 ret = FALSE;
5131 __ENDTRY
5132 return ret;
5135 static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
5136 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5137 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5139 BOOL ret = TRUE;
5141 __TRY
5143 if (pbEncoded[0] == ASN_SEQUENCEOF)
5145 DWORD bytesNeeded, dataLen, remainingLen, cValue;
5147 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
5149 BYTE lenBytes;
5150 const BYTE *ptr;
5152 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
5153 bytesNeeded = sizeof(CRYPT_SEQUENCE_OF_ANY);
5154 cValue = 0;
5155 ptr = pbEncoded + 1 + lenBytes;
5156 remainingLen = dataLen;
5157 while (ret && remainingLen)
5159 DWORD nextLen;
5161 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
5162 if (ret)
5164 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
5166 remainingLen -= 1 + nextLenBytes + nextLen;
5167 ptr += 1 + nextLenBytes + nextLen;
5168 bytesNeeded += sizeof(CRYPT_DER_BLOB);
5169 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
5170 bytesNeeded += 1 + nextLenBytes + nextLen;
5171 cValue++;
5174 if (ret)
5176 CRYPT_SEQUENCE_OF_ANY *seq;
5177 BYTE *nextPtr;
5178 DWORD i;
5180 if (!pvStructInfo)
5181 *pcbStructInfo = bytesNeeded;
5182 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
5183 pvStructInfo, pcbStructInfo, bytesNeeded)))
5185 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5186 pvStructInfo = *(BYTE **)pvStructInfo;
5187 seq = pvStructInfo;
5188 seq->cValue = cValue;
5189 seq->rgValue = (CRYPT_DER_BLOB *)((BYTE *)seq +
5190 sizeof(*seq));
5191 nextPtr = (BYTE *)seq->rgValue +
5192 cValue * sizeof(CRYPT_DER_BLOB);
5193 ptr = pbEncoded + 1 + lenBytes;
5194 remainingLen = dataLen;
5195 i = 0;
5196 while (ret && remainingLen)
5198 DWORD nextLen;
5200 ret = CRYPT_GetLen(ptr, remainingLen, &nextLen);
5201 if (ret)
5203 DWORD nextLenBytes = GET_LEN_BYTES(ptr[1]);
5205 seq->rgValue[i].cbData = 1 + nextLenBytes +
5206 nextLen;
5207 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
5208 seq->rgValue[i].pbData = (BYTE *)ptr;
5209 else
5211 seq->rgValue[i].pbData = nextPtr;
5212 memcpy(nextPtr, ptr, 1 + nextLenBytes +
5213 nextLen);
5214 nextPtr += 1 + nextLenBytes + nextLen;
5216 remainingLen -= 1 + nextLenBytes + nextLen;
5217 ptr += 1 + nextLenBytes + nextLen;
5218 i++;
5221 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5222 CRYPT_FreeSpace(pDecodePara, seq);
5227 else
5229 SetLastError(CRYPT_E_ASN1_BADTAG);
5230 ret = FALSE;
5233 __EXCEPT_PAGE_FAULT
5235 SetLastError(STATUS_ACCESS_VIOLATION);
5236 ret = FALSE;
5238 __ENDTRY
5239 return ret;
5242 static BOOL CRYPT_AsnDecodeDistPointName(const BYTE *pbEncoded,
5243 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5244 DWORD *pcbDecoded)
5246 BOOL ret;
5248 if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 0))
5250 DWORD bytesNeeded = 0, dataLen;
5252 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
5254 struct AsnArrayDescriptor arrayDesc = {
5255 ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
5256 offsetof(CRL_DIST_POINT_NAME, u.FullName.cAltEntry),
5257 offsetof(CRL_DIST_POINT_NAME, u.FullName.rgAltEntry),
5258 FINALMEMBERSIZE(CRL_DIST_POINT_NAME, u),
5259 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
5260 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
5261 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
5262 DWORD nameLen;
5264 if (dataLen)
5266 ret = CRYPT_AsnDecodeArray(&arrayDesc,
5267 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
5268 dwFlags, NULL, NULL, &nameLen, NULL);
5269 bytesNeeded = sizeof(CRL_DIST_POINT_NAME) + nameLen -
5270 FINALMEMBERSIZE(CRL_DIST_POINT_NAME, u);
5272 else
5273 bytesNeeded = sizeof(CRL_DIST_POINT_NAME);
5274 if (pcbDecoded)
5275 *pcbDecoded = 1 + lenBytes + dataLen;
5276 if (!pvStructInfo)
5277 *pcbStructInfo = bytesNeeded;
5278 else if (*pcbStructInfo < bytesNeeded)
5280 *pcbStructInfo = bytesNeeded;
5281 SetLastError(ERROR_MORE_DATA);
5282 ret = FALSE;
5284 else
5286 CRL_DIST_POINT_NAME *name = pvStructInfo;
5288 *pcbStructInfo = bytesNeeded;
5289 if (dataLen)
5291 name->dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
5292 ret = CRYPT_AsnDecodeArray(&arrayDesc,
5293 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes,
5294 dwFlags, NULL, &name->u.FullName.cAltEntry, &nameLen,
5295 NULL);
5297 else
5298 name->dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
5302 else
5304 SetLastError(CRYPT_E_ASN1_BADTAG);
5305 ret = FALSE;
5307 return ret;
5310 static BOOL CRYPT_AsnDecodeDistPoint(const BYTE *pbEncoded, DWORD cbEncoded,
5311 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5313 struct AsnDecodeSequenceItem items[] = {
5314 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
5315 DistPointName), CRYPT_AsnDecodeDistPointName,
5316 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
5317 DistPointName.u.FullName.rgAltEntry), 0 },
5318 { ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
5319 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
5320 offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
5321 { ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
5322 CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
5323 offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
5325 CRL_DIST_POINT *point = pvStructInfo;
5326 BOOL ret;
5328 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5329 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5330 pcbDecoded, point ? point->DistPointName.u.FullName.rgAltEntry : NULL);
5331 return ret;
5334 static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
5335 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5336 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5338 BOOL ret;
5340 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
5341 pDecodePara, pvStructInfo, *pcbStructInfo);
5343 __TRY
5345 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
5346 offsetof(CRL_DIST_POINTS_INFO, cDistPoint),
5347 offsetof(CRL_DIST_POINTS_INFO, rgDistPoint),
5348 sizeof(CRL_DIST_POINTS_INFO),
5349 CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
5350 offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
5351 CRL_DIST_POINTS_INFO *info = pvStructInfo;
5353 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5354 info->rgDistPoint = (CRL_DIST_POINT *)(info + 1);
5355 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5356 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
5358 __EXCEPT_PAGE_FAULT
5360 SetLastError(STATUS_ACCESS_VIOLATION);
5361 ret = FALSE;
5363 __ENDTRY
5364 return ret;
5367 static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(DWORD dwCertEncodingType,
5368 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5369 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5371 BOOL ret;
5373 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
5374 pDecodePara, pvStructInfo, *pcbStructInfo);
5376 __TRY
5378 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
5379 offsetof(CERT_ENHKEY_USAGE, cUsageIdentifier),
5380 offsetof(CERT_ENHKEY_USAGE, rgpszUsageIdentifier),
5381 sizeof(CERT_ENHKEY_USAGE),
5382 CRYPT_AsnDecodeOidInternal, sizeof(LPSTR), TRUE, 0 };
5383 CERT_ENHKEY_USAGE *usage = pvStructInfo;
5385 if (pvStructInfo && !(dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5386 usage->rgpszUsageIdentifier = (LPSTR *)(usage + 1);
5387 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5388 dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
5390 __EXCEPT_PAGE_FAULT
5392 SetLastError(STATUS_ACCESS_VIOLATION);
5393 ret = FALSE;
5395 __ENDTRY
5396 return ret;
5399 static BOOL WINAPI CRYPT_AsnDecodeIssuingDistPoint(DWORD dwCertEncodingType,
5400 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5401 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5403 BOOL ret;
5405 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
5406 pDecodePara, pvStructInfo, *pcbStructInfo);
5408 __TRY
5410 struct AsnDecodeSequenceItem items[] = {
5411 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_ISSUING_DIST_POINT,
5412 DistPointName), CRYPT_AsnDecodeDistPointName,
5413 sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE,
5414 offsetof(CRL_ISSUING_DIST_POINT,
5415 DistPointName.u.FullName.rgAltEntry), 0 },
5416 { ASN_CONTEXT | 1, offsetof(CRL_ISSUING_DIST_POINT,
5417 fOnlyContainsUserCerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
5418 FALSE, 0 },
5419 { ASN_CONTEXT | 2, offsetof(CRL_ISSUING_DIST_POINT,
5420 fOnlyContainsCACerts), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE,
5421 FALSE, 0 },
5422 { ASN_CONTEXT | 3, offsetof(CRL_ISSUING_DIST_POINT,
5423 OnlySomeReasonFlags), CRYPT_AsnDecodeBitsInternal,
5424 sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CRL_ISSUING_DIST_POINT,
5425 OnlySomeReasonFlags.pbData), 0 },
5426 { ASN_CONTEXT | 4, offsetof(CRL_ISSUING_DIST_POINT,
5427 fIndirectCRL), CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0 },
5430 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5431 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
5432 pcbStructInfo, NULL, NULL);
5434 __EXCEPT_PAGE_FAULT
5436 SetLastError(STATUS_ACCESS_VIOLATION);
5437 ret = FALSE;
5439 __ENDTRY
5440 return ret;
5443 static BOOL CRYPT_AsnDecodeMaximum(const BYTE *pbEncoded,
5444 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5445 DWORD *pcbDecoded)
5447 BOOL ret;
5448 DWORD max, size = sizeof(max);
5450 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
5451 pvStructInfo, *pcbStructInfo, pcbDecoded);
5453 if (!cbEncoded)
5455 SetLastError(CRYPT_E_ASN1_EOD);
5456 return FALSE;
5458 if (pbEncoded[0] != (ASN_CONTEXT | 1))
5460 SetLastError(CRYPT_E_ASN1_BADTAG);
5461 return FALSE;
5463 if ((ret = CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags,
5464 &max, &size, pcbDecoded)))
5466 DWORD bytesNeeded = FINALMEMBERSIZE(CERT_GENERAL_SUBTREE, fMaximum);
5468 if (!pvStructInfo)
5469 *pcbStructInfo = bytesNeeded;
5470 else if (*pcbStructInfo < bytesNeeded)
5472 *pcbStructInfo = bytesNeeded;
5473 SetLastError(ERROR_MORE_DATA);
5474 ret = FALSE;
5476 else
5478 CERT_GENERAL_SUBTREE *subtree = CONTAINING_RECORD(pvStructInfo,
5479 CERT_GENERAL_SUBTREE, fMaximum);
5481 *pcbStructInfo = bytesNeeded;
5482 /* The BOOL is implicit: if the integer is present, then it's
5483 * TRUE.
5485 subtree->fMaximum = TRUE;
5486 subtree->dwMaximum = max;
5489 TRACE("returning %d\n", ret);
5490 return ret;
5493 static BOOL CRYPT_AsnDecodeSubtree(const BYTE *pbEncoded,
5494 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5495 DWORD *pcbDecoded)
5497 BOOL ret;
5498 struct AsnDecodeSequenceItem items[] = {
5499 { 0, offsetof(CERT_GENERAL_SUBTREE, Base),
5500 CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE, TRUE,
5501 offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL), 0 },
5502 { ASN_CONTEXT | 0, offsetof(CERT_GENERAL_SUBTREE, dwMinimum),
5503 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), TRUE, FALSE, 0, 0 },
5504 { ASN_CONTEXT | 1, offsetof(CERT_GENERAL_SUBTREE, fMaximum),
5505 CRYPT_AsnDecodeMaximum, FINALMEMBERSIZE(CERT_GENERAL_SUBTREE, fMaximum),
5506 TRUE, FALSE, 0, 0 },
5508 CERT_GENERAL_SUBTREE *subtree = pvStructInfo;
5510 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
5511 pvStructInfo, *pcbStructInfo, pcbDecoded);
5513 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5514 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5515 pcbDecoded, subtree ? subtree->Base.u.pwszURL : NULL);
5516 if (pcbDecoded)
5518 TRACE("%ld\n", *pcbDecoded);
5519 if (*pcbDecoded < cbEncoded)
5520 TRACE("%02x %02x\n", *(pbEncoded + *pcbDecoded),
5521 *(pbEncoded + *pcbDecoded + 1));
5523 TRACE("returning %d\n", ret);
5524 return ret;
5527 static BOOL CRYPT_AsnDecodePermittedSubtree(const BYTE *pbEncoded,
5528 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5529 DWORD *pcbDecoded)
5531 BOOL ret = TRUE;
5532 struct AsnArrayDescriptor arrayDesc = { 0,
5533 offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
5534 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree),
5535 MEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree,
5536 cExcludedSubtree),
5537 CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
5538 offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
5540 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
5541 pvStructInfo, *pcbStructInfo, pcbDecoded);
5543 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5544 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5545 return ret;
5548 static BOOL CRYPT_AsnDecodeExcludedSubtree(const BYTE *pbEncoded,
5549 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5550 DWORD *pcbDecoded)
5552 BOOL ret = TRUE;
5553 struct AsnArrayDescriptor arrayDesc = { 0,
5554 offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5555 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree),
5556 FINALMEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5557 CRYPT_AsnDecodeSubtree, sizeof(CERT_GENERAL_SUBTREE), TRUE,
5558 offsetof(CERT_GENERAL_SUBTREE, Base.u.pwszURL) };
5560 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
5561 pvStructInfo, *pcbStructInfo, pcbDecoded);
5563 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5564 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5565 return ret;
5568 static BOOL WINAPI CRYPT_AsnDecodeNameConstraints(DWORD dwCertEncodingType,
5569 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5570 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5572 BOOL ret = FALSE;
5574 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
5575 pDecodePara, pvStructInfo, *pcbStructInfo);
5577 __TRY
5579 struct AsnDecodeSequenceItem items[] = {
5580 { ASN_CONTEXT | ASN_CONSTRUCTOR | 0,
5581 offsetof(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree),
5582 CRYPT_AsnDecodePermittedSubtree,
5583 MEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cPermittedSubtree,
5584 cExcludedSubtree), TRUE, TRUE,
5585 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgPermittedSubtree), 0 },
5586 { ASN_CONTEXT | ASN_CONSTRUCTOR | 1,
5587 offsetof(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5588 CRYPT_AsnDecodeExcludedSubtree,
5589 FINALMEMBERSIZE(CERT_NAME_CONSTRAINTS_INFO, cExcludedSubtree),
5590 TRUE, TRUE,
5591 offsetof(CERT_NAME_CONSTRAINTS_INFO, rgExcludedSubtree), 0 },
5594 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5595 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
5596 pcbStructInfo, NULL, NULL);
5598 __EXCEPT_PAGE_FAULT
5600 SetLastError(STATUS_ACCESS_VIOLATION);
5602 __ENDTRY
5603 return ret;
5606 static BOOL CRYPT_AsnDecodeIssuerSerialNumber(const BYTE *pbEncoded,
5607 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5608 DWORD *pcbDecoded)
5610 BOOL ret;
5611 struct AsnDecodeSequenceItem items[] = {
5612 { 0, offsetof(CERT_ISSUER_SERIAL_NUMBER, Issuer), CRYPT_AsnDecodeDerBlob,
5613 sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER,
5614 Issuer.pbData) },
5615 { ASN_INTEGER, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber),
5616 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
5617 TRUE, offsetof(CERT_ISSUER_SERIAL_NUMBER, SerialNumber.pbData), 0 },
5619 CERT_ISSUER_SERIAL_NUMBER *issuerSerial = pvStructInfo;
5621 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
5622 pvStructInfo, *pcbStructInfo, pcbDecoded);
5624 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5625 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5626 pcbDecoded, issuerSerial ? issuerSerial->Issuer.pbData : NULL);
5627 if (ret && issuerSerial && !issuerSerial->SerialNumber.cbData)
5629 SetLastError(CRYPT_E_ASN1_CORRUPT);
5630 ret = FALSE;
5632 TRACE("returning %d\n", ret);
5633 return ret;
5636 static BOOL CRYPT_AsnDecodePKCSSignerInfoInternal(const BYTE *pbEncoded,
5637 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5638 DWORD *pcbDecoded)
5640 CMSG_SIGNER_INFO *info = pvStructInfo;
5641 struct AsnDecodeSequenceItem items[] = {
5642 { ASN_INTEGER, offsetof(CMSG_SIGNER_INFO, dwVersion),
5643 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5644 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, Issuer),
5645 CRYPT_AsnDecodeIssuerSerialNumber, sizeof(CERT_ISSUER_SERIAL_NUMBER),
5646 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, Issuer.pbData), 0 },
5647 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashAlgorithm),
5648 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5649 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
5650 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5651 offsetof(CMSG_SIGNER_INFO, AuthAttrs),
5652 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5653 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
5654 { ASN_SEQUENCEOF, offsetof(CMSG_SIGNER_INFO, HashEncryptionAlgorithm),
5655 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5656 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO,
5657 HashEncryptionAlgorithm.pszObjId), 0 },
5658 { ASN_OCTETSTRING, offsetof(CMSG_SIGNER_INFO, EncryptedHash),
5659 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB),
5660 FALSE, TRUE, offsetof(CMSG_SIGNER_INFO, EncryptedHash.pbData), 0 },
5661 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5662 offsetof(CMSG_SIGNER_INFO, UnauthAttrs),
5663 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5664 TRUE, TRUE, offsetof(CMSG_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
5666 BOOL ret;
5668 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
5669 pvStructInfo, *pcbStructInfo);
5671 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5672 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5673 pcbDecoded, info ? info->Issuer.pbData : NULL);
5674 return ret;
5677 static BOOL WINAPI CRYPT_AsnDecodePKCSSignerInfo(DWORD dwCertEncodingType,
5678 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5679 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5681 BOOL ret = FALSE;
5683 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
5684 pDecodePara, pvStructInfo, *pcbStructInfo);
5686 __TRY
5688 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded, cbEncoded,
5689 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
5690 if (ret && pvStructInfo)
5692 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
5693 pcbStructInfo, *pcbStructInfo);
5694 if (ret)
5696 CMSG_SIGNER_INFO *info;
5698 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5699 pvStructInfo = *(BYTE **)pvStructInfo;
5700 info = pvStructInfo;
5701 info->Issuer.pbData = ((BYTE *)info +
5702 sizeof(CMSG_SIGNER_INFO));
5703 ret = CRYPT_AsnDecodePKCSSignerInfoInternal(pbEncoded,
5704 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5705 pcbStructInfo, NULL);
5706 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5707 CRYPT_FreeSpace(pDecodePara, info);
5711 __EXCEPT_PAGE_FAULT
5713 SetLastError(STATUS_ACCESS_VIOLATION);
5715 __ENDTRY
5716 TRACE("returning %d\n", ret);
5717 return ret;
5720 static BOOL verify_and_copy_certificate(const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5721 void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5723 PCCERT_CONTEXT cert;
5725 cert = CertCreateCertificateContext(X509_ASN_ENCODING, pbEncoded, cbEncoded);
5726 if (!cert)
5728 WARN("CertCreateCertificateContext error %#lx\n", GetLastError());
5729 *pcbStructInfo = 0;
5730 *pcbDecoded = 0;
5731 return TRUE;
5734 CertFreeCertificateContext(cert);
5736 return CRYPT_AsnDecodeCopyBytes(pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo, pcbDecoded);
5739 static BOOL CRYPT_AsnDecodeCMSCertEncoded(const BYTE *pbEncoded,
5740 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5741 DWORD *pcbDecoded)
5743 BOOL ret;
5744 struct AsnArrayDescriptor arrayDesc = { 0,
5745 offsetof(CRYPT_SIGNED_INFO, cCertEncoded),
5746 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded),
5747 MEMBERSIZE(CRYPT_SIGNED_INFO, cCertEncoded, cCrlEncoded),
5748 verify_and_copy_certificate,
5749 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
5751 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
5752 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
5754 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5755 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5756 return ret;
5759 static BOOL CRYPT_AsnDecodeCMSCrlEncoded(const BYTE *pbEncoded,
5760 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5761 DWORD *pcbDecoded)
5763 BOOL ret;
5764 struct AsnArrayDescriptor arrayDesc = { 0,
5765 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded),
5766 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded),
5767 MEMBERSIZE(CRYPT_SIGNED_INFO, cCrlEncoded, content),
5768 CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_DER_BLOB),
5769 TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
5771 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
5772 pvStructInfo, pvStructInfo ? *pcbStructInfo : 0, pcbDecoded);
5774 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5775 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5776 return ret;
5779 static BOOL CRYPT_AsnDecodeCMSSignerId(const BYTE *pbEncoded,
5780 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5781 DWORD *pcbDecoded)
5783 CERT_ID *id = pvStructInfo;
5784 BOOL ret = FALSE;
5786 if (*pbEncoded == ASN_SEQUENCEOF)
5788 ret = CRYPT_AsnDecodeIssuerSerialNumber(pbEncoded, cbEncoded, dwFlags,
5789 id ? &id->u.IssuerSerialNumber : NULL, pcbStructInfo, pcbDecoded);
5790 if (ret)
5792 if (id)
5793 id->dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
5794 if (*pcbStructInfo > sizeof(CERT_ISSUER_SERIAL_NUMBER))
5795 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
5796 sizeof(CERT_ISSUER_SERIAL_NUMBER);
5797 else
5798 *pcbStructInfo = sizeof(CERT_ID);
5801 else if (*pbEncoded == (ASN_CONTEXT | 0))
5803 ret = CRYPT_AsnDecodeOctets(pbEncoded, cbEncoded, dwFlags,
5804 id ? &id->u.KeyId : NULL, pcbStructInfo, pcbDecoded);
5805 if (ret)
5807 if (id)
5808 id->dwIdChoice = CERT_ID_KEY_IDENTIFIER;
5809 if (*pcbStructInfo > sizeof(CRYPT_DATA_BLOB))
5810 *pcbStructInfo = sizeof(CERT_ID) + *pcbStructInfo -
5811 sizeof(CRYPT_DATA_BLOB);
5812 else
5813 *pcbStructInfo = sizeof(CERT_ID);
5816 else
5817 SetLastError(CRYPT_E_ASN1_BADTAG);
5818 return ret;
5821 static BOOL CRYPT_AsnDecodeCMSSignerInfoInternal(const BYTE *pbEncoded,
5822 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
5823 DWORD *pcbDecoded)
5825 CMSG_CMS_SIGNER_INFO *info = pvStructInfo;
5826 struct AsnDecodeSequenceItem items[] = {
5827 { ASN_INTEGER, offsetof(CMSG_CMS_SIGNER_INFO, dwVersion),
5828 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5829 { 0, offsetof(CMSG_CMS_SIGNER_INFO, SignerId),
5830 CRYPT_AsnDecodeCMSSignerId, sizeof(CERT_ID), FALSE, TRUE,
5831 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData), 0 },
5832 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm),
5833 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5834 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, HashAlgorithm.pszObjId), 0 },
5835 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5836 offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs),
5837 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5838 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, AuthAttrs.rgAttr), 0 },
5839 { ASN_SEQUENCEOF, offsetof(CMSG_CMS_SIGNER_INFO, HashEncryptionAlgorithm),
5840 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
5841 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO,
5842 HashEncryptionAlgorithm.pszObjId), 0 },
5843 { ASN_OCTETSTRING, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash),
5844 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DER_BLOB),
5845 FALSE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, EncryptedHash.pbData), 0 },
5846 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5847 offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs),
5848 CRYPT_AsnDecodePKCSAttributesInternal, sizeof(CRYPT_ATTRIBUTES),
5849 TRUE, TRUE, offsetof(CMSG_CMS_SIGNER_INFO, UnauthAttrs.rgAttr), 0 },
5851 BOOL ret;
5853 TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
5854 pvStructInfo, *pcbStructInfo);
5856 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5857 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5858 pcbDecoded, info ? info->SignerId.u.KeyId.pbData : NULL);
5859 return ret;
5862 static BOOL WINAPI CRYPT_AsnDecodeCMSSignerInfo(DWORD dwCertEncodingType,
5863 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
5864 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
5866 BOOL ret = FALSE;
5868 TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
5869 pDecodePara, pvStructInfo, *pcbStructInfo);
5871 __TRY
5873 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded, cbEncoded,
5874 dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
5875 if (ret && pvStructInfo)
5877 ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
5878 pcbStructInfo, *pcbStructInfo);
5879 if (ret)
5881 CMSG_CMS_SIGNER_INFO *info;
5883 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
5884 pvStructInfo = *(BYTE **)pvStructInfo;
5885 info = pvStructInfo;
5886 info->SignerId.u.KeyId.pbData = ((BYTE *)info +
5887 sizeof(CMSG_CMS_SIGNER_INFO));
5888 ret = CRYPT_AsnDecodeCMSSignerInfoInternal(pbEncoded,
5889 cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
5890 pcbStructInfo, NULL);
5891 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
5892 CRYPT_FreeSpace(pDecodePara, info);
5896 __EXCEPT_PAGE_FAULT
5898 SetLastError(STATUS_ACCESS_VIOLATION);
5900 __ENDTRY
5901 TRACE("returning %d\n", ret);
5902 return ret;
5905 static BOOL CRYPT_DecodeSignerArray(const BYTE *pbEncoded, DWORD cbEncoded,
5906 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5908 BOOL ret;
5909 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
5910 offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
5911 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo),
5912 FINALMEMBERSIZE(CRYPT_SIGNED_INFO, cSignerInfo),
5913 CRYPT_AsnDecodeCMSSignerInfoInternal, sizeof(CMSG_CMS_SIGNER_INFO), TRUE,
5914 offsetof(CMSG_CMS_SIGNER_INFO, SignerId.u.KeyId.pbData) };
5916 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
5917 pvStructInfo, *pcbStructInfo, pcbDecoded);
5919 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
5920 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
5921 return ret;
5924 BOOL CRYPT_AsnDecodeCMSSignedInfo(const BYTE *pbEncoded, DWORD cbEncoded,
5925 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
5926 CRYPT_SIGNED_INFO *signedInfo, DWORD *pcbSignedInfo)
5928 BOOL ret = FALSE;
5929 struct AsnDecodeSequenceItem items[] = {
5930 { ASN_INTEGER, offsetof(CRYPT_SIGNED_INFO, version),
5931 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5932 /* Placeholder for the hash algorithms - redundant with those in the
5933 * signers, so just ignore them.
5935 { ASN_CONSTRUCTOR | ASN_SETOF, 0, NULL, 0, TRUE, FALSE, 0, 0 },
5936 { ASN_SEQUENCE, offsetof(CRYPT_SIGNED_INFO, content),
5937 CRYPT_AsnDecodePKCSContentInfoInternal, sizeof(CRYPT_CONTENT_INFO),
5938 FALSE, TRUE, offsetof(CRYPT_SIGNED_INFO, content.pszObjId), 0 },
5939 { ASN_CONSTRUCTOR | ASN_CONTEXT | 0,
5940 offsetof(CRYPT_SIGNED_INFO, cCertEncoded), CRYPT_AsnDecodeCMSCertEncoded,
5941 MEMBERSIZE(CRYPT_SIGNED_INFO, cCertEncoded, cCrlEncoded), TRUE, TRUE,
5942 offsetof(CRYPT_SIGNED_INFO, rgCertEncoded), 0 },
5943 { ASN_CONSTRUCTOR | ASN_CONTEXT | 1,
5944 offsetof(CRYPT_SIGNED_INFO, cCrlEncoded), CRYPT_AsnDecodeCMSCrlEncoded,
5945 MEMBERSIZE(CRYPT_SIGNED_INFO, cCrlEncoded, content), TRUE, TRUE,
5946 offsetof(CRYPT_SIGNED_INFO, rgCrlEncoded), 0 },
5947 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_SIGNED_INFO, cSignerInfo),
5948 CRYPT_DecodeSignerArray,
5949 FINALMEMBERSIZE(CRYPT_SIGNED_INFO, cSignerInfo), TRUE, TRUE,
5950 offsetof(CRYPT_SIGNED_INFO, rgSignerInfo), 0 },
5953 TRACE("%p, %ld, %08lx, %p, %p, %p\n", pbEncoded, cbEncoded, dwFlags,
5954 pDecodePara, signedInfo, pcbSignedInfo);
5956 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5957 pbEncoded, cbEncoded, dwFlags, pDecodePara, signedInfo, pcbSignedInfo,
5958 NULL, NULL);
5959 TRACE("returning %d\n", ret);
5960 return ret;
5963 static BOOL CRYPT_AsnDecodeRecipientInfo(const BYTE *pbEncoded, DWORD cbEncoded,
5964 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
5966 BOOL ret;
5967 CMSG_KEY_TRANS_RECIPIENT_INFO *info = pvStructInfo;
5968 struct AsnDecodeSequenceItem items[] = {
5969 { ASN_INTEGER, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, dwVersion),
5970 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
5971 { ASN_SEQUENCEOF, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
5972 RecipientId.u.IssuerSerialNumber), CRYPT_AsnDecodeIssuerSerialNumber,
5973 sizeof(CERT_ISSUER_SERIAL_NUMBER), FALSE, TRUE,
5974 offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
5975 RecipientId.u.IssuerSerialNumber.Issuer.pbData), 0 },
5976 { ASN_SEQUENCEOF, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
5977 KeyEncryptionAlgorithm), CRYPT_AsnDecodeAlgorithmId,
5978 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
5979 offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
5980 KeyEncryptionAlgorithm.pszObjId), 0 },
5981 { ASN_OCTETSTRING, offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, EncryptedKey),
5982 CRYPT_AsnDecodeOctets, sizeof(CRYPT_DATA_BLOB), FALSE, TRUE,
5983 offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO, EncryptedKey.pbData), 0 },
5986 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
5987 pvStructInfo, *pcbStructInfo, pcbDecoded);
5989 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
5990 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
5991 pcbDecoded, info ? info->RecipientId.u.IssuerSerialNumber.Issuer.pbData :
5992 NULL);
5993 if (info)
5994 info->RecipientId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
5995 TRACE("returning %d\n", ret);
5996 return ret;
5999 static BOOL CRYPT_DecodeRecipientInfoArray(const BYTE *pbEncoded,
6000 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6001 DWORD *pcbDecoded)
6003 BOOL ret;
6004 struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
6005 offsetof(CRYPT_ENVELOPED_DATA, cRecipientInfo),
6006 offsetof(CRYPT_ENVELOPED_DATA, rgRecipientInfo),
6007 MEMBERSIZE(CRYPT_ENVELOPED_DATA, cRecipientInfo, encryptedContentInfo),
6008 CRYPT_AsnDecodeRecipientInfo, sizeof(CMSG_KEY_TRANS_RECIPIENT_INFO), TRUE,
6009 offsetof(CMSG_KEY_TRANS_RECIPIENT_INFO,
6010 RecipientId.u.IssuerSerialNumber.Issuer.pbData) };
6012 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
6013 pvStructInfo, *pcbStructInfo, pcbDecoded);
6015 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
6016 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
6017 TRACE("returning %d\n", ret);
6018 return ret;
6021 static BOOL CRYPT_AsnDecodeEncryptedContentInfo(const BYTE *pbEncoded,
6022 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6023 DWORD *pcbDecoded)
6025 BOOL ret;
6026 CRYPT_ENCRYPTED_CONTENT_INFO *info = pvStructInfo;
6027 struct AsnDecodeSequenceItem items[] = {
6028 { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
6029 contentType), CRYPT_AsnDecodeOidInternal, sizeof(LPSTR),
6030 FALSE, TRUE, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
6031 contentType), 0 },
6032 { ASN_SEQUENCEOF, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
6033 contentEncryptionAlgorithm), CRYPT_AsnDecodeAlgorithmId,
6034 sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
6035 offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
6036 contentEncryptionAlgorithm.pszObjId), 0 },
6037 { ASN_CONTEXT | 0, offsetof(CRYPT_ENCRYPTED_CONTENT_INFO,
6038 encryptedContent), CRYPT_AsnDecodeOctets,
6039 sizeof(CRYPT_DATA_BLOB), TRUE, TRUE,
6040 offsetof(CRYPT_ENCRYPTED_CONTENT_INFO, encryptedContent.pbData) },
6043 TRACE("%p, %ld, %08lx, %p, %ld, %p\n", pbEncoded, cbEncoded, dwFlags,
6044 pvStructInfo, *pcbStructInfo, pcbDecoded);
6046 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
6047 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo,
6048 pcbDecoded, info ? info->contentType : NULL);
6049 TRACE("returning %d\n", ret);
6050 return ret;
6053 BOOL CRYPT_AsnDecodePKCSEnvelopedData(const BYTE *pbEncoded, DWORD cbEncoded,
6054 DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
6055 CRYPT_ENVELOPED_DATA *envelopedData, DWORD *pcbEnvelopedData)
6057 BOOL ret;
6058 struct AsnDecodeSequenceItem items[] = {
6059 { ASN_INTEGER, offsetof(CRYPT_ENVELOPED_DATA, version),
6060 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE, 0, 0 },
6061 { ASN_CONSTRUCTOR | ASN_SETOF, offsetof(CRYPT_ENVELOPED_DATA,
6062 cRecipientInfo), CRYPT_DecodeRecipientInfoArray,
6063 MEMBERSIZE(CRYPT_ENVELOPED_DATA, cRecipientInfo, encryptedContentInfo),
6064 FALSE, TRUE, offsetof(CRYPT_ENVELOPED_DATA, rgRecipientInfo), 0 },
6065 { ASN_SEQUENCEOF, offsetof(CRYPT_ENVELOPED_DATA, encryptedContentInfo),
6066 CRYPT_AsnDecodeEncryptedContentInfo,
6067 sizeof(CRYPT_ENCRYPTED_CONTENT_INFO), FALSE, TRUE,
6068 offsetof(CRYPT_ENVELOPED_DATA, encryptedContentInfo.contentType), 0 },
6071 TRACE("%p, %ld, %08lx, %p, %p, %p\n", pbEncoded, cbEncoded, dwFlags,
6072 pDecodePara, envelopedData, pcbEnvelopedData);
6074 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
6075 pbEncoded, cbEncoded, dwFlags, pDecodePara, envelopedData,
6076 pcbEnvelopedData, NULL, NULL);
6077 TRACE("returning %d\n", ret);
6078 return ret;
6081 static BOOL WINAPI CRYPT_AsnDecodeObjectIdentifier(DWORD dwCertEncodingType,
6082 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
6083 CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
6085 DWORD bytesNeeded = 0;
6086 BOOL ret;
6088 __TRY
6090 ret = CRYPT_AsnDecodeOidInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
6091 NULL, &bytesNeeded, NULL);
6092 if (ret)
6094 if (!pvStructInfo)
6095 *pcbStructInfo = bytesNeeded;
6096 else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, bytesNeeded)))
6098 LPSTR *info;
6100 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
6101 pvStructInfo = *(BYTE **)pvStructInfo;
6103 info = pvStructInfo;
6104 *info = (void *)((BYTE *)info + sizeof(*info));
6105 ret = CRYPT_AsnDecodeOidInternal(pbEncoded, cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG,
6106 pvStructInfo, &bytesNeeded, NULL);
6107 if (!ret && (dwFlags & CRYPT_DECODE_ALLOC_FLAG))
6108 CRYPT_FreeSpace(pDecodePara, info);
6112 __EXCEPT_PAGE_FAULT
6114 SetLastError(STATUS_ACCESS_VIOLATION);
6115 ret = FALSE;
6117 __ENDTRY
6118 return ret;
6121 static BOOL WINAPI CRYPT_AsnDecodeEccSignature(DWORD dwCertEncodingType,
6122 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
6123 CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
6125 BOOL ret;
6126 struct AsnDecodeSequenceItem items[] = {
6127 { ASN_INTEGER, offsetof(CERT_ECC_SIGNATURE, r),
6128 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_UINT_BLOB), FALSE,
6129 TRUE, offsetof(CERT_ECC_SIGNATURE, r.pbData), 0 },
6130 { ASN_INTEGER, offsetof(CERT_ECC_SIGNATURE, s),
6131 CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_UINT_BLOB), FALSE,
6132 TRUE, offsetof(CERT_ECC_SIGNATURE, s.pbData), 0 },
6135 __TRY
6137 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
6138 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
6139 pcbStructInfo, NULL, NULL);
6141 __EXCEPT_PAGE_FAULT
6143 SetLastError(STATUS_ACCESS_VIOLATION);
6144 ret = FALSE;
6146 __ENDTRY
6147 return ret;
6150 static BOOL CRYPT_AsnDecodeOCSPResponseStatus(const BYTE *pbEncoded,
6151 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6152 DWORD *pcbDecoded)
6154 if (!cbEncoded)
6156 SetLastError(CRYPT_E_ASN1_EOD);
6157 return FALSE;
6159 if (pbEncoded[0] != ASN_ENUMERATED)
6161 SetLastError(CRYPT_E_ASN1_BADTAG);
6162 return FALSE;
6165 return CRYPT_AsnDecodeIntInternal(pbEncoded, cbEncoded, dwFlags, pvStructInfo,
6166 pcbStructInfo, pcbDecoded);
6169 static BOOL CRYPT_AsnDecodeOCSPResponseBytes(const BYTE *pbEncoded,
6170 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6171 DWORD *pcbDecoded)
6173 DWORD dataLen;
6174 BOOL ret;
6176 if (!cbEncoded)
6178 SetLastError(CRYPT_E_ASN1_EOD);
6179 return FALSE;
6181 if (pbEncoded[0] != (ASN_CONTEXT | ASN_CONSTRUCTOR))
6183 SetLastError(CRYPT_E_ASN1_BADTAG);
6184 return FALSE;
6187 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
6189 struct AsnDecodeSequenceItem items[] = {
6190 { ASN_OBJECTIDENTIFIER, 0,
6191 CRYPT_AsnDecodeOidIgnoreTag, sizeof(LPSTR), FALSE, TRUE,
6192 0, 0 },
6193 { ASN_OCTETSTRING, sizeof(LPSTR),
6194 CRYPT_AsnDecodeOctets, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
6195 sizeof(LPSTR) + offsetof(CRYPT_OBJID_BLOB, pbData), 0 },
6197 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
6198 DWORD bytesNeeded;
6200 if (dataLen)
6202 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
6203 pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes, dwFlags, NULL,
6204 pvStructInfo, pcbStructInfo, &bytesNeeded, NULL);
6205 if (ret) *pcbDecoded = bytesNeeded + lenBytes + 1;
6208 return ret;
6211 static BOOL WINAPI CRYPT_AsnDecodeOCSPResponse(DWORD dwCertEncodingType,
6212 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
6213 CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
6215 BOOL ret;
6216 struct AsnDecodeSequenceItem items[] = {
6217 { ASN_ENUMERATED, offsetof(OCSP_RESPONSE_INFO, dwStatus),
6218 CRYPT_AsnDecodeOCSPResponseStatus, sizeof(DWORD), FALSE, FALSE,
6219 0, 0 },
6220 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(OCSP_RESPONSE_INFO, pszObjId),
6221 CRYPT_AsnDecodeOCSPResponseBytes, sizeof(LPSTR) + sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
6222 offsetof(OCSP_RESPONSE_INFO, pszObjId), 0 },
6225 __TRY
6227 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
6228 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
6229 pcbStructInfo, NULL, NULL);
6231 __EXCEPT_PAGE_FAULT
6233 SetLastError(STATUS_ACCESS_VIOLATION);
6234 ret = FALSE;
6236 __ENDTRY
6237 return ret;
6240 static BOOL CRYPT_AsnDecodeOCSPSignatureInfoCertEncoded(const BYTE *pbEncoded,
6241 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6242 DWORD *pcbDecoded)
6244 BOOL ret;
6245 struct AsnArrayDescriptor arrayDesc = { 0,
6246 offsetof(OCSP_SIGNATURE_INFO, cCertEncoded), offsetof(OCSP_SIGNATURE_INFO, rgCertEncoded),
6247 FINALMEMBERSIZE(OCSP_SIGNATURE_INFO, cCertEncoded), verify_and_copy_certificate,
6248 sizeof(CRYPT_DER_BLOB), TRUE, offsetof(CRYPT_DER_BLOB, pbData) };
6250 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
6251 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
6252 return ret;
6255 static BOOL WINAPI CRYPT_AsnDecodeOCSPBasicSignedResponse(DWORD dwCertEncodingType,
6256 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
6257 CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
6259 BOOL ret;
6260 struct AsnDecodeSequenceItem items[] = {
6261 { 0, offsetof(OCSP_BASIC_SIGNED_RESPONSE_INFO, ToBeSigned),
6262 CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
6263 offsetof(OCSP_BASIC_SIGNED_RESPONSE_INFO, ToBeSigned.pbData), 0 },
6264 { ASN_SEQUENCEOF, offsetof(OCSP_BASIC_SIGNED_RESPONSE_INFO, SignatureInfo.SignatureAlgorithm),
6265 CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
6266 offsetof(OCSP_BASIC_SIGNED_RESPONSE_INFO, SignatureInfo.SignatureAlgorithm.pszObjId), 0 },
6267 { ASN_BITSTRING, offsetof(OCSP_BASIC_SIGNED_RESPONSE_INFO, SignatureInfo.Signature),
6268 CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
6269 offsetof(OCSP_BASIC_SIGNED_RESPONSE_INFO, SignatureInfo.Signature.pbData) },
6270 { 0, offsetof(OCSP_BASIC_SIGNED_RESPONSE_INFO, SignatureInfo.cCertEncoded),
6271 CRYPT_AsnDecodeOCSPSignatureInfoCertEncoded, FINALMEMBERSIZE(OCSP_SIGNATURE_INFO, cCertEncoded),
6272 TRUE, TRUE, offsetof(OCSP_BASIC_SIGNED_RESPONSE_INFO, SignatureInfo.rgCertEncoded) },
6275 __TRY
6277 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
6278 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
6279 pcbStructInfo, NULL, NULL);
6281 __EXCEPT_PAGE_FAULT
6283 SetLastError(STATUS_ACCESS_VIOLATION);
6284 ret = FALSE;
6286 __ENDTRY
6287 return ret;
6290 static BOOL CRYPT_AsnDecodeOCSPHashAlgorithm(const BYTE *pbEncoded,
6291 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6292 DWORD *pcbDecoded)
6294 DWORD dataLen;
6295 BOOL ret;
6297 if (!cbEncoded)
6299 SetLastError(CRYPT_E_ASN1_EOD);
6300 return FALSE;
6302 if (pbEncoded[0] != ASN_SEQUENCEOF)
6304 SetLastError(CRYPT_E_ASN1_BADTAG);
6305 return FALSE;
6308 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
6310 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
6311 DWORD bytesDecoded;
6312 if (dataLen)
6314 ret = CRYPT_AsnDecodeAlgorithmId(pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes, dwFlags,
6315 pvStructInfo, pcbStructInfo, &bytesDecoded);
6316 if (ret) *pcbDecoded = bytesDecoded + lenBytes + 1;
6319 return ret;
6322 static BOOL CRYPT_AsnDecodeOCSPNextUpdate(const BYTE *pbEncoded,
6323 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6324 DWORD *pcbDecoded)
6326 DWORD dataLen;
6327 BOOL ret;
6329 if (!cbEncoded)
6331 SetLastError(CRYPT_E_ASN1_EOD);
6332 return FALSE;
6334 if (pbEncoded[0] != (ASN_CONTEXT | ASN_CONSTRUCTOR))
6336 SetLastError(CRYPT_E_ASN1_BADTAG);
6337 return FALSE;
6340 if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
6342 BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
6343 DWORD bytesDecoded;
6344 if (dataLen)
6346 ret = CRYPT_AsnDecodeGeneralizedTime(pbEncoded + 1 + lenBytes, cbEncoded - 1 - lenBytes, dwFlags,
6347 pvStructInfo, pcbStructInfo, &bytesDecoded);
6348 if (ret) *pcbDecoded = bytesDecoded + lenBytes + 1;
6351 return ret;
6354 static BOOL CRYPT_AsnDecodeOCSPBasicResponseEntry(const BYTE *pbEncoded, DWORD cbEncoded,
6355 DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo, DWORD *pcbDecoded)
6357 struct AsnDecodeSequenceItem items[] = {
6358 { ASN_SEQUENCEOF, offsetof(OCSP_BASIC_RESPONSE_ENTRY, CertId.HashAlgorithm.pszObjId),
6359 CRYPT_AsnDecodeOCSPHashAlgorithm, sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
6360 offsetof(OCSP_BASIC_RESPONSE_ENTRY, CertId.HashAlgorithm.pszObjId), 0 },
6361 { ASN_OCTETSTRING, offsetof(OCSP_BASIC_RESPONSE_ENTRY, CertId.IssuerNameHash),
6362 CRYPT_AsnDecodeOctets, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
6363 offsetof(OCSP_BASIC_RESPONSE_ENTRY, CertId.IssuerNameHash.pbData), 0 },
6364 { ASN_OCTETSTRING, offsetof(OCSP_BASIC_RESPONSE_ENTRY, CertId.IssuerKeyHash),
6365 CRYPT_AsnDecodeOctets, sizeof(CRYPT_HASH_BLOB), FALSE, TRUE,
6366 offsetof(OCSP_BASIC_RESPONSE_ENTRY, CertId.IssuerKeyHash.pbData), 0 },
6367 { ASN_INTEGER, offsetof(OCSP_BASIC_RESPONSE_ENTRY, CertId.SerialNumber),
6368 CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
6369 offsetof(OCSP_BASIC_RESPONSE_ENTRY, CertId.SerialNumber.pbData), 0 },
6370 { ASN_CONTEXT, offsetof(OCSP_BASIC_RESPONSE_ENTRY, dwCertStatus),
6371 CRYPT_AsnDecodeIntInternal, sizeof(DWORD), FALSE, FALSE,
6372 0, 0 },
6373 /* FIXME: pRevokedInfo */
6374 { ASN_GENERALTIME, offsetof(OCSP_BASIC_RESPONSE_ENTRY, ThisUpdate),
6375 CRYPT_AsnDecodeGeneralizedTime, sizeof(FILETIME), FALSE, FALSE,
6376 0, 0 },
6377 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(OCSP_BASIC_RESPONSE_ENTRY, NextUpdate),
6378 CRYPT_AsnDecodeOCSPNextUpdate, sizeof(FILETIME), TRUE, FALSE,
6379 0, 0 },
6380 { ASN_CONTEXT | ASN_CONSTRUCTOR /* FIXME */, offsetof(OCSP_BASIC_RESPONSE_ENTRY, cExtension),
6381 CRYPT_AsnDecodeCertExtensions, FINALMEMBERSIZE(OCSP_BASIC_RESPONSE_ENTRY, cExtension),
6382 TRUE, TRUE, offsetof(OCSP_BASIC_RESPONSE_ENTRY, rgExtension), 0 },
6385 return CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
6386 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo,
6387 pcbStructInfo, pcbDecoded, NULL);
6390 static BOOL CRYPT_AsnDecodeOCSPBasicResponseEntriesArray(const BYTE *pbEncoded,
6391 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6392 DWORD *pcbDecoded)
6394 struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
6395 offsetof(OCSP_BASIC_RESPONSE_INFO, cResponseEntry), offsetof(OCSP_BASIC_RESPONSE_INFO, rgResponseEntry),
6396 MEMBERSIZE(OCSP_BASIC_RESPONSE_INFO, cResponseEntry, cExtension),
6397 CRYPT_AsnDecodeOCSPBasicResponseEntry, sizeof(OCSP_BASIC_RESPONSE_ENTRY),
6398 FALSE, 0 };
6400 return CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
6401 dwFlags, NULL, pvStructInfo, pcbStructInfo, pcbDecoded);
6404 static BOOL CRYPT_AsnDecodeResponderID(const BYTE *pbEncoded,
6405 DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, DWORD *pcbStructInfo,
6406 DWORD *pcbDecoded)
6408 OCSP_BASIC_RESPONSE_INFO *info = pvStructInfo;
6409 BYTE tag = pbEncoded[0] & ~3, choice = pbEncoded[0] & 3;
6410 DWORD decodedLen, dataLen, lenBytes, bytesNeeded = sizeof(*info), len;
6411 CERT_NAME_BLOB *blob;
6413 if (tag != (ASN_CONTEXT | ASN_CONSTRUCTOR))
6415 WARN("Unexpected tag %02x\n", tag);
6416 SetLastError(CRYPT_E_ASN1_BADTAG);
6417 return FALSE;
6419 if (choice > 2)
6421 WARN("Unexpected choice %02x\n", choice);
6422 SetLastError(CRYPT_E_ASN1_CORRUPT);
6423 return FALSE;
6426 if (pvStructInfo && *pcbStructInfo >= bytesNeeded)
6427 info->dwResponderIdChoice = choice;
6429 if (!CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))
6430 return FALSE;
6431 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
6432 cbEncoded -= 1 + lenBytes;
6433 decodedLen = 1 + lenBytes;
6435 if (dataLen > cbEncoded)
6437 SetLastError(CRYPT_E_ASN1_EOD);
6438 return FALSE;
6440 pbEncoded += 1 + lenBytes;
6441 if (pbEncoded[0] != ASN_OCTETSTRING)
6443 WARN("Unexpected tag %02x\n", pbEncoded[0]);
6444 SetLastError(CRYPT_E_ASN1_BADTAG);
6445 return FALSE;
6448 if (!CRYPT_GetLen(pbEncoded, cbEncoded, &len))
6449 return FALSE;
6450 lenBytes = GET_LEN_BYTES(pbEncoded[1]);
6451 decodedLen += 1 + lenBytes + len;
6452 cbEncoded -= 1 + lenBytes;
6454 if (len > cbEncoded)
6456 SetLastError(CRYPT_E_ASN1_EOD);
6457 return FALSE;
6459 pbEncoded += 1 + lenBytes;
6461 if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG)) bytesNeeded += len;
6462 if (pvStructInfo && *pcbStructInfo >= bytesNeeded)
6464 blob = &info->u.ByNameResponderId;
6465 blob->cbData = len;
6466 if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
6467 blob->pbData = (BYTE *)pbEncoded;
6468 else if (blob->cbData)
6470 blob->pbData = (BYTE *)(info + 1);
6471 memcpy(blob->pbData, pbEncoded, blob->cbData);
6475 if (pcbDecoded)
6476 *pcbDecoded = decodedLen;
6478 if (!pvStructInfo)
6480 *pcbStructInfo = bytesNeeded;
6481 return TRUE;
6484 if (*pcbStructInfo < bytesNeeded)
6486 SetLastError(ERROR_MORE_DATA);
6487 *pcbStructInfo = bytesNeeded;
6488 return FALSE;
6491 *pcbStructInfo = bytesNeeded;
6492 return TRUE;
6495 static BOOL WINAPI CRYPT_AsnDecodeOCSPBasicResponse(DWORD dwCertEncodingType,
6496 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
6497 CRYPT_DECODE_PARA *pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
6499 struct AsnDecodeSequenceItem items[] = {
6500 { 0, 0,
6501 CRYPT_AsnDecodeResponderID, offsetof(OCSP_BASIC_RESPONSE_INFO, ProducedAt), FALSE, TRUE,
6502 offsetof(OCSP_BASIC_RESPONSE_INFO, u.ByNameResponderId.pbData), 0 },
6503 { ASN_GENERALTIME, offsetof(OCSP_BASIC_RESPONSE_INFO, ProducedAt),
6504 CRYPT_AsnDecodeGeneralizedTime, sizeof(FILETIME), FALSE, FALSE,
6505 0, 0 },
6506 { ASN_SEQUENCEOF, offsetof(OCSP_BASIC_RESPONSE_INFO, cResponseEntry),
6507 CRYPT_AsnDecodeOCSPBasicResponseEntriesArray, MEMBERSIZE(OCSP_BASIC_RESPONSE_INFO, cResponseEntry, cExtension),
6508 TRUE, TRUE, offsetof(OCSP_BASIC_RESPONSE_INFO, rgResponseEntry) },
6509 { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(OCSP_BASIC_RESPONSE_INFO, cExtension),
6510 CRYPT_AsnDecodeCertExtensions, FINALMEMBERSIZE(OCSP_BASIC_RESPONSE_INFO, cExtension),
6511 TRUE, TRUE, offsetof(OCSP_BASIC_RESPONSE_INFO, rgExtension), 0 },
6513 BOOL ret;
6515 __TRY
6517 ret = CRYPT_AsnDecodeSequence(items, ARRAY_SIZE(items),
6518 pbEncoded, cbEncoded, dwFlags, pDecodePara, pvStructInfo,
6519 pcbStructInfo, NULL, NULL);
6521 __EXCEPT_PAGE_FAULT
6523 SetLastError(STATUS_ACCESS_VIOLATION);
6524 ret = FALSE;
6526 __ENDTRY
6527 return ret;
6530 static CryptDecodeObjectExFunc CRYPT_GetBuiltinDecoder(DWORD dwCertEncodingType,
6531 LPCSTR lpszStructType)
6533 CryptDecodeObjectExFunc decodeFunc = NULL;
6535 if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING
6536 && (dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
6538 SetLastError(ERROR_FILE_NOT_FOUND);
6539 return NULL;
6541 if (IS_INTOID(lpszStructType))
6543 switch (LOWORD(lpszStructType))
6545 case LOWORD(X509_CERT):
6546 decodeFunc = CRYPT_AsnDecodeCertSignedContent;
6547 break;
6548 case LOWORD(X509_CERT_TO_BE_SIGNED):
6549 decodeFunc = CRYPT_AsnDecodeCert;
6550 break;
6551 case LOWORD(X509_CERT_CRL_TO_BE_SIGNED):
6552 decodeFunc = CRYPT_AsnDecodeCRL;
6553 break;
6554 case LOWORD(X509_EXTENSIONS):
6555 decodeFunc = CRYPT_AsnDecodeExtensions;
6556 break;
6557 case LOWORD(X509_NAME_VALUE):
6558 decodeFunc = CRYPT_AsnDecodeNameValue;
6559 break;
6560 case LOWORD(X509_NAME):
6561 decodeFunc = CRYPT_AsnDecodeName;
6562 break;
6563 case LOWORD(X509_PUBLIC_KEY_INFO):
6564 decodeFunc = CRYPT_AsnDecodePubKeyInfo;
6565 break;
6566 case LOWORD(X509_AUTHORITY_KEY_ID):
6567 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
6568 break;
6569 case LOWORD(X509_ALTERNATE_NAME):
6570 decodeFunc = CRYPT_AsnDecodeAltName;
6571 break;
6572 case LOWORD(X509_BASIC_CONSTRAINTS):
6573 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
6574 break;
6575 case LOWORD(X509_BASIC_CONSTRAINTS2):
6576 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
6577 break;
6578 case LOWORD(X509_CERT_POLICIES):
6579 decodeFunc = CRYPT_AsnDecodeCertPolicies;
6580 break;
6581 case LOWORD(RSA_CSP_PUBLICKEYBLOB):
6582 decodeFunc = CRYPT_AsnDecodeRsaPubKey;
6583 break;
6584 case LOWORD(PKCS_RSA_PRIVATE_KEY):
6585 decodeFunc = CRYPT_AsnDecodeRsaPrivKey;
6586 break;
6587 case LOWORD(X509_UNICODE_NAME):
6588 decodeFunc = CRYPT_AsnDecodeUnicodeName;
6589 break;
6590 case LOWORD(PKCS_ATTRIBUTE):
6591 decodeFunc = CRYPT_AsnDecodePKCSAttribute;
6592 break;
6593 case LOWORD(X509_UNICODE_NAME_VALUE):
6594 decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
6595 break;
6596 case LOWORD(X509_OCTET_STRING):
6597 decodeFunc = CRYPT_AsnDecodeOctetString;
6598 break;
6599 case LOWORD(X509_BITS):
6600 case LOWORD(X509_KEY_USAGE):
6601 decodeFunc = CRYPT_AsnDecodeBits;
6602 break;
6603 case LOWORD(X509_INTEGER):
6604 decodeFunc = CRYPT_AsnDecodeInt;
6605 break;
6606 case LOWORD(X509_MULTI_BYTE_INTEGER):
6607 decodeFunc = CRYPT_AsnDecodeInteger;
6608 break;
6609 case LOWORD(X509_MULTI_BYTE_UINT):
6610 decodeFunc = CRYPT_AsnDecodeUnsignedInteger;
6611 break;
6612 case LOWORD(X509_ENUMERATED):
6613 decodeFunc = CRYPT_AsnDecodeEnumerated;
6614 break;
6615 case LOWORD(X509_CHOICE_OF_TIME):
6616 decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
6617 break;
6618 case LOWORD(X509_AUTHORITY_KEY_ID2):
6619 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
6620 break;
6621 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
6622 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
6623 break;
6624 case LOWORD(PKCS_CONTENT_INFO):
6625 decodeFunc = CRYPT_AsnDecodePKCSContentInfo;
6626 break;
6627 case LOWORD(X509_SEQUENCE_OF_ANY):
6628 decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
6629 break;
6630 case LOWORD(PKCS_UTC_TIME):
6631 decodeFunc = CRYPT_AsnDecodeUtcTime;
6632 break;
6633 case LOWORD(X509_CRL_DIST_POINTS):
6634 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
6635 break;
6636 case LOWORD(X509_ENHANCED_KEY_USAGE):
6637 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
6638 break;
6639 case LOWORD(PKCS_CTL):
6640 decodeFunc = CRYPT_AsnDecodeCTL;
6641 break;
6642 case LOWORD(PKCS_SMIME_CAPABILITIES):
6643 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
6644 break;
6645 case LOWORD(X509_PKIX_POLICY_QUALIFIER_USERNOTICE):
6646 decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
6647 break;
6648 case LOWORD(PKCS_ATTRIBUTES):
6649 decodeFunc = CRYPT_AsnDecodePKCSAttributes;
6650 break;
6651 case LOWORD(X509_ISSUING_DIST_POINT):
6652 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
6653 break;
6654 case LOWORD(X509_NAME_CONSTRAINTS):
6655 decodeFunc = CRYPT_AsnDecodeNameConstraints;
6656 break;
6657 case LOWORD(X509_POLICY_MAPPINGS):
6658 decodeFunc = CRYPT_AsnDecodeCertPolicyMappings;
6659 break;
6660 case LOWORD(X509_POLICY_CONSTRAINTS):
6661 decodeFunc = CRYPT_AsnDecodeCertPolicyConstraints;
6662 break;
6663 case LOWORD(PKCS7_SIGNER_INFO):
6664 decodeFunc = CRYPT_AsnDecodePKCSSignerInfo;
6665 break;
6666 case LOWORD(CMS_SIGNER_INFO):
6667 decodeFunc = CRYPT_AsnDecodeCMSSignerInfo;
6668 break;
6669 case LOWORD(X509_OBJECT_IDENTIFIER):
6670 decodeFunc = CRYPT_AsnDecodeObjectIdentifier;
6671 break;
6672 case LOWORD(X509_ECC_SIGNATURE):
6673 decodeFunc = CRYPT_AsnDecodeEccSignature;
6674 break;
6675 case LOWORD(CNG_RSA_PUBLIC_KEY_BLOB):
6676 decodeFunc = CRYPT_AsnDecodeRsaPubKey_Bcrypt;
6677 break;
6678 case LOWORD(OCSP_RESPONSE):
6679 decodeFunc = CRYPT_AsnDecodeOCSPResponse;
6680 break;
6681 case LOWORD(OCSP_BASIC_SIGNED_RESPONSE):
6682 decodeFunc = CRYPT_AsnDecodeOCSPBasicSignedResponse;
6683 break;
6684 case LOWORD(OCSP_BASIC_RESPONSE):
6685 decodeFunc = CRYPT_AsnDecodeOCSPBasicResponse;
6686 break;
6687 default:
6688 FIXME("Unimplemented decoder for lpszStructType OID %d\n", LOWORD(lpszStructType));
6691 else if (!strcmp(lpszStructType, szOID_CERT_EXTENSIONS))
6692 decodeFunc = CRYPT_AsnDecodeExtensions;
6693 else if (!strcmp(lpszStructType, szOID_RSA_signingTime))
6694 decodeFunc = CRYPT_AsnDecodeUtcTime;
6695 else if (!strcmp(lpszStructType, szOID_RSA_SMIMECapabilities))
6696 decodeFunc = CRYPT_AsnDecodeSMIMECapabilities;
6697 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
6698 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
6699 else if (!strcmp(lpszStructType, szOID_LEGACY_POLICY_MAPPINGS))
6700 decodeFunc = CRYPT_AsnDecodeCertPolicyMappings;
6701 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
6702 decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
6703 else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
6704 decodeFunc = CRYPT_AsnDecodeEnumerated;
6705 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
6706 decodeFunc = CRYPT_AsnDecodeBits;
6707 else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
6708 decodeFunc = CRYPT_AsnDecodeOctetString;
6709 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
6710 decodeFunc = CRYPT_AsnDecodeBasicConstraints;
6711 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
6712 decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
6713 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
6714 decodeFunc = CRYPT_AsnDecodeAltName;
6715 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
6716 decodeFunc = CRYPT_AsnDecodeAltName;
6717 else if (!strcmp(lpszStructType, szOID_NEXT_UPDATE_LOCATION))
6718 decodeFunc = CRYPT_AsnDecodeAltName;
6719 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
6720 decodeFunc = CRYPT_AsnDecodeAltName;
6721 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
6722 decodeFunc = CRYPT_AsnDecodeAltName;
6723 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
6724 decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
6725 else if (!strcmp(lpszStructType, szOID_CERT_POLICIES))
6726 decodeFunc = CRYPT_AsnDecodeCertPolicies;
6727 else if (!strcmp(lpszStructType, szOID_POLICY_MAPPINGS))
6728 decodeFunc = CRYPT_AsnDecodeCertPolicyMappings;
6729 else if (!strcmp(lpszStructType, szOID_POLICY_CONSTRAINTS))
6730 decodeFunc = CRYPT_AsnDecodeCertPolicyConstraints;
6731 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
6732 decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
6733 else if (!strcmp(lpszStructType, szOID_ISSUING_DIST_POINT))
6734 decodeFunc = CRYPT_AsnDecodeIssuingDistPoint;
6735 else if (!strcmp(lpszStructType, szOID_NAME_CONSTRAINTS))
6736 decodeFunc = CRYPT_AsnDecodeNameConstraints;
6737 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
6738 decodeFunc = CRYPT_AsnDecodeAuthorityInfoAccess;
6739 else if (!strcmp(lpszStructType, szOID_PKIX_POLICY_QUALIFIER_USERNOTICE))
6740 decodeFunc = CRYPT_AsnDecodePolicyQualifierUserNotice;
6741 else if (!strcmp(lpszStructType, szOID_CTL))
6742 decodeFunc = CRYPT_AsnDecodeCTL;
6743 else if (!strcmp(lpszStructType, szOID_ECC_PUBLIC_KEY))
6744 decodeFunc = CRYPT_AsnDecodeObjectIdentifier;
6745 else
6746 FIXME("Unsupported decoder for lpszStructType %s\n", lpszStructType);
6747 return decodeFunc;
6750 static CryptDecodeObjectFunc CRYPT_LoadDecoderFunc(DWORD dwCertEncodingType,
6751 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
6753 static HCRYPTOIDFUNCSET set = NULL;
6754 CryptDecodeObjectFunc decodeFunc = NULL;
6756 if (!set)
6757 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_FUNC, 0);
6758 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
6759 (void **)&decodeFunc, hFunc);
6760 return decodeFunc;
6763 static CryptDecodeObjectExFunc CRYPT_LoadDecoderExFunc(DWORD dwCertEncodingType,
6764 LPCSTR lpszStructType, HCRYPTOIDFUNCADDR *hFunc)
6766 static HCRYPTOIDFUNCSET set = NULL;
6767 CryptDecodeObjectExFunc decodeFunc = NULL;
6769 if (!set)
6770 set = CryptInitOIDFunctionSet(CRYPT_OID_DECODE_OBJECT_EX_FUNC, 0);
6771 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
6772 (void **)&decodeFunc, hFunc);
6773 return decodeFunc;
6776 BOOL WINAPI CryptDecodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
6777 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo,
6778 DWORD *pcbStructInfo)
6780 return CryptDecodeObjectEx(dwCertEncodingType, lpszStructType,
6781 pbEncoded, cbEncoded, dwFlags, NULL, pvStructInfo, pcbStructInfo);
6784 BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
6785 const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
6786 PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
6788 BOOL ret = FALSE;
6789 CryptDecodeObjectExFunc decodeFunc;
6790 HCRYPTOIDFUNCADDR hFunc = NULL;
6792 TRACE_(crypt)("(0x%08lx, %s, %p, %ld, 0x%08lx, %p, %p, %p)\n",
6793 dwCertEncodingType, debugstr_a(lpszStructType), pbEncoded,
6794 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
6796 if (!pvStructInfo && !pcbStructInfo)
6798 SetLastError(ERROR_INVALID_PARAMETER);
6799 return FALSE;
6801 if (cbEncoded > MAX_ENCODED_LEN)
6803 FIXME_(crypt)("Returning CRYPT_E_ASN1_LARGE, cbEncoded %lu.\n", cbEncoded);
6804 SetLastError(CRYPT_E_ASN1_LARGE);
6805 return FALSE;
6808 SetLastError(NOERROR);
6809 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
6811 if (!pvStructInfo)
6813 SetLastError(ERROR_INVALID_PARAMETER);
6814 return FALSE;
6816 *(BYTE **)pvStructInfo = NULL;
6818 decodeFunc = CRYPT_GetBuiltinDecoder(dwCertEncodingType, lpszStructType);
6819 if (!decodeFunc)
6821 TRACE_(crypt)("OID %s not found or unimplemented, looking for DLL\n",
6822 debugstr_a(lpszStructType));
6823 decodeFunc = CRYPT_LoadDecoderExFunc(dwCertEncodingType, lpszStructType,
6824 &hFunc);
6826 if (decodeFunc)
6827 ret = decodeFunc(dwCertEncodingType, lpszStructType, pbEncoded,
6828 cbEncoded, dwFlags, pDecodePara, pvStructInfo, pcbStructInfo);
6829 else
6831 CryptDecodeObjectFunc pCryptDecodeObject =
6832 CRYPT_LoadDecoderFunc(dwCertEncodingType, lpszStructType, &hFunc);
6834 /* Try CryptDecodeObject function. Don't call CryptDecodeObject
6835 * directly, as that could cause an infinite loop.
6837 if (pCryptDecodeObject)
6839 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
6841 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
6842 pbEncoded, cbEncoded, dwFlags, NULL, pcbStructInfo);
6843 if (ret && (ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
6844 pvStructInfo, pcbStructInfo, *pcbStructInfo)))
6846 ret = pCryptDecodeObject(dwCertEncodingType,
6847 lpszStructType, pbEncoded, cbEncoded, dwFlags,
6848 *(BYTE **)pvStructInfo, pcbStructInfo);
6849 if (!ret)
6850 CRYPT_FreeSpace(pDecodePara, *(BYTE **)pvStructInfo);
6853 else
6854 ret = pCryptDecodeObject(dwCertEncodingType, lpszStructType,
6855 pbEncoded, cbEncoded, dwFlags, pvStructInfo, pcbStructInfo);
6858 if (hFunc)
6859 CryptFreeOIDFunctionAddress(hFunc, 0);
6860 TRACE_(crypt)("returning %d\n", ret);
6861 return ret;
6864 BOOL WINAPI PFXIsPFXBlob(CRYPT_DATA_BLOB *pPFX)
6866 BOOL ret;
6868 TRACE_(crypt)("(%p)\n", pPFX);
6870 /* A PFX blob is an asn.1-encoded sequence, consisting of at least a
6871 * version integer of length 1 (3 encoded byes) and at least one other
6872 * datum (two encoded bytes), plus at least two bytes for the outer
6873 * sequence. Thus, even an empty PFX blob is at least 7 bytes in length.
6875 if (pPFX->cbData < 7)
6876 ret = FALSE;
6877 else if (pPFX->pbData[0] == ASN_SEQUENCE)
6879 DWORD len;
6881 if ((ret = CRYPT_GetLengthIndefinite(pPFX->pbData, pPFX->cbData, &len)))
6883 BYTE lenLen = GET_LEN_BYTES(pPFX->pbData[1]);
6885 /* Need at least three bytes for the integer version */
6886 if (pPFX->cbData < 1 + lenLen + 3)
6887 ret = FALSE;
6888 else if (pPFX->pbData[1 + lenLen] != ASN_INTEGER || /* Tag */
6889 pPFX->pbData[1 + lenLen + 1] != 1 || /* Definite length */
6890 pPFX->pbData[1 + lenLen + 2] != 3) /* PFX version */
6891 ret = FALSE;
6894 else
6895 ret = FALSE;
6896 return ret;